From cf82a405a0fbc1c210699b222eb5677871609aea Mon Sep 17 00:00:00 2001 From: rlnt Date: Tue, 23 Apr 2024 09:17:07 +0200 Subject: [PATCH 1/5] add fill all and empty all actions --- .../client/gui/me/common/MEStorageScreen.java | 19 ++- .../java/appeng/helpers/InventoryAction.java | 2 +- src/main/java/appeng/menu/AEBaseMenu.java | 127 +++++++++++------- .../appeng/menu/me/common/MEStorageMenu.java | 15 ++- 4 files changed, 103 insertions(+), 60 deletions(-) diff --git a/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java b/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java index 974d4f400c0..85b979249a8 100644 --- a/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java +++ b/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java @@ -228,13 +228,22 @@ protected void handleGridInventoryEntryMouseClick(@Nullable GridInventoryEntry e AELog.debug("Clicked on grid inventory entry serial=%s, key=%s", entry.getSerial(), entry.getWhat()); } - // Is there an emptying action? If so, send it to the server - if (mouseButton == 1 && clickType == ClickType.PICKUP && !menu.getCarried().isEmpty()) { - var emptyingAction = ContainerItemStrategies.getEmptyingAction(menu.getCarried()); - if (emptyingAction != null && menu.isKeyVisible(emptyingAction.what())) { - menu.handleInteraction(-1, InventoryAction.EMPTY_ITEM); + // Check for emptying and filling actions and send them to the server + if (!menu.getCarried().isEmpty()) { + if (mouseButton == 0 && entry != null && ContainerItemStrategies.isKeySupported(entry.getWhat())) { + menu.handleInteraction(entry.getSerial(), + clickType == ClickType.QUICK_MOVE ? InventoryAction.FILL_ALL_ITEM : InventoryAction.FILL_ITEM); return; } + + if (mouseButton == 1) { + var emptyingAction = ContainerItemStrategies.getEmptyingAction(menu.getCarried()); + if (emptyingAction != null && menu.isKeyVisible(emptyingAction.what())) { + menu.handleInteraction(-1, clickType == ClickType.QUICK_MOVE ? InventoryAction.EMPTY_ALL_ITEM + : InventoryAction.EMPTY_ITEM); + return; + } + } } if (entry == null) { diff --git a/src/main/java/appeng/helpers/InventoryAction.java b/src/main/java/appeng/helpers/InventoryAction.java index 1ca929dcdb7..cb8817bfcd0 100644 --- a/src/main/java/appeng/helpers/InventoryAction.java +++ b/src/main/java/appeng/helpers/InventoryAction.java @@ -26,7 +26,7 @@ public enum InventoryAction { CRAFT_STACK, CRAFT_ITEM, CRAFT_SHIFT, // fluid term - FILL_ITEM, EMPTY_ITEM, + FILL_ITEM, FILL_ALL_ITEM, EMPTY_ITEM, EMPTY_ALL_ITEM, // extra... MOVE_REGION, PICKUP_SINGLE, ROLL_UP, ROLL_DOWN, AUTO_CRAFT, PLACE_SINGLE, diff --git a/src/main/java/appeng/menu/AEBaseMenu.java b/src/main/java/appeng/menu/AEBaseMenu.java index 1d2852490cb..57edd950c8d 100644 --- a/src/main/java/appeng/menu/AEBaseMenu.java +++ b/src/main/java/appeng/menu/AEBaseMenu.java @@ -46,6 +46,7 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; +import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.network.PacketDistributor; import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; @@ -559,13 +560,14 @@ public void doAction(ServerPlayer player, InventoryAction action, int slot, long var realInv = configInv.getDelegate(); var realInvSlot = appEngSlot.slot; - if (action == InventoryAction.FILL_ITEM) { + if (action == InventoryAction.FILL_ITEM || action == InventoryAction.FILL_ALL_ITEM) { var what = realInv.getKey(realInvSlot); handleFillingHeldItem( (amount, mode) -> realInv.extract(realInvSlot, what, amount, mode), - what); - } else if (action == InventoryAction.EMPTY_ITEM) { - handleEmptyHeldItem((what, amount, mode) -> realInv.insert(realInvSlot, what, amount, mode)); + what, action == InventoryAction.FILL_ALL_ITEM); + } else if (action == InventoryAction.EMPTY_ITEM || action == InventoryAction.EMPTY_ALL_ITEM) { + handleEmptyHeldItem((what, amount, mode) -> realInv.insert(realInvSlot, what, amount, mode), + action == InventoryAction.EMPTY_ALL_ITEM); } } @@ -588,46 +590,57 @@ protected interface FillingSource { long extract(long amount, Actionable mode); } - protected final void handleFillingHeldItem(FillingSource source, AEKey what) { + protected final void handleFillingHeldItem(FillingSource source, AEKey what, boolean fillAll) { var ctx = ContainerItemStrategies.findCarriedContextForKey(what, getPlayer(), this); if (ctx == null) { return; } - // Check if we can pull out of the system - var canPull = source.extract(Long.MAX_VALUE, Actionable.SIMULATE); - if (canPull <= 0) { - return; - } + int maxIterations = 10_000; + long amount = fillAll ? Long.MAX_VALUE : FluidType.BUCKET_VOLUME; + boolean filled = false; - // Check how much we can store in the item - long amountAllowed = ctx.insert(what, canPull, Actionable.SIMULATE); - if (amountAllowed == 0) { - return; // Nothing. - } + do { + // Check if we can pull out of the system + var canPull = source.extract(amount, Actionable.SIMULATE); + if (canPull <= 0) { + break; + } - // Now actually pull out of the system - var extracted = source.extract(amountAllowed, Actionable.MODULATE); - if (extracted <= 0) { - // Something went wrong - AELog.error("Unable to pull fluid out of the ME system even though the simulation said yes "); - return; - } + // Check how much we can store in the item + long amountAllowed = ctx.insert(what, canPull, Actionable.SIMULATE); + if (amountAllowed == 0) { + break; // Nothing. + } - // How much could fit into the carried container - long inserted = ctx.insert(what, extracted, Actionable.MODULATE); - if (inserted == 0) { - return; - } + // Now actually pull out of the system + var extracted = source.extract(amountAllowed, Actionable.MODULATE); + if (extracted <= 0) { + // Something went wrong + AELog.error("Unable to pull fluid out of the ME system even though the simulation said yes "); + break; + } + + // Actually store possible amount in the held item + long inserted = ctx.insert(what, extracted, Actionable.MODULATE); + if (inserted == 0) { + break; + } - ctx.playFillSound(getPlayer(), what); + filled = true; + maxIterations--; + } while (fillAll && maxIterations > 0); + + if (filled) { + ctx.playFillSound(getPlayer(), what); + } } protected interface EmptyingSink { long insert(AEKey what, long amount, Actionable mode); } - protected final void handleEmptyHeldItem(EmptyingSink sink) { + protected final void handleEmptyHeldItem(EmptyingSink sink, boolean emptyAll) { var ctx = ContainerItemStrategies.findCarriedContext(null, getPlayer(), this); if (ctx == null) { return; @@ -635,34 +648,50 @@ protected final void handleEmptyHeldItem(EmptyingSink sink) { // See how much we can drain from the item var content = ctx.getExtractableContent(); - if (content == null) { + if (content == null || content.amount() == 0) { return; } var what = content.what(); - var amount = content.amount(); + long amount = emptyAll ? Long.MAX_VALUE : FluidType.BUCKET_VOLUME; + int maxIterations = 10_000; + boolean emptied = false; + + do { + // Check if we can pull out of the container + var canExtract = ctx.extract(what, amount, Actionable.SIMULATE); + if (canExtract <= 0) { + break; + } - // Check if we can push into the system - var canInsert = sink.insert(what, amount, Actionable.SIMULATE); - if (canInsert <= 0) { - return; - } + // Check if we can push into the system + var amountAllowed = sink.insert(what, canExtract, Actionable.SIMULATE); + if (amountAllowed <= 0) { + break; + } - // Actually drain - var extracted = ctx.extract(what, canInsert, Actionable.MODULATE); - if (extracted != canInsert) { - AELog.error( - "Fluid item [%s] reported a different possible amount to drain than it actually provided.", - getCarried()); - return; - } + // Actually drain + var extracted = ctx.extract(what, amountAllowed, Actionable.MODULATE); + if (extracted != amountAllowed) { + AELog.error( + "Fluid item [%s] reported a different possible amount to drain than it actually provided.", + getCarried()); + break; + } - if (sink.insert(what, extracted, Actionable.MODULATE) != extracted) { - AELog.error("Failed to insert previously simulated %s into ME system", what); - return; - } + // Actually push into the system + if (sink.insert(what, extracted, Actionable.MODULATE) != extracted) { + AELog.error("Failed to insert previously simulated %s into ME system", what); + break; + } - ctx.playEmptySound(getPlayer(), what); + emptied = true; + maxIterations--; + } while (emptyAll && maxIterations > 0); + + if (emptied) { + ctx.playEmptySound(getPlayer(), what); + } } private void handleFakeSlotAction(FakeSlot fakeSlot, InventoryAction action) { diff --git a/src/main/java/appeng/menu/me/common/MEStorageMenu.java b/src/main/java/appeng/menu/me/common/MEStorageMenu.java index d7efd8dc5f3..422063fb7b8 100644 --- a/src/main/java/appeng/menu/me/common/MEStorageMenu.java +++ b/src/main/java/appeng/menu/me/common/MEStorageMenu.java @@ -420,12 +420,17 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli } if (action == InventoryAction.FILL_ITEM) { - tryFillContainerItem(clickedKey, false); + tryFillContainerItem(clickedKey, false, false); + } else if (action == InventoryAction.FILL_ALL_ITEM) { + tryFillContainerItem(clickedKey, false, true); } else if (action == InventoryAction.SHIFT_CLICK) { - tryFillContainerItem(clickedKey, true); + tryFillContainerItem(clickedKey, true, false); } else if (action == InventoryAction.EMPTY_ITEM) { handleEmptyHeldItem((what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, - getActionSource(), mode)); + getActionSource(), mode), false); + } else if (action == InventoryAction.EMPTY_ALL_ITEM) { + handleEmptyHeldItem((what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, + getActionSource(), mode), true); } else if (action == InventoryAction.AUTO_CRAFT) { var locator = getLocator(); if (locator != null && clickedKey != null) { @@ -556,7 +561,7 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli } } - private void tryFillContainerItem(@Nullable AEKey clickedKey, boolean moveToPlayer) { + private void tryFillContainerItem(@Nullable AEKey clickedKey, boolean moveToPlayer, boolean fillAll) { // Special handling for fluids to facilitate filling water/lava buckets which are often // needed for crafting and placement in-world. boolean grabbedEmptyBucket = false; @@ -575,7 +580,7 @@ private void tryFillContainerItem(@Nullable AEKey clickedKey, boolean moveToPlay handleFillingHeldItem( (amount, mode) -> StorageHelper.poweredExtraction(energySource, storage, clickedKey, amount, getActionSource(), mode), - clickedKey); + clickedKey, fillAll); // If we grabbed an empty bucket, and after trying to fill it, it's still empty, put it back! if (grabbedEmptyBucket && getCarried().is(Items.BUCKET)) { From 92f967e694e7b9068b374477533571a19ab1283b Mon Sep 17 00:00:00 2001 From: rlnt Date: Sun, 28 Apr 2024 22:45:17 +0200 Subject: [PATCH 2/5] use key-defined amount per operation --- src/main/java/appeng/menu/AEBaseMenu.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/appeng/menu/AEBaseMenu.java b/src/main/java/appeng/menu/AEBaseMenu.java index 57edd950c8d..49c12000e18 100644 --- a/src/main/java/appeng/menu/AEBaseMenu.java +++ b/src/main/java/appeng/menu/AEBaseMenu.java @@ -597,7 +597,7 @@ protected final void handleFillingHeldItem(FillingSource source, AEKey what, boo } int maxIterations = 10_000; - long amount = fillAll ? Long.MAX_VALUE : FluidType.BUCKET_VOLUME; + long amount = fillAll ? Long.MAX_VALUE : what.getAmountPerUnit(); boolean filled = false; do { @@ -653,7 +653,7 @@ protected final void handleEmptyHeldItem(EmptyingSink sink, boolean emptyAll) { } var what = content.what(); - long amount = emptyAll ? Long.MAX_VALUE : FluidType.BUCKET_VOLUME; + long amount = emptyAll ? Long.MAX_VALUE : what.getAmountPerUnit(); int maxIterations = 10_000; boolean emptied = false; From 9ba8ba4360f4534f8aa3d4bd317402e309b88038 Mon Sep 17 00:00:00 2001 From: rlnt Date: Mon, 29 Apr 2024 10:17:49 +0200 Subject: [PATCH 3/5] spotless apply --- src/main/java/appeng/menu/AEBaseMenu.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/appeng/menu/AEBaseMenu.java b/src/main/java/appeng/menu/AEBaseMenu.java index 49c12000e18..582375e246d 100644 --- a/src/main/java/appeng/menu/AEBaseMenu.java +++ b/src/main/java/appeng/menu/AEBaseMenu.java @@ -46,7 +46,6 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; -import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.network.PacketDistributor; import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; From f76894d9a0600725497ff81ddcf89093650c16b1 Mon Sep 17 00:00:00 2001 From: rlnt Date: Thu, 30 May 2024 16:51:37 +0200 Subject: [PATCH 4/5] changes according to reviews --- .../client/gui/me/common/MEStorageScreen.java | 5 +++-- .../java/appeng/helpers/InventoryAction.java | 2 +- src/main/java/appeng/menu/AEBaseMenu.java | 21 ++++++++++--------- .../appeng/menu/me/common/MEStorageMenu.java | 4 ++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java b/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java index 85b979249a8..ce4371c504c 100644 --- a/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java +++ b/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java @@ -232,14 +232,15 @@ protected void handleGridInventoryEntryMouseClick(@Nullable GridInventoryEntry e if (!menu.getCarried().isEmpty()) { if (mouseButton == 0 && entry != null && ContainerItemStrategies.isKeySupported(entry.getWhat())) { menu.handleInteraction(entry.getSerial(), - clickType == ClickType.QUICK_MOVE ? InventoryAction.FILL_ALL_ITEM : InventoryAction.FILL_ITEM); + clickType == ClickType.QUICK_MOVE ? InventoryAction.FILL_ENTIRE_ITEM + : InventoryAction.FILL_ITEM); return; } if (mouseButton == 1) { var emptyingAction = ContainerItemStrategies.getEmptyingAction(menu.getCarried()); if (emptyingAction != null && menu.isKeyVisible(emptyingAction.what())) { - menu.handleInteraction(-1, clickType == ClickType.QUICK_MOVE ? InventoryAction.EMPTY_ALL_ITEM + menu.handleInteraction(-1, clickType == ClickType.QUICK_MOVE ? InventoryAction.EMPTY_ENTIRE_ITEM : InventoryAction.EMPTY_ITEM); return; } diff --git a/src/main/java/appeng/helpers/InventoryAction.java b/src/main/java/appeng/helpers/InventoryAction.java index cb8817bfcd0..7bbe5a0882c 100644 --- a/src/main/java/appeng/helpers/InventoryAction.java +++ b/src/main/java/appeng/helpers/InventoryAction.java @@ -26,7 +26,7 @@ public enum InventoryAction { CRAFT_STACK, CRAFT_ITEM, CRAFT_SHIFT, // fluid term - FILL_ITEM, FILL_ALL_ITEM, EMPTY_ITEM, EMPTY_ALL_ITEM, + FILL_ITEM, FILL_ENTIRE_ITEM, EMPTY_ITEM, EMPTY_ENTIRE_ITEM, // extra... MOVE_REGION, PICKUP_SINGLE, ROLL_UP, ROLL_DOWN, AUTO_CRAFT, PLACE_SINGLE, diff --git a/src/main/java/appeng/menu/AEBaseMenu.java b/src/main/java/appeng/menu/AEBaseMenu.java index 582375e246d..b20e0f643dd 100644 --- a/src/main/java/appeng/menu/AEBaseMenu.java +++ b/src/main/java/appeng/menu/AEBaseMenu.java @@ -81,6 +81,7 @@ public abstract class AEBaseMenu extends AbstractContainerMenu { private static final int MAX_STRING_LENGTH = 32767; + private static final int MAX_CONTAINER_TRANSFER_ITERATIONS = 256; private static final String HIDE_SLOT = "HideSlot"; private final IActionSource mySrc; @@ -559,14 +560,14 @@ public void doAction(ServerPlayer player, InventoryAction action, int slot, long var realInv = configInv.getDelegate(); var realInvSlot = appEngSlot.slot; - if (action == InventoryAction.FILL_ITEM || action == InventoryAction.FILL_ALL_ITEM) { + if (action == InventoryAction.FILL_ITEM || action == InventoryAction.FILL_ENTIRE_ITEM) { var what = realInv.getKey(realInvSlot); handleFillingHeldItem( (amount, mode) -> realInv.extract(realInvSlot, what, amount, mode), - what, action == InventoryAction.FILL_ALL_ITEM); - } else if (action == InventoryAction.EMPTY_ITEM || action == InventoryAction.EMPTY_ALL_ITEM) { + what, action == InventoryAction.FILL_ENTIRE_ITEM); + } else if (action == InventoryAction.EMPTY_ITEM || action == InventoryAction.EMPTY_ENTIRE_ITEM) { handleEmptyHeldItem((what, amount, mode) -> realInv.insert(realInvSlot, what, amount, mode), - action == InventoryAction.EMPTY_ALL_ITEM); + action == InventoryAction.EMPTY_ENTIRE_ITEM); } } @@ -595,11 +596,11 @@ protected final void handleFillingHeldItem(FillingSource source, AEKey what, boo return; } - int maxIterations = 10_000; long amount = fillAll ? Long.MAX_VALUE : what.getAmountPerUnit(); boolean filled = false; + int maxIterations = fillAll ? MAX_CONTAINER_TRANSFER_ITERATIONS : 1; - do { + while (maxIterations > 0) { // Check if we can pull out of the system var canPull = source.extract(amount, Actionable.SIMULATE); if (canPull <= 0) { @@ -628,7 +629,7 @@ protected final void handleFillingHeldItem(FillingSource source, AEKey what, boo filled = true; maxIterations--; - } while (fillAll && maxIterations > 0); + } if (filled) { ctx.playFillSound(getPlayer(), what); @@ -653,10 +654,10 @@ protected final void handleEmptyHeldItem(EmptyingSink sink, boolean emptyAll) { var what = content.what(); long amount = emptyAll ? Long.MAX_VALUE : what.getAmountPerUnit(); - int maxIterations = 10_000; + int maxIterations = emptyAll ? MAX_CONTAINER_TRANSFER_ITERATIONS : 1; boolean emptied = false; - do { + while (maxIterations > 0) { // Check if we can pull out of the container var canExtract = ctx.extract(what, amount, Actionable.SIMULATE); if (canExtract <= 0) { @@ -686,7 +687,7 @@ protected final void handleEmptyHeldItem(EmptyingSink sink, boolean emptyAll) { emptied = true; maxIterations--; - } while (emptyAll && maxIterations > 0); + } if (emptied) { ctx.playEmptySound(getPlayer(), what); diff --git a/src/main/java/appeng/menu/me/common/MEStorageMenu.java b/src/main/java/appeng/menu/me/common/MEStorageMenu.java index 422063fb7b8..e1258596075 100644 --- a/src/main/java/appeng/menu/me/common/MEStorageMenu.java +++ b/src/main/java/appeng/menu/me/common/MEStorageMenu.java @@ -421,14 +421,14 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli if (action == InventoryAction.FILL_ITEM) { tryFillContainerItem(clickedKey, false, false); - } else if (action == InventoryAction.FILL_ALL_ITEM) { + } else if (action == InventoryAction.FILL_ENTIRE_ITEM) { tryFillContainerItem(clickedKey, false, true); } else if (action == InventoryAction.SHIFT_CLICK) { tryFillContainerItem(clickedKey, true, false); } else if (action == InventoryAction.EMPTY_ITEM) { handleEmptyHeldItem((what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, getActionSource(), mode), false); - } else if (action == InventoryAction.EMPTY_ALL_ITEM) { + } else if (action == InventoryAction.EMPTY_ENTIRE_ITEM) { handleEmptyHeldItem((what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, getActionSource(), mode), true); } else if (action == InventoryAction.AUTO_CRAFT) { From 432894b0c1a335d8b8dfca559edccb60acc1af6f Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Fri, 31 May 2024 13:22:07 +0200 Subject: [PATCH 5/5] Move decision on which action to take fully to client-side. --- .../client/gui/me/common/MEStorageScreen.java | 37 +++++---- .../java/appeng/helpers/InventoryAction.java | 3 +- .../appeng/menu/me/common/MEStorageMenu.java | 77 ++++++++----------- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java b/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java index ce4371c504c..130d35b68be 100644 --- a/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java +++ b/src/main/java/appeng/client/gui/me/common/MEStorageScreen.java @@ -228,22 +228,31 @@ protected void handleGridInventoryEntryMouseClick(@Nullable GridInventoryEntry e AELog.debug("Clicked on grid inventory entry serial=%s, key=%s", entry.getSerial(), entry.getWhat()); } - // Check for emptying and filling actions and send them to the server - if (!menu.getCarried().isEmpty()) { - if (mouseButton == 0 && entry != null && ContainerItemStrategies.isKeySupported(entry.getWhat())) { - menu.handleInteraction(entry.getSerial(), - clickType == ClickType.QUICK_MOVE ? InventoryAction.FILL_ENTIRE_ITEM - : InventoryAction.FILL_ITEM); - return; + // Left-Clicking on an entry that is supported by a container strategy will either fill the currently + // held container, or it will consume a container from the grid to be filled. + // Holding shift tries to fill the entire container, while only transferring a single unit otherwise. + if (mouseButton == 0 && entry != null && ContainerItemStrategies.isKeySupported(entry.getWhat())) { + InventoryAction action; + if (clickType != ClickType.QUICK_MOVE) { + action = InventoryAction.FILL_ITEM; // Simple click fills item in hand or puts filled item in hand + } else { + // Shift-click on fluid with an empty hand -> move filled container to player + action = menu.getCarried().isEmpty() ? InventoryAction.FILL_ENTIRE_ITEM_MOVE_TO_PLAYER + : InventoryAction.FILL_ENTIRE_ITEM; } - if (mouseButton == 1) { - var emptyingAction = ContainerItemStrategies.getEmptyingAction(menu.getCarried()); - if (emptyingAction != null && menu.isKeyVisible(emptyingAction.what())) { - menu.handleInteraction(-1, clickType == ClickType.QUICK_MOVE ? InventoryAction.EMPTY_ENTIRE_ITEM - : InventoryAction.EMPTY_ITEM); - return; - } + menu.handleInteraction(entry.getSerial(), action); + return; + } + + // Right-clicking with an item in hand tries to empty the container into the network + // Holding shift tries to empty the entire container, while only transferring a single unit otherwise. + if (mouseButton == 1 && !menu.getCarried().isEmpty()) { + var emptyingAction = ContainerItemStrategies.getEmptyingAction(menu.getCarried()); + if (emptyingAction != null && menu.isKeyVisible(emptyingAction.what())) { + menu.handleInteraction(-1, clickType == ClickType.QUICK_MOVE ? InventoryAction.EMPTY_ENTIRE_ITEM + : InventoryAction.EMPTY_ITEM); + return; } } diff --git a/src/main/java/appeng/helpers/InventoryAction.java b/src/main/java/appeng/helpers/InventoryAction.java index 7bbe5a0882c..c83a39bf5d8 100644 --- a/src/main/java/appeng/helpers/InventoryAction.java +++ b/src/main/java/appeng/helpers/InventoryAction.java @@ -26,7 +26,8 @@ public enum InventoryAction { CRAFT_STACK, CRAFT_ITEM, CRAFT_SHIFT, // fluid term - FILL_ITEM, FILL_ENTIRE_ITEM, EMPTY_ITEM, EMPTY_ENTIRE_ITEM, + FILL_ITEM, FILL_ITEM_MOVE_TO_PLAYER, FILL_ENTIRE_ITEM, FILL_ENTIRE_ITEM_MOVE_TO_PLAYER, EMPTY_ITEM, + EMPTY_ENTIRE_ITEM, // extra... MOVE_REGION, PICKUP_SINGLE, ROLL_UP, ROLL_DOWN, AUTO_CRAFT, PLACE_SINGLE, diff --git a/src/main/java/appeng/menu/me/common/MEStorageMenu.java b/src/main/java/appeng/menu/me/common/MEStorageMenu.java index e1258596075..ee2431b564c 100644 --- a/src/main/java/appeng/menu/me/common/MEStorageMenu.java +++ b/src/main/java/appeng/menu/me/common/MEStorageMenu.java @@ -43,7 +43,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.shorts.ShortSet; -import appeng.api.behaviors.ContainerItemStrategies; import appeng.api.config.Actionable; import appeng.api.config.Setting; import appeng.api.config.Settings; @@ -409,29 +408,8 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli return; } - if (action == InventoryAction.PICKUP_OR_SET_DOWN && ContainerItemStrategies.isKeySupported(clickedKey)) { - action = InventoryAction.FILL_ITEM; - } - - if (action == InventoryAction.SPLIT_OR_PLACE_SINGLE) { - if (ContainerItemStrategies.getContainedStack(getCarried()) != null) { - action = InventoryAction.EMPTY_ITEM; - } - } - - if (action == InventoryAction.FILL_ITEM) { - tryFillContainerItem(clickedKey, false, false); - } else if (action == InventoryAction.FILL_ENTIRE_ITEM) { - tryFillContainerItem(clickedKey, false, true); - } else if (action == InventoryAction.SHIFT_CLICK) { - tryFillContainerItem(clickedKey, true, false); - } else if (action == InventoryAction.EMPTY_ITEM) { - handleEmptyHeldItem((what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, - getActionSource(), mode), false); - } else if (action == InventoryAction.EMPTY_ENTIRE_ITEM) { - handleEmptyHeldItem((what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, - getActionSource(), mode), true); - } else if (action == InventoryAction.AUTO_CRAFT) { + // Handle auto-crafting requests + if (action == InventoryAction.AUTO_CRAFT) { var locator = getLocator(); if (locator != null && clickedKey != null) { CraftAmountMenu.open(player, locator, clickedKey, clickedKey.getAmountPerUnit()); @@ -439,6 +417,24 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli return; } + // Attempt fluid related actions first + switch (action) { + case FILL_ITEM -> tryFillContainerItem(clickedKey, false, false); + case FILL_ITEM_MOVE_TO_PLAYER -> tryFillContainerItem(clickedKey, true, false); + case FILL_ENTIRE_ITEM -> tryFillContainerItem(clickedKey, false, true); + case FILL_ENTIRE_ITEM_MOVE_TO_PLAYER -> tryFillContainerItem(clickedKey, true, true); + case EMPTY_ITEM -> + handleEmptyHeldItem( + (what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, + getActionSource(), mode), + false); + case EMPTY_ENTIRE_ITEM -> + handleEmptyHeldItem( + (what, amount, mode) -> StorageHelper.poweredInsert(energySource, storage, what, amount, + getActionSource(), mode), + true); + } + // Handle interactions where the player wants to put something into the network if (clickedKey == null) { if (action == InventoryAction.SPLIT_OR_PLACE_SINGLE || action == InventoryAction.ROLL_DOWN) { @@ -449,16 +445,14 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli return; } + // Any of the remaining actions are for items only if (!(clickedKey instanceof AEItemKey clickedItem)) { return; } switch (action) { - case SHIFT_CLICK: - moveOneStackToPlayer(clickedItem); - break; - - case ROLL_DOWN: { + case SHIFT_CLICK -> moveOneStackToPlayer(clickedItem); + case ROLL_DOWN -> { // Insert 1 of the carried stack into the network (or at least try to), regardless of what we're // hovering in the network inventory. var carried = getCarried(); @@ -470,9 +464,7 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli } } } - break; - case ROLL_UP: - case PICKUP_SINGLE: { + case ROLL_UP, PICKUP_SINGLE -> { // Extract 1 of the hovered stack from the network (or at least try to), and add it to the carried item var item = getCarried(); @@ -496,8 +488,7 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli } } } - break; - case PICKUP_OR_SET_DOWN: { + case PICKUP_OR_SET_DOWN -> { if (!getCarried().isEmpty()) { putCarriedItemIntoNetwork(false); } else { @@ -514,8 +505,7 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli } } } - break; - case SPLIT_OR_PLACE_SINGLE: + case SPLIT_OR_PLACE_SINGLE -> { if (!getCarried().isEmpty()) { putCarriedItemIntoNetwork(true); } else { @@ -538,26 +528,23 @@ protected void handleNetworkInteraction(ServerPlayer player, @Nullable AEKey cli setCarried(ItemStack.EMPTY); } } - - break; - case CREATIVE_DUPLICATE: + } + case CREATIVE_DUPLICATE -> { if (player.getAbilities().instabuild) { var is = clickedItem.toStack(); is.setCount(is.getMaxStackSize()); setCarried(is); } - break; - case MOVE_REGION: + } + case MOVE_REGION -> { final int playerInv = player.getInventory().items.size(); for (int slotNum = 0; slotNum < playerInv; slotNum++) { if (!moveOneStackToPlayer(clickedItem)) { break; } } - break; - default: - AELog.warn("Received unhandled inventory action %s from client in %s", action, getClass()); - break; + } + default -> AELog.warn("Received unhandled inventory action %s from client in %s", action, getClass()); } }