package resonantinduction.mechanical.fluid.prefab; import java.io.IOException; import java.util.ArrayList; import java.util.List; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.packet.Packet; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidContainerRegistry; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.FluidTankInfo; import org.bouncycastle.util.Arrays; import resonantinduction.core.network.ISimplePacketReceiver; import resonantinduction.core.tilenetwork.INetworkPart; import resonantinduction.core.tilenetwork.ITileNetwork; import resonantinduction.mechanical.fluid.network.NetworkFluidTiles; import resonantinduction.mechanical.fluid.pipes.FluidPartsMaterial; import resonantinduction.old.api.fluid.FluidMasterList; import resonantinduction.old.api.fluid.INetworkFluidPart; import resonantinduction.old.transport.ResonantInductionTransport; import universalelectricity.api.vector.Vector3; import calclavia.lib.network.PacketHandler; import com.google.common.io.ByteArrayDataInput; import cpw.mods.fml.common.network.Player; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; public abstract class TileEntityFluidNetworkTile extends TileEntityFluidDevice implements INetworkFluidPart, ISimplePacketReceiver { private int updateTick = 1; public static int refreshRate = 10; protected FluidTank tank; protected FluidTankInfo[] internalTanksInfo = new FluidTankInfo[1]; protected List connectedBlocks = new ArrayList(); public boolean[] renderConnection = new boolean[6]; protected int heat = 0, maxHeat = 20000; protected int damage = 0, maxDamage = 1000; protected int subID = 0; protected int tankCap; protected FluidStack prevStack = null; protected NetworkFluidTiles network; public TileEntityFluidNetworkTile() { this(1); } public TileEntityFluidNetworkTile(int tankCap) { if (tankCap <= 0) { tankCap = 1; } this.tankCap = tankCap; this.tank = new FluidTank(this.tankCap * FluidContainerRegistry.BUCKET_VOLUME); this.internalTanksInfo[0] = this.tank.getInfo(); } public FluidTank getTank() { if (tank == null) { this.tank = new FluidTank(this.tankCap * FluidContainerRegistry.BUCKET_VOLUME); this.internalTanksInfo[0] = this.tank.getInfo(); } return tank; } @Override public void updateEntity() { super.updateEntity(); if (!worldObj.isRemote) { if (ticks % this.updateTick == 0) { this.updateTick = this.worldObj.rand.nextInt(5) * 40 + 20; this.refresh(); } if (ticks % TileEntityFluidNetworkTile.refreshRate == 0) { if (this.getTank().getFluid() == null && this.prevStack == null) { // Do nothing } else if ((this.getTank().getFluid() == null && this.prevStack != null) || (this.getTank().getFluid() != null && this.prevStack == null) || (this.getTank().getFluid().amount != this.prevStack.amount)) { this.sendTankUpdate(0); } this.prevStack = this.tank.getFluid(); } } } @Override public void invalidate() { this.getTileNetwork().splitNetwork(this); super.invalidate(); } @Override public int fill(ForgeDirection from, FluidStack resource, boolean doFill) { if (this.getTileNetwork() != null && resource != null) { return this.getTileNetwork().fillNetworkTank(this, resource, doFill); } return 0; } @Override public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) { if (this.getTileNetwork() != null && resource != null) { if (this.getTileNetwork().getNetworkTank() != null && this.getTileNetwork().getNetworkTank().getFluid() != null && this.getTileNetwork().getNetworkTank().getFluid().isFluidEqual(resource)) { return this.getTileNetwork().drainNetworkTank(this.worldObj, resource.amount, doDrain); } } return null; } @Override public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) { if (this.getTileNetwork() != null) { return this.getTileNetwork().drainNetworkTank(this.worldObj, maxDrain, 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 from) { return new FluidTankInfo[] { this.getTileNetwork().getNetworkTankInfo() }; } @Override public List getNetworkConnections() { return this.connectedBlocks; } @Override public void refresh() { if (this.worldObj != null && !this.worldObj.isRemote) { boolean[] previousConnections = this.renderConnection.clone(); this.connectedBlocks.clear(); this.renderConnection = new boolean[6]; for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { this.validateConnectionSide(new Vector3(this).modifyPositionFromSide(dir).getTileEntity(this.worldObj), dir); } /** Only send packet updates if visuallyConnected changed. */ if (!Arrays.areEqual(previousConnections, this.renderConnection)) { this.sendRenderUpdate(); } } } /** * Checks to make sure the connection is valid to the tileEntity * * @param tileEntity - the tileEntity being checked * @param side - side the connection is too */ public void validateConnectionSide(TileEntity tileEntity, ForgeDirection side) { if (!this.worldObj.isRemote) { if (tileEntity instanceof INetworkFluidPart) { if (this.canTileConnect(Connection.NETWORK, side.getOpposite())) { this.getTileNetwork().mergeNetwork(((INetworkFluidPart) tileEntity).getTileNetwork(), (INetworkPart) tileEntity); this.renderConnection[side.ordinal()] = true; connectedBlocks.add(tileEntity); } } } } @Override public NetworkFluidTiles getTileNetwork() { if (!(this.network instanceof NetworkFluidTiles)) { this.network = new NetworkFluidTiles(this); } return this.network; } @Override public void setTileNetwork(ITileNetwork fluidNetwork) { if (fluidNetwork instanceof NetworkFluidTiles) { this.network = (NetworkFluidTiles) fluidNetwork; } } @Override public FluidTankInfo[] getTankInfo() { if (this.internalTanksInfo == null) { this.internalTanksInfo = new FluidTankInfo[] { this.getTank().getInfo() }; } return this.internalTanksInfo; } @Override public int fillTankContent(int index, FluidStack stack, boolean doFill) { if (index == 0) { int p = this.getTank().getFluid() != null ? this.getTank().getFluid().amount : 0; int fill = this.getTank().fill(stack, doFill); if (p != fill && doFill) { this.internalTanksInfo[index] = this.getTank().getInfo(); } return fill; } return 0; } @Override public FluidStack drainTankContent(int index, int volume, boolean doDrain) { if (index == 0) { FluidStack prev = this.getTank().getFluid(); FluidStack stack = this.getTank().drain(volume, doDrain); if (prev != null && (stack == null || prev.amount != stack.amount) && doDrain) { this.internalTanksInfo[index] = this.getTank().getInfo(); } return stack; } return null; } @Override public boolean canTileConnect(Connection type, ForgeDirection dir) { if (this.damage >= this.maxDamage) { return false; } return type == Connection.FLUIDS || type == Connection.NETWORK; } @Override public boolean canPassThrew(FluidStack fluid, ForgeDirection from, ForgeDirection to) { return this.connectedBlocks.get(from.ordinal()) != null && this.connectedBlocks.get(to.ordinal()) != null && this.damage < this.maxDamage; } @Override public boolean onPassThrew(FluidStack fluid, ForgeDirection from, ForgeDirection to) { FluidPartsMaterial mat = FluidPartsMaterial.get(this.getBlockMetadata()); if (fluid != null && fluid.getFluid() != null && mat != null) { if (fluid.getFluid().isGaseous(fluid) && !mat.canSupportGas) { // TODO lose 25% of the gas, and render the escaping gas as a particle effect this.getTileNetwork().drainNetworkTank(this.worldObj, (int) (fluid.amount * .05), true); } else if (FluidMasterList.isMolten(fluid.getFluid()) && !mat.canSupportMoltenFluids) { // TODO start to heat up the pipe to melting point. When it hits melting point turn // the pipe to its molten metal equal // TODO also once it reaches a set heat level start burning up blocks around the // pipe such as wood // this.heat += FluidMasterList.getHeatPerPass(fluid.getFluid()); if (heat >= this.maxHeat) { this.worldObj.setBlock(xCoord, yCoord, zCoord, Block.fire.blockID); return true; } } else if (!fluid.getFluid().isGaseous(fluid) && !mat.canSupportFluids) { this.damage += 1; if (this.damage >= this.maxDamage) { // TODO test this and make sure its right, as well black fluid block in some // cases this.getBlockType().dropBlockAsItem(worldObj, xCoord, yCoord, zCoord, 0, 0); this.worldObj.setBlock(xCoord, yCoord, zCoord, 0); return true; } } } return false; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); this.damage = nbt.getInteger("damage"); this.heat = nbt.getInteger("heat"); this.subID = nbt.getInteger("subID"); if (nbt.hasKey("stored")) { NBTTagCompound tag = nbt.getCompoundTag("stored"); String name = tag.getString("LiquidName"); int amount = nbt.getInteger("Amount"); Fluid fluid = FluidRegistry.getFluid(name); if (fluid != null) { FluidStack liquid = new FluidStack(fluid, amount); this.getTank().setFluid(liquid); internalTanksInfo[0] = this.getTank().getInfo(); } } else { this.getTank().readFromNBT(nbt.getCompoundTag("FluidTank")); internalTanksInfo[0] = this.getTank().getInfo(); } } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setInteger("damage", this.damage); nbt.setInteger("heat", this.heat); nbt.setInteger("subID", this.subID); nbt.setCompoundTag("FluidTank", this.getTank().writeToNBT(new NBTTagCompound())); } @Override public boolean simplePacket(String id, ByteArrayDataInput data, Player player) { try { if (this.worldObj.isRemote) { if (id.equalsIgnoreCase("DescriptionPacket")) { this.subID = data.readInt(); this.renderConnection[0] = data.readBoolean(); this.renderConnection[1] = data.readBoolean(); this.renderConnection[2] = data.readBoolean(); this.renderConnection[3] = data.readBoolean(); this.renderConnection[4] = data.readBoolean(); this.renderConnection[5] = data.readBoolean(); this.tank = new FluidTank(data.readInt()); this.getTank().readFromNBT(PacketHandler.readNBTTagCompound(data)); this.internalTanksInfo[0] = this.getTank().getInfo(); return true; } else if (id.equalsIgnoreCase("RenderPacket")) { this.subID = data.readInt(); this.renderConnection[0] = data.readBoolean(); this.renderConnection[1] = data.readBoolean(); this.renderConnection[2] = data.readBoolean(); this.renderConnection[3] = data.readBoolean(); this.renderConnection[4] = data.readBoolean(); this.renderConnection[5] = data.readBoolean(); return true; } else if (id.equalsIgnoreCase("SingleTank")) { this.tank = new FluidTank(data.readInt()); this.getTank().readFromNBT(PacketHandler.readNBTTagCompound(data)); this.internalTanksInfo[0] = this.getTank().getInfo(); return true; } } } catch (IOException e) { System.out.println("// Fluid Mechanics Tank packet read error"); e.printStackTrace(); return true; } return false; } @Override public Packet getDescriptionPacket() { Object[] data = new Object[9]; data[0] = this.subID; data[1] = this.renderConnection[0]; data[2] = this.renderConnection[1]; data[3] = this.renderConnection[2]; data[4] = this.renderConnection[3]; data[5] = this.renderConnection[4]; data[6] = this.renderConnection[5]; data[7] = this.getTank().getCapacity(); data[8] = this.getTank().writeToNBT(new NBTTagCompound()); return ResonantInductionTransport.getTilePacket().getPacket(this, "DescriptionPacket", data); } public void sendRenderUpdate() { Object[] data = new Object[7]; data[0] = this.subID; data[1] = this.renderConnection[0]; data[2] = this.renderConnection[1]; data[3] = this.renderConnection[2]; data[4] = this.renderConnection[3]; data[5] = this.renderConnection[4]; data[6] = this.renderConnection[5]; PacketHandler.sendPacketToClients(ResonantInductionTransport.getTilePacket().getPacket(this, "RenderPacket", data)); } public void sendTankUpdate(int index) { if (this.getTank() != null && index == 0) { PacketHandler.sendPacketToClients(ResonantInductionTransport.getTilePacket().getPacket(this, "SingleTank", this.getTank().getCapacity(), this.getTank().writeToNBT(new NBTTagCompound())), this.worldObj, new Vector3(this), 60); } } @Override public String getMeterReading(EntityPlayer user, ForgeDirection side, EnumTools tool) { if (tool == EnumTools.PIPE_GUAGE) { String out = "Debug: " + this.getTileNetwork().toString(); out += " "; for (boolean b : this.renderConnection) { out += "|" + (b ? "T" : "F"); } return out + " Vol: " + this.getTileNetwork().getNetworkTank().getFluidAmount(); } return null; } @Override @SideOnly(Side.CLIENT) public AxisAlignedBB getRenderBoundingBox() { return AxisAlignedBB.getAABBPool().getAABB(this.xCoord, this.yCoord, this.zCoord, this.xCoord + 1, this.yCoord + 1, this.zCoord + 1); } public int getSubID() { return this.subID; } public void setSubID(int id) { this.subID = id; } }