package micdoodle8.mods.galacticraft.core.tile; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import micdoodle8.mods.galacticraft.core.Constants; import micdoodle8.mods.galacticraft.core.GalacticraftCore; import micdoodle8.mods.galacticraft.core.network.PacketDynamic; import micdoodle8.mods.galacticraft.core.tick.TickHandlerServer; import micdoodle8.mods.galacticraft.core.util.DelayTimer; import micdoodle8.mods.galacticraft.core.util.GCCoreUtil; import micdoodle8.mods.galacticraft.core.wrappers.ScheduledBlockChange; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.*; import net.minecraftforge.fml.client.FMLClientHandler; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.List; public class TileEntityFluidTank extends TileEntityAdvanced implements IFluidHandler { public FluidTankGC fluidTank = new FluidTankGC(16000, this); public boolean updateClient = false; private DelayTimer delayTimer = new DelayTimer(1); private AxisAlignedBB renderAABB; public void onBreak() { if (fluidTank.getFluidAmount() > 0) { FluidEvent.fireEvent(new FluidEvent.FluidSpilledEvent(fluidTank.getFluid(), worldObj, pos)); if (!this.worldObj.isRemote && fluidTank.getFluidAmount() > 1000) { Block b = fluidTank.getFluid().getFluid().getBlock(); TickHandlerServer.scheduleNewBlockChange(GCCoreUtil.getDimensionID(this.worldObj), new ScheduledBlockChange(pos, b, 0, 3)); } } } @Override public void update() { super.update(); if (fluidTank.getFluid() != null) { moveFluidDown(); } if (!this.worldObj.isRemote && updateClient && delayTimer.markTimeIfDelay(this.worldObj)) { PacketDynamic packet = new PacketDynamic(this); GalacticraftCore.packetPipeline.sendToAllAround(packet, new NetworkRegistry.TargetPoint(GCCoreUtil.getDimensionID(this.worldObj), getPos().getX(), getPos().getY(), getPos().getZ(), this.getPacketRange())); this.updateClient = false; } } @Override public int fill(EnumFacing from, FluidStack resource, boolean doFill) { if (resource == null) { return 0; } FluidStack copy = resource.copy(); int totalUsed = 0; TileEntityFluidTank toFill = getLastTank(); FluidStack fluid = toFill.fluidTank.getFluid(); if (fluid != null && fluid.amount > 0 && !fluid.isFluidEqual(copy)) { return 0; } while (toFill != null && copy.amount > 0) { int used = toFill.fluidTank.fill(copy, doFill); if (used > 0) { toFill.updateClient = true; } copy.amount -= used; totalUsed += used; toFill = getNextTank(toFill.getPos()); } return totalUsed; } @Override public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain) { if (resource == null) { return null; } TileEntityFluidTank last = getLastTank(); if (!resource.isFluidEqual(last.fluidTank.getFluid())) { return null; } return drain(from, resource.amount, doDrain); } @Override public FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain) { TileEntityFluidTank last = getLastTank(); FluidStack stack = last.fluidTank.drain(maxDrain, doDrain); if (doDrain && stack != null && stack.amount > 0) { last.updateClient = true; } return stack; } @Override public boolean canFill(EnumFacing from, Fluid fluid) { return fluidTank.getFluid() == null || fluidTank.getFluid().getFluid() == null || fluid == null || fluidTank.getFluid().getFluid() == fluid; } @Override public boolean canDrain(EnumFacing from, Fluid fluid) { return fluid == null || fluidTank.getFluid() != null && fluidTank.getFluid().getFluid() == fluid; } @Override public FluidTankInfo[] getTankInfo(EnumFacing from) { FluidTank compositeTank = new FluidTank(fluidTank.getCapacity()); TileEntityFluidTank last = getLastTank(); if (last != null && last.fluidTank.getFluid() != null) { compositeTank.setFluid(last.fluidTank.getFluid().copy()); } else { return new FluidTankInfo[] { compositeTank.getInfo() }; } int capacity = last.fluidTank.getCapacity(); last = getNextTank(last.getPos()); while (last != null) { FluidStack fluid = last.fluidTank.getFluid(); if (fluid == null || fluid.amount == 0) { } else if (!compositeTank.getFluid().isFluidEqual(fluid)) { break; } else { compositeTank.getFluid().amount += fluid.amount; } capacity += last.fluidTank.getCapacity(); last = getNextTank(last.getPos()); } compositeTank.setCapacity(capacity); return new FluidTankInfo[] { compositeTank.getInfo() }; } public void moveFluidDown() { TileEntityFluidTank next = getPreviousTank(this.getPos()); if (next != null) { int used = next.fluidTank.fill(fluidTank.getFluid(), true); if (used > 0) { this.updateClient = true; next.updateClient = true; fluidTank.drain(used, true); } } } public TileEntityFluidTank getLastTank() { TileEntityFluidTank lastTank = this; while (true) { TileEntityFluidTank tank = getPreviousTank(lastTank.getPos()); if (tank != null) { lastTank = tank; } else { break; } } return lastTank; } public TileEntityFluidTank getNextTank(BlockPos current) { TileEntity above = worldObj.getTileEntity(current.up()); if (above instanceof TileEntityFluidTank) { return (TileEntityFluidTank) above; } return null; } public TileEntityFluidTank getPreviousTank(BlockPos current) { TileEntity below = this.worldObj.getTileEntity(current.down()); if (below instanceof TileEntityFluidTank) { return (TileEntityFluidTank) below; } return null; } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); if (compound.hasKey("fuelTank")) { this.fluidTank.readFromNBT(compound.getCompoundTag("fuelTank")); } this.updateClient = true; } @Override public void writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); if (this.fluidTank.getFluid() != null) { compound.setTag("fuelTank", this.fluidTank.writeToNBT(new NBTTagCompound())); } } @Override public Packet getDescriptionPacket() { NBTTagCompound nbt = new NBTTagCompound(); nbt.setString("net-type", "desc-packet"); PacketDynamic packet = new PacketDynamic(this); ByteBuf buf = Unpooled.buffer(); packet.encodeInto(buf); byte[] bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); nbt.setByteArray("net-data", bytes); S35PacketUpdateTileEntity tileUpdate = new S35PacketUpdateTileEntity(getPos(), 0, nbt); return tileUpdate; } @Override @SideOnly(Side.CLIENT) public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { if (!worldObj.isRemote) { return; } if (pkt.getNbtCompound() == null) { throw new RuntimeException("[GC] Missing NBTTag compound!"); } NBTTagCompound nbt = pkt.getNbtCompound(); try { if ("desc-packet".equals(nbt.getString("net-type"))) { byte[] bytes = nbt.getByteArray("net-data"); ByteBuf data = Unpooled.wrappedBuffer(bytes); PacketDynamic packet = new PacketDynamic(); packet.decodeInto(data); packet.handleClientSide(FMLClientHandler.instance().getClientPlayerEntity()); } } catch (Throwable t) { throw new RuntimeException("[GC] Failed to read a packet! (" + nbt.getTag("net-type") + ", " + nbt.getTag("net-data"), t); } } @Override public void addExtraNetworkedData(List<Object> networkedList) { if (!this.worldObj.isRemote) { if (fluidTank == null) { networkedList.add(0); networkedList.add(""); networkedList.add(0); } else { networkedList.add(fluidTank.getCapacity()); networkedList.add(fluidTank.getFluid() == null ? "" : fluidTank.getFluid().getFluid().getName()); networkedList.add(fluidTank.getFluidAmount()); } } } @Override public void readExtraNetworkedData(ByteBuf buffer) { if (this.worldObj.isRemote) { int capacity = buffer.readInt(); String fluidName = ByteBufUtils.readUTF8String(buffer); FluidTankGC fluidTank = new FluidTankGC(capacity, this); int amount = buffer.readInt(); if (fluidName.equals("")) { fluidTank.setFluid(null); } else { Fluid fluid = FluidRegistry.getFluid(fluidName); fluidTank.setFluid(new FluidStack(fluid, amount)); } this.fluidTank = fluidTank; } } @Override public double getPacketRange() { return 40; } @Override public int getPacketCooldown() { return 1; } @Override public boolean isNetworkedTile() { return false; } @Override @SideOnly(Side.CLIENT) public AxisAlignedBB getRenderBoundingBox() { if (this.renderAABB == null) { this.renderAABB = new AxisAlignedBB(pos, pos.add(1, 1, 1)); } return this.renderAABB; } @Override @SideOnly(Side.CLIENT) public double getMaxRenderDistanceSquared() { return Constants.RENDERDISTANCE_MEDIUM; } }