diff --git a/patches/minecraft/net/minecraft/item/ItemBucket.java.patch b/patches/minecraft/net/minecraft/item/ItemBucket.java.patch index 738f4220cb..15162b1111 100644 --- a/patches/minecraft/net/minecraft/item/ItemBucket.java.patch +++ b/patches/minecraft/net/minecraft/item/ItemBucket.java.patch @@ -9,23 +9,16 @@ if (raytraceresult == null) { -@@ -181,4 +183,23 @@ +@@ -181,4 +183,16 @@ } } } + + @Override -+ public net.minecraftforge.common.capabilities.ICapabilityProvider initCapabilities(ItemStack stack, net.minecraft.nbt.NBTTagCompound nbt) { ++ public net.minecraftforge.common.capabilities.ICapabilityProvider initCapabilities(ItemStack stack, @Nullable net.minecraft.nbt.NBTTagCompound nbt) { + if (this.getClass() == ItemBucket.class) + { -+ if (net.minecraftforge.fluids.FluidRegistry.isUniversalBucketEnabled()) -+ { -+ return new net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper(stack); -+ } -+ else -+ { -+ return new net.minecraftforge.fluids.capability.wrappers.FluidContainerRegistryWrapper(stack); // when fluid container registry is gone, just use FluidBucketWrapper -+ } ++ return new net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper(stack); + } + else + { diff --git a/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java b/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java index 58cc3f6541..b7487f4734 100644 --- a/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java +++ b/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java @@ -19,6 +19,8 @@ package net.minecraftforge.fluids; +import javax.annotation.Nonnull; + import net.minecraft.block.BlockDispenser; import net.minecraft.dispenser.BehaviorDefaultDispenseItem; import net.minecraft.dispenser.IBlockSource; @@ -27,9 +29,7 @@ import net.minecraft.tileentity.TileEntityDispenser; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import javax.annotation.Nonnull; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; /** * Fills or drains a fluid container item using a Dispenser. @@ -47,7 +47,8 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem private final BehaviorDefaultDispenseItem dispenseBehavior = new BehaviorDefaultDispenseItem(); - public ItemStack dispenseStack(IBlockSource source, ItemStack stack) + @Nonnull + public ItemStack dispenseStack(@Nonnull IBlockSource source, @Nonnull ItemStack stack) { if (FluidUtil.getFluidContained(stack) != null) { @@ -63,29 +64,32 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem * Picks up fluid in front of a Dispenser and fills a container with it. */ @Nonnull - private ItemStack fillContainer(IBlockSource source, @Nonnull ItemStack stack) + private ItemStack fillContainer(@Nonnull IBlockSource source, @Nonnull ItemStack stack) { World world = source.getWorld(); EnumFacing dispenserFacing = source.getBlockState().getValue(BlockDispenser.FACING); BlockPos blockpos = source.getBlockPos().offset(dispenserFacing); - ItemStack result = FluidUtil.tryPickUpFluid(stack, null, world, blockpos, dispenserFacing.getOpposite()); - if (result == null) + FluidActionResult actionResult = FluidUtil.tryPickUpFluid(stack, null, world, blockpos, dispenserFacing.getOpposite()); + ItemStack resultStack = actionResult.getResult(); + + if (!actionResult.isSuccess() || resultStack.func_190926_b()) { return super.dispenseStack(source, stack); } if (stack.func_190916_E() == 1) { - stack.deserializeNBT(result.serializeNBT()); + return resultStack; } - else if (((TileEntityDispenser)source.getBlockTileEntity()).addItemStack(result) < 0) + else if (((TileEntityDispenser)source.getBlockTileEntity()).addItemStack(resultStack) < 0) { - this.dispenseBehavior.dispense(source, result); + this.dispenseBehavior.dispense(source, resultStack); } - stack.func_190918_g(1); - return stack; + ItemStack stackCopy = stack.copy(); + stackCopy.func_190918_g(1); + return stackCopy; } /** @@ -93,9 +97,9 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem */ private ItemStack dumpContainer(IBlockSource source, ItemStack stack) { - ItemStack dispensedStack = stack.copy(); - dispensedStack.func_190920_e(1); - IFluidHandler fluidHandler = FluidUtil.getFluidHandler(dispensedStack); + ItemStack singleStack = stack.copy(); + singleStack.func_190920_e(1); + IFluidHandlerItem fluidHandler = FluidUtil.getFluidHandler(singleStack); if (fluidHandler == null) { return super.dispenseStack(source, stack); @@ -108,17 +112,20 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem if (fluidStack != null && fluidStack.amount == Fluid.BUCKET_VOLUME && FluidUtil.tryPlaceFluid(null, source.getWorld(), fluidStack, blockpos)) { fluidHandler.drain(Fluid.BUCKET_VOLUME, true); + ItemStack drainedStack = fluidHandler.getContainer(); if (stack.func_190916_E() == 1) { - stack.deserializeNBT(dispensedStack.serializeNBT()); + return drainedStack; } - else if (((TileEntityDispenser)source.getBlockTileEntity()).addItemStack(dispensedStack) < 0) + else if (!drainedStack.func_190926_b() && ((TileEntityDispenser)source.getBlockTileEntity()).addItemStack(drainedStack) < 0) { - this.dispenseBehavior.dispense(source, dispensedStack); + this.dispenseBehavior.dispense(source, drainedStack); } - return stack; + ItemStack stackCopy = stack.copy(); + stackCopy.func_190918_g(1); + return stackCopy; } else { diff --git a/src/main/java/net/minecraftforge/fluids/FluidActionResult.java b/src/main/java/net/minecraftforge/fluids/FluidActionResult.java new file mode 100644 index 0000000000..0023c0b606 --- /dev/null +++ b/src/main/java/net/minecraftforge/fluids/FluidActionResult.java @@ -0,0 +1,64 @@ +/* + * 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; + +import javax.annotation.Nonnull; + +import net.minecraft.item.ItemStack; + +/** + * Holds the result of a fluid action from {@link FluidUtil}. + * + * Failed actions will always have {@link #isSuccess()} == false and an empty ItemStack result. See {@link #FAILURE}. + * + * Successful actions will always have {@link #isSuccess()} == true. + * Successful actions may have an empty ItemStack result in some cases, + * for example the action succeeded and the resulting item was consumed. + */ +public class FluidActionResult +{ + public static final FluidActionResult FAILURE = new FluidActionResult(false, ItemStack.field_190927_a); + + public final boolean success; + @Nonnull + public final ItemStack result; + + public FluidActionResult(@Nonnull ItemStack result) + { + this(true, result); + } + + private FluidActionResult(boolean success, @Nonnull ItemStack result) + { + this.success = success; + this.result = result; + } + + public boolean isSuccess() + { + return success; + } + + @Nonnull + public ItemStack getResult() + { + return result; + } +} diff --git a/src/main/java/net/minecraftforge/fluids/FluidUtil.java b/src/main/java/net/minecraftforge/fluids/FluidUtil.java index d5e4070cff..f2ae6748a9 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidUtil.java +++ b/src/main/java/net/minecraftforge/fluids/FluidUtil.java @@ -36,6 +36,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fluids.capability.wrappers.BlockLiquidWrapper; import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper; import net.minecraftforge.items.IItemHandler; @@ -53,37 +54,51 @@ public class FluidUtil * First it tries to fill the container item from the fluid handler, * if that action fails then it tries to drain the container item into the fluid handler. * - * Returns true if interaction was successful. - * Returns false if interaction failed. + * @param stack The filled or empty fluid container. + * Will not be modified directly, if modifications are necessary a modified copy is returned in the result. + * @param fluidHandler The fluid handler to interact with. + * @param player The player doing the interaction between the item and fluid handler. + * @return a {@link FluidActionResult} holding the result and resulting container. */ - public static boolean interactWithFluidHandler(ItemStack stack, IFluidHandler fluidHandler, EntityPlayer player) + @Nonnull + public static FluidActionResult interactWithFluidHandler(@Nonnull ItemStack stack, IFluidHandler fluidHandler, EntityPlayer player) { - if (stack == null || fluidHandler == null || player == null) + if (stack.func_190926_b() || fluidHandler == null || player == null) { - return false; + return FluidActionResult.FAILURE; } IItemHandler playerInventory = new InvWrapper(player.inventory); - return tryFillContainerAndStow(stack, fluidHandler, playerInventory, Integer.MAX_VALUE, player) || - tryEmptyContainerAndStow(stack, fluidHandler, playerInventory, Integer.MAX_VALUE, player); + + FluidActionResult fillResult = tryFillContainerAndStow(stack, fluidHandler, playerInventory, Integer.MAX_VALUE, player); + if (fillResult.isSuccess()) + { + return fillResult; + } + else + { + return tryEmptyContainerAndStow(stack, fluidHandler, playerInventory, Integer.MAX_VALUE, player); + } } /** * Fill a container from the given fluidSource. * * @param container The container to be filled. Will not be modified. + * Separate handling must be done to reduce the stack size, stow containers, etc, on success. + * See {@link #tryFillContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer)}. * @param fluidSource The fluid handler to be drained. * @param maxAmount The largest amount of fluid that should be transferred. * @param player The player to make the filling noise. Pass null for no noise. * @param doFill true if the container should actually be filled, false if it should be simulated. - * @return The filled container or null if the liquid couldn't be taken from the tank. + * @return a {@link FluidActionResult} holding the filled container if successful. */ @Nonnull - public static ItemStack tryFillContainer(@Nonnull ItemStack container, IFluidHandler fluidSource, int maxAmount, @Nullable EntityPlayer player, boolean doFill) + public static FluidActionResult tryFillContainer(@Nonnull ItemStack container, IFluidHandler fluidSource, int maxAmount, @Nullable EntityPlayer player, boolean doFill) { - container = container.copy(); // do not modify the input - container.func_190920_e(1); - IFluidHandler containerFluidHandler = getFluidHandler(container); + ItemStack containerCopy = container.copy(); // do not modify the input + containerCopy.func_190920_e(1); + IFluidHandlerItem containerFluidHandler = getFluidHandler(containerCopy); if (containerFluidHandler != null) { FluidStack simulatedTransfer = tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, false); @@ -102,30 +117,33 @@ public class FluidUtil { containerFluidHandler.fill(simulatedTransfer, true); } - return container; + + ItemStack resultContainer = containerFluidHandler.getContainer(); + return new FluidActionResult(resultContainer); } } - return null; + return FluidActionResult.FAILURE; } /** * Takes a filled container and tries to empty it into the given tank. * * @param container The filled container. Will not be modified. + * Separate handling must be done to reduce the stack size, stow containers, etc, on success. + * See {@link #tryEmptyContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer)}. * @param fluidDestination The fluid handler to be filled by the container. * @param maxAmount The largest amount of fluid that should be transferred. * @param player Player for making the bucket drained sound. Pass null for no noise. * @param doDrain true if the container should actually be drained, false if it should be simulated. - * @return The empty container if successful, null if the fluid handler couldn't be filled. - * NOTE The empty container will have a stackSize of 0 when a filled container is consumable, - * i.e. it has a "null" empty container but has successfully been emptied. + * @return a {@link FluidActionResult} holding the empty container if the fluid handler was filled. + * NOTE If the container is consumable, the empty container will be null on success. */ @Nonnull - public static ItemStack tryEmptyContainer(@Nonnull ItemStack container, IFluidHandler fluidDestination, int maxAmount, @Nullable EntityPlayer player, boolean doDrain) + public static FluidActionResult tryEmptyContainer(@Nonnull ItemStack container, IFluidHandler fluidDestination, int maxAmount, @Nullable EntityPlayer player, boolean doDrain) { - container = container.copy(); // do not modify the input - container.func_190920_e(1); - IFluidHandler containerFluidHandler = getFluidHandler(container); + ItemStack containerCopy = container.copy(); // do not modify the input + containerCopy.func_190920_e(1); + IFluidHandlerItem containerFluidHandler = getFluidHandler(containerCopy); if (containerFluidHandler != null) { FluidStack simulatedTransfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, false); @@ -144,10 +162,12 @@ public class FluidUtil { containerFluidHandler.drain(simulatedTransfer, true); } - return container; + + ItemStack resultContainer = containerFluidHandler.getContainer(); + return new FluidActionResult(resultContainer); } } - return null; + return FluidActionResult.FAILURE; } /** @@ -157,62 +177,65 @@ public class FluidUtil * If the inventory does not accept it, it will be given to the player or dropped at the players feet. * If player is null in this case, the action will be aborted. * - * @param container The Fluid Container Itemstack to fill. This stack WILL be modified on success. + * @param container The Fluid Container ItemStack to fill. + * Will not be modified directly, if modifications are necessary a modified copy is returned in the result. * @param fluidSource The fluid source to fill from * @param inventory An inventory where any additionally created item (filled container if multiple empty are present) are put * @param maxAmount Maximum amount of fluid to take from the tank. - * @param player The player that gets the items the inventory can't take. Can be null, only used if the inventory cannot take the filled stack. - * @return True if the container was filled successfully and stowed, false otherwise. + * @param player The player that gets the items the inventory can't take. + * Can be null, only used if the inventory cannot take the filled stack. + * @return a {@link FluidActionResult} holding the result and the resulting container. The resulting container is empty on failure. */ - public static boolean tryFillContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidSource, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player) + @Nonnull + public static FluidActionResult tryFillContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidSource, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player) { if (container.func_190926_b()) { - return false; + return FluidActionResult.FAILURE; } if (player != null && player.capabilities.isCreativeMode) { - ItemStack filledReal = tryFillContainer(container, fluidSource, maxAmount, player, true); - if (filledReal != null) + FluidActionResult filledReal = tryFillContainer(container, fluidSource, maxAmount, player, true); + if (filledReal.isSuccess()) { - return true; + return new FluidActionResult(container); // creative mode: item does not change } } - else if (container.func_190916_E() == 1) // don't need to stow anything, just fill and edit the container stack + else if (container.func_190916_E() == 1) // don't need to stow anything, just fill the container stack { - ItemStack filledReal = tryFillContainer(container, fluidSource, maxAmount, player, true); - if (filledReal != null) + FluidActionResult filledReal = tryFillContainer(container, fluidSource, maxAmount, player, true); + if (filledReal.isSuccess()) { - container.deserializeNBT(filledReal.serializeNBT()); - return true; + return filledReal; } } else { - ItemStack filledSimulated = tryFillContainer(container, fluidSource, maxAmount, player, false); - if (filledSimulated != null) + FluidActionResult filledSimulated = tryFillContainer(container, fluidSource, maxAmount, player, false); + if (filledSimulated.isSuccess()) { // check if we can give the itemStack to the inventory - ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, filledSimulated, true); - if (remainder == null || player != null) + ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, filledSimulated.getResult(), true); + if (remainder.func_190926_b() || player != null) { - ItemStack filledReal = tryFillContainer(container, fluidSource, maxAmount, player, true); - remainder = ItemHandlerHelper.insertItemStacked(inventory, filledReal, false); + FluidActionResult filledReal = tryFillContainer(container, fluidSource, maxAmount, player, true); + remainder = ItemHandlerHelper.insertItemStacked(inventory, filledReal.getResult(), false); // give it to the player or drop it at their feet - if (remainder != null && player != null) + if (!remainder.func_190926_b() && player != null) { ItemHandlerHelper.giveItemToPlayer(player, remainder); } - container.func_190918_g(1); - return true; + ItemStack containerCopy = container.copy(); + containerCopy.func_190918_g(1); + return new FluidActionResult(containerCopy); } } } - return false; + return FluidActionResult.FAILURE; } /** @@ -222,72 +245,64 @@ public class FluidUtil * If the inventory does not accept the emptied container, it will be given to the player or dropped at the players feet. * If player is null in this case, the action will be aborted. * - * @param container The filled Fluid Container Itemstack to empty. This stack WILL be modified on success. + * @param container The filled Fluid Container Itemstack to empty. + * Will not be modified directly, if modifications are necessary a modified copy is returned in the result. * @param fluidDestination The fluid destination to fill from the fluid container. * @param inventory An inventory where any additionally created item (filled container if multiple empty are present) are put * @param maxAmount Maximum amount of fluid to take from the tank. * @param player The player that gets the items the inventory can't take. Can be null, only used if the inventory cannot take the filled stack. - * @return True if the container was filled successfully and stowed, false otherwise. + * @return a {@link FluidActionResult} holding the result and the resulting container. The resulting container is empty on failure. */ - public static boolean tryEmptyContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidDestination, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player) + @Nonnull + public static FluidActionResult tryEmptyContainerAndStow(@Nonnull ItemStack container, IFluidHandler fluidDestination, IItemHandler inventory, int maxAmount, @Nullable EntityPlayer player) { if (container.func_190926_b()) { - return false; + return FluidActionResult.FAILURE; } if (player != null && player.capabilities.isCreativeMode) { - ItemStack emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, true); - if (emptiedReal != null) + FluidActionResult emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, true); + if (emptiedReal.isSuccess()) { - return true; + return new FluidActionResult(container); // creative mode: item does not change } } else if (container.func_190916_E() == 1) // don't need to stow anything, just fill and edit the container stack { - ItemStack emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, true); - if (emptiedReal.func_190926_b()) + FluidActionResult emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, true); + if (emptiedReal.isSuccess()) { - container.func_190918_g(1); + return emptiedReal; } - else - { - container.deserializeNBT(emptiedReal.serializeNBT()); - } - return true; } else { - ItemStack emptiedSimulated = tryEmptyContainer(container, fluidDestination, maxAmount, player, false); - if (emptiedSimulated.func_190926_b()) - { - tryEmptyContainer(container, fluidDestination, maxAmount, player, true); - container.func_190918_g(1); - return true; - } - else + FluidActionResult emptiedSimulated = tryEmptyContainer(container, fluidDestination, maxAmount, player, false); + if (emptiedSimulated.isSuccess()) { // check if we can give the itemStack to the inventory - ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, emptiedSimulated, true); - if (remainder == null || player != null) + ItemStack remainder = ItemHandlerHelper.insertItemStacked(inventory, emptiedSimulated.getResult(), true); + if (remainder.func_190926_b() || player != null) { - ItemStack emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, true); - remainder = ItemHandlerHelper.insertItemStacked(inventory, emptiedReal, false); + FluidActionResult emptiedReal = tryEmptyContainer(container, fluidDestination, maxAmount, player, true); + remainder = ItemHandlerHelper.insertItemStacked(inventory, emptiedReal.getResult(), false); // give it to the player or drop it at their feet - if (remainder != null && player != null) + if (!remainder.func_190926_b() && player != null) { ItemHandlerHelper.giveItemToPlayer(player, remainder); } - container.func_190918_g(1); - return true; + ItemStack containerCopy = container.copy(); + containerCopy.func_190918_g(1); + return new FluidActionResult(containerCopy); } } } - return false; + return FluidActionResult.FAILURE; } /** @@ -308,11 +323,19 @@ public class FluidUtil int fillableAmount = fluidDestination.fill(drainable, false); if (fillableAmount > 0) { - FluidStack drained = fluidSource.drain(fillableAmount, doTransfer); - if (drained != null) + if (doTransfer) { - drained.amount = fluidDestination.fill(drained, doTransfer); - return drained; + FluidStack drained = fluidSource.drain(fillableAmount, true); + if (drained != null) + { + drained.amount = fluidDestination.fill(drained, true); + return drained; + } + } + else + { + drainable.amount = fillableAmount; + return drainable; } } } @@ -320,23 +343,25 @@ public class FluidUtil } /** - * Helper method to get an IFluidHandler for an itemStack. + * Helper method to get an {@link IFluidHandlerItem} for an itemStack. * - * The itemStack passed in here WILL be modified, the IFluidHandler acts on it directly. + * The itemStack passed in here WILL be modified, the {@link IFluidHandlerItem} acts on it directly. + * Some {@link IFluidHandlerItem} will change the item entirely, always use {@link IFluidHandlerItem#getContainer()} + * after using the fluid handler to get the resulting item back. * * Note that the itemStack MUST have a stackSize of 1 if you want to fill or drain it. - * You can't fill or drain a whole stack at once, if you do then liquid is multiplied or destroyed. + * You can't fill or drain multiple items at once, if you do then liquid is multiplied or destroyed. * * Vanilla buckets will be converted to universal buckets if they are enabled. * * Returns null if the itemStack passed in does not have a fluid handler. */ @Nullable - public static IFluidHandler getFluidHandler(ItemStack itemStack) + public static IFluidHandlerItem getFluidHandler(@Nonnull ItemStack itemStack) { - if (itemStack != null && itemStack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null)) + if (itemStack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)) { - return itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + return itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); } else { @@ -348,13 +373,13 @@ public class FluidUtil * Helper method to get the fluid contained in an itemStack */ @Nullable - public static FluidStack getFluidContained(ItemStack container) + public static FluidStack getFluidContained(@Nonnull ItemStack container) { - if (container != null) + if (!container.func_190926_b()) { container = container.copy(); container.func_190920_e(1); - IFluidHandler fluidHandler = FluidUtil.getFluidHandler(container); + IFluidHandlerItem fluidHandler = FluidUtil.getFluidHandler(container); if (fluidHandler != null) { return fluidHandler.drain(Integer.MAX_VALUE, false); @@ -453,18 +478,20 @@ public class FluidUtil /** * Attempts to pick up a fluid in the world and put it in an empty container item. * - * @param emptyContainer The empty container to fill. Will not be modified. + * @param emptyContainer The empty container to fill. + * Will not be modified directly, if modifications are necessary a modified copy is returned in the result. * @param playerIn The player filling the container. Optional. * @param worldIn The world the fluid is in. * @param pos The position of the fluid in the world. * @param side The side of the fluid that is being drained. - * @return a filled container if it was successful. returns null on failure. + * @return a {@link FluidActionResult} holding the result and the resulting container. */ @Nonnull - public static ItemStack tryPickUpFluid(@Nonnull ItemStack emptyContainer, @Nullable EntityPlayer playerIn, World worldIn, BlockPos pos, EnumFacing side) + public static FluidActionResult tryPickUpFluid(@Nonnull ItemStack emptyContainer, @Nullable EntityPlayer playerIn, World worldIn, BlockPos pos, EnumFacing side) { - if (emptyContainer.func_190926_b() || worldIn == null || pos == null) { - return ItemStack.field_190927_a; + if (emptyContainer.func_190926_b() || worldIn == null || pos == null) + { + return FluidActionResult.FAILURE; } IBlockState state = worldIn.getBlockState(pos); @@ -475,9 +502,13 @@ public class FluidUtil IFluidHandler targetFluidHandler = FluidUtil.getFluidHandler(worldIn, pos, side); if (targetFluidHandler != null) { - return FluidUtil.tryFillContainer(emptyContainer, targetFluidHandler, Integer.MAX_VALUE, playerIn, true); + FluidActionResult fluidActionResult = FluidUtil.tryFillContainer(emptyContainer, targetFluidHandler, Integer.MAX_VALUE, playerIn, true); + if (fluidActionResult.isSuccess()) + { + return fluidActionResult; + } } } - return null; + return FluidActionResult.FAILURE; } } diff --git a/src/main/java/net/minecraftforge/fluids/UniversalBucket.java b/src/main/java/net/minecraftforge/fluids/UniversalBucket.java index 6bf34e6e2f..23d3aff06a 100644 --- a/src/main/java/net/minecraftforge/fluids/UniversalBucket.java +++ b/src/main/java/net/minecraftforge/fluids/UniversalBucket.java @@ -38,6 +38,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.event.entity.player.FillBucketEvent; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper; import net.minecraftforge.fml.common.eventhandler.Event; import net.minecraftforge.fml.common.eventhandler.EventPriority; @@ -46,6 +47,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.ItemHandlerHelper; +import javax.annotation.Nonnull; + /** * A universal bucket that can hold any liquid */ @@ -53,6 +56,7 @@ public class UniversalBucket extends Item { private final int capacity; // how much the bucket holds + @Nonnull private final ItemStack empty; // empty item to return and recognize when filling private final boolean nbtSensitive; @@ -66,7 +70,7 @@ public class UniversalBucket extends Item * @param empty Item used for filling with the bucket event and returned when emptied * @param nbtSensitive Whether the empty item is NBT sensitive (usually true if empty and full are the same items) */ - public UniversalBucket(int capacity, ItemStack empty, boolean nbtSensitive) + public UniversalBucket(int capacity, @Nonnull ItemStack empty, boolean nbtSensitive) { this.capacity = capacity; this.empty = empty; @@ -82,13 +86,13 @@ public class UniversalBucket extends Item @Override public boolean hasContainerItem(ItemStack stack) { - return getEmpty() != null; + return !getEmpty().func_190926_b(); } @Override public ItemStack getContainerItem(ItemStack itemStack) { - if (getEmpty() != null) + if (!getEmpty().func_190926_b()) { // Create a copy such that the game can't mess with it return getEmpty().copy(); @@ -107,10 +111,11 @@ public class UniversalBucket extends Item // add all fluids that the bucket can be filled with FluidStack fs = new FluidStack(fluid, getCapacity()); ItemStack stack = new ItemStack(this); - IFluidHandler fluidHandler = new FluidBucketWrapper(stack); + IFluidHandlerItem fluidHandler = new FluidBucketWrapper(stack); if (fluidHandler.fill(fs, true) == fs.amount) { - subItems.add(stack); + ItemStack filled = fluidHandler.getContainer(); + subItems.add(filled); } } } @@ -122,7 +127,7 @@ public class UniversalBucket extends Item FluidStack fluidStack = getFluid(stack); if (fluidStack == null) { - if(getEmpty() != null) + if(!getEmpty().func_190926_b()) { return getEmpty().getDisplayName(); } @@ -176,7 +181,7 @@ public class UniversalBucket extends Item player.addStat(StatList.getObjectUseStats(this)); itemstack.func_190918_g(1); - ItemStack emptyStack = getEmpty() != null ? getEmpty().copy() : new ItemStack(this); + ItemStack emptyStack = !getEmpty().func_190926_b() ? getEmpty().copy() : new ItemStack(this); // check whether we replace the item or add the empty one to the inventory if (itemstack.func_190926_b()) @@ -228,11 +233,11 @@ public class UniversalBucket extends Item ItemStack singleBucket = emptyBucket.copy(); singleBucket.func_190920_e(1); - ItemStack filledBucket = FluidUtil.tryPickUpFluid(singleBucket, event.getEntityPlayer(), world, pos, target.sideHit); - if (filledBucket != null) + FluidActionResult filledResult = FluidUtil.tryPickUpFluid(singleBucket, event.getEntityPlayer(), world, pos, target.sideHit); + if (filledResult.isSuccess()) { event.setResult(Event.Result.ALLOW); - event.setFilledBucket(filledBucket); + event.setFilledBucket(filledResult.getResult()); } else { @@ -242,7 +247,8 @@ public class UniversalBucket extends Item } } - public static ItemStack getFilledBucket(UniversalBucket item, Fluid fluid) + @Nonnull + public static ItemStack getFilledBucket(@Nonnull UniversalBucket item, Fluid fluid) { ItemStack bucket = new ItemStack(item); @@ -256,11 +262,11 @@ public class UniversalBucket extends Item } else if (fluid == FluidRegistry.WATER) { - bucket.deserializeNBT(new ItemStack(Items.WATER_BUCKET).serializeNBT()); + return new ItemStack(Items.WATER_BUCKET); } else if (fluid == FluidRegistry.LAVA) { - bucket.deserializeNBT(new ItemStack(Items.LAVA_BUCKET).serializeNBT()); + return new ItemStack(Items.LAVA_BUCKET); } return bucket; @@ -276,6 +282,7 @@ public class UniversalBucket extends Item return capacity; } + @Nonnull public ItemStack getEmpty() { return empty; @@ -287,7 +294,7 @@ public class UniversalBucket extends Item } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt) + public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, NBTTagCompound nbt) { return new FluidBucketWrapper(stack); } diff --git a/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java b/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java index 0a260d5de6..6685c42c6f 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java +++ b/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java @@ -19,6 +19,10 @@ package net.minecraftforge.fluids.capability; +import java.util.concurrent.Callable; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; @@ -29,49 +33,18 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.IFluidTank; - -import java.util.concurrent.Callable; +import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack; public class CapabilityFluidHandler { @CapabilityInject(IFluidHandler.class) public static Capability FLUID_HANDLER_CAPABILITY = null; + @CapabilityInject(IFluidHandlerItem.class) + public static Capability FLUID_HANDLER_ITEM_CAPABILITY = null; public static void register() { - CapabilityManager.INSTANCE.register(IFluidHandler.class, new Capability.IStorage() - { - @Override - public NBTBase writeNBT(Capability capability, IFluidHandler instance, EnumFacing side) - { - if (!(instance instanceof IFluidTank)) - throw new RuntimeException("IFluidHandler instance does not implement IFluidTank"); - NBTTagCompound nbt = new NBTTagCompound(); - IFluidTank tank = (IFluidTank) instance; - FluidStack fluid = tank.getFluid(); - if (fluid != null) - { - fluid.writeToNBT(nbt); - } - else - { - nbt.setString("Empty", ""); - } - nbt.setInteger("Capacity", tank.getCapacity()); - return nbt; - } - - @Override - public void readNBT(Capability capability, IFluidHandler instance, EnumFacing side, NBTBase nbt) - { - if (!(instance instanceof IFluidTank)) - throw new RuntimeException("IFluidHandler instance is not instance of FluidTank"); - NBTTagCompound tags = (NBTTagCompound) nbt; - FluidTank tank = (FluidTank) instance; - tank.setCapacity(tags.getInteger("Capacity")); - tank.readFromNBT(tags); - } - }, new Callable() + CapabilityManager.INSTANCE.register(IFluidHandler.class, new DefaultFluidHandlerStorage(), new Callable() { @Override public IFluidHandler call() throws Exception @@ -79,6 +52,46 @@ public class CapabilityFluidHandler return new FluidTank(Fluid.BUCKET_VOLUME); } }); + + CapabilityManager.INSTANCE.register(IFluidHandlerItem.class, new DefaultFluidHandlerStorage(), new Callable() { + @Override + public IFluidHandlerItem call() throws Exception + { + return new FluidHandlerItemStack(new ItemStack(Items.BUCKET), Fluid.BUCKET_VOLUME); + } + }); } + private static class DefaultFluidHandlerStorage implements Capability.IStorage { + @Override + public NBTBase writeNBT(Capability capability, T instance, EnumFacing side) + { + if (!(instance instanceof IFluidTank)) + throw new RuntimeException("IFluidHandler instance does not implement IFluidTank"); + NBTTagCompound nbt = new NBTTagCompound(); + IFluidTank tank = (IFluidTank) instance; + FluidStack fluid = tank.getFluid(); + if (fluid != null) + { + fluid.writeToNBT(nbt); + } + else + { + nbt.setString("Empty", ""); + } + nbt.setInteger("Capacity", tank.getCapacity()); + return nbt; + } + + @Override + public void readNBT(Capability capability, T instance, EnumFacing side, NBTBase nbt) + { + if (!(instance instanceof IFluidTank)) + throw new RuntimeException("IFluidHandler instance is not instance of FluidTank"); + NBTTagCompound tags = (NBTTagCompound) nbt; + FluidTank tank = (FluidTank) instance; + tank.setCapacity(tags.getInteger("Capacity")); + tank.readFromNBT(tags); + } + } } diff --git a/src/main/java/net/minecraftforge/fluids/capability/IFluidHandlerItem.java b/src/main/java/net/minecraftforge/fluids/capability/IFluidHandlerItem.java new file mode 100644 index 0000000000..760bf09c3b --- /dev/null +++ b/src/main/java/net/minecraftforge/fluids/capability/IFluidHandlerItem.java @@ -0,0 +1,41 @@ +/* + * 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; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; + +/** + * ItemStacks handled by an {@link IFluidHandler} may change, so this class allows + * users of the fluid handler to get the container after it has been used. + */ +public interface IFluidHandlerItem extends IFluidHandler +{ + /** + * Get the container currently acted on by this fluid handler. + * The ItemStack may be different from its initial state, in the case of fluid containers that have different items + * for their filled and empty states. + * May be an empty item if the container was drained and is consumable. + */ + @Nonnull + ItemStack getContainer(); +} diff --git a/src/main/java/net/minecraftforge/fluids/capability/ItemFluidContainer.java b/src/main/java/net/minecraftforge/fluids/capability/ItemFluidContainer.java index 7937c57972..542d602fa7 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/ItemFluidContainer.java +++ b/src/main/java/net/minecraftforge/fluids/capability/ItemFluidContainer.java @@ -25,6 +25,9 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + /** * A simple fluid container, to replace the functionality of the old FluidContainerRegistry and IFluidContainerItem. * This fluid container may be set so that is can only completely filled or empty. (binary) @@ -43,7 +46,7 @@ public class ItemFluidContainer extends Item } @Override - public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt) + public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, @Nullable NBTTagCompound nbt) { return new FluidHandlerItemStack(stack, capacity); } diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java index eec96b51b7..f4b715528d 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java @@ -19,6 +19,7 @@ package net.minecraftforge.fluids.capability.templates; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.item.ItemStack; @@ -29,7 +30,7 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fluids.*; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.FluidTankProperties; -import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fluids.capability.IFluidTankProperties; /** @@ -41,23 +42,31 @@ import net.minecraftforge.fluids.capability.IFluidTankProperties; * Additional examples are provided to enable consumable fluid containers (see {@link Consumable}), * fluid containers with different empty and full items (see {@link SwapEmpty}, */ -public class FluidHandlerItemStack implements IFluidHandler, ICapabilityProvider +public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProvider { public static final String FLUID_NBT_KEY = "Fluid"; - protected final ItemStack container; - protected final int capacity; + @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 FluidHandlerItemStack(ItemStack container, int capacity) + public FluidHandlerItemStack(@Nonnull ItemStack container, int capacity) { this.container = container; this.capacity = capacity; } + @Nonnull + @Override + public ItemStack getContainer() + { + return container; + } + @Nullable public FluidStack getFluid() { @@ -184,8 +193,7 @@ public class FluidHandlerItemStack implements IFluidHandler, ICapabilityProvider /** * 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--" + * Can be used to swap out or destroy the container. */ protected void setContainerToEmpty() { @@ -195,14 +203,14 @@ public class FluidHandlerItemStack implements IFluidHandler, ICapabilityProvider @Override public boolean hasCapability(Capability capability, EnumFacing facing) { - return capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY; } @SuppressWarnings("unchecked") @Override public T getCapability(Capability capability, EnumFacing facing) { - return capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ? (T) this : null; + return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY ? (T) this : null; } /** @@ -240,7 +248,7 @@ public class FluidHandlerItemStack implements IFluidHandler, ICapabilityProvider protected void setContainerToEmpty() { super.setContainerToEmpty(); - container.deserializeNBT(emptyContainer.serializeNBT()); + container = emptyContainer; } } } diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java index d7259fe5fa..9a65e7362b 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java @@ -19,6 +19,7 @@ package net.minecraftforge.fluids.capability.templates; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.item.ItemStack; @@ -28,33 +29,41 @@ 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; -import net.minecraftforge.fluids.capability.IFluidHandler; /** * FluidHandlerItemStackSimple is a template capability provider for ItemStacks. - * Data is stored directly in the vanilla NBT, in the same way as the old deprecated {@link ItemFluidContainer}. + * 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 IFluidHandler, ICapabilityProvider +public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabilityProvider { public static final String FLUID_NBT_KEY = "Fluid"; - protected final ItemStack container; - protected final int capacity; + @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(ItemStack container, int capacity) + public FluidHandlerItemStackSimple(@Nonnull ItemStack container, int capacity) { this.container = container; this.capacity = capacity; } + @Nonnull + @Override + public ItemStack getContainer() + { + return container; + } + @Nullable public FluidStack getFluid() { @@ -171,14 +180,14 @@ public class FluidHandlerItemStackSimple implements IFluidHandler, ICapabilityPr @Override public boolean hasCapability(Capability capability, EnumFacing facing) { - return capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY; } @SuppressWarnings("unchecked") @Override public T getCapability(Capability capability, EnumFacing facing) { - return capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ? (T) this : null; + return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY ? (T) this : null; } /** @@ -216,7 +225,7 @@ public class FluidHandlerItemStackSimple implements IFluidHandler, ICapabilityPr protected void setContainerToEmpty() { super.setContainerToEmpty(); - container.deserializeNBT(emptyContainer.serializeNBT()); + container = emptyContainer; } } } diff --git a/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java index 9ad262ed16..ad73b8c95b 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java +++ b/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java @@ -19,6 +19,7 @@ package net.minecraftforge.fluids.capability.wrappers; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.init.Items; @@ -33,6 +34,7 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; 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.UniversalBucket; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; @@ -42,15 +44,23 @@ import net.minecraftforge.fluids.capability.IFluidHandler; * Wrapper for vanilla and forge buckets. * Swaps between empty bucket and filled bucket of the correct type. */ -public class FluidBucketWrapper implements IFluidHandler, ICapabilityProvider +public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvider { - protected final ItemStack container; + @Nonnull + protected ItemStack container; - public FluidBucketWrapper(ItemStack container) + public FluidBucketWrapper(@Nonnull ItemStack container) { this.container = container; } + @Nonnull + @Override + public ItemStack getContainer() + { + return container; + } + public boolean canFillFluidType(FluidStack fluid) { if (fluid.getFluid() == FluidRegistry.WATER || fluid.getFluid() == FluidRegistry.LAVA || fluid.getFluid().getName().equals("milk")) @@ -89,24 +99,23 @@ public class FluidBucketWrapper implements IFluidHandler, ICapabilityProvider protected void setFluid(Fluid fluid) { if (fluid == null) { - container.deserializeNBT(new ItemStack(Items.BUCKET).serializeNBT()); + container = new ItemStack(Items.BUCKET); } else if (fluid == FluidRegistry.WATER) { - container.deserializeNBT(new ItemStack(Items.WATER_BUCKET).serializeNBT()); + container = new ItemStack(Items.WATER_BUCKET); } else if (fluid == FluidRegistry.LAVA) { - container.deserializeNBT(new ItemStack(Items.LAVA_BUCKET).serializeNBT()); + container = new ItemStack(Items.LAVA_BUCKET); } else if (fluid.getName().equals("milk")) { - container.deserializeNBT(new ItemStack(Items.MILK_BUCKET).serializeNBT()); + container = new ItemStack(Items.MILK_BUCKET); } else if (FluidRegistry.isUniversalBucketEnabled() && FluidRegistry.getBucketFluids().contains(fluid)) { - ItemStack filledBucket = UniversalBucket.getFilledBucket(ForgeModContainer.getInstance().universalBucket, fluid); - container.deserializeNBT(filledBucket.serializeNBT()); + container = UniversalBucket.getFilledBucket(ForgeModContainer.getInstance().universalBucket, fluid); } } @@ -179,15 +188,15 @@ public class FluidBucketWrapper implements IFluidHandler, ICapabilityProvider @Override public boolean hasCapability(Capability capability, EnumFacing facing) { - return capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + return capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY; } @Override public T getCapability(Capability capability, EnumFacing facing) { - if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) + if (capability == CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) { - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(this); + return CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY.cast(this); } return null; } diff --git a/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java b/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java index 8a908abf1d..cb6fd7bda5 100644 --- a/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java +++ b/src/main/java/net/minecraftforge/items/ItemHandlerHelper.java @@ -98,9 +98,10 @@ public class ItemHandlerHelper * This is equivalent to the behaviour of a player picking up an item. * Note: This function stacks items without subtypes with different metadata together. */ - public static ItemStack insertItemStacked(IItemHandler inventory, ItemStack stack, boolean simulate) + @Nonnull + public static ItemStack insertItemStacked(IItemHandler inventory, @Nonnull ItemStack stack, boolean simulate) { - if (inventory == null || stack == null) + if (inventory == null || stack.func_190926_b()) return stack; // not stackable -> just insert into a new slot @@ -119,7 +120,7 @@ public class ItemHandlerHelper { stack = inventory.insertItem(i, stack, simulate); - if (stack == null) + if (stack.func_190926_b()) { break; } @@ -127,15 +128,15 @@ public class ItemHandlerHelper } // insert remainder into empty slots - if (stack != null) + if (!stack.func_190926_b()) { // find empty slot for (int i = 0; i < sizeInventory; i++) { - if (inventory.getStackInSlot(i) == null) + if (inventory.getStackInSlot(i).func_190926_b()) { stack = inventory.insertItem(i, stack, simulate); - if (stack == null) + if (stack.func_190926_b()) { break; } diff --git a/src/test/java/net/minecraftforge/debug/DynBucketTest.java b/src/test/java/net/minecraftforge/debug/DynBucketTest.java index bbede5abd9..23ae0fea96 100644 --- a/src/test/java/net/minecraftforge/debug/DynBucketTest.java +++ b/src/test/java/net/minecraftforge/debug/DynBucketTest.java @@ -47,6 +47,7 @@ import net.minecraftforge.fluids.IFluidBlock; import net.minecraftforge.fluids.UniversalBucket; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; @@ -68,7 +69,7 @@ public class DynBucketTest private static final ResourceLocation simpleTankName = new ResourceLocation(MODID, "simpletank"); private static final ResourceLocation testItemName = new ResourceLocation(MODID, "testitem"); - private static final boolean ENABLE = false; + private static final boolean ENABLE = true; static { @@ -152,13 +153,14 @@ public class DynBucketTest FluidStack fs = new FluidStack(fluid, Fluid.BUCKET_VOLUME); ItemStack bucket = event.getEmptyBucket(); - IFluidHandler fluidHandler = FluidUtil.getFluidHandler(bucket); + IFluidHandlerItem fluidHandler = FluidUtil.getFluidHandler(bucket); if (fluidHandler != null) { int fillAmount = fluidHandler.fill(fs, true); if (fillAmount > 0) { - event.setFilledBucket(bucket); + ItemStack filledBucket = fluidHandler.getContainer(); + event.setFilledBucket(filledBucket); event.setResult(Result.ALLOW); } } @@ -269,7 +271,7 @@ public class DynBucketTest } // do the thing with the tank and the buckets - if (FluidUtil.interactWithFluidHandler(heldItem, tank, playerIn)) + if (FluidUtil.interactWithFluidHandler(heldItem, tank, playerIn).isSuccess()) { return true; } diff --git a/src/test/java/net/minecraftforge/debug/ModelFluidDebug.java b/src/test/java/net/minecraftforge/debug/ModelFluidDebug.java index 2e6be96d7f..70a407756e 100644 --- a/src/test/java/net/minecraftforge/debug/ModelFluidDebug.java +++ b/src/test/java/net/minecraftforge/debug/ModelFluidDebug.java @@ -27,7 +27,7 @@ public class ModelFluidDebug public static final String MODID = "forgedebugmodelfluid"; public static final String VERSION = "1.0"; - public static final boolean ENABLE = false; + public static final boolean ENABLE = true; @SidedProxy public static CommonProxy proxy; diff --git a/src/test/java/net/minecraftforge/test/FluidHandlerTest.java b/src/test/java/net/minecraftforge/test/FluidHandlerTest.java index 1c00af6106..fa7308fd35 100644 --- a/src/test/java/net/minecraftforge/test/FluidHandlerTest.java +++ b/src/test/java/net/minecraftforge/test/FluidHandlerTest.java @@ -1,6 +1,5 @@ package net.minecraftforge.test; -import java.util.ArrayList; import java.util.List; import net.minecraft.creativetab.CreativeTabs; @@ -11,7 +10,7 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidUtil; -import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.Mod; @@ -19,10 +18,12 @@ import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent; import net.minecraftforge.fml.common.registry.ForgeRegistries; import net.minecraftforge.fml.relauncher.Side; +import javax.annotation.Nonnull; + @Mod(modid="fluidhandlertest", name="FluidHandlerTest", version="0.0.0") public class FluidHandlerTest { - public static final boolean ENABLE = false; + public static final boolean ENABLE = true; @Mod.EventHandler public void loadComplete(FMLLoadCompleteEvent event) @@ -38,24 +39,45 @@ public class FluidHandlerTest private static void testFluidContainer(ItemStack stack) { - ItemStack drainedStack = stack.copy(); - IFluidHandler fluidHandler = FluidUtil.getFluidHandler(drainedStack); + ItemStack originalStack = stack.copy(); + + ItemStack preDrainStack = stack.copy(); + IFluidHandlerItem fluidHandler = FluidUtil.getFluidHandler(preDrainStack); if (fluidHandler != null) { FluidStack drain = fluidHandler.drain(Integer.MAX_VALUE, true); + ItemStack drainedStack = fluidHandler.getContainer(); FMLLog.info("Draining " + stackString(stack) + " gives " + fluidString(drain) + " and " + stackString(drainedStack)); + if (drain == null && !ItemStack.areItemStacksEqual(originalStack, preDrainStack)) + { + throw new RuntimeException("ItemStack was altered by its fluid handler when drain did nothing."); + } + for (Fluid fluid : FluidRegistry.getRegisteredFluids().values()) { - ItemStack filledStack = stack.copy(); - fluidHandler = FluidUtil.getFluidHandler(filledStack); + ItemStack preFillStack = stack.copy(); + fluidHandler = FluidUtil.getFluidHandler(preFillStack); if (fluidHandler != null) { int filled = fluidHandler.fill(new FluidStack(fluid, Integer.MAX_VALUE), true); + ItemStack filledStack = fluidHandler.getContainer(); + if (filled > 0) { FMLLog.info("Filling " + stackString(stack) + " with " + fluidString(new FluidStack(fluid, filled)) + " gives " + stackString(filledStack)); } + else + { + if (!ItemStack.areItemStacksEqual(originalStack, preFillStack)) + { + throw new RuntimeException("ItemStack was altered by its fluid handler when fill did nothing."); + } + if (!ItemStack.areItemStacksEqual(preFillStack, filledStack)) + { + throw new RuntimeException("ItemStack was altered by its fluid handler when fill did nothing."); + } + } } } } @@ -73,7 +95,7 @@ public class FluidHandlerTest } } - private static String stackString(ItemStack stack) + private static String stackString(@Nonnull ItemStack stack) { if (stack.func_190926_b()) { @@ -82,7 +104,7 @@ public class FluidHandlerTest else { String resourceDomain; - if (stack.getItem() == null || stack.getItem().getRegistryName() == null) + if (stack.getItem().getRegistryName() == null) { resourceDomain = "unknown"; }