package cofh.lib.util.helpers; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTSizeTracker; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.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.FluidTankInfo; import net.minecraftforge.fluids.IFluidBlock; import net.minecraftforge.fluids.IFluidContainerItem; import net.minecraftforge.fluids.IFluidHandler; /** * Contains various helper functions to assist with {@link Fluid} and Fluid-related manipulation and interaction. * * @author King Lemming * */ public class FluidHelper { public static final int BUCKET_VOLUME = FluidContainerRegistry.BUCKET_VOLUME; public static final Fluid WATER_FLUID = FluidRegistry.WATER; public static final Fluid LAVA_FLUID = FluidRegistry.LAVA; public static final FluidStack WATER = new FluidStack(WATER_FLUID, BUCKET_VOLUME); public static final FluidStack LAVA = new FluidStack(LAVA_FLUID, BUCKET_VOLUME); public static final FluidTankInfo[] NULL_TANK_INFO = new FluidTankInfo[]{}; private FluidHelper() { } /* IFluidContainer Interaction */ public static FluidStack extractFluidFromHeldContainer(EntityPlayer player, int maxDrain, boolean doDrain) { ItemStack container = player.getCurrentEquippedItem(); return isFluidContainerItem(container) ? ((IFluidContainerItem) container.getItem()).drain(container, maxDrain, doDrain) : null; } public static int insertFluidIntoHeldContainer(EntityPlayer player, FluidStack resource, boolean doFill) { ItemStack container = player.getCurrentEquippedItem(); return isFluidContainerItem(container) ? ((IFluidContainerItem) container.getItem()).fill(container, resource, doFill) : 0; } public static boolean isPlayerHoldingFluidContainerItem(EntityPlayer player) { return isFluidContainerItem(player.getCurrentEquippedItem()); } public static boolean isFluidContainerItem(ItemStack container) { return container != null && container.getItem() instanceof IFluidContainerItem; } public static FluidStack getFluidStackFromContainerItem(ItemStack container) { return ((IFluidContainerItem) container.getItem()).getFluid(container); } public static ItemStack setDefaultFluidTag(ItemStack container, FluidStack resource) { container.setTagCompound(new NBTTagCompound()); NBTTagCompound fluidTag = resource.writeToNBT(new NBTTagCompound()); container.stackTagCompound.setTag("Fluid", fluidTag); return container; } /* IFluidHandler Interaction */ public static FluidStack extractFluidFromAdjacentFluidHandler(TileEntity tile, int side, int maxDrain, boolean doDrain) { TileEntity handler = BlockHelper.getAdjacentTileEntity(tile, side); return handler instanceof IFluidHandler ? ((IFluidHandler) handler).drain(ForgeDirection.VALID_DIRECTIONS[side ^ 1], maxDrain, doDrain) : null; } public static int insertFluidIntoAdjacentFluidHandler(TileEntity tile, int side, FluidStack fluid, boolean doFill) { TileEntity handler = BlockHelper.getAdjacentTileEntity(tile, side); return handler instanceof IFluidHandler ? ((IFluidHandler) handler).fill(ForgeDirection.VALID_DIRECTIONS[side ^ 1], fluid, doFill) : 0; } // TODO: Replace with sided version post-1.8 Fluid revamp public static boolean isAdjacentFluidHandler(TileEntity tile, int side) { return BlockHelper.getAdjacentTileEntity(tile, side) instanceof IFluidHandler; } // TODO: Replace with sided version post-1.8 Fluid revamp public static boolean isFluidHandler(TileEntity tile) { return tile instanceof IFluidHandler; } /* Fluid Container Registry Interaction */ public static boolean fillContainerFromHandler(World world, IFluidHandler handler, EntityPlayer player, FluidStack tankFluid) { ItemStack container = player.getCurrentEquippedItem(); if (FluidContainerRegistry.isEmptyContainer(container)) { ItemStack returnStack = FluidContainerRegistry.fillFluidContainer(tankFluid, container); FluidStack fluid = FluidContainerRegistry.getFluidForFilledItem(returnStack); if (fluid == null || returnStack == null) { return false; } if (!player.capabilities.isCreativeMode) { if (container.stackSize == 1) { container = container.copy(); player.inventory.setInventorySlotContents(player.inventory.currentItem, returnStack); } else if (!player.inventory.addItemStackToInventory(returnStack)) { return false; } handler.drain(ForgeDirection.UNKNOWN, fluid.amount, true); container.stackSize--; if (container.stackSize <= 0) { container = null; } } else { handler.drain(ForgeDirection.UNKNOWN, fluid.amount, true); } return true; } return false; } public static boolean fillHandlerWithContainer(World world, IFluidHandler handler, EntityPlayer player) { ItemStack container = player.getCurrentEquippedItem(); FluidStack fluid = FluidContainerRegistry.getFluidForFilledItem(container); if (fluid != null) { if (handler.fill(ForgeDirection.UNKNOWN, fluid, false) == fluid.amount || player.capabilities.isCreativeMode) { if (ServerHelper.isClientWorld(world)) { return true; } handler.fill(ForgeDirection.UNKNOWN, fluid, true); if (!player.capabilities.isCreativeMode) { player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemHelper.consumeItem(container)); } return true; } } return false; } /* PACKETS */ public static void writeFluidStackToPacket(FluidStack fluid, DataOutput data) throws IOException { if (!isValidFluidStack(fluid)) { data.writeShort(-1); } else { byte[] abyte = CompressedStreamTools.compress(fluid.writeToNBT(new NBTTagCompound())); data.writeShort((short) abyte.length); data.write(abyte); } } public static FluidStack readFluidStackFromPacket(DataInput data) throws IOException { short length = data.readShort(); if (length < 0) { return null; } else { byte[] abyte = new byte[length]; data.readFully(abyte); return FluidStack.loadFluidStackFromNBT(CompressedStreamTools.func_152457_a(abyte, new NBTSizeTracker(2097152L))); } } /* HELPERS */ public static boolean isValidFluidStack(FluidStack fluid) { return fluid == null ? false : fluid.fluidID == 0 ? false : FluidRegistry.getFluidName(fluid) != null; } public static int getFluidLuminosity(FluidStack fluid) { return fluid == null ? 0 : getFluidLuminosity(fluid.getFluid()); } public static int getFluidLuminosity(Fluid fluid) { return fluid == null ? 0 : fluid.getLuminosity(); } public static FluidStack getFluidFromWorld(World world, int x, int y, int z) { Block bId = world.getBlock(x, y, z); int bMeta = world.getBlockMetadata(x, y, z); if (Block.isEqualTo(bId, Blocks.water)) { if (bMeta == 0) { return WATER.copy(); } else { return null; } } else if (Block.isEqualTo(bId, Blocks.lava)) { if (bMeta == 0) { return LAVA.copy(); } else { return null; } } else if (bId instanceof IFluidBlock) { IFluidBlock block = (IFluidBlock) bId; return block.drain(world, x, y, z, true); } return null; } public static Fluid lookupFluidForBlock(Block block) { if (block == Blocks.flowing_water) { return WATER_FLUID; } if (block == Blocks.flowing_lava) { return LAVA_FLUID; } return FluidRegistry.lookupFluidForBlock(block); } public static FluidStack getFluidForFilledItem(ItemStack container) { if (container != null && container.getItem() instanceof IFluidContainerItem) { return ((IFluidContainerItem) container.getItem()).getFluid(container); } return FluidContainerRegistry.getFluidForFilledItem(container); } public static boolean isFluidEqualOrNull(FluidStack resourceA, FluidStack resourceB) { return resourceA == null || resourceB == null || resourceA.isFluidEqual(resourceB); } public static boolean isFluidEqualOrNull(Fluid fluidA, FluidStack resourceB) { return fluidA == null || resourceB == null || fluidA == resourceB.getFluid(); } public static boolean isFluidEqualOrNull(Fluid fluidA, Fluid fluidB) { return fluidA == null || fluidB == null || fluidA == fluidB; } public static boolean isFluidEqual(FluidStack resourceA, FluidStack resourceB) { return resourceA != null && resourceA.isFluidEqual(resourceB); } public static boolean isFluidEqual(Fluid fluidA, FluidStack resourceB) { return fluidA != null && resourceB != null && fluidA == resourceB.getFluid(); } public static boolean isFluidEqual(Fluid fluidA, Fluid fluidB) { return fluidA != null && fluidB != null && fluidA.equals(fluidB); } }