package mcjty.deepresonance.grid.tank; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import elec332.core.multiblock.dynamic.AbstractDynamicMultiBlock; import elec332.core.util.NBTHelper; import elec332.core.world.WorldHelper; import mcjty.deepresonance.blocks.tank.TileTank; import mcjty.deepresonance.fluid.DRFluidRegistry; import mcjty.deepresonance.grid.InternalGridTank; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraftforge.fluids.*; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; /** * Created by Elec332 on 10-8-2015. */ @SuppressWarnings("unused") public class DRTankMultiBlock extends AbstractDynamicMultiBlock<DRTankWorldHolder, DRTankMultiBlock> implements IFluidHandler, IFluidTank{ public static final int TANK_BUCKETS = 16; public DRTankMultiBlock(TileEntity tile, DRTankWorldHolder worldHolder) { super(tile, worldHolder); this.tank = new InternalGridTank(TANK_BUCKETS * FluidContainerRegistry.BUCKET_VOLUME); this.renderData = Maps.newHashMap(); if (tile instanceof TileTank && ((TileTank)tile).getSaveData() != null){ tank.fill(FluidStack.loadFluidStackFromNBT(((TileTank)tile).getSaveData().getCompoundTag("fluid")), true); } needsSorting = true; setClientRenderFluid(); markAllBlocksForUpdate(); } private boolean needsSorting; private InternalGridTank tank; private Map<Integer, List<BlockPos>> renderData; private Fluid check; @Override public void tick() { if (world.getTotalWorldTime() % 20L == 0L){ setTankFluidHeights(); setClientRenderFluid(); if (check != tank.getStoredFluid()){ markAllBlocksForUpdate(); check = tank.getStoredFluid(); } } } @Override protected void invalidate() { super.invalidate(); for (BlockPos loc : Lists.newArrayList(allLocations)){ TileTank tank = getTank(loc); if (tank != null) { setDataToTile(tank); } } } @Override protected void mergeWith(DRTankMultiBlock multiBlock) { super.mergeWith(multiBlock); tank.merge(multiBlock.tank); setClientRenderFluid(); needsSorting = true; setTankFluidHeights(); markEverythingDirty(); markAllBlocksForUpdate(); } public void setDataToTile(TileTank tile){ NBTTagCompound tagCompound = new NBTTagCompound(); FluidStack myTank = getFluidShare(tile); Fluid lastSeenFluid = getStoredFluid(); if (myTank != null) { NBTTagCompound fluidTag = new NBTTagCompound(); myTank.writeToNBT(fluidTag); tagCompound.setTag("fluid", fluidTag); } if (lastSeenFluid != null) { tagCompound.setString("lastSeenFluid", FluidRegistry.getFluidName(lastSeenFluid)); } tile.setSaveData(tagCompound); if (WorldHelper.chunkLoaded(world, tile.getPos())) { tile.markDirty(); } } public int getComparatorInputOverride(){ float f = (float)tank.getStoredAmount()/getCapacity(); return (int)(f * 15); } public void markEverythingDirty(){ for (BlockPos loc : allLocations){ TileTank tank = getTank(loc); if (tank != null) { tank.markDirty(); } } } public void markAllBlocksForUpdate(){ allLocations.forEach(p -> { IBlockState state = world.getBlockState(p); world.notifyBlockUpdate(p, state, state, 3); }); } private void setTankFluidHeights(){ if (needsSorting){ renderData.clear(); Collections.sort(allLocations, new Comparator<BlockPos>() { @Override public int compare(BlockPos o1, BlockPos o2) { return o1.getY() - o2.getY(); } }); for (BlockPos loc : allLocations){ List<BlockPos> list = renderData.get(loc.getY()); if (list == null){ renderData.put(loc.getY(), list = Lists.newArrayList()); } list.add(loc); } needsSorting = false; } int total = tank.getStoredAmount(); List<Integer> list8776 = Lists.newArrayList(renderData.keySet()); Collections.sort(list8776); for (Integer j : list8776){ List<BlockPos> list = renderData.get(j); float filled = 0.0f; if (total > 0) { int i = list.size(); int toAdd = Math.min(total, i * TANK_BUCKETS * FluidContainerRegistry.BUCKET_VOLUME); total -= toAdd; filled = (float) toAdd / (i * TANK_BUCKETS * FluidContainerRegistry.BUCKET_VOLUME); } for (BlockPos loc : list) { TileTank tank = getTank(loc); if (tank != null) { tank.sendPacket(3, new NBTHelper().addToTag(filled, "render").serializeNBT()); } } } } public FluidStack getFluidShare(TileTank tile){ return tank.getShare(allLocations.size(), allLocations.indexOf(tile.getPos()) == 0); } public Fluid getStoredFluid(){ return tank.getStoredFluid(); } @Override public FluidStack getFluid() { return tank.getStoredFluidStack(); } @Override public int getFluidAmount() { return tank.getStoredAmount(); } @Override public int getCapacity() { return tank.getMaxAmount(); } @Override public FluidTankInfo getInfo() { return new FluidTankInfo(getFluid(), getCapacity()); } @Override public int fill(FluidStack resource, boolean doFill) { int ret = tank.fill(resource, doFill); if (doFill) { setClientRenderFluid(); setTankFluidHeights(); } return ret; } @Override public FluidStack drain(int maxDrain, boolean doDrain) { FluidStack ret = tank.drain(maxDrain, doDrain); if (doDrain) setTankFluidHeights(); return ret; } public String getTankInfo(){ return tank.getInfo(); } public int getFreeSpace(){ return getCapacity() - getFluidAmount(); } private TileTank getTank(BlockPos loc){ TileEntity tile = WorldHelper.chunkLoaded(world, loc) ? WorldHelper.getTileAt(world, loc) : null; return tile instanceof TileTank ? (TileTank) tile : null; } @Override public int fill(EnumFacing from, FluidStack resource, boolean doFill) { int ret = fill(resource, doFill); if (doFill) { setClientRenderFluid(); setTankFluidHeights(); markEverythingDirty(); } return ret; } @Override public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain) { if (resource == null || !resource.isFluidEqual(tank.getStoredFluidStack())) { return null; } FluidStack ret = drain(resource.amount, doDrain); if (doDrain) { setTankFluidHeights(); markEverythingDirty(); } return ret; } @Override public FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain) { FluidStack ret = drain(maxDrain, doDrain); if (doDrain) { setTankFluidHeights(); markEverythingDirty(); } return ret; } @Override public boolean canFill(EnumFacing from, Fluid fluid) { return true; } @Override public boolean canDrain(EnumFacing from, Fluid fluid) { return false; } @Override public FluidTankInfo[] getTankInfo(EnumFacing from) { return new FluidTankInfo[] { getInfo() }; } private void setClientRenderFluid() { markEverythingDirty(); for (BlockPos loc : allLocations) { TileTank tank = getTank(loc); if (tank != null) { tank.lastSeenFluid = getStoredFluid(); tank.sendPacket(1, new NBTHelper().addToTag(DRFluidRegistry.getFluidName(getStoredFluid()), "fluid").serializeNBT()); } } } }