package mekanism.common.util;
import mekanism.api.util.StackUtils;
import mekanism.common.tile.TileEntityContainerBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public final class FluidContainerUtils
{
public static boolean isFluidContainer(ItemStack stack)
{
return stack != null && stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null);
}
public static FluidStack extractFluid(FluidTank tileTank, ItemStack container)
{
return extractFluid(tileTank, container, FluidChecker.check(tileTank.getFluid()));
}
public static FluidStack extractFluid(FluidTank tileTank, ItemStack container, FluidChecker checker)
{
return extractFluid(tileTank.getCapacity()-tileTank.getFluidAmount(), container, checker);
}
public static FluidStack extractFluid(int needed, ItemStack container, FluidChecker checker)
{
IFluidHandler handler = FluidUtil.getFluidHandler(container);
if(handler == null || FluidUtil.getFluidContained(container) == null)
{
return null;
}
if(checker != null && !checker.isValid(FluidUtil.getFluidContained(container).getFluid()))
{
return null;
}
return handler.drain(needed, true);
}
public static int insertFluid(FluidTank tileTank, ItemStack container)
{
return insertFluid(tileTank.getFluid(), container);
}
public static int insertFluid(FluidStack fluid, ItemStack container)
{
IFluidHandler handler = FluidUtil.getFluidHandler(container);
if(fluid == null)
{
return 0;
}
return handler.fill(fluid, true);
}
public static void handleContainerItemFill(TileEntityContainerBlock tileEntity, FluidTank tank, int inSlot, int outSlot)
{
tank.setFluid(handleContainerItemFill(tileEntity, tileEntity.inventory, tank.getFluid(), inSlot, outSlot));
}
public static FluidStack handleContainerItemFill(TileEntity tileEntity, ItemStack[] inventory, FluidStack stack, int inSlot, int outSlot)
{
if(stack != null)
{
ItemStack inputCopy = StackUtils.size(inventory[inSlot].copy(), 1);
int drained = insertFluid(stack, inputCopy);
if(inventory[outSlot] != null && (!ItemHandlerHelper.canItemStacksStack(inventory[outSlot], inputCopy) || inventory[outSlot].stackSize == inventory[outSlot].getMaxStackSize()))
{
return stack;
}
stack.amount -= drained;
if(inventory[outSlot] == null)
{
inventory[outSlot] = inputCopy;
}
else if(ItemHandlerHelper.canItemStacksStack(inventory[outSlot], inputCopy))
{
inventory[outSlot].stackSize++;
}
inventory[inSlot].stackSize--;
if(inventory[inSlot].stackSize == 0)
{
inventory[inSlot] = null;
}
if(stack.amount == 0)
{
stack = null;
}
tileEntity.markDirty();
}
return stack;
}
public static void handleContainerItemEmpty(TileEntityContainerBlock tileEntity, FluidTank tank, int inSlot, int outSlot)
{
handleContainerItemEmpty(tileEntity, tank, inSlot, outSlot, null);
}
public static void handleContainerItemEmpty(TileEntityContainerBlock tileEntity, FluidTank tank, int inSlot, int outSlot, FluidChecker checker)
{
tank.setFluid(handleContainerItemEmpty(tileEntity, tileEntity.inventory, tank.getFluid(), tank.getCapacity()-tank.getFluidAmount(), inSlot, outSlot, checker));
}
public static FluidStack handleContainerItemEmpty(TileEntity tileEntity, ItemStack[] inventory, FluidStack stored, int needed, int inSlot, int outSlot, final FluidChecker checker)
{
final Fluid storedFinal = stored != null ? stored.getFluid() : null;
final ItemStack input = StackUtils.size(inventory[inSlot].copy(), 1);
FluidStack ret = extractFluid(needed, input, new FluidChecker() {
@Override
public boolean isValid(Fluid f)
{
return (checker == null || checker.isValid(f)) && (storedFinal == null || storedFinal == f);
}
});
ItemStack inputCopy = input.copy();
if(inputCopy.stackSize == 0)
{
inputCopy = null;
}
if(FluidUtil.getFluidContained(inputCopy) == null && inputCopy != null)
{
if(inventory[outSlot] != null && (!ItemHandlerHelper.canItemStacksStack(inventory[outSlot], inputCopy) || inventory[outSlot].stackSize == inventory[outSlot].getMaxStackSize()))
{
return stored;
}
}
if(ret != null)
{
if(stored == null)
{
stored = ret;
}
else {
stored.amount += ret.amount;
}
needed -= ret.amount;
tileEntity.markDirty();
}
if(FluidUtil.getFluidContained(inputCopy) == null || needed == 0)
{
if(inputCopy != null)
{
if(inventory[outSlot] == null)
{
inventory[outSlot] = inputCopy;
}
else if(ItemHandlerHelper.canItemStacksStack(inventory[outSlot], inputCopy))
{
inventory[outSlot].stackSize++;
}
}
inventory[inSlot].stackSize--;
if(inventory[inSlot].stackSize == 0)
{
inventory[inSlot] = null;
}
tileEntity.markDirty();
}
else {
inventory[inSlot] = inputCopy;
}
return stored;
}
public static void handleContainerItem(TileEntityContainerBlock tileEntity, ContainerEditMode editMode, FluidTank tank, int inSlot, int outSlot)
{
handleContainerItem(tileEntity, editMode, tank, inSlot, outSlot, null);
}
public static void handleContainerItem(TileEntityContainerBlock tileEntity, ContainerEditMode editMode, FluidTank tank, int inSlot, int outSlot, FluidChecker checker)
{
tank.setFluid(handleContainerItem(tileEntity, tileEntity.inventory, editMode, tank.getFluid(), tank.getCapacity()-tank.getFluidAmount(), inSlot, outSlot, checker));
}
public static FluidStack handleContainerItem(TileEntity tileEntity, ItemStack[] inventory, ContainerEditMode editMode, FluidStack stack, int needed, int inSlot, int outSlot, final FluidChecker checker)
{
FluidStack fluidStack = FluidUtil.getFluidContained(inventory[inSlot]);
if(editMode == ContainerEditMode.FILL || (editMode == ContainerEditMode.BOTH && fluidStack == null))
{
return handleContainerItemFill(tileEntity, inventory, stack, inSlot, outSlot);
}
else if(editMode == ContainerEditMode.EMPTY || (editMode == ContainerEditMode.BOTH && fluidStack != null))
{
return handleContainerItemEmpty(tileEntity, inventory, stack, needed, inSlot, outSlot, checker);
}
return stack;
}
public static enum ContainerEditMode
{
BOTH("fluidedit.both"),
FILL("fluidedit.fill"),
EMPTY("fluidedit.empty");
private String display;
public String getDisplay()
{
return LangUtils.localize(display);
}
private ContainerEditMode(String s)
{
display = s;
}
}
public static class FluidChecker
{
public boolean isValid(Fluid f)
{
return true;
}
public static FluidChecker check(FluidStack fluid)
{
final Fluid type = fluid != null ? fluid.getFluid() : null;
return new FluidChecker() {
@Override
public boolean isValid(Fluid f)
{
return type == null || type == f;
}
};
}
public static FluidChecker check(final Fluid type)
{
return new FluidChecker() {
@Override
public boolean isValid(Fluid f)
{
return type == null || type == f;
}
};
}
}
}