Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fill all and Empty All Container Actions #7891

Merged
merged 5 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add fill all and empty all actions
  • Loading branch information
rlnt committed May 30, 2024
commit cf82a405a0fbc1c210699b222eb5677871609aea
19 changes: 14 additions & 5 deletions src/main/java/appeng/client/gui/me/common/MEStorageScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/appeng/helpers/InventoryAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
127 changes: 78 additions & 49 deletions src/main/java/appeng/menu/AEBaseMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -588,81 +590,108 @@ 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;
}

// 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) {
Expand Down
15 changes: 10 additions & 5 deletions src/main/java/appeng/menu/me/common/MEStorageMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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)) {
Expand Down