/*
* Minecraft Forge
* Copyright (c) 2016.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fluids.capability.templates;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.FluidTankProperties;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import net.minecraftforge.fluids.capability.IFluidTankProperties;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
/**
* FluidHandlerItemStackSimple is a template capability provider for ItemStacks.
* Data is stored directly in the vanilla NBT, in the same way as the old ItemFluidContainer.
*
* This implementation only allows item containers to be fully filled or emptied, similar to vanilla buckets.
*/
public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabilityProvider
{
public static final String FLUID_NBT_KEY = "Fluid";
@Nonnull
protected ItemStack container;
protected int capacity;
/**
* @param container The container itemStack, data is stored on it directly as NBT.
* @param capacity The maximum capacity of this fluid tank.
*/
public FluidHandlerItemStackSimple(@Nonnull ItemStack container, int capacity)
{
this.container = container;
this.capacity = capacity;
}
@Nonnull
@Override
public ItemStack getContainer()
{
return container;
}
@Nullable
public FluidStack getFluid()
{
NBTTagCompound tagCompound = container.getTagCompound();
if (tagCompound == null || !tagCompound.hasKey(FLUID_NBT_KEY))
{
return null;
}
return FluidStack.loadFluidStackFromNBT(tagCompound.getCompoundTag(FLUID_NBT_KEY));
}
protected void setFluid(FluidStack fluid)
{
if (!container.hasTagCompound())
{
container.setTagCompound(new NBTTagCompound());
}
NBTTagCompound fluidTag = new NBTTagCompound();
fluid.writeToNBT(fluidTag);
container.getTagCompound().setTag(FLUID_NBT_KEY, fluidTag);
}
@Override
public IFluidTankProperties[] getTankProperties()
{
return new IFluidTankProperties[] { new FluidTankProperties(getFluid(), capacity) };
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
if (container.getCount() != 1 || resource == null || resource.amount <= 0 || !canFillFluidType(resource))
{
return 0;
}
FluidStack contained = getFluid();
if (contained == null)
{
int fillAmount = Math.min(capacity, resource.amount);
if (fillAmount == capacity) {
if (doFill) {
FluidStack filled = resource.copy();
filled.amount = fillAmount;
setFluid(filled);
}
return fillAmount;
}
}
return 0;
}
@Override
public FluidStack drain(FluidStack resource, boolean doDrain)
{
if (container.getCount() != 1 || resource == null || resource.amount <= 0 || !resource.isFluidEqual(getFluid()))
{
return null;
}
return drain(resource.amount, doDrain);
}
@Override
public FluidStack drain(int maxDrain, boolean doDrain)
{
if (container.getCount() != 1 || maxDrain <= 0)
{
return null;
}
FluidStack contained = getFluid();
if (contained == null || contained.amount <= 0 || !canDrainFluidType(contained))
{
return null;
}
final int drainAmount = Math.min(contained.amount, maxDrain);
if (drainAmount == capacity) {
FluidStack drained = contained.copy();
if (doDrain) {
setContainerToEmpty();
}
return drained;
}
return null;
}
public boolean canFillFluidType(FluidStack fluid)
{
return true;
}
public boolean canDrainFluidType(FluidStack fluid)
{
return true;
}
/**
* Override this method for special handling.
* Can be used to swap out the container's item for a different one with "container.setItem".
* Can be used to destroy the container with "container.stackSize--"
*/
protected void setContainerToEmpty()
{
container.getTagCompound().removeTag(FLUID_NBT_KEY);
}
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing)
{
return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY;
}
@SuppressWarnings("unchecked")
@Override
@Nullable
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY ? (T) this : null;
}
/**
* Destroys the container item when it's emptied.
*/
public static class Consumable extends FluidHandlerItemStackSimple
{
public Consumable(ItemStack container, int capacity)
{
super(container, capacity);
}
@Override
protected void setContainerToEmpty()
{
super.setContainerToEmpty();
container.shrink(1);
}
}
/**
* Swaps the container item for a different one when it's emptied.
*/
public static class SwapEmpty extends FluidHandlerItemStackSimple
{
protected final ItemStack emptyContainer;
public SwapEmpty(ItemStack container, ItemStack emptyContainer, int capacity)
{
super(container, capacity);
this.emptyContainer = emptyContainer;
}
@Override
protected void setContainerToEmpty()
{
super.setContainerToEmpty();
container = emptyContainer;
}
}
}