diff --git a/dependencies.gradle b/dependencies.gradle index e8c93979a..a470e2713 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -39,14 +39,18 @@ dependencies { implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.68-GTNH:dev") compileOnly("com.github.GTNewHorizons:Hodgepodge:2.7.60:dev") { transitive = false } - compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.283:dev") { transitive = false } + + devOnlyNonPublishable("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.283: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") //compileOnly rfg.deobf("curse.maven:neverenoughanimation-1062347:6552319") 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.68-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..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,14 +9,10 @@ import net.minecraftforge.fluids.IFluidTank; import codechicken.nei.recipe.StackInfo; -import gregtech.api.util.GTUtility; 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,82 +23,44 @@ 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; + public static ItemStack getFullFluidContainer(ItemStack itemStack, FluidStack fluidToFill) { 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); - } - return fluidStack; - } + FluidStack containerFluid = container.getFluid(itemStack); + int containerFluidAmount = containerFluid != null ? containerFluid.amount : 0; - public static ItemStack fillFluidContainer(FluidStack fluidStack, ItemStack itemStack) { - ItemStack filledContainer = fillFluidContainerWithoutIFluidContainerItem(fluidStack, itemStack); - if (filledContainer == null) { - filledContainer = fillFluidContainerWithIFluidContainerItem(fluidStack, itemStack); - } - 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.amount -= newFluid.amount; - } - return filledContainer; - } + ItemStack copyStack = itemStack.copy(); + int filled = container.fill(copyStack, fluidToFill, true); - public static ItemStack fillFluidContainerWithoutIFluidContainerItem(FluidStack fluidStack, ItemStack itemStack) { - if (ModularUI.Mods.GT5U.isLoaded()) { - return GTUtility.fillFluidContainer(fluidStack, itemStack, true, false); + if (containerFluidAmount + filled == container.getCapacity(copyStack)) { + return copyStack; + } + + return null; } - return null; + + return FluidContainerRegistry.fillFluidContainer(fluidToFill, itemStack); } - public static ItemStack fillFluidContainerWithIFluidContainerItem(FluidStack fluidStack, ItemStack itemStack) { - if (itemStack.getItem() instanceof IFluidContainerItem itemContainer) { - int tFilledAmount = itemContainer.fill(itemStack, fluidStack, true); - if (tFilledAmount > 0) { - fluidStack.amount -= tFilledAmount; - return itemStack; + public static ItemStack getEmptyFluidContainer(ItemStack itemStack) { + if (itemStack.getItem() instanceof IFluidContainerItem container) { + FluidStack fluidStack = container.getFluid(itemStack); + if (fluidStack == null) { + return null; } - } - 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) + ItemStack stack = itemStack.copy(); + FluidStack drained = container.drain(stack, Integer.MAX_VALUE, true); + + if (drained == null || drained.amount < fluidStack.amount) { return null; + } + return stack; } - if (stack == null) { - stack = FluidContainerRegistry.drainFluidContainer(itemStack.copy()); - } - return stack; - } - public static ItemStack getContainerForFilledItemWithoutIFluidContainerItem(ItemStack itemStack) { - if (ModularUI.Mods.GT5U.isLoaded()) { - return GTUtility.getContainerForFilledItem(itemStack, false); - } - 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..2bc6c2e9f 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; @@ -146,7 +147,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; } @@ -170,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); } } @@ -195,7 +196,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 { @@ -238,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; @@ -246,31 +252,102 @@ 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; + + // 1. Try to fill some containers completely + if (heldItem.stackSize > 1) { + int drained = batchDrainFluidToContainers(heldItem, heldFluid, processFullStack); + + if (drained > 0) { + playSound(initialFluid, false); + 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. + // Note: stackSize = 0 means that the stack got replaced as per replaceCursorItemStack implementation + if (heldItem.stackSize == 0) { + return; + } + } + + // 2. Try to fill one container in a stack + int amountToFill = Math.min(containerCapacity - containerAmount, fluidTank.getFluidAmount()); + if (amountToFill <= 0) { 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; + + 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, false); + } + } + } else { + int filled = this.batchDrainFluidToContainers(heldItem, heldFluid, processFullStack); + if (filled > 0) { + playSound(initialFluid, false); } - replaceCursorItemStack(filledContainer); - playSound(currentFluid, false); } } + private int batchDrainFluidToContainers(ItemStack heldItem, @Nullable FluidStack heldFluid, boolean processFullStack) { + ItemStack heldItemSizedOne = heldItem.copy(); + heldItemSizedOne.stackSize = 1; + + FluidStack tankFluid = fluidTank.getFluid(); + 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) { + 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)) { + return; + } + ItemStack heldItem = getSyncManager().getCursorItem(); if (heldItem == null || heldItem.stackSize == 0) { return; @@ -278,35 +355,83 @@ 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) { + boolean soundPlayed = false; + + // 1. Try to empty some filled containers completely + if (heldItem.stackSize > 1) { + int filled = batchFillFluidFromContainers(heldItem, heldFluid, processFullStack); + + if (filled > 0) { + playSound(heldFluid, true); + soundPlayed = true; + } + + // 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. + // Note: stackSize = 0 means that the stack got replaced as per replaceCursorItemStack implementation + if (heldItem.stackSize == 0) { + return; + } + } + + // 2. Try to drain one container in a stack + int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); + int amountToDrain = Math.min(heldFluid.amount, 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.batchFillFluidFromContainers(heldItem, heldFluid, processFullStack); + if (filled > 0) { + playSound(heldFluid, true); + } } + } - int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); - if (freeSpace <= 0) { - return; + private int batchFillFluidFromContainers(ItemStack heldItem, FluidStack heldFluid, boolean processFullStack) { + ItemStack heldItemSizedOne = heldItem.copy(); + heldItemSizedOne.stackSize = 1; + + ItemStack emptyContainer = FluidInteractions.getEmptyFluidContainer(heldItemSizedOne); + if (emptyContainer == null) { + return 0; } - ItemStack itemStackEmptied = null; - int fluidAmountTaken = 0; - if (freeSpace >= heldFluid.amount) { - itemStackEmptied = FluidInteractions.getContainerForFilledItem(heldItemSizedOne); - fluidAmountTaken = heldFluid.amount; + int freeSpace = fluidTank.getCapacity() - fluidTank.getFluidAmount(); + int containersToEmpty = Math.min(freeSpace / heldFluid.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 = heldFluid.amount * containersToEmpty; + fluidTank.fill(new FluidStack(heldFluid.getFluid(), amountToFill), true); + return amountToFill; } public void tryScrollPhantom(MouseData mouseData) { @@ -345,20 +470,31 @@ 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. + * Guarantees mutating original heldStack stackSize even if it has to be 0. + * Expects heldStack.stackSize >= resultStack.stackSize + */ protected void replaceCursorItemStack(ItemStack resultStack) { EntityPlayer player = getSyncManager().getPlayer(); + ItemStack heldStack = getSyncManager().getCursorItem(); int resultStackMaxStackSize = resultStack.getMaxStackSize(); + while (resultStack.stackSize > resultStackMaxStackSize) { - player.inventory.getItemStack().stackSize -= resultStackMaxStackSize; + heldStack.stackSize -= resultStackMaxStackSize; addItemToPlayerInventory(player, resultStack.splitStack(resultStackMaxStackSize)); } - if (getSyncManager().getCursorItem().stackSize == resultStack.stackSize) { + + heldStack.stackSize -= resultStack.stackSize; + + if (heldStack.stackSize <= 0) { + heldStack.stackSize = 0; getSyncManager().setCursorItem(resultStack); } else { - ItemStack heldItem = getSyncManager().getCursorItem(); - heldItem.stackSize -= resultStack.stackSize; - getSyncManager().setCursorItem(heldItem); addItemToPlayerInventory(player, resultStack); + // it's the same held item stack, but we need to sync changed stack size + getSyncManager().setCursorItem(heldStack); } }