From cf854ac4a49ace7f823941d7be418a1792d727d6 Mon Sep 17 00:00:00 2001 From: danyadev Date: Wed, 4 Feb 2026 17:23:30 +0300 Subject: [PATCH 01/11] refactor getEmptyContainerForFilledItem method - Renamed method to be more clear - Return null if draining IFluidContainerItem does not result in an empty container --- dependencies.gradle | 6 ++-- .../utils/fluid/FluidInteractions.java | 32 ++++++++++--------- .../value/sync/FluidSlotSyncHandler.java | 2 +- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 416c202b6..e20744f3b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -39,7 +39,9 @@ dependencies { implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.48-GTNH:dev") compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.39:dev") { transitive = false } - compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.197:dev") { transitive = false } + devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { + exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' + } compileOnly("com.github.GTNewHorizons:ModularUI:1.3.1:dev") { transitive = false } implementation("com.github.GTNewHorizons:Baubles-Expanded:2.2.6-GTNH:dev") { transitive = false } compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev") @@ -47,7 +49,7 @@ dependencies { compileOnly files("libs/neverenoughanimations-v1.0.6-1-7-10.8+91c551807b-dirty-dev.jar") compileOnly("org.jetbrains:annotations:24.0.1") - //runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.8.48-GTNH:dev") + runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.8.60-GTNH:dev") // For Thaumcraft runtime //runtimeOnlyNonPublishable("com.github.GTNewHorizons:Baubles:1.0.4:dev") diff --git a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java index de7af71e2..be92c70b5 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java +++ b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java @@ -85,24 +85,26 @@ public static ItemStack fillFluidContainerWithIFluidContainerItem(FluidStack flu return null; } - public static ItemStack getContainerForFilledItem(ItemStack itemStack) { - ItemStack stack = getContainerForFilledItemWithoutIFluidContainerItem(itemStack); - if (stack == null && itemStack.getItem() instanceof IFluidContainerItem container) { - stack = itemStack.copy(); - if (container.drain(stack, Integer.MAX_VALUE, true) == null) - return null; - } - if (stack == null) { - stack = FluidContainerRegistry.drainFluidContainer(itemStack.copy()); + public static ItemStack getEmptyContainerForFilledItem(ItemStack itemStack) { + if (ModularUI.Mods.GT5U.isLoaded()) { + ItemStack stack = GTUtility.getContainerForFilledItem(itemStack, false); + if (stack != null) { + return stack; + } } - return stack; - } - public static ItemStack getContainerForFilledItemWithoutIFluidContainerItem(ItemStack itemStack) { - if (ModularUI.Mods.GT5U.isLoaded()) { - return GTUtility.getContainerForFilledItem(itemStack, false); + if (itemStack.getItem() instanceof IFluidContainerItem container) { + ItemStack stack = itemStack.copy(); + int amount = container.getFluid(itemStack).amount; + FluidStack drained = container.drain(stack, Integer.MAX_VALUE, true); + + if (drained == null || drained.amount < amount) { + return null; + } + return stack; } - return null; + + return FluidContainerRegistry.drainFluidContainer(itemStack); } public static int getRealCapacity(IFluidTank fluidTank) { diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index 0f67e1c45..09460e633 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -291,7 +291,7 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack ItemStack itemStackEmptied = null; int fluidAmountTaken = 0; if (freeSpace >= heldFluid.amount) { - itemStackEmptied = FluidInteractions.getContainerForFilledItem(heldItemSizedOne); + itemStackEmptied = FluidInteractions.getEmptyContainerForFilledItem(heldItemSizedOne); fluidAmountTaken = heldFluid.amount; } From 681f088aad59cec797fdd84dbc6e4587ca582293 Mon Sep 17 00:00:00 2001 From: danyadev Date: Wed, 4 Feb 2026 17:30:56 +0300 Subject: [PATCH 02/11] deduplicate getFluidForRealItem / getFluidForRealItem methods they were the same, except the latter one used unnecessary ItemStack copying also disabled checking IFluidContainerItem in GTUtility method because we are already checking it earlier --- .../utils/fluid/FluidInteractions.java | 31 +++---------------- .../value/sync/FluidSlotSyncHandler.java | 4 +-- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java index be92c70b5..babfd029b 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java +++ b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java @@ -13,10 +13,7 @@ public class FluidInteractions { - /** - * Gets fluid actually stored in item. Used for transferring fluid. - */ - public static FluidStack getFluidForRealItem(ItemStack itemStack) { + public static FluidStack getFluidForItem(ItemStack itemStack) { FluidStack fluidStack = null; if (itemStack.getItem() instanceof IFluidContainerItem container) { fluidStack = container.getFluid(itemStack); @@ -27,28 +24,8 @@ public static FluidStack getFluidForRealItem(ItemStack itemStack) { if (fluidStack == null && ModularUI.Mods.NEI.isLoaded()) { fluidStack = StackInfo.getFluid(itemStack); } - if (ModularUI.Mods.GT5U.isLoaded() && fluidStack == null) { - fluidStack = GTUtility.getFluidForFilledItem(itemStack, true); - } - return fluidStack; - } - - /** - * Gets fluid for use in phantom slot. - */ - public static FluidStack getFluidForPhantomItem(ItemStack itemStack) { - FluidStack fluidStack = null; - if (itemStack.getItem() instanceof IFluidContainerItem container) { - fluidStack = container.getFluid(itemStack.copy()); - } - if (fluidStack == null) { - fluidStack = FluidContainerRegistry.getFluidForFilledItem(itemStack.copy()); - } - if (fluidStack == null && ModularUI.Mods.NEI.isLoaded()) { - fluidStack = StackInfo.getFluid(itemStack.copy()); - } - if (ModularUI.Mods.GT5U.isLoaded() && fluidStack == null) { - fluidStack = GTUtility.getFluidForFilledItem(itemStack, true); + if (fluidStack == null && ModularUI.Mods.GT5U.isLoaded()) { + fluidStack = GTUtility.getFluidForFilledItem(itemStack, false); } return fluidStack; } @@ -61,7 +38,7 @@ public static ItemStack fillFluidContainer(FluidStack fluidStack, ItemStack item if (filledContainer == null) { filledContainer = FluidContainerRegistry.fillFluidContainer(fluidStack, itemStack); if (filledContainer == null) return itemStack; // give up and return original clicked stack - FluidStack newFluid = getFluidForRealItem(filledContainer); + FluidStack newFluid = getFluidForItem(filledContainer); fluidStack.amount -= newFluid.amount; } return filledContainer; diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index 09460e633..ed1dc993c 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -146,7 +146,7 @@ private void tryClickContainer(MouseData mouseData) { ItemStack heldItemSizedOne = heldItem.copy(); heldItemSizedOne.stackSize = 1; FluidStack currentFluid = fluidTank.getFluid(); - FluidStack heldFluid = FluidInteractions.getFluidForRealItem(heldItemSizedOne); + FluidStack heldFluid = FluidInteractions.getFluidForItem(heldItemSizedOne); if (heldFluid != null && heldFluid.amount <= 0) { heldFluid = null; } @@ -195,7 +195,7 @@ private void tryClickPhantom(MouseData mouseData, ItemStack cursorStack) { } else { ItemStack heldItemSizedOne = cursorStack.copy(); heldItemSizedOne.stackSize = 1; - FluidStack heldFluid = FluidInteractions.getFluidForPhantomItem(heldItemSizedOne); + FluidStack heldFluid = FluidInteractions.getFluidForItem(heldItemSizedOne); if ((controlsAmount || currentFluid == null) && heldFluid != null) { fillPhantom(heldFluid); } else { From d26a99957ed9dde54431df3ab4e811ea53db054f Mon Sep 17 00:00:00 2001 From: danyadev Date: Wed, 4 Feb 2026 21:15:01 +0300 Subject: [PATCH 03/11] refactor fillFluid added support for IFluidContainerItem like GT Large Cell or Certus Fluid Tank to partially fill the slot when they hold more than the slot can currently accept also considered a situation when you hold a stack of filled containers - if the slot can accept only 0.5 or 1.5 worth of the container amount, it will drain exactly that amount and give back half the container --- .../value/sync/FluidSlotSyncHandler.java | 110 ++++++++++++++---- 1 file changed, 85 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index ed1dc993c..4923e245b 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -10,6 +10,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidContainerItem; import net.minecraftforge.fluids.IFluidTank; import org.jetbrains.annotations.NotNull; @@ -271,6 +272,11 @@ protected void drainFluid(boolean processFullStack) { } protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack) { + FluidStack currentFluid = fluidTank.getFluid(); + if (currentFluid != null && !currentFluid.isFluidEqual(heldFluid)) { + return; + } + ItemStack heldItem = getSyncManager().getCursorItem(); if (heldItem == null || heldItem.stackSize == 0) { return; @@ -278,35 +284,80 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack ItemStack heldItemSizedOne = heldItem.copy(); heldItemSizedOne.stackSize = 1; - FluidStack currentFluid = fluidTank.getFluid(); - if (currentFluid != null && !currentFluid.isFluidEqual(heldFluid)) { - return; + + if (heldItem.getItem() instanceof IFluidContainerItem container) { + FluidStack containerFluid = container.getFluid(heldItemSizedOne); + int containerCapacity = container.getCapacity(heldItemSizedOne); + boolean soundPlayed = false; + + // 1. Try to empty some full containers completely + if (containerCapacity == containerFluid.amount) { + int initialHeldItemsCount = heldItem.stackSize; + int filled = fillFluidUsingFullContainers(heldItem, containerFluid, processFullStack); + + if (filled > 0) { + playSound(heldFluid, true); + soundPlayed = true; + } + + // Return if there are no full containers left + if (filled == initialHeldItemsCount * containerCapacity) { + return; + } + } + + // 2. Try to drain one container in a stack + int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); + int amountToDrain = Math.min(containerCapacity, freeSpace); + if (amountToDrain <= 0) { + return; + } + + ItemStack itemToDrain = heldItemSizedOne.copy(); + FluidStack drained = container.drain(itemToDrain, amountToDrain, true); + + if (drained != null && drained.amount > 0) { + fluidTank.fill(drained, true); + replaceCursorItemStack(itemToDrain); + + if (!soundPlayed) { + playSound(heldFluid, true); + } + } + } else { + int filled = this.fillFluidUsingFullContainers(heldItem, heldFluid, processFullStack); + if (filled > 0) { + playSound(heldFluid, true); + } } + } - int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); - if (freeSpace <= 0) { - return; + private int fillFluidUsingFullContainers(ItemStack heldItem, FluidStack fluid, boolean processFullStack) { + ItemStack heldItemSizedOne = heldItem.copy(); + heldItemSizedOne.stackSize = 1; + + ItemStack emptyContainer = FluidInteractions.getEmptyContainerForFilledItem(heldItemSizedOne); + if (emptyContainer == null) { + return 0; } - ItemStack itemStackEmptied = null; - int fluidAmountTaken = 0; - if (freeSpace >= heldFluid.amount) { - itemStackEmptied = FluidInteractions.getEmptyContainerForFilledItem(heldItemSizedOne); - fluidAmountTaken = heldFluid.amount; + int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); + int containersToEmpty = Math.min(freeSpace / fluid.amount, heldItem.stackSize); + + if (!processFullStack && containersToEmpty > 1) { + containersToEmpty = 1; } - if (itemStackEmptied == null) { - return; + if (containersToEmpty == 0) { + return 0; } - int parallel = processFullStack ? Math.min(freeSpace / fluidAmountTaken, heldItem.stackSize) : 1; - FluidStack copiedFluidStack = heldFluid.copy(); - copiedFluidStack.amount = fluidAmountTaken * parallel; - fluidTank.fill(copiedFluidStack, true); + emptyContainer.stackSize = containersToEmpty; + replaceCursorItemStack(emptyContainer); - itemStackEmptied.stackSize = parallel; - replaceCursorItemStack(itemStackEmptied); - playSound(heldFluid, true); + int amountToFill = fluid.amount * containersToEmpty; + fluidTank.fill(new FluidStack(fluid.getFluid(), amountToFill), true); + return amountToFill; } public void tryScrollPhantom(MouseData mouseData) { @@ -345,19 +396,28 @@ public void tryScrollPhantom(MouseData mouseData) { private void playSound(FluidStack fluid, boolean fill) { } + /** + * Replaces heldStack with resultStack. If player held more items in stack, remaining amount will be kept in its hand. + * Requires heldStack.stackSize >= resultStack.stackSize + */ protected void replaceCursorItemStack(ItemStack resultStack) { EntityPlayer player = getSyncManager().getPlayer(); + ItemStack heldStack = getSyncManager().getCursorItem(); int resultStackMaxStackSize = resultStack.getMaxStackSize(); + + assert heldStack.stackSize >= resultStack.stackSize; + while (resultStack.stackSize > resultStackMaxStackSize) { - player.inventory.getItemStack().stackSize -= resultStackMaxStackSize; + heldStack.stackSize -= resultStackMaxStackSize; addItemToPlayerInventory(player, resultStack.splitStack(resultStackMaxStackSize)); } - if (getSyncManager().getCursorItem().stackSize == resultStack.stackSize) { + + if (heldStack.stackSize == resultStack.stackSize) { getSyncManager().setCursorItem(resultStack); } else { - ItemStack heldItem = getSyncManager().getCursorItem(); - heldItem.stackSize -= resultStack.stackSize; - getSyncManager().setCursorItem(heldItem); + heldStack.stackSize -= resultStack.stackSize; + // it's the same held item stack, but we need to sync changed amount + getSyncManager().setCursorItem(heldStack); addItemToPlayerInventory(player, resultStack); } } From 01baaeb7036a7a3bc31f85610c22be8b151e016a Mon Sep 17 00:00:00 2001 From: danyadev Date: Wed, 4 Feb 2026 22:55:39 +0300 Subject: [PATCH 04/11] refactor fillFluidContainer - instead of returning an original itemStack when fillFluidContainer() returns null, return null respectively --- .../utils/fluid/FluidInteractions.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java index babfd029b..7ead7c9da 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java +++ b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java @@ -31,31 +31,32 @@ public static FluidStack getFluidForItem(ItemStack itemStack) { } public static ItemStack fillFluidContainer(FluidStack fluidStack, ItemStack itemStack) { - ItemStack filledContainer = fillFluidContainerWithoutIFluidContainerItem(fluidStack, itemStack); + ItemStack filledContainer = null; + + if (ModularUI.Mods.GT5U.isLoaded()) { + filledContainer = GTUtility.fillFluidContainer(fluidStack, itemStack, true, false); + } + if (filledContainer == null) { - filledContainer = fillFluidContainerWithIFluidContainerItem(fluidStack, itemStack); + filledContainer = fillIFluidContainerItem(fluidStack, itemStack); } + if (filledContainer == null) { filledContainer = FluidContainerRegistry.fillFluidContainer(fluidStack, itemStack); - if (filledContainer == null) return itemStack; // give up and return original clicked stack - FluidStack newFluid = getFluidForItem(filledContainer); - fluidStack.amount -= newFluid.amount; + if (filledContainer != null) { + FluidStack newFluid = getFluidForItem(filledContainer); + fluidStack.amount -= newFluid.amount; + } } - return filledContainer; - } - public static ItemStack fillFluidContainerWithoutIFluidContainerItem(FluidStack fluidStack, ItemStack itemStack) { - if (ModularUI.Mods.GT5U.isLoaded()) { - return GTUtility.fillFluidContainer(fluidStack, itemStack, true, false); - } - return null; + return filledContainer; } - public static ItemStack fillFluidContainerWithIFluidContainerItem(FluidStack fluidStack, ItemStack itemStack) { + public static ItemStack fillIFluidContainerItem(FluidStack fluidStack, ItemStack itemStack) { if (itemStack.getItem() instanceof IFluidContainerItem itemContainer) { - int tFilledAmount = itemContainer.fill(itemStack, fluidStack, true); - if (tFilledAmount > 0) { - fluidStack.amount -= tFilledAmount; + int filledAmount = itemContainer.fill(itemStack, fluidStack, true); + if (filledAmount > 0) { + fluidStack.amount -= filledAmount; return itemStack; } } From 74334e261ec2f767f02167a29334d7946455b882 Mon Sep 17 00:00:00 2001 From: danyadev Date: Thu, 5 Feb 2026 01:42:53 +0300 Subject: [PATCH 05/11] refactor drainFluid - same as the fillFluid refactoring - also allowed mass-filling or mass-draining when you have several partially-filled containers in one stack, not just completely filled --- .../utils/fluid/FluidInteractions.java | 38 +++-- .../value/sync/FluidSlotSyncHandler.java | 136 +++++++++++++----- 2 files changed, 121 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java index 7ead7c9da..0cda3f7a9 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java +++ b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java @@ -30,40 +30,38 @@ public static FluidStack getFluidForItem(ItemStack itemStack) { return fluidStack; } - public static ItemStack fillFluidContainer(FluidStack fluidStack, ItemStack itemStack) { + public static ItemStack getFilledFluidContainer(FluidStack fluidStack, ItemStack itemStack) { ItemStack filledContainer = null; if (ModularUI.Mods.GT5U.isLoaded()) { - filledContainer = GTUtility.fillFluidContainer(fluidStack, itemStack, true, false); + filledContainer = GTUtility.fillFluidContainer(fluidStack, itemStack, false, false); } - if (filledContainer == null) { - filledContainer = fillIFluidContainerItem(fluidStack, itemStack); + if (filledContainer == null && itemStack.getItem() instanceof IFluidContainerItem container) { + FluidStack containerFluid = container.getFluid(itemStack); + int containerFluidAmount = containerFluid != null ? containerFluid.amount : 0; + + if (containerFluid != null && containerFluid.getFluid() != fluidStack.getFluid()) { + return null; + } + + if (containerFluidAmount + fluidStack.amount >= container.getCapacity(itemStack)) { + ItemStack copyStack = itemStack.copy(); + container.fill(copyStack, fluidStack, true); + return copyStack; + } + + return null; } if (filledContainer == null) { filledContainer = FluidContainerRegistry.fillFluidContainer(fluidStack, itemStack); - if (filledContainer != null) { - FluidStack newFluid = getFluidForItem(filledContainer); - fluidStack.amount -= newFluid.amount; - } } return filledContainer; } - public static ItemStack fillIFluidContainerItem(FluidStack fluidStack, ItemStack itemStack) { - if (itemStack.getItem() instanceof IFluidContainerItem itemContainer) { - int filledAmount = itemContainer.fill(itemStack, fluidStack, true); - if (filledAmount > 0) { - fluidStack.amount -= filledAmount; - return itemStack; - } - } - return null; - } - - public static ItemStack getEmptyContainerForFilledItem(ItemStack itemStack) { + public static ItemStack getEmptyFluidContainer(ItemStack itemStack) { if (ModularUI.Mods.GT5U.isLoaded()) { ItemStack stack = GTUtility.getContainerForFilledItem(itemStack, false); if (stack != null) { diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index 4923e245b..34423703f 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -171,12 +171,12 @@ private void tryClickContainer(MouseData mouseData) { if (!canDrainSlot) { return; } - drainFluid(processFullStack); + drainFluid(heldFluid, processFullStack); } else { if (!canDrainSlot) { return; } - drainFluid(processFullStack); + drainFluid(heldFluid, processFullStack); } } @@ -239,7 +239,12 @@ private void fillPhantom(@NotNull FluidStack heldFluid) { } } - protected void drainFluid(boolean processFullStack) { + protected void drainFluid(@Nullable FluidStack heldFluid, boolean processFullStack) { + FluidStack initialFluid = fluidTank.getFluid(); + if (initialFluid == null) { + return; + } + ItemStack heldItem = getSyncManager().getCursorItem(); if (heldItem == null || heldItem.stackSize == 0) { return; @@ -247,30 +252,92 @@ protected void drainFluid(boolean processFullStack) { ItemStack heldItemSizedOne = heldItem.copy(); heldItemSizedOne.stackSize = 1; - FluidStack currentFluid = fluidTank.getFluid(); - if (currentFluid == null) { - return; - } - currentFluid = currentFluid.copy(); - int originalFluidAmount = fluidTank.getFluidAmount(); - ItemStack filledContainer = FluidInteractions.fillFluidContainer(currentFluid, heldItemSizedOne); - if (filledContainer != null) { - int filledAmount = originalFluidAmount - currentFluid.amount; - if (filledAmount < 1) { + if (heldItem.getItem() instanceof IFluidContainerItem container) { + int containerCapacity = container.getCapacity(heldItemSizedOne); + int containerAmount = heldFluid != null ? heldFluid.amount : 0; + boolean soundPlayed = false; + + if (containerCapacity == containerAmount) { return; } - fluidTank.drain(filledAmount, true); - if (processFullStack) { - int additionalParallel = Math.min(heldItem.stackSize - 1, currentFluid.amount / filledAmount); - fluidTank.drain(filledAmount * additionalParallel, true); - filledContainer.stackSize += additionalParallel; + + // 1. Try to fill some containers completely + if (heldItem.stackSize > 1) { + int initialHeldItemsCount = heldItem.stackSize; + int drained = drainFluidByFillingContainers(heldItem, heldFluid, processFullStack); + + if (drained > 0) { + playSound(initialFluid, true); + soundPlayed = true; + } + + // Return if we already filled one container and we don't want to fill others + if (drained > 0 && !processFullStack) { + return; + } + + // Return if all the containers are filled + if (drained == initialHeldItemsCount * (containerCapacity - containerAmount)) { + return; + } + } + + // 2. Try to fill one container in a stack + int amountToFill = Math.min(containerCapacity - containerAmount, fluidTank.getFluidAmount()); + if (amountToFill <= 0) { + return; + } + + ItemStack itemToFill = heldItemSizedOne.copy(); + int filled = container.fill(itemToFill, new FluidStack(initialFluid, amountToFill), true); + + if (filled > 0) { + fluidTank.drain(filled, true); + replaceCursorItemStack(itemToFill); + + if (!soundPlayed) { + playSound(initialFluid, true); + } + } + } else { + int filled = this.drainFluidByFillingContainers(heldItem, heldFluid, processFullStack); + if (filled > 0) { + playSound(initialFluid, true); } - replaceCursorItemStack(filledContainer); - playSound(currentFluid, false); } } + private int drainFluidByFillingContainers(ItemStack heldItem, @Nullable FluidStack heldFluid, boolean processFullStack) { + ItemStack heldItemSizedOne = heldItem.copy(); + heldItemSizedOne.stackSize = 1; + + FluidStack tankFluid = fluidTank.getFluid(); + ItemStack fullContainer = FluidInteractions.getFilledFluidContainer(tankFluid, heldItemSizedOne); + if (fullContainer == null) { + return 0; + } + + FluidStack fullContainerFluid = FluidInteractions.getFluidForItem(fullContainer); + int amountToFill = fullContainerFluid.amount - (heldFluid != null ? heldFluid.amount : 0); + int containersToFill = Math.min(tankFluid.amount / amountToFill, heldItem.stackSize); + + if (!processFullStack && containersToFill > 1) { + containersToFill = 1; + } + + if (containersToFill == 0) { + return 0; + } + + fullContainer.stackSize = containersToFill; + replaceCursorItemStack(fullContainer); + + int amountToDrain = containersToFill * amountToFill; + fluidTank.drain(amountToDrain, true); + return amountToDrain; + } + protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack) { FluidStack currentFluid = fluidTank.getFluid(); if (currentFluid != null && !currentFluid.isFluidEqual(heldFluid)) { @@ -286,29 +353,32 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack heldItemSizedOne.stackSize = 1; if (heldItem.getItem() instanceof IFluidContainerItem container) { - FluidStack containerFluid = container.getFluid(heldItemSizedOne); - int containerCapacity = container.getCapacity(heldItemSizedOne); boolean soundPlayed = false; - // 1. Try to empty some full containers completely - if (containerCapacity == containerFluid.amount) { + // 1. Try to empty some filled containers completely + if (heldItem.stackSize > 1) { int initialHeldItemsCount = heldItem.stackSize; - int filled = fillFluidUsingFullContainers(heldItem, containerFluid, processFullStack); + int filled = fillFluidUsingFullContainers(heldItem, heldFluid, processFullStack); if (filled > 0) { playSound(heldFluid, true); soundPlayed = true; } - // Return if there are no full containers left - if (filled == initialHeldItemsCount * containerCapacity) { + // Return if we already drained one container and we don't want to drain others + if (filled > 0 && !processFullStack) { + return; + } + + // Return if there are no filled containers left + if (filled == initialHeldItemsCount * heldFluid.amount) { return; } } // 2. Try to drain one container in a stack int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); - int amountToDrain = Math.min(containerCapacity, freeSpace); + int amountToDrain = Math.min(heldFluid.amount, freeSpace); if (amountToDrain <= 0) { return; } @@ -332,17 +402,17 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack } } - private int fillFluidUsingFullContainers(ItemStack heldItem, FluidStack fluid, boolean processFullStack) { + private int fillFluidUsingFullContainers(ItemStack heldItem, FluidStack heldFluid, boolean processFullStack) { ItemStack heldItemSizedOne = heldItem.copy(); heldItemSizedOne.stackSize = 1; - ItemStack emptyContainer = FluidInteractions.getEmptyContainerForFilledItem(heldItemSizedOne); + ItemStack emptyContainer = FluidInteractions.getEmptyFluidContainer(heldItemSizedOne); if (emptyContainer == null) { return 0; } int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); - int containersToEmpty = Math.min(freeSpace / fluid.amount, heldItem.stackSize); + int containersToEmpty = Math.min(freeSpace / heldFluid.amount, heldItem.stackSize); if (!processFullStack && containersToEmpty > 1) { containersToEmpty = 1; @@ -355,8 +425,8 @@ private int fillFluidUsingFullContainers(ItemStack heldItem, FluidStack fluid, b emptyContainer.stackSize = containersToEmpty; replaceCursorItemStack(emptyContainer); - int amountToFill = fluid.amount * containersToEmpty; - fluidTank.fill(new FluidStack(fluid.getFluid(), amountToFill), true); + int amountToFill = heldFluid.amount * containersToEmpty; + fluidTank.fill(new FluidStack(heldFluid.getFluid(), amountToFill), true); return amountToFill; } From 8508f86048a222eb0623f138dc5a6906465858c5 Mon Sep 17 00:00:00 2001 From: danyadev Date: Thu, 5 Feb 2026 13:30:15 +0300 Subject: [PATCH 06/11] better method names & fix NPEs --- .../utils/fluid/FluidInteractions.java | 19 ++++--- .../value/sync/FluidSlotSyncHandler.java | 57 +++++++++++-------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java index 0cda3f7a9..70886996b 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java +++ b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java @@ -30,24 +30,25 @@ public static FluidStack getFluidForItem(ItemStack itemStack) { return fluidStack; } - public static ItemStack getFilledFluidContainer(FluidStack fluidStack, ItemStack itemStack) { + public static ItemStack getFullFluidContainer(ItemStack itemStack, FluidStack fluidToFill) { ItemStack filledContainer = null; if (ModularUI.Mods.GT5U.isLoaded()) { - filledContainer = GTUtility.fillFluidContainer(fluidStack, itemStack, false, false); + filledContainer = GTUtility.fillFluidContainer(fluidToFill, itemStack, false, false); } if (filledContainer == null && itemStack.getItem() instanceof IFluidContainerItem container) { FluidStack containerFluid = container.getFluid(itemStack); int containerFluidAmount = containerFluid != null ? containerFluid.amount : 0; - if (containerFluid != null && containerFluid.getFluid() != fluidStack.getFluid()) { + if (containerFluid != null && containerFluid.getFluid() != fluidToFill.getFluid()) { return null; } - if (containerFluidAmount + fluidStack.amount >= container.getCapacity(itemStack)) { - ItemStack copyStack = itemStack.copy(); - container.fill(copyStack, fluidStack, true); + ItemStack copyStack = itemStack.copy(); + int filled = container.fill(copyStack, fluidToFill, true); + + if (containerFluidAmount + filled == container.getCapacity(copyStack)) { return copyStack; } @@ -55,7 +56,7 @@ public static ItemStack getFilledFluidContainer(FluidStack fluidStack, ItemStack } if (filledContainer == null) { - filledContainer = FluidContainerRegistry.fillFluidContainer(fluidStack, itemStack); + filledContainer = FluidContainerRegistry.fillFluidContainer(fluidToFill, itemStack); } return filledContainer; @@ -71,10 +72,10 @@ public static ItemStack getEmptyFluidContainer(ItemStack itemStack) { if (itemStack.getItem() instanceof IFluidContainerItem container) { ItemStack stack = itemStack.copy(); - int amount = container.getFluid(itemStack).amount; + FluidStack fluidStack = container.getFluid(itemStack); FluidStack drained = container.drain(stack, Integer.MAX_VALUE, true); - if (drained == null || drained.amount < amount) { + if (drained == null || fluidStack == null || drained.amount < fluidStack.amount) { return null; } return stack; diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index 34423703f..8023f6315 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -258,17 +258,12 @@ protected void drainFluid(@Nullable FluidStack heldFluid, boolean processFullSta int containerAmount = heldFluid != null ? heldFluid.amount : 0; boolean soundPlayed = false; - if (containerCapacity == containerAmount) { - return; - } - // 1. Try to fill some containers completely if (heldItem.stackSize > 1) { - int initialHeldItemsCount = heldItem.stackSize; - int drained = drainFluidByFillingContainers(heldItem, heldFluid, processFullStack); + int drained = batchDrainFluidToContainers(heldItem, heldFluid, processFullStack); if (drained > 0) { - playSound(initialFluid, true); + playSound(initialFluid, false); soundPlayed = true; } @@ -277,8 +272,9 @@ protected void drainFluid(@Nullable FluidStack heldFluid, boolean processFullSta return; } - // Return if all the containers are filled - if (drained == initialHeldItemsCount * (containerCapacity - containerAmount)) { + // Return if all the containers are filled. + // Note: stackSize = 0 means that the stack got replaced as per replaceCursorItemStack implementation + if (heldItem.stackSize == 0) { return; } } @@ -297,29 +293,37 @@ protected void drainFluid(@Nullable FluidStack heldFluid, boolean processFullSta replaceCursorItemStack(itemToFill); if (!soundPlayed) { - playSound(initialFluid, true); + playSound(initialFluid, false); } } } else { - int filled = this.drainFluidByFillingContainers(heldItem, heldFluid, processFullStack); + int filled = this.batchDrainFluidToContainers(heldItem, heldFluid, processFullStack); if (filled > 0) { - playSound(initialFluid, true); + playSound(initialFluid, false); } } } - private int drainFluidByFillingContainers(ItemStack heldItem, @Nullable FluidStack heldFluid, boolean processFullStack) { + private int batchDrainFluidToContainers(ItemStack heldItem, @Nullable FluidStack heldFluid, boolean processFullStack) { ItemStack heldItemSizedOne = heldItem.copy(); heldItemSizedOne.stackSize = 1; FluidStack tankFluid = fluidTank.getFluid(); - ItemStack fullContainer = FluidInteractions.getFilledFluidContainer(tankFluid, heldItemSizedOne); + ItemStack fullContainer = FluidInteractions.getFullFluidContainer(heldItemSizedOne, tankFluid); if (fullContainer == null) { return 0; } FluidStack fullContainerFluid = FluidInteractions.getFluidForItem(fullContainer); + if (fullContainerFluid == null) { + return 0; + } + int amountToFill = fullContainerFluid.amount - (heldFluid != null ? heldFluid.amount : 0); + if (amountToFill <= 0) { + return 0; + } + int containersToFill = Math.min(tankFluid.amount / amountToFill, heldItem.stackSize); if (!processFullStack && containersToFill > 1) { @@ -357,8 +361,7 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack // 1. Try to empty some filled containers completely if (heldItem.stackSize > 1) { - int initialHeldItemsCount = heldItem.stackSize; - int filled = fillFluidUsingFullContainers(heldItem, heldFluid, processFullStack); + int filled = batchFillFluidFromContainers(heldItem, heldFluid, processFullStack); if (filled > 0) { playSound(heldFluid, true); @@ -370,8 +373,9 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack return; } - // Return if there are no filled containers left - if (filled == initialHeldItemsCount * heldFluid.amount) { + // Return if there are no filled containers left. + // Note: stackSize = 0 means that the stack got replaced as per replaceCursorItemStack implementation + if (heldItem.stackSize == 0) { return; } } @@ -395,14 +399,14 @@ protected void fillFluid(@NotNull FluidStack heldFluid, boolean processFullStack } } } else { - int filled = this.fillFluidUsingFullContainers(heldItem, heldFluid, processFullStack); + int filled = this.batchFillFluidFromContainers(heldItem, heldFluid, processFullStack); if (filled > 0) { playSound(heldFluid, true); } } } - private int fillFluidUsingFullContainers(ItemStack heldItem, FluidStack heldFluid, boolean processFullStack) { + private int batchFillFluidFromContainers(ItemStack heldItem, FluidStack heldFluid, boolean processFullStack) { ItemStack heldItemSizedOne = heldItem.copy(); heldItemSizedOne.stackSize = 1; @@ -467,7 +471,9 @@ private void playSound(FluidStack fluid, boolean fill) { } /** - * Replaces heldStack with resultStack. If player held more items in stack, remaining amount will be kept in its hand. + * Replaces heldStack with resultStack. + * If player held more items in stack, remaining amount will be kept in its hand. + * Guarantees mutating original heldStack stackSize even if it has to be 0. * Requires heldStack.stackSize >= resultStack.stackSize */ protected void replaceCursorItemStack(ItemStack resultStack) { @@ -482,13 +488,14 @@ protected void replaceCursorItemStack(ItemStack resultStack) { addItemToPlayerInventory(player, resultStack.splitStack(resultStackMaxStackSize)); } - if (heldStack.stackSize == resultStack.stackSize) { + heldStack.stackSize -= resultStack.stackSize; + + if (heldStack.stackSize == 0) { getSyncManager().setCursorItem(resultStack); } else { - heldStack.stackSize -= resultStack.stackSize; - // it's the same held item stack, but we need to sync changed amount - getSyncManager().setCursorItem(heldStack); addItemToPlayerInventory(player, resultStack); + // it's the same held item stack, but we need to sync changed stack size + getSyncManager().setCursorItem(heldStack); } } From 0484cec1ef871082fd55c3e4e6e621c4c5067080 Mon Sep 17 00:00:00 2001 From: danyadev Date: Mon, 9 Feb 2026 18:46:31 +0300 Subject: [PATCH 07/11] don't rely on GTUtilities fluid methods as I figured out in my latest GT refactoring, they don't have any special fluid handling so we don't lose any profit by using our own implementation only --- .../utils/fluid/FluidInteractions.java | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java index 70886996b..92ac465f2 100644 --- a/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java +++ b/src/main/java/com/cleanroommc/modularui/utils/fluid/FluidInteractions.java @@ -9,7 +9,6 @@ import net.minecraftforge.fluids.IFluidTank; import codechicken.nei.recipe.StackInfo; -import gregtech.api.util.GTUtility; public class FluidInteractions { @@ -24,27 +23,14 @@ public static FluidStack getFluidForItem(ItemStack itemStack) { if (fluidStack == null && ModularUI.Mods.NEI.isLoaded()) { fluidStack = StackInfo.getFluid(itemStack); } - if (fluidStack == null && ModularUI.Mods.GT5U.isLoaded()) { - fluidStack = GTUtility.getFluidForFilledItem(itemStack, false); - } return fluidStack; } public static ItemStack getFullFluidContainer(ItemStack itemStack, FluidStack fluidToFill) { - ItemStack filledContainer = null; - - if (ModularUI.Mods.GT5U.isLoaded()) { - filledContainer = GTUtility.fillFluidContainer(fluidToFill, itemStack, false, false); - } - - if (filledContainer == null && itemStack.getItem() instanceof IFluidContainerItem container) { + if (itemStack.getItem() instanceof IFluidContainerItem container) { FluidStack containerFluid = container.getFluid(itemStack); int containerFluidAmount = containerFluid != null ? containerFluid.amount : 0; - if (containerFluid != null && containerFluid.getFluid() != fluidToFill.getFluid()) { - return null; - } - ItemStack copyStack = itemStack.copy(); int filled = container.fill(copyStack, fluidToFill, true); @@ -55,27 +41,20 @@ public static ItemStack getFullFluidContainer(ItemStack itemStack, FluidStack fl return null; } - if (filledContainer == null) { - filledContainer = FluidContainerRegistry.fillFluidContainer(fluidToFill, itemStack); - } - - return filledContainer; + return FluidContainerRegistry.fillFluidContainer(fluidToFill, itemStack); } public static ItemStack getEmptyFluidContainer(ItemStack itemStack) { - if (ModularUI.Mods.GT5U.isLoaded()) { - ItemStack stack = GTUtility.getContainerForFilledItem(itemStack, false); - if (stack != null) { - return stack; + if (itemStack.getItem() instanceof IFluidContainerItem container) { + FluidStack fluidStack = container.getFluid(itemStack); + if (fluidStack == null) { + return null; } - } - if (itemStack.getItem() instanceof IFluidContainerItem container) { ItemStack stack = itemStack.copy(); - FluidStack fluidStack = container.getFluid(itemStack); FluidStack drained = container.drain(stack, Integer.MAX_VALUE, true); - if (drained == null || fluidStack == null || drained.amount < fluidStack.amount) { + if (drained == null || drained.amount < fluidStack.amount) { return null; } return stack; From af036de77b8d0f9ad05c7acaee9a9a02a52ec614 Mon Sep 17 00:00:00 2001 From: chrombread Date: Fri, 13 Feb 2026 13:36:18 -0800 Subject: [PATCH 08/11] comment out the gt5u dependency as its not needed for most testing --- dependencies.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index e20744f3b..1a6eca714 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -39,9 +39,9 @@ dependencies { implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.48-GTNH:dev") compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.39:dev") { transitive = false } - devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { - exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' - } + //devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { + // exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' + //} compileOnly("com.github.GTNewHorizons:ModularUI:1.3.1:dev") { transitive = false } implementation("com.github.GTNewHorizons:Baubles-Expanded:2.2.6-GTNH:dev") { transitive = false } compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev") From dee92f7a9e76651fcab8add73f08cd9f50f6e188 Mon Sep 17 00:00:00 2001 From: chrombread Date: Fri, 13 Feb 2026 13:36:37 -0800 Subject: [PATCH 09/11] a space oops --- dependencies.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 1a6eca714..1adcc85ed 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -39,9 +39,9 @@ dependencies { implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.48-GTNH:dev") compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.39:dev") { transitive = false } - //devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { - // exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' - //} + // devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { + // exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' + // } compileOnly("com.github.GTNewHorizons:ModularUI:1.3.1:dev") { transitive = false } implementation("com.github.GTNewHorizons:Baubles-Expanded:2.2.6-GTNH:dev") { transitive = false } compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev") From fcc081fa9d39f526e97f482ce2d0d90478d73fce Mon Sep 17 00:00:00 2001 From: chrombread Date: Fri, 13 Feb 2026 13:41:33 -0800 Subject: [PATCH 10/11] nevermind im a fool --- dependencies.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 1adcc85ed..e20744f3b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -39,9 +39,9 @@ dependencies { implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.48-GTNH:dev") compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.39:dev") { transitive = false } - // devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { - // exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' - // } + devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.253:dev") { + exclude group: 'com.github.GTNewHorizons', module: 'ModularUI2' + } compileOnly("com.github.GTNewHorizons:ModularUI:1.3.1:dev") { transitive = false } implementation("com.github.GTNewHorizons:Baubles-Expanded:2.2.6-GTNH:dev") { transitive = false } compileOnly("thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev") From 07e4f409c12b5ecedc56848bdb9c59e3e930f501 Mon Sep 17 00:00:00 2001 From: danyadev Date: Sat, 14 Feb 2026 00:58:36 +0300 Subject: [PATCH 11/11] stop using assert --- .../modularui/value/sync/FluidSlotSyncHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java index 8023f6315..2bc6c2e9f 100644 --- a/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java +++ b/src/main/java/com/cleanroommc/modularui/value/sync/FluidSlotSyncHandler.java @@ -474,15 +474,13 @@ private void playSound(FluidStack fluid, boolean fill) { * Replaces heldStack with resultStack. * If player held more items in stack, remaining amount will be kept in its hand. * Guarantees mutating original heldStack stackSize even if it has to be 0. - * Requires heldStack.stackSize >= resultStack.stackSize + * Expects heldStack.stackSize >= resultStack.stackSize */ protected void replaceCursorItemStack(ItemStack resultStack) { EntityPlayer player = getSyncManager().getPlayer(); ItemStack heldStack = getSyncManager().getCursorItem(); int resultStackMaxStackSize = resultStack.getMaxStackSize(); - assert heldStack.stackSize >= resultStack.stackSize; - while (resultStack.stackSize > resultStackMaxStackSize) { heldStack.stackSize -= resultStackMaxStackSize; addItemToPlayerInventory(player, resultStack.splitStack(resultStackMaxStackSize)); @@ -490,7 +488,8 @@ protected void replaceCursorItemStack(ItemStack resultStack) { heldStack.stackSize -= resultStack.stackSize; - if (heldStack.stackSize == 0) { + if (heldStack.stackSize <= 0) { + heldStack.stackSize = 0; getSyncManager().setCursorItem(resultStack); } else { addItemToPlayerInventory(player, resultStack);