mods.railcraft.common.fluids.TankManager.java Source code

Java tutorial

Introduction

Here is the source code for mods.railcraft.common.fluids.TankManager.java

Source

/* 
 * Copyright (c) CovertJaguar, 2014 http://railcraft.info
 * 
 * This code is the property of CovertJaguar
 * and may only be used with explicit written
 * permission unless otherwise specified on the
 * license page at http://railcraft.info/wiki/info:license.
 */
package mods.railcraft.common.fluids;

import com.google.common.collect.ForwardingList;
import mods.railcraft.common.fluids.tanks.StandardTank;
import mods.railcraft.common.plugins.forge.NBTPlugin;
import mods.railcraft.common.plugins.forge.NBTPlugin.NBTList;
import mods.railcraft.common.util.misc.AdjacentTileCache;
import mods.railcraft.common.util.misc.ITileFilter;
import mods.railcraft.common.util.network.PacketBuilder;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ICrafting;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.*;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author CovertJaguar <http://www.railcraft.info>
 */
public class TankManager extends ForwardingList<StandardTank> implements IFluidHandler, List<StandardTank> {
    public static final ITileFilter TANK_FILTER = new ITileFilter() {
        @Override
        public boolean matches(TileEntity tile) {
            return tile instanceof IFluidHandler;
        }
    };
    private static final byte NETWORK_DATA = 3;
    private final List<StandardTank> tanks = new ArrayList<StandardTank>();

    public TankManager() {
    }

    public TankManager(StandardTank... tanks) {
        addAll(Arrays.asList(tanks));
    }

    public static IFluidHandler getTankFromTile(TileEntity tile) {
        IFluidHandler tank = null;
        if (tile instanceof IFluidHandler)
            tank = (IFluidHandler) tile;
        return tank;
    }

    @Override
    protected List<StandardTank> delegate() {
        return tanks;
    }

    @Override
    public boolean add(StandardTank tank) {
        boolean added = tanks.add(tank);
        int index = tanks.indexOf(tank);
        tank.setTankIndex(index);
        return added;
    }

    public void writeTanksToNBT(NBTTagCompound data) {
        NBTTagList tagList = new NBTTagList();
        for (byte slot = 0; slot < tanks.size(); slot++) {
            StandardTank tank = tanks.get(slot);
            if (tank.getFluid() != null) {
                NBTTagCompound tag = new NBTTagCompound();
                tag.setByte("tank", slot);
                tank.writeToNBT(tag);
                tagList.appendTag(tag);
            }
        }
        data.setTag("tanks", tagList);
    }

    public void readTanksFromNBT(NBTTagCompound data) {
        NBTList<NBTTagCompound> tagList = NBTPlugin.getNBTList(data, "tanks", NBTPlugin.EnumNBTType.COMPOUND);
        for (NBTTagCompound tag : tagList) {
            int slot = tag.getByte("tank");
            if (slot >= 0 && slot < tanks.size())
                tanks.get(slot).readFromNBT(tag);
        }
    }

    public void writePacketData(DataOutputStream data) throws IOException {
        for (int i = 0; i < tanks.size(); i++) {
            writePacketData(data, i);
        }
    }

    public void writePacketData(DataOutputStream data, int tankIndex) throws IOException {
        if (tankIndex >= tanks.size())
            return;
        StandardTank tank = tanks.get(tankIndex);
        FluidStack fluidStack = tank.getFluid();
        if (fluidStack != null) {
            data.writeShort(FluidHelper.getFluidId(fluidStack));
            data.writeInt(fluidStack.amount);
            data.writeInt(fluidStack.getFluid().getColor(fluidStack));
        } else
            data.writeShort(-1);
    }

    public void readPacketData(DataInputStream data) throws IOException {
        for (int i = 0; i < tanks.size(); i++) {
            readPacketData(data, i);
        }
    }

    public void readPacketData(DataInputStream data, int tankIndex) throws IOException {
        if (tankIndex >= tanks.size())
            return;
        StandardTank tank = tanks.get(tankIndex);
        int fluidId = data.readShort();
        if (fluidId != -1) {
            tank.renderData.fluid = FluidRegistry.getFluid(fluidId);
            tank.renderData.amount = data.readInt();
            tank.renderData.color = data.readInt();
        } else
            tank.renderData.reset();
    }

    public void initGuiData(Container container, ICrafting player, int tankIndex) {
        if (tankIndex >= tanks.size())
            return;
        StandardTank tank = tanks.get(tankIndex);
        FluidStack fluidStack = tanks.get(tankIndex).getFluid();
        int color = tank.getColor();
        int fluidId = -1;
        int fluidAmount = 0;
        if (fluidStack != null && fluidStack.amount > 0) {
            fluidId = fluidStack.getFluid().getID();
            fluidAmount = fluidStack.amount;
        }

        player.sendProgressBarUpdate(container, tankIndex * NETWORK_DATA + 0, fluidId);
        PacketBuilder.instance().sendGuiIntegerPacket((EntityPlayerMP) player, container.windowId,
                tankIndex * NETWORK_DATA + 1, fluidAmount);
        PacketBuilder.instance().sendGuiIntegerPacket((EntityPlayerMP) player, container.windowId,
                tankIndex * NETWORK_DATA + 2, color);

        tank.renderData.fluid = tank.getFluidType();
        tank.renderData.amount = fluidAmount;
        tank.renderData.color = color;
    }

    public void updateGuiData(Container container, List crafters, int tankIndex) {
        StandardTank tank = tanks.get(tankIndex);
        FluidStack fluidStack = tank.getFluid();
        int color = tank.getColor();
        int pColor = tank.renderData.color;

        for (Object crafter1 : crafters) {
            ICrafting crafter = (ICrafting) crafter1;
            EntityPlayerMP player = (EntityPlayerMP) crafter1;
            if (fluidStack == null ^ tank.renderData.fluid == null) {
                int fluidId = -1;
                int fluidAmount = 0;
                if (fluidStack != null) {
                    fluidId = FluidHelper.getFluidId(fluidStack);
                    fluidAmount = fluidStack.amount;
                }
                crafter.sendProgressBarUpdate(container, tankIndex * NETWORK_DATA + 0, fluidId);
                PacketBuilder.instance().sendGuiIntegerPacket(player, container.windowId,
                        tankIndex * NETWORK_DATA + 1, fluidAmount);
            } else if (fluidStack != null && tank.renderData.fluid != null) {
                if (fluidStack.getFluid() != tank.renderData.fluid)
                    crafter.sendProgressBarUpdate(container, tankIndex * NETWORK_DATA + 0,
                            FluidHelper.getFluidId(fluidStack));
                if (fluidStack.amount != tank.renderData.amount)
                    PacketBuilder.instance().sendGuiIntegerPacket(player, container.windowId,
                            tankIndex * NETWORK_DATA + 1, fluidStack.amount);
                if (color != pColor)
                    PacketBuilder.instance().sendGuiIntegerPacket(player, container.windowId,
                            tankIndex * NETWORK_DATA + 2, color);
            }
        }

        tank.renderData.fluid = tank.getFluidType();
        tank.renderData.amount = tank.getFluidAmount();
        tank.renderData.color = color;
    }

    public void processGuiUpdate(int messageId, int data) {
        int tankIndex = messageId / NETWORK_DATA;

        if (tankIndex >= tanks.size())
            return;
        StandardTank tank = tanks.get(tankIndex);
        switch (messageId % NETWORK_DATA) {
        case 0:
            tank.renderData.fluid = FluidRegistry.getFluid(data);
            break;
        case 1:
            tank.renderData.amount = data;
            break;
        case 2:
            tank.renderData.color = data;
            break;
        }
    }

    @Override
    public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
        return fill(0, resource, doFill);
    }

    public int fill(int tankIndex, FluidStack resource, boolean doFill) {
        if (tankIndex < 0 || tankIndex >= tanks.size() || resource == null)
            return 0;

        return tanks.get(tankIndex).fill(resource, doFill);
    }

    @Override
    public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
        return drain(0, maxDrain, doDrain);
    }

    public FluidStack drain(int tankIndex, int maxDrain, boolean doDrain) {
        if (tankIndex < 0 || tankIndex >= tanks.size())
            return null;

        return tanks.get(tankIndex).drain(maxDrain, doDrain);
    }

    @Override
    public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
        for (StandardTank tank : tanks) {
            if (tankCanDrainFluid(tank, resource))
                return tank.drain(resource.amount, doDrain);
        }
        return null;
    }

    @Override
    public boolean canFill(ForgeDirection from, Fluid fluid) {
        return true;
    }

    @Override
    public boolean canDrain(ForgeDirection from, Fluid fluid) {
        return true;
    }

    @Override
    public FluidTankInfo[] getTankInfo(ForgeDirection direction) {
        List<FluidTankInfo> info = new ArrayList<FluidTankInfo>(size());
        for (StandardTank tank : this) {
            if (!tank.isHidden())
                info.add(tank.getInfo());
        }
        return info.toArray(new FluidTankInfo[info.size()]);
    }

    public FluidTankInfo[] getTankInfo() {
        return getTankInfo(ForgeDirection.UNKNOWN);
    }

    @Override
    public StandardTank get(int tankIndex) {
        if (tankIndex < 0 || tankIndex >= tanks.size())
            return null;
        return tanks.get(tankIndex);
    }

    public void setCapacity(int tankIndex, int capacity) {
        StandardTank tank = get(tankIndex);
        tank.setCapacity(capacity);
        FluidStack fluidStack = tank.getFluid();
        if (fluidStack != null && fluidStack.amount > capacity)
            fluidStack.amount = capacity;
    }

    public void outputLiquid(AdjacentTileCache cache, ITileFilter filter, ForgeDirection[] sides, int tankIndex,
            int amount) {
        for (ForgeDirection side : sides) {
            TileEntity tile = cache.getTileOnSide(side);
            if (!filter.matches(tile))
                continue;
            IFluidHandler tank = getTankFromTile(tile);
            if (tank == null)
                continue;
            outputLiquid((IFluidHandler) tile, side, tankIndex, amount);
        }
    }

    public void outputLiquid(IFluidHandler[] outputs, int tankIndex, int amount) {
        for (int side = 0; side < 6; side++) {
            IFluidHandler nearbyTank = outputs[side];
            if (nearbyTank != null)
                outputLiquid(nearbyTank, ForgeDirection.getOrientation(side), tankIndex, amount);
        }
    }

    private void outputLiquid(IFluidHandler tank, ForgeDirection side, int tankIndex, int amount) {
        FluidStack available = drain(tankIndex, amount, false);
        if (available != null) {
            int used = tank.fill(side.getOpposite(), available, true);
            if (used > 0)
                drain(tankIndex, used, true);
        }
    }

    private boolean tankAcceptsFluid(StandardTank tank, FluidStack fluidStack) {
        if (fluidStack == null)
            return false;
        return tank.fill(fluidStack, false) > 0;
    }

    private boolean tankCanDrain(StandardTank tank) {
        FluidStack drained = tank.drain(1, false);
        return drained != null && drained.amount > 0;
    }

    private boolean tankCanDrainFluid(StandardTank tank, FluidStack fluidStack) {
        if (fluidStack == null)
            return false;
        if (!Fluids.areEqual(tank.getFluidType(), fluidStack))
            return false;
        return tankCanDrain(tank);
    }
}