Skip to content

Commit b329ad3

Browse files
committed
fix sorting bugs
1 parent cba100f commit b329ad3

4 files changed

Lines changed: 73 additions & 43 deletions

File tree

‎src/main/java/invtweaks/events/ClientEvents.java‎

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
2222
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
2323
import net.minecraft.client.gui.screens.inventory.EffectRenderingInventoryScreen;
24+
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
25+
import net.minecraft.sounds.SoundEvents;
2426
import net.minecraft.world.entity.HumanoidArm;
25-
import net.minecraft.world.entity.player.Inventory;
2627
import net.minecraft.world.entity.player.Player;
2728
import net.minecraft.world.inventory.CraftingContainer;
2829
import net.minecraft.world.inventory.Slot;
@@ -57,6 +58,11 @@ private static void requestSort(boolean isPlayer, String screenClass) {
5758
}
5859
}
5960

61+
private static void requestSortFromInput(boolean isPlayer, String screenClass) {
62+
Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
63+
requestSort(isPlayer, screenClass);
64+
}
65+
6066
//region onScreenEventInit
6167

6268
public static @Nullable Slot getDefaultButtonPlacement(Collection<Slot> slots, Predicate<Slot> filter) {
@@ -75,8 +81,12 @@ private static void requestSort(boolean isPlayer, String screenClass) {
7581
@SubscribeEvent
7682
public static void onScreenEventInit(ScreenEvent.Init.Post event) {
7783
if (event.getScreen() instanceof AbstractContainerScreen<?> screen && !(screen instanceof CreativeModeInventoryScreen)) {
84+
if (InvTweaksConfig.isDebugEnabled()) {
85+
InvTweaksMod.LOGGER.info("Opened screen {} with menu {}", screen.getClass().getName(), screen.getMenu().getClass().getName());
86+
}
87+
7888
// first, work with player inventory
79-
Slot placement = getDefaultButtonPlacement(screen.getMenu().slots, slot -> slot.container instanceof Inventory);
89+
Slot placement = getDefaultButtonPlacement(screen.getMenu().slots, Utils::isPlayerSlot);
8090
if (placement != null
8191
&& InvTweaksConfig.isSortEnabled(true)
8292
&& InvTweaksConfig.isButtonEnabled(true)) {
@@ -102,7 +112,7 @@ public static void onScreenEventInit(ScreenEvent.Init.Post event) {
102112
x = override.getX();
103113
y = override.getY();
104114
}
105-
placement = getDefaultButtonPlacement(screen.getMenu().slots, slot -> !(slot.container instanceof Inventory || slot.container instanceof CraftingContainer));
115+
placement = getDefaultButtonPlacement(screen.getMenu().slots, slot -> slot.isActive() && !(Utils.isPlayerSlot(slot) || slot.container instanceof CraftingContainer));
106116
if (placement != null) {
107117
if (x == InvTweaksConfig.NO_POS_OVERRIDE) {
108118
x = placement.x + 17;
@@ -114,7 +124,8 @@ public static void onScreenEventInit(ScreenEvent.Init.Post event) {
114124

115125
if (InvTweaksConfig.isSortEnabled(false)) {
116126
try {
117-
if (InvTweaksConfig.isButtonEnabled(false)) {
127+
boolean hasButtonPosition = x != InvTweaksConfig.NO_POS_OVERRIDE && y != InvTweaksConfig.NO_POS_OVERRIDE;
128+
if (hasButtonPosition && InvTweaksConfig.isButtonEnabled(false)) {
118129
event.addListener(new InvTweaksButtonSort(screen.getGuiLeft() + x, screen.getGuiTop() + y, btn -> requestSort(false, screen.getClass().getName())));
119130
}
120131
screensWithExtSort.add(screen);
@@ -147,24 +158,24 @@ public static void onKeyPressed(ScreenEvent.KeyPressed.Pre event) {
147158
InvTweaksConfig.isSortEnabled(true) &&
148159
KeyMappings.SORT_PLAYER.isActiveAndMatches(InputConstants.getKey(event.getKeyCode(), event.getScanCode()))
149160
) {
150-
requestSort(true, screen.getClass().getName());
161+
requestSortFromInput(true, screen.getClass().getName());
151162
}
152163
if (
153164
InvTweaksConfig.isSortEnabled(false) &&
154165
screensWithExtSort.contains(event.getScreen()) &&
155166
KeyMappings.SORT_INVENTORY.isActiveAndMatches(InputConstants.getKey(event.getKeyCode(), event.getScanCode()))
156167
) {
157-
requestSort(false, screen.getClass().getName());
168+
requestSortFromInput(false, screen.getClass().getName());
158169
}
159170

160171
Slot slot = screen.getSlotUnderMouse();
161172
if (slot != null) {
162-
boolean isPlayerSort = Utils.isPlayerContainer(slot.container, screen, Minecraft.getInstance().player);;
173+
boolean isPlayerSort = Utils.isPlayerSlot(slot);
163174
if (InvTweaksConfig.isSortEnabled(isPlayerSort)
164175
&& (isPlayerSort || screensWithExtSort.contains(event.getScreen()))
165176
&& KeyMappings.SORT_EITHER.isActiveAndMatches(
166177
InputConstants.getKey(event.getKeyCode(), event.getScanCode()))) {
167-
requestSort(isPlayerSort, screen.getClass().getName());
178+
requestSortFromInput(isPlayerSort, screen.getClass().getName());
168179
}
169180
}
170181
}
@@ -188,9 +199,9 @@ public static void onMouseButtonPressed(ScreenEvent.MouseButtonPressed.Pre event
188199
if (Minecraft.getInstance().player != null && Minecraft.getInstance().player.hasInfiniteMaterials() && !slot.getItem().isEmpty()) {
189200
return;
190201
}
191-
boolean isPlayerSort = Utils.isPlayerContainer(slot.container, screen, Minecraft.getInstance().player);
202+
boolean isPlayerSort = Utils.isPlayerSlot(slot);
192203
if (InvTweaksConfig.isSortEnabled(isPlayerSort) && (isPlayerSort || screensWithExtSort.contains(event.getScreen()))) {
193-
requestSort(isPlayerSort, screen.getClass().getName());
204+
requestSortFromInput(isPlayerSort, screen.getClass().getName());
194205
event.setCanceled(true); // stop pick block event
195206
}
196207
}

‎src/main/java/invtweaks/events/ServerEvents.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import net.neoforged.fml.common.EventBusSubscriber;
1919
import net.neoforged.neoforge.capabilities.Capabilities;
2020
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent;
21+
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
2122
import net.neoforged.neoforge.event.tick.PlayerTickEvent;
2223
import net.neoforged.neoforge.items.IItemHandler;
2324
import net.neoforged.neoforge.network.PacketDistributor;
@@ -70,6 +71,11 @@ public static void onEntityJoin(EntityJoinLevelEvent event) {
7071
}
7172
}
7273

74+
@SubscribeEvent
75+
public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
76+
InvTweaksConfig.clearPlayer(event.getEntity());
77+
}
78+
7379
private static void searchForSubstitute(Player ent, InteractionHand hand, Item item) {
7480
IntList frozen = Optional.ofNullable(InvTweaksConfig.getPlayerRules(ent).catToInventorySlots("/FROZEN"))
7581
.map(IntArrayList::new) // prevent modification

‎src/main/java/invtweaks/util/Sorting.java‎

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
import net.minecraft.world.inventory.ClickType;
2020
import net.minecraft.world.inventory.Slot;
2121
import net.minecraft.world.item.ItemStack;
22+
import net.neoforged.neoforge.items.IItemHandlerModifiable;
2223
import net.neoforged.neoforge.items.SlotItemHandler;
2324
import org.apache.commons.lang3.tuple.Pair;
2425

26+
import javax.annotation.Nullable;
2527
import java.util.*;
2628
import java.util.function.Function;
2729
import java.util.stream.Collectors;
@@ -41,6 +43,10 @@ public static void executeSort(Player player, boolean isPlayerSort, String scree
4143
.<IntList>map(IntArrayList::new) // copy list to prevent modification
4244
.orElseGet(IntArrayList::new);
4345
lockedSlots.addAll(Optional.ofNullable(rules.catToInventorySlots("/FROZEN")).orElse(IntLists.EMPTY_LIST));
46+
player.containerMenu.slots.stream()
47+
.filter(slot -> Utils.isPlayerSlot(slot) && !slot.mayPickup(player))
48+
.mapToInt(Slot::getSlotIndex)
49+
.forEach(lockedSlots::add);
4450
lockedSlots.sort(null);
4551

4652
if (player instanceof ServerPlayer serverPlayer) {
@@ -64,8 +70,8 @@ public static void executeSort(Player player, boolean isPlayerSort, String scree
6470
.filter(idx -> 0 <= idx && idx < cont.slots.size())
6571
.mapToObj(cont.slots::get)
6672
: cont.slots.stream())
67-
.filter(slot -> (slot instanceof SlotItemHandler || slot.container.getContainerSize() > 0) && !(slot.container instanceof Inventory))
68-
.filter(slot -> slot.mayPickup(player) && (slot.mayPlace(slot.getItem()) || !slot.hasItem()))
73+
.filter(slot -> (slot instanceof SlotItemHandler handlerSlot ? handlerSlot.getItemHandler() instanceof IItemHandlerModifiable : slot.container.getContainerSize() > 0) && !Utils.isPlayerSlot(slot))
74+
.filter(slot -> slot.isActive() && slot.mayPickup(player) && (slot.mayPlace(slot.getItem()) || !slot.hasItem()))
6975
.collect(Collectors.toCollection(ArrayList::new));
7076

7177
if (player instanceof ServerPlayer serverPlayer) {
@@ -83,7 +89,7 @@ public static void playerSortClient(Player player, Map<String, Category> cats, R
8389
MultiPlayerGameMode pc = Minecraft.getInstance().gameMode;
8490
Int2ObjectMap<Slot> indexToSlot =
8591
player.containerMenu.slots.stream()
86-
.filter(slot -> slot.container instanceof Inventory)
92+
.filter(Utils::isPlayerSlot)
8793
.filter(slot -> 0 <= slot.getSlotIndex() && slot.getSlotIndex() < 36)
8894
.collect(
8995
Collectors.toMap(
@@ -241,35 +247,38 @@ public static void inventorySortClient(Player player, List<Slot> validSlots) {
241247
}
242248

243249
public static void inventorySortServer(ServerPlayer serverPlayer, List<Slot> validSlots) {
244-
if (!validSlots.iterator().hasNext()) return;
250+
if (validSlots.isEmpty()) return;
245251
List<ItemStack> stacks = Utils.condensed(() -> validSlots.stream()
246252
.map(Slot::getItem)
247253
.filter(st -> !st.isEmpty())
248254
.iterator());
249255
stacks.sort(Utils.FALLBACK_COMPARATOR);
250256

257+
List<Pair<Slot, ItemStack>> placements = new ArrayList<>();
251258
Iterator<Slot> slotIt = validSlots.iterator();
252259
for (ItemStack stack : stacks) {
253-
Slot cur = null;
254-
while (slotIt.hasNext() && !(cur = slotIt.next()).mayPlace(stack)) {
255-
assert true;
256-
}
257-
if (cur == null || !cur.mayPlace(stack)) {
258-
return; // nope right out of the sort
260+
ItemStack remaining = stack.copy();
261+
while (!remaining.isEmpty()) {
262+
Slot cur = nextAcceptingSlot(slotIt, remaining);
263+
if (cur == null) {
264+
return;
265+
}
266+
placements.add(Pair.of(cur, remaining.split(cur.getMaxStackSize(remaining))));
259267
}
260268
}
261269

262-
// execute sort
263270
validSlots.forEach(slot -> slot.set(ItemStack.EMPTY));
264-
slotIt = validSlots.iterator();
265-
for (ItemStack stack : stacks) {
266-
Slot cur = null;
267-
while (slotIt.hasNext() && !(cur = slotIt.next()).mayPlace(stack)) {
268-
assert true;
271+
placements.forEach(placement -> placement.getKey().set(placement.getValue()));
272+
}
273+
274+
private static @Nullable Slot nextAcceptingSlot(Iterator<Slot> slotIt, ItemStack stack) {
275+
while (slotIt.hasNext()) {
276+
Slot slot = slotIt.next();
277+
if (slot.mayPlace(stack) && slot.getMaxStackSize(stack) > 0) {
278+
return slot;
269279
}
270-
assert cur != null;
271-
cur.set(stack);
272280
}
281+
return null;
273282
}
274283

275284
/**

‎src/main/java/invtweaks/util/Utils.java‎

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
import com.google.common.collect.Streams;
55
import it.unimi.dsi.fastutil.ints.IntArrays;
66
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
7-
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
87
import net.minecraft.core.component.DataComponentMap;
98
import net.minecraft.core.registries.BuiltInRegistries;
10-
import net.minecraft.world.Container;
119
import net.minecraft.world.entity.player.Inventory;
12-
import net.minecraft.world.entity.player.Player;
1310
import net.minecraft.world.inventory.Slot;
1411
import net.minecraft.world.item.ItemStack;
12+
import net.neoforged.neoforge.items.IItemHandler;
1513
import net.neoforged.neoforge.items.ItemStackHandler;
14+
import net.neoforged.neoforge.items.SlotItemHandler;
1615
import net.neoforged.neoforge.items.wrapper.InvWrapper;
16+
import net.neoforged.neoforge.items.wrapper.PlayerInvWrapper;
17+
import net.neoforged.neoforge.items.wrapper.PlayerMainInvWrapper;
1718

18-
import javax.annotation.Nullable;
1919
import javax.annotation.ParametersAreNonnullByDefault;
2020
import java.util.*;
2121
import java.util.function.Supplier;
@@ -181,7 +181,12 @@ public static Map<Equivalence.Wrapper<ItemStack>, Set<Slot>> gatheredSlots(
181181
public static List<ItemStack> condensed(Iterable<ItemStack> iterable) {
182182
List<ItemStack> coll = collated(iterable, ArrayList::new);
183183
// TODO special handling for Nether Chests-esque mods?
184-
ItemStackHandler stackBuffer = new ItemStackHandler(coll.size());
184+
ItemStackHandler stackBuffer = new ItemStackHandler(coll.size()) {
185+
@Override
186+
public int getSlotLimit(int slot) {
187+
return Integer.MAX_VALUE;
188+
}
189+
};
185190
int index = 0;
186191
for (ItemStack stack : coll) {
187192
stack = stack.copy();
@@ -195,16 +200,15 @@ public static List<ItemStack> condensed(Iterable<ItemStack> iterable) {
195200
.collect(Collectors.toCollection(ArrayList::new));
196201
}
197202

198-
199-
public static boolean isPlayerContainer(Container container, AbstractContainerScreen<?> screen, @Nullable Player player) {
200-
Slot slot = screen.getSlotUnderMouse();
201-
if (slot != null) {
202-
if (slot.container instanceof InvWrapper invWrapper) {
203-
return invWrapper.getInv() instanceof Inventory;
204-
}
205-
if (slot.container instanceof Inventory) {
206-
return true;
207-
}
203+
public static boolean isPlayerSlot(Slot slot) {
204+
if (slot.container instanceof Inventory) {
205+
return true;
206+
}
207+
if (slot instanceof SlotItemHandler handlerSlot) {
208+
IItemHandler handler = handlerSlot.getItemHandler();
209+
return handler instanceof PlayerMainInvWrapper
210+
|| handler instanceof PlayerInvWrapper
211+
|| (handler instanceof InvWrapper invWrapper && invWrapper.getInv() instanceof Inventory);
208212
}
209213
return false;
210214
}

0 commit comments

Comments
 (0)