/* * Copyright (c) CovertJaguar, 2014 http://railcraft.info * * This code is the property of CovertJaguar * and may only be used with explicit written * permission unless otherwise specified on the * license page at http://railcraft.info/wiki/info:license. */ package mods.railcraft.common.fluids; import mods.railcraft.common.fluids.tanks.StandardTank; import mods.railcraft.common.items.ModItems; import mods.railcraft.common.plugins.forge.WorldPlugin; import mods.railcraft.common.util.inventory.InvTools; import net.minecraft.block.Block; import net.minecraft.block.BlockLiquid; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.*; import net.minecraftforge.fluids.FluidContainerRegistry.FluidContainerData; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * @author CovertJaguar <http://www.railcraft.info> */ public final class FluidHelper { public static final int BUCKET_FILL_TIME = 8; public static final int NETWORK_UPDATE_INTERVAL = 128; public static final int BUCKET_VOLUME = 1000; public static final int PROCESS_VOLUME = BUCKET_VOLUME * 4; private static final List<FluidRegistrar> adapters = new ArrayList<FluidRegistrar>(); static { adapters.add(ForestryFluidRegistrar.INSTANCE); adapters.add(ForgeFluidRegistrar.INSTANCE); } private FluidHelper() { } public static boolean handleRightClick(IFluidHandler tank, ForgeDirection side, EntityPlayer player, boolean fill, boolean drain) { if (player == null) return false; ItemStack current = player.inventory.getCurrentItem(); if (current != null) { FluidItemHelper.DrainReturn drainReturn = FluidItemHelper.drainContainer(current, PROCESS_VOLUME); if (fill && drainReturn.fluidDrained != null) { int used = tank.fill(side, drainReturn.fluidDrained, false); if (used > 0) { drainReturn = FluidItemHelper.drainContainer(current, used); if (!player.capabilities.isCreativeMode) { if (current.stackSize > 1) { if (drainReturn.container != null && !player.inventory.addItemStackToInventory(drainReturn.container)) return false; player.inventory.setInventorySlotContents(player.inventory.currentItem, InvTools.depleteItem(current)); } else { player.inventory.setInventorySlotContents(player.inventory.currentItem, drainReturn.container); } player.inventory.markDirty(); } tank.fill(side, drainReturn.fluidDrained, true); return true; } } else if (drain) { FluidStack available = tank.drain(side, PROCESS_VOLUME, false); if (available != null) { FluidItemHelper.FillReturn fillReturn = FluidItemHelper.fillContainer(current, available); if (fillReturn.amount > 0) { if (current.stackSize > 1) { if (fillReturn.container != null && !player.inventory.addItemStackToInventory(fillReturn.container)) return false; player.inventory.setInventorySlotContents(player.inventory.currentItem, InvTools.depleteItem(current)); } else { player.inventory.setInventorySlotContents(player.inventory.currentItem, fillReturn.container); } player.inventory.markDirty(); tank.drain(side, fillReturn.amount, true); return true; } } } } return false; } public static void processContainers(StandardTank tank, IInventory inv, int inputSlot, int outputSlot) { processContainers(tank, inv, inputSlot, outputSlot, tank.getFluidType(), true, true); } public static void processContainers(StandardTank tank, IInventory inv, int inputSlot, int outputSlot, Fluid fluidToFill, boolean processFilled, boolean processEmpty) { TankManager tankManger = new TankManager(); tankManger.add(tank); processContainers(tankManger, inv, inputSlot, outputSlot, fluidToFill, processFilled, processEmpty); } public static void processContainers(TankManager tank, IInventory inv, int inputSlot, int outputSlot, Fluid fluidToFill) { processContainers(tank, inv, inputSlot, outputSlot, fluidToFill, true, true); } public static void processContainers(IFluidHandler fluidHandler, IInventory inv, int inputSlot, int outputSlot, Fluid fluidToFill, boolean processFilled, boolean processEmpty) { ItemStack input = inv.getStackInSlot(inputSlot); if (input == null) return; if (processFilled && drainContainers(fluidHandler, inv, inputSlot, outputSlot)) return; if (processEmpty && fluidToFill != null) fillContainers(fluidHandler, inv, inputSlot, outputSlot, fluidToFill); } public static boolean fillContainers(IFluidHandler fluidHandler, IInventory inv, int inputSlot, int outputSlot, Fluid fluidToFill) { if (fluidToFill == null) return false; ItemStack input = inv.getStackInSlot(inputSlot); ItemStack output = inv.getStackInSlot(outputSlot); FluidItemHelper.FillReturn fill = FluidItemHelper.fillContainer(input, new FluidStack(fluidToFill, PROCESS_VOLUME)); if (fill.container != null && hasPlaceToPutContainer(output, fill.container)) { FluidStack drain = fluidHandler.drain(ForgeDirection.UNKNOWN, fill.amount, false); if (drain != null && drain.amount == fill.amount) { fill = FluidItemHelper.fillContainer(input, drain); if (fill.container != null && fill.amount == drain.amount) { fluidHandler.drain(ForgeDirection.UNKNOWN, fill.amount, true); storeContainer(inv, inputSlot, outputSlot, fill.container); } return true; } } return false; } public static boolean drainContainers(IFluidHandler fluidHandler, IInventory inv, int inputSlot, int outputSlot) { ItemStack input = inv.getStackInSlot(inputSlot); ItemStack output = inv.getStackInSlot(outputSlot); if (input != null) { FluidItemHelper.DrainReturn drain = FluidItemHelper.drainContainer(input, PROCESS_VOLUME); if (drain.fluidDrained != null && (drain.container == null || hasPlaceToPutContainer(output, drain.container))) { int used = fluidHandler.fill(ForgeDirection.UNKNOWN, drain.fluidDrained, false); if ((drain.isAtomic && used == drain.fluidDrained.amount) || (!drain.isAtomic && drain.fluidDrained.amount > 0)) { fluidHandler.fill(ForgeDirection.UNKNOWN, drain.fluidDrained, true); storeContainer(inv, inputSlot, outputSlot, drain.container); return true; } } } return false; } private static boolean hasPlaceToPutContainer(ItemStack output, ItemStack container) { if (output == null) return true; return output.stackSize < output.getMaxStackSize() && InvTools.isItemEqual(container, output); } /** * We can assume that if null is passed for the container that the container * was consumed by the process and we should just remove the input container. */ private static void storeContainer(IInventory inv, int inputSlot, int outputSlot, ItemStack container) { if (container == null) { inv.decrStackSize(inputSlot, 1); return; } ItemStack output = inv.getStackInSlot(outputSlot); if (output == null) inv.setInventorySlotContents(outputSlot, container); else output.stackSize++; inv.decrStackSize(inputSlot, 1); } public static boolean registerBucket(FluidStack liquid, ItemStack filled) { ItemStack empty = new ItemStack(Items.bucket); return registerContainer(liquid, filled, empty); } public static boolean registerBottle(FluidStack liquid, ItemStack filled) { ItemStack empty = new ItemStack(Items.glass_bottle); return registerContainer(liquid, filled, empty); } public static boolean registerWax(FluidStack liquid, ItemStack filled) { ItemStack empty = ModItems.waxCapsule.get(); return registerContainer(liquid, filled, empty); } public static boolean registerRefactory(FluidStack liquid, ItemStack filled) { ItemStack empty = ModItems.refractoryEmpty.get(); return registerContainer(liquid, filled, empty); } public static boolean registerCan(FluidStack liquid, ItemStack filled) { ItemStack empty = ModItems.canEmpty.get(); return registerContainer(liquid, filled, empty); } public static boolean registerCell(FluidStack liquid, ItemStack filled) { ItemStack empty = ModItems.cellEmpty.get(); return registerContainer(liquid, filled, empty); } private static boolean registerContainer(FluidStack fluidStack, ItemStack filled, ItemStack empty) { if (empty != null) { FluidContainerData container = new FluidContainerData(fluidStack, filled, empty); registerContainer(container); return true; } return false; } public static void registerContainer(FluidContainerData container) { for (FluidRegistrar adapter : adapters) { adapter.registerContainer(container); } } public static Collection<ItemStack> getContainersFilledWith(FluidStack fluidStack) { List<ItemStack> containers = new ArrayList<ItemStack>(); for (FluidContainerData data : FluidContainerRegistry.getRegisteredFluidContainerData()) { FluidStack inContainer = FluidItemHelper.getFluidStackInContainer(data.filledContainer); if (inContainer != null && inContainer.containsFluid(fluidStack)) containers.add(data.filledContainer.copy()); } return containers; } public static void nerfWaterBottle() { for (FluidContainerData data : FluidContainerRegistry.getRegisteredFluidContainerData()) { if (data.filledContainer.getItem() == Items.potionitem && data.emptyContainer.getItem() == Items.glass_bottle && Fluids.WATER.is(data.fluid)) { data.fluid.amount = 333; return; } } } public static FluidStack drainBlock(World world, int x, int y, int z, boolean doDrain) { return drainBlock(world.getBlock(x, y, z), world, x, y, z, doDrain); } public static FluidStack drainBlock(Block block, World world, int x, int y, int z, boolean doDrain) { if (block instanceof IFluidBlock) { IFluidBlock fluidBlock = (IFluidBlock) block; if (fluidBlock.canDrain(world, x, y, z)) return fluidBlock.drain(world, x, y, z, doDrain); } else if (block == Blocks.water || block == Blocks.flowing_water) { int meta = world.getBlockMetadata(x, y, z); if (meta != 0) return null; if (doDrain) world.setBlockToAir(x, y, z); return new FluidStack(FluidRegistry.WATER, FluidContainerRegistry.BUCKET_VOLUME); } else if (block == Blocks.lava || block == Blocks.flowing_lava) { int meta = world.getBlockMetadata(x, y, z); if (meta != 0) return null; if (doDrain) world.setBlockToAir(x, y, z); return new FluidStack(FluidRegistry.LAVA, FluidContainerRegistry.BUCKET_VOLUME); } return null; } public static boolean isFullFluidBlock(World world, int x, int y, int z) { return isFullFluidBlock(WorldPlugin.getBlock(world, x, y, z), world, x, y, z); } public static boolean isFullFluidBlock(Block block, World world, int x, int y, int z) { if (block instanceof BlockLiquid || block instanceof IFluidBlock) return world.getBlockMetadata(x, y, z) == 0; return false; } public static Fluid getFluid(Block block) { if (block instanceof IFluidBlock) return ((IFluidBlock) block).getFluid(); else if (block == Blocks.water || block == Blocks.flowing_water) return FluidRegistry.WATER; else if (block == Blocks.lava || block == Blocks.flowing_lava) return FluidRegistry.LAVA; return null; } public static int getFluidId(FluidStack stack) { if (stack == null) return -1; if (stack.getFluid() == null) return -1; return FluidRegistry.getFluidID(stack.getFluid().getName()); } }