package eiteam.esteemedinnovation.converter; import eiteam.esteemedinnovation.api.steamnet.SteamNetwork; import eiteam.esteemedinnovation.api.tile.SteamTransporterTileEntity; import eiteam.esteemedinnovation.api.wrench.Wrenchable; import eiteam.esteemedinnovation.api.util.FluidHelper; import eiteam.esteemedinnovation.commons.CrossMod; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import javax.annotation.Nullable; public class TileEntityFluidSteamConverter extends SteamTransporterTileEntity implements Wrenchable { public int runTicks = 0; private boolean lastRunning = false; public boolean pushing = false; // Indicates that converter is pushing steam actively. private static final int PUSH_MAX = 250; // in mb a tick @Nullable private FluidTank tank; private final Fluid fluid; public TileEntityFluidSteamConverter() { Fluid steam = FluidRegistry.getFluid("steam"); if (steam == null && CrossMod.IC2) { steam = FluidRegistry.getFluid("ic2steam"); } if (steam != null) { tank = new FluidTank(steam, 0, getCapacity()); } fluid = steam; } @Override public SPacketUpdateTileEntity getUpdatePacket() { NBTTagCompound access = getUpdateTag(); access.setShort("RunTicks", (short) runTicks); access.setBoolean("IsPushing", pushing); return new SPacketUpdateTileEntity(pos, 1, access); } @Override public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { super.onDataPacket(net, pkt); NBTTagCompound access = pkt.getNbtCompound(); if (runTicks == 0 && access.getShort("RunTicks") != 0) { runTicks = access.getShort("RunTicks"); } pushing = access.getBoolean("IsPushing"); markForResync(); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setBoolean("IsPushing", pushing); if (tank != null) { tank.writeToNBT(nbt); } return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); if (tank != null) { tank.readFromNBT(nbt); } pushing = nbt.getBoolean("IsPushing"); } @Override public boolean canUpdate(IBlockState target) { return target.getBlock() == ConverterModule.PRESSURE_CONVERTER; } @Override public void safeUpdate() { if (runTicks > 0) { runTicks--; } if (runTicks > 0 != lastRunning) { markForResync(); } lastRunning = runTicks > 0; EnumFacing dir = worldObj.getBlockState(pos).getValue(BlockFluidSteamConverter.FACING); setDistributionDirections(new EnumFacing[] { dir.getOpposite() }); if (fluid != null && tank != null && pushing) { TileEntity tileEntity = worldObj.getTileEntity(getOffsetPos(dir)); if (tileEntity != null) { SteamNetwork steamNetwork = getNetwork(); IFluidHandler handler = FluidHelper.getFluidHandler(tileEntity, dir); if (handler != null && steamNetwork != null) { //To make for some interesting feedback systems, active push amount is based on current network pressure //This could be considered for non pushing systems, but there's no guarantee of consistency of the pull rate //from different mods, so something complicated would have to be done to audit that behaviour. //todo: external config for converter behaviour? //todo: apply limiting mechanism to non-pushing state? int maxDrain = (int) (PUSH_MAX * steamNetwork.getPressure()); if (maxDrain > 0) { tank.fill(new FluidStack(fluid, maxDrain), true); FluidStack avail = tank.drain(maxDrain, false); int taken = handler.fill(avail, true); steamNetwork.decrSteam(taken); if (taken > 0 && runTicks <= 0) { runTicks = 100; markForResync(); } } } } } super.safeUpdate(); } @Override public boolean onWrench(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, IBlockState state, float hitX, float hitY, float hitZ) { if (player.isSneaking()) { pushing = !pushing; } else { int steam = getSteamShare(); getNetwork().split(this, true); setDistributionDirections(new EnumFacing[] { state.getValue(BlockFluidSteamConverter.FACING).getOpposite() }); SteamNetwork.newOrJoin(this); getNetwork().addSteam(steam); } markForResync(); return false; } @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { EnumFacing dir = worldObj.getBlockState(pos).getValue(BlockFluidSteamConverter.FACING); return (tank != null && dir == facing && capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) || super.hasCapability(capability, facing); } @SuppressWarnings("unchecked") @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { EnumFacing dir = worldObj.getBlockState(pos).getValue(BlockFluidSteamConverter.FACING); if (tank != null && dir == facing && capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { return (T) tank; } return super.getCapability(capability, facing); } }