Skip to content

Commit 73f43af

Browse files
Categorized inventory gui priority
1 parent 110fcfb commit 73f43af

File tree

11 files changed

+85
-62
lines changed

11 files changed

+85
-62
lines changed

invui/src/main/java/xyz/xenondevs/invui/gui/AbstractGui.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import xyz.xenondevs.invui.internal.util.SlotUtils;
1616
import xyz.xenondevs.invui.inventory.Inventory;
1717
import xyz.xenondevs.invui.inventory.ObscuredInventory;
18+
import xyz.xenondevs.invui.inventory.OperationCategory;
1819
import xyz.xenondevs.invui.inventory.event.ItemPreUpdateEvent;
1920
import xyz.xenondevs.invui.inventory.event.PlayerUpdateReason;
2021
import xyz.xenondevs.invui.inventory.event.UpdateReason;
@@ -242,7 +243,7 @@ private void handleInvItemShift(Click click, Inventory inventory, int slot) {
242243
// move into the first inventory that accepts the item, sorted by priority
243244
var inventories = window.getGuis().stream()
244245
.flatMap(gui -> gui.getInventories(inventory).stream())
245-
.sorted(Comparator.comparingInt(Inventory::getGuiPriority).reversed())
246+
.sorted(Comparator.<Inventory>comparingInt(inv -> inv.getGuiPriority(OperationCategory.ADD)).reversed())
246247
.toList();
247248

248249
int leftOverAmount = putIntoFirstInventory(updateReason, clicked, inventories);
@@ -354,8 +355,8 @@ private void handleInvBundleSelect(Player player, Inventory inventory, int slot,
354355

355356
/**
356357
* Puts the given {@link ItemStack} into the first inventory that accepts it, starting with the
357-
* {@link Inventory#getGuiPriority() highest priority} inventory. If one inventory accepts any amount
358-
* of items, further inventories will not be queried, meaning that an item stack will not be split
358+
* {@link Inventory#getGuiPriority(OperationCategory)} for {@link OperationCategory#ADD} highest priority inventory.
359+
* If one inventory accepts any amount of items, further inventories will not be queried, meaning that an item stack will not be split
359360
* across multiple inventories.
360361
*
361362
* @param updateReason the update reason to use
@@ -364,7 +365,13 @@ private void handleInvBundleSelect(Player player, Inventory inventory, int slot,
364365
* @return the amount of items that are left over
365366
*/
366367
protected int putIntoFirstInventory(UpdateReason updateReason, ItemStack itemStack, Inventory... ignored) {
367-
return putIntoFirstInventory(updateReason, itemStack, getInventories(ignored));
368+
return putIntoFirstInventory(
369+
updateReason,
370+
itemStack,
371+
getInventories(ignored).stream()
372+
.sorted(Comparator.<Inventory>comparingInt(inv -> inv.getGuiPriority(OperationCategory.ADD)).reversed())
373+
.toList()
374+
);
368375
}
369376

370377
/**
@@ -389,13 +396,12 @@ protected int putIntoFirstInventory(UpdateReason updateReason, ItemStack itemSta
389396
}
390397

391398
/**
392-
* Gets a map of all inventories and their visible slots in this gui, ignoring the specified inventories,
393-
* sorted by their {@link Inventory#getGuiPriority()}, with the highest priorities coming first.
399+
* Gets a map of all inventories and their visible slots in this gui, ignoring the specified inventories.
394400
*
395401
* @param ignored the inventories to ignore
396402
* @return a map of all inventories and their visible slots
397403
*/
398-
private SequencedMap<Inventory, Set<Integer>> getAllActiveInventorySlots(Inventory... ignored) {
404+
private Map<? extends Inventory, Set<Integer>> getAllActiveInventorySlots(Inventory... ignored) {
399405
if (isFrozen())
400406
return Collections.emptySortedMap();
401407

@@ -424,18 +430,16 @@ private SequencedMap<Inventory, Set<Integer>> getAllActiveInventorySlots(Invento
424430
}
425431
}
426432

427-
return slots.entrySet().stream()
428-
.sorted(Comparator.<Map.Entry<Inventory, Set<Integer>>>comparingInt(entry -> entry.getKey().getGuiPriority()).reversed())
429-
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new));
433+
return slots;
430434
}
431435

432436
@Override
433-
public SequencedCollection<? extends Inventory> getInventories(Inventory... ignored) {
437+
public Collection<? extends Inventory> getInventories(Inventory... ignored) {
434438
if (!ignoreObscuredInventorySlots)
435-
return Collections.unmodifiableSequencedCollection(getAllActiveInventorySlots(ignored).sequencedKeySet());
439+
return Collections.unmodifiableCollection(getAllActiveInventorySlots(ignored).keySet());
436440

437441
ArrayList<Inventory> inventories = new ArrayList<>();
438-
for (Map.Entry<Inventory, Set<Integer>> entry : getAllActiveInventorySlots(ignored).entrySet()) {
442+
for (Map.Entry<? extends Inventory, Set<Integer>> entry : getAllActiveInventorySlots(ignored).entrySet()) {
439443
Inventory inventory = entry.getKey();
440444
Set<Integer> slots = entry.getValue();
441445
inventories.add(new ObscuredInventory(inventory, slot -> !slots.contains(slot)));

invui/src/main/java/xyz/xenondevs/invui/gui/Gui.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -622,16 +622,16 @@ default void setGui(char key, Gui gui) {
622622

623623
/**
624624
* Gets an unmodifiable sequenced collection of all inventories visible in this gui,
625-
* including those that are part of nested guis, ignoring the specified inventories,
626-
* sorted by their {@link Inventory#getGuiPriority()}, with the highest priorities coming first.
625+
* including those that are part of nested guis, ignoring the specified inventories.
626+
* Slots that are embedded multiple times are only returned once.
627627
* If {@link #isIgnoreObscuredInventorySlots()} is true, the obscured slots will not be visible
628628
* in the returned inventories.
629629
* If the gui or any nested gui containing an inventory is frozen, those slots will also not be visible.
630630
*
631631
* @param ignored the inventories to ignore
632632
* @return a sequenced collection of all inventories visible in this gui
633633
*/
634-
SequencedCollection<? extends Inventory> getInventories(Inventory... ignored);
634+
Collection<? extends Inventory> getInventories(Inventory... ignored);
635635

636636
//<editor-fold desc="fill methods">
637637

invui/src/main/java/xyz/xenondevs/invui/inventory/CompositeInventory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ private static int calculateSize(Collection<? extends Inventory> inventories) {
6262
}
6363

6464
@Override
65-
public int[] getIterationOrder(IterationOrderCategory category) {
65+
public int[] getIterationOrder(OperationCategory category) {
6666
int[] iterationOrder = new int[getSize()];
6767
int i = 0;
6868
int offset = 0;
@@ -212,7 +212,7 @@ public boolean hasEventHandlers() {
212212
}
213213

214214
@Override
215-
public void setIterationOrder(IterationOrderCategory category, int[] iterationOrder) {
215+
public void setIterationOrder(OperationCategory category, int[] iterationOrder) {
216216
throw new UnsupportedOperationException("Iteration order needs to be set in the backing inventories");
217217
}
218218

invui/src/main/java/xyz/xenondevs/invui/inventory/Inventory.java

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ public sealed abstract class Inventory permits VirtualInventory, CompositeInvent
5757
private @Nullable List<Consumer<InventoryClickEvent>> clickHandlers;
5858
private @Nullable List<Consumer<ItemPreUpdateEvent>> preUpdateHandlers;
5959
private @Nullable List<Consumer<ItemPostUpdateEvent>> postUpdateHandlers;
60-
private int guiPriority = 0;
61-
private final Map<IterationOrderCategory, int[]> iterationOrders;
60+
private final Map<OperationCategory, int[]> iterationOrders;
61+
private final Map<OperationCategory, Integer> guiPriorities;
6262

6363
@SuppressWarnings("unchecked")
6464
public Inventory(int size) {
6565
this.size = size;
6666
viewers = new Set[size];
67-
iterationOrders = CollectionUtils.newEnumMap(IterationOrderCategory.class, k -> IntStream.range(0, size).toArray());
67+
iterationOrders = CollectionUtils.newEnumMap(OperationCategory.class, k -> IntStream.range(0, size).toArray());
68+
guiPriorities = CollectionUtils.newEnumMap(OperationCategory.class, k -> 0);
6869
}
6970

7071
/**
@@ -81,7 +82,7 @@ public int getSize() {
8182
*
8283
* @param iterationOrder The new iteration order. Must include all slots and no duplicates.
8384
*/
84-
public void setIterationOrder(IterationOrderCategory category, int[] iterationOrder) {
85+
public void setIterationOrder(OperationCategory category, int[] iterationOrder) {
8586
if (iterationOrder.length != size)
8687
throw new IllegalArgumentException("Iteration order size must match inventory size");
8788

@@ -102,7 +103,7 @@ public void setIterationOrder(IterationOrderCategory category, int[] iterationOr
102103
* @param category The category of iteration operations
103104
* @return The current iteration order.
104105
*/
105-
public int[] getIterationOrder(IterationOrderCategory category) {
106+
public int[] getIterationOrder(OperationCategory category) {
106107
return iterationOrders.get(category).clone();
107108
}
108109

@@ -111,7 +112,7 @@ public int[] getIterationOrder(IterationOrderCategory category) {
111112
* such as {@link #addItem(UpdateReason, ItemStack)} or {@link #collectSimilar(UpdateReason, ItemStack, int)}.
112113
*/
113114
public void reverseIterationOrder() {
114-
for (var category : IterationOrderCategory.values()) {
115+
for (var category : OperationCategory.values()) {
115116
reverseIterationOrder(category);
116117
}
117118
}
@@ -121,7 +122,7 @@ public void reverseIterationOrder() {
121122
*
122123
* @param category The category of operations where the iteration order should be reversed
123124
*/
124-
public void reverseIterationOrder(IterationOrderCategory category) {
125+
public void reverseIterationOrder(OperationCategory category) {
125126
setIterationOrder(category, ArrayUtils.reversed(getIterationOrder(category)));
126127
}
127128

@@ -511,25 +512,37 @@ public void callPostUpdateEvent(@Nullable UpdateReason updateReason, int slot, @
511512
}
512513

513514
/**
514-
* Gets the priority for click actions in a {@link Gui}, such as shift clicking or cursor collection
515-
* with multiple {@link Inventory VirtualInventories}.
515+
* Gets the gui priority for operations of the given category.
516+
* This priority is used to determine the order in which operations are applied to gui-embedded inventories.
516517
*
517518
* @return The priority for click actions, {@link Inventory VirtualInventories} with
518519
* a higher priority get prioritized.
519520
*/
520-
public int getGuiPriority() {
521-
return guiPriority;
521+
public int getGuiPriority(OperationCategory category) {
522+
return guiPriorities.get(category);
522523
}
523524

524525
/**
525-
* Sets the priority for click actions in a {@link Gui}, such as shift-clicking or cursor collection
526-
* with multiple {@link Inventory VirtualInventories}.
526+
* Sets the gui priority for all operation types.
527+
* This priority is used to determine the order in which operations are applied to gui-embedded inventories.
527528
*
528-
* @param guiPriority The priority for click actions, {@link Inventory VirtualInventories} with
529-
* a higher priority get prioritized.
529+
* @param priority The priority
530530
*/
531-
public void setGuiPriority(int guiPriority) {
532-
this.guiPriority = guiPriority;
531+
public void setGuiPriority(int priority) {
532+
for (var category : OperationCategory.values()) {
533+
setGuiPriority(category, priority);
534+
}
535+
}
536+
537+
/**
538+
* Sets the gui priority for operations of the given category.
539+
* This priority is used to determine the order in which operations are applied to gui-embedded inventories.
540+
*
541+
* @param category The category of operations to set the priority for.
542+
* @param priority The priority
543+
*/
544+
public void setGuiPriority(OperationCategory category, int priority) {
545+
guiPriorities.put(category, priority);
533546
}
534547

535548
/**
@@ -1016,7 +1029,7 @@ private int addToPartialSlots(
10161029
int amountLeft,
10171030
@Nullable ItemStack[] items
10181031
) {
1019-
for (int slot : getIterationOrder(IterationOrderCategory.ADD)) {
1032+
for (int slot : getIterationOrder(OperationCategory.ADD)) {
10201033
if (amountLeft <= 0)
10211034
break;
10221035

@@ -1059,7 +1072,7 @@ private int addToEmptySlots(
10591072
int amountLeft,
10601073
@Nullable ItemStack[] items
10611074
) {
1062-
for (int slot : getIterationOrder(IterationOrderCategory.ADD)) {
1075+
for (int slot : getIterationOrder(OperationCategory.ADD)) {
10631076
if (amountLeft <= 0)
10641077
break;
10651078

@@ -1177,7 +1190,7 @@ public int simulateSingleAdd(@Nullable ItemStack itemStack) {
11771190
int amountLeft = itemStack.getAmount();
11781191

11791192
// find all slots where the item partially fits
1180-
for (int slot : getIterationOrder(IterationOrderCategory.ADD)) {
1193+
for (int slot : getIterationOrder(OperationCategory.ADD)) {
11811194
if (amountLeft == 0)
11821195
break;
11831196

@@ -1194,7 +1207,7 @@ public int simulateSingleAdd(@Nullable ItemStack itemStack) {
11941207
}
11951208

11961209
// remaining items would be added to empty slots
1197-
for (int slot : getIterationOrder(IterationOrderCategory.ADD)) {
1210+
for (int slot : getIterationOrder(OperationCategory.ADD)) {
11981211
if (amountLeft == 0)
11991212
break;
12001213

@@ -1256,7 +1269,7 @@ public int collectSimilar(@Nullable UpdateReason updateReason, ItemStack templat
12561269
@Nullable ItemStack[] items = getUnsafeItems();
12571270

12581271
// find partial slots and take items from there
1259-
for (int slot : getIterationOrder(IterationOrderCategory.COLLECT)) {
1272+
for (int slot : getIterationOrder(OperationCategory.COLLECT)) {
12601273
ItemStack currentStack = items[slot];
12611274
if (currentStack == null || currentStack.getAmount() >= maxStackSize || !template.isSimilar(currentStack))
12621275
continue;
@@ -1267,7 +1280,7 @@ public int collectSimilar(@Nullable UpdateReason updateReason, ItemStack templat
12671280
}
12681281

12691282
// only taking from partial stacks wasn't enough, take from a full slot
1270-
for (int slot : getIterationOrder(IterationOrderCategory.COLLECT)) {
1283+
for (int slot : getIterationOrder(OperationCategory.COLLECT)) {
12711284
ItemStack currentStack = items[slot];
12721285
if (currentStack == null || currentStack.getAmount() < maxStackSize || !template.isSimilar(currentStack))
12731286
continue;
@@ -1292,7 +1305,7 @@ public int removeIf(@Nullable UpdateReason updateReason, Predicate<ItemStack> pr
12921305
@Nullable ItemStack[] items = getUnsafeItems();
12931306

12941307
int removed = 0;
1295-
for (int slot : getIterationOrder(IterationOrderCategory.OTHER)) {
1308+
for (int slot : getIterationOrder(OperationCategory.OTHER)) {
12961309
ItemStack item = items[slot];
12971310
if (item != null && predicate.test(item.clone()) && setItem(updateReason, slot, null)) {
12981311
removed += item.getAmount();
@@ -1314,7 +1327,7 @@ public int removeFirst(@Nullable UpdateReason updateReason, int amount, Predicat
13141327
@Nullable ItemStack[] items = getUnsafeItems();
13151328

13161329
int leftOver = amount;
1317-
for (int slot : getIterationOrder(IterationOrderCategory.OTHER)) {
1330+
for (int slot : getIterationOrder(OperationCategory.OTHER)) {
13181331
ItemStack item = items[slot];
13191332
if (item != null && predicate.test(item.clone())) {
13201333
leftOver -= takeFrom(updateReason, slot, leftOver);
@@ -1336,7 +1349,7 @@ public int removeSimilar(@Nullable UpdateReason updateReason, ItemStack itemStac
13361349
@Nullable ItemStack[] items = getUnsafeItems();
13371350

13381351
int removed = 0;
1339-
for (int slot : getIterationOrder(IterationOrderCategory.OTHER)) {
1352+
for (int slot : getIterationOrder(OperationCategory.OTHER)) {
13401353
ItemStack item = items[slot];
13411354
if (item != null && item.isSimilar(itemStack) && setItem(updateReason, slot, null)) {
13421355
removed += item.getAmount();
@@ -1358,7 +1371,7 @@ public int removeFirstSimilar(@Nullable UpdateReason updateReason, int amount, I
13581371
@Nullable ItemStack[] items = getUnsafeItems();
13591372

13601373
int leftOver = amount;
1361-
for (int slot : getIterationOrder(IterationOrderCategory.OTHER)) {
1374+
for (int slot : getIterationOrder(OperationCategory.OTHER)) {
13621375
ItemStack item = items[slot];
13631376
if (item != null && item.isSimilar(itemStack)) {
13641377
leftOver -= takeFrom(updateReason, slot, leftOver);

invui/src/main/java/xyz/xenondevs/invui/inventory/ObscuredInventory.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private static int calculateSize(Inventory inventory, IntPredicate isObscured) {
5252
}
5353

5454
@Override
55-
public int[] getIterationOrder(IterationOrderCategory category) {
55+
public int[] getIterationOrder(OperationCategory category) {
5656
int[] iterationOrder = new int[slots.length];
5757
int i = 0;
5858
for (int slot : inventory.getIterationOrder(category)) {
@@ -156,17 +156,17 @@ public boolean hasEventHandlers() {
156156
}
157157

158158
@Override
159-
public int getGuiPriority() {
160-
return inventory.getGuiPriority();
159+
public int getGuiPriority(OperationCategory category) {
160+
return inventory.getGuiPriority(category);
161161
}
162162

163163
@Override
164-
public void setIterationOrder(IterationOrderCategory category, int[] iterationOrder) {
164+
public void setIterationOrder(OperationCategory category, int[] iterationOrder) {
165165
throw new UnsupportedOperationException("Iteration order needs to be set in the backing inventory");
166166
}
167167

168168
@Override
169-
public void setGuiPriority(int guiPriority) {
169+
public void setGuiPriority(int priority) {
170170
throw new UnsupportedOperationException("Gui priority needs to be set in the backing inventory");
171171
}
172172

invui/src/main/java/xyz/xenondevs/invui/inventory/IterationOrderCategory.java renamed to invui/src/main/java/xyz/xenondevs/invui/inventory/OperationCategory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import java.util.function.Predicate;
77

88
/**
9-
* Category of functions that iterate over slots in the inventory.
9+
* Category of inventory-related operations.
1010
*/
11-
public enum IterationOrderCategory {
11+
public enum OperationCategory {
1212

1313
/**
1414
* Operations that add items to the inventory, such as {@link Inventory#addItem(UpdateReason, ItemStack)}.

invui/src/main/java/xyz/xenondevs/invui/inventory/VirtualInventory.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,10 @@ public VirtualInventory(int size) {
160160
*/
161161
public VirtualInventory(VirtualInventory inventory) {
162162
this(inventory.uuid, inventory.size, ItemUtils.clone(inventory.items), inventory.maxStackSizes.clone());
163-
setGuiPriority(inventory.getGuiPriority());
163+
for (var category : OperationCategory.values()) {
164+
setIterationOrder(category, inventory.getIterationOrder(category));
165+
setGuiPriority(category, inventory.getGuiPriority(category));
166+
}
164167
setPreUpdateHandlers(inventory.getPreUpdateHandlers());
165168
setPostUpdateHandlers(inventory.getPostUpdateHandlers());
166169
setResizeHandlers(inventory.getResizeHandlers());

invui/src/main/java/xyz/xenondevs/invui/window/AbstractSplitWindow.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import xyz.xenondevs.invui.gui.SlotElement;
1010
import xyz.xenondevs.invui.internal.menu.CustomContainerMenu;
1111
import xyz.xenondevs.invui.inventory.Inventory;
12-
import xyz.xenondevs.invui.inventory.IterationOrderCategory;
12+
import xyz.xenondevs.invui.inventory.OperationCategory;
1313
import xyz.xenondevs.invui.inventory.ReferencingInventory;
1414

1515
import java.util.function.Supplier;
@@ -57,8 +57,9 @@ protected AbstractGui supplyLowerGui(Player viewer) {
5757
if (lowerGuiSupplier == null) {
5858
AbstractGui gui = (AbstractGui) Gui.empty(9, 4);
5959
Inventory inv = ReferencingInventory.fromPlayerStorageContents(viewer.getInventory());
60-
inv.reverseIterationOrder(IterationOrderCategory.ADD);
61-
inv.setGuiPriority(Integer.MAX_VALUE); // expected vanilla-like behavior: shift-click moves between upper and lower inv
60+
inv.reverseIterationOrder(OperationCategory.ADD); // shift-clicking moves to bottom right
61+
inv.setGuiPriority(OperationCategory.ADD, Integer.MAX_VALUE); // shift-click always moves between upper and lower inv
62+
inv.setGuiPriority(OperationCategory.COLLECT, Integer.MIN_VALUE); // double-click collects from lower inv last
6263
gui.fillRectangle(0, 0, 9, inv, true);
6364
return gui;
6465
}

0 commit comments

Comments
 (0)