/* * 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; } } }