Skip to content

Commit 664271f

Browse files
committed
fix: 🐛 Fixed interaction for items that allow other items stacking on them in Sophisticated Guis
1 parent 3be3255 commit 664271f

7 files changed

Lines changed: 207 additions & 42 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ loader_version_range=[4,)
1313
mod_id=sophisticatedcore
1414
mod_name=Sophisticated Core
1515
mod_license=All Rights Reserved
16-
mod_version=1.3.58
16+
mod_version=1.3.59
1717
mod_group_id=sophisticatedcore
1818
mod_authors=P3pp3rF1y
1919
mod_description=A library / shared functionality mod for Sophisticated Storage and Backpacks

src/main/java/net/p3pp3rf1y/sophisticatedcore/common/gui/SlotSuppliedHandler.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import net.minecraft.world.item.ItemStack;
44
import net.neoforged.neoforge.items.IItemHandler;
55
import net.neoforged.neoforge.items.SlotItemHandler;
6+
import net.p3pp3rf1y.sophisticatedcore.inventory.ISlotChangeListener;
67

78
import java.util.function.Supplier;
89

@@ -31,4 +32,12 @@ public boolean mayPlace(ItemStack stack) {
3132
public int getMaxStackSize() {
3233
return itemHandlerSupplier.get().getSlotLimit(slot);
3334
}
35+
36+
@Override
37+
public void setChanged() {
38+
super.setChanged();
39+
if (itemHandlerSupplier.get() instanceof ISlotChangeListener contentsChangeListener) {
40+
contentsChangeListener.onSlotChanged(slot);
41+
}
42+
}
3443
}

src/main/java/net/p3pp3rf1y/sophisticatedcore/common/gui/StorageContainerMenuBase.java

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,43 +1172,39 @@ protected void doClick(int slotId, int dragType, ClickType clickType, Player pla
11721172
ItemStack slotStack = slot7.getItem();
11731173
ItemStack carriedStack = getCarried();
11741174
player.updateTutorialInventoryAction(carriedStack, slot7.getItem(), clickaction);
1175-
if (!carriedStack.overrideStackedOnOther(slot7, clickaction, player)) {
1176-
if (!slotStack.overrideOtherStackedOnMe(carriedStack, slot7, clickaction, player, createCarriedSlotAccess())) {
1177-
if (slotStack.isEmpty()) {
1178-
if (!carriedStack.isEmpty()) {
1179-
int l2 = clickaction == ClickAction.PRIMARY ? carriedStack.getCount() : 1;
1180-
setCarried(slot7.safeInsert(carriedStack, l2));
1175+
if (!carriedStack.overrideStackedOnOther(slot7, clickaction, player) && !slotStack.overrideOtherStackedOnMe(carriedStack, slot7, clickaction, player, createCarriedSlotAccess())) {
1176+
if (slotStack.isEmpty()) {
1177+
if (!carriedStack.isEmpty()) {
1178+
int l2 = clickaction == ClickAction.PRIMARY ? carriedStack.getCount() : 1;
1179+
setCarried(slot7.safeInsert(carriedStack, l2));
1180+
}
1181+
} else if (slot7.mayPickup(player)) {
1182+
if (carriedStack.isEmpty()) {
1183+
int countToRemove;
1184+
countToRemove = Math.min(slotStack.getCount(), slotStack.getMaxStackSize());
1185+
if (clickaction == ClickAction.SECONDARY) {
1186+
countToRemove = countToRemove / 2 + countToRemove % 2;
11811187
}
1182-
} else if (slot7.mayPickup(player)) {
1183-
if (carriedStack.isEmpty()) {
1184-
int countToRemove;
1185-
countToRemove = Math.min(slotStack.getCount(), slotStack.getMaxStackSize());
1186-
if (clickaction == ClickAction.SECONDARY) {
1187-
countToRemove = countToRemove / 2 + countToRemove % 2;
1188-
}
1189-
Optional<ItemStack> optional1 = slot7.tryRemove(countToRemove, Integer.MAX_VALUE, player);
1190-
optional1.ifPresent((p_150421_) -> {
1191-
setCarried(p_150421_);
1192-
slot7.onTake(player, p_150421_);
1193-
});
1194-
} else if (slot7.mayPlace(carriedStack)) {
1195-
if (ItemStack.isSameItemSameComponents(slotStack, carriedStack)) {
1196-
int j3 = clickaction == ClickAction.PRIMARY ? carriedStack.getCount() : 1;
1197-
setCarried(slot7.safeInsert(carriedStack, j3));
1198-
} else if (carriedStack.getCount() <= slot7.getMaxStackSize(carriedStack) && slotStack.getCount() <= slotStack.getMaxStackSize()) {
1199-
slot7.set(carriedStack);
1200-
setCarried(slotStack);
1201-
}
1202-
} else if (ItemStack.isSameItemSameComponents(slotStack, carriedStack)) {
1203-
Optional<ItemStack> optional = slot7.tryRemove(slotStack.getCount(), carriedStack.getMaxStackSize() - carriedStack.getCount(), player);
1204-
optional.ifPresent((p_150428_) -> {
1205-
carriedStack.grow(p_150428_.getCount());
1206-
slot7.onTake(player, p_150428_);
1207-
});
1188+
Optional<ItemStack> optional1 = slot7.tryRemove(countToRemove, Integer.MAX_VALUE, player);
1189+
optional1.ifPresent((p_150421_) -> {
1190+
setCarried(p_150421_);
1191+
slot7.onTake(player, p_150421_);
1192+
});
1193+
} else if (slot7.mayPlace(carriedStack)) {
1194+
if (ItemStack.isSameItemSameComponents(slotStack, carriedStack)) {
1195+
int j3 = clickaction == ClickAction.PRIMARY ? carriedStack.getCount() : 1;
1196+
setCarried(slot7.safeInsert(carriedStack, j3));
1197+
} else if (carriedStack.getCount() <= slot7.getMaxStackSize(carriedStack) && slotStack.getCount() <= slotStack.getMaxStackSize()) {
1198+
slot7.set(carriedStack);
1199+
setCarried(slotStack);
12081200
}
1201+
} else if (ItemStack.isSameItemSameComponents(slotStack, carriedStack)) {
1202+
Optional<ItemStack> optional = slot7.tryRemove(slotStack.getCount(), carriedStack.getMaxStackSize() - carriedStack.getCount(), player);
1203+
optional.ifPresent((p_150428_) -> {
1204+
carriedStack.grow(p_150428_.getCount());
1205+
slot7.onTake(player, p_150428_);
1206+
});
12091207
}
1210-
} else {
1211-
slot7.set(slotStack);
12121208
}
12131209
}
12141210

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package net.p3pp3rf1y.sophisticatedcore.inventory;
2+
3+
public interface ISlotChangeListener {
4+
void onSlotChanged(int slot);
5+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright (c) Forge Development LLC and contributors
3+
* SPDX-License-Identifier: LGPL-2.1-only
4+
*/
5+
6+
package net.p3pp3rf1y.sophisticatedcore.inventory;
7+
8+
import com.google.common.base.Preconditions;
9+
import net.minecraft.core.NonNullList;
10+
import net.minecraft.core.component.DataComponentType;
11+
import net.minecraft.world.item.Item;
12+
import net.minecraft.world.item.ItemStack;
13+
import net.minecraft.world.item.component.ItemContainerContents;
14+
import net.neoforged.neoforge.common.MutableDataComponentHolder;
15+
import net.neoforged.neoforge.items.IItemHandlerModifiable;
16+
17+
public class StatefulComponentItemHandler implements IItemHandlerModifiable, ISlotChangeListener {
18+
protected NonNullList<ItemStack> stacks;
19+
protected final MutableDataComponentHolder parent;
20+
protected final DataComponentType<ItemContainerContents> component;
21+
protected final int size;
22+
23+
public StatefulComponentItemHandler(MutableDataComponentHolder parent, DataComponentType<ItemContainerContents> component, int size) {
24+
this.parent = parent;
25+
this.component = component;
26+
this.size = size;
27+
Preconditions.checkArgument(size <= 256, "The max size of ItemContainerContents is 256 slots.");
28+
fillStacks();
29+
}
30+
31+
private void fillStacks() {
32+
ItemContainerContents contents = getContents();
33+
stacks = NonNullList.withSize(size, ItemStack.EMPTY);
34+
contents.copyInto(stacks);
35+
}
36+
37+
@Override
38+
public int getSlots() {
39+
return size;
40+
}
41+
42+
@Override
43+
public ItemStack getStackInSlot(int slot) {
44+
validateSlotIndex(slot);
45+
return stacks.get(slot);
46+
}
47+
48+
@Override
49+
public void setStackInSlot(int slot, ItemStack stack) {
50+
validateSlotIndex(slot);
51+
if (!isItemValid(slot, stack)) {
52+
throw new RuntimeException("Invalid stack " + stack + " for slot " + slot + ")");
53+
}
54+
ItemStack existing = stacks.get(slot);
55+
if (!ItemStack.matches(stack, existing)) {
56+
updateContents(stack, slot);
57+
}
58+
}
59+
60+
@Override
61+
public ItemStack insertItem(int slot, ItemStack toInsert, boolean simulate) {
62+
validateSlotIndex(slot);
63+
64+
if (toInsert.isEmpty()) {
65+
return ItemStack.EMPTY;
66+
}
67+
68+
if (!isItemValid(slot, toInsert)) {
69+
return toInsert;
70+
}
71+
72+
ItemStack existing = stacks.get(slot);
73+
74+
int insertLimit = Math.min(getSlotLimit(slot), toInsert.getMaxStackSize());
75+
76+
if (!existing.isEmpty()) {
77+
if (!ItemStack.isSameItemSameComponents(toInsert, existing)) {
78+
return toInsert;
79+
}
80+
81+
insertLimit -= existing.getCount();
82+
}
83+
84+
if (insertLimit <= 0) {
85+
return toInsert;
86+
}
87+
88+
int inserted = Math.min(insertLimit, toInsert.getCount());
89+
90+
if (!simulate) {
91+
updateContents(toInsert.copyWithCount(existing.getCount() + inserted), slot);
92+
}
93+
94+
return toInsert.copyWithCount(toInsert.getCount() - inserted);
95+
}
96+
97+
@Override
98+
public ItemStack extractItem(int slot, int amount, boolean simulate) {
99+
validateSlotIndex(slot);
100+
101+
if (amount == 0) {
102+
return ItemStack.EMPTY;
103+
}
104+
105+
ItemStack existing = stacks.get(slot);
106+
107+
if (existing.isEmpty()) {
108+
return ItemStack.EMPTY;
109+
}
110+
111+
int toExtract = Math.min(amount, existing.getMaxStackSize());
112+
113+
if (!simulate) {
114+
updateContents(existing.copyWithCount(existing.getCount() - toExtract), slot);
115+
}
116+
117+
return existing.copyWithCount(toExtract);
118+
}
119+
120+
@Override
121+
public int getSlotLimit(int slot) {
122+
return Item.ABSOLUTE_MAX_STACK_SIZE;
123+
}
124+
125+
@Override
126+
public boolean isItemValid(int slot, ItemStack stack) {
127+
return stack.getItem().canFitInsideContainerItems();
128+
}
129+
130+
protected void onContentsChanged(int slot, ItemStack oldStack, ItemStack newStack) {
131+
}
132+
133+
protected ItemContainerContents getContents() {
134+
return parent.getOrDefault(component, ItemContainerContents.EMPTY);
135+
}
136+
137+
protected void updateContents(ItemStack stack, int slot) {
138+
validateSlotIndex(slot);
139+
ItemStack oldStack = stacks.get(slot);
140+
stacks.set(slot, stack);
141+
parent.set(component, ItemContainerContents.fromItems(stacks));
142+
onContentsChanged(slot, oldStack, stack);
143+
}
144+
145+
protected final void validateSlotIndex(int slot) {
146+
if (slot < 0 || slot >= getSlots()) {
147+
throw new RuntimeException("Slot " + slot + " not in valid range - [0," + getSlots() + ")");
148+
}
149+
}
150+
151+
@Override
152+
public void onSlotChanged(int slot) {
153+
updateContents(getStackInSlot(slot), slot);
154+
}
155+
}

src/main/java/net/p3pp3rf1y/sophisticatedcore/upgrades/crafting/CraftingUpgradeWrapper.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
import net.minecraft.core.component.DataComponents;
44
import net.minecraft.world.item.ItemStack;
5-
import net.neoforged.neoforge.items.ComponentItemHandler;
65
import net.p3pp3rf1y.sophisticatedcore.api.IStorageWrapper;
76
import net.p3pp3rf1y.sophisticatedcore.init.ModCoreDataComponents;
7+
import net.p3pp3rf1y.sophisticatedcore.inventory.StatefulComponentItemHandler;
88
import net.p3pp3rf1y.sophisticatedcore.upgrades.UpgradeWrapperBase;
99

1010
import java.util.function.Consumer;
1111

1212
public class CraftingUpgradeWrapper extends UpgradeWrapperBase<CraftingUpgradeWrapper, CraftingUpgradeItem> {
13-
private final ComponentItemHandler inventory;
13+
private final StatefulComponentItemHandler inventory;
1414

1515
public CraftingUpgradeWrapper(IStorageWrapper storageWrapper, ItemStack upgrade, Consumer<ItemStack> upgradeSaveHandler) {
1616
super(storageWrapper, upgrade, upgradeSaveHandler);
1717

18-
inventory = new ComponentItemHandler(upgrade, DataComponents.CONTAINER, 9) {
18+
inventory = new StatefulComponentItemHandler(upgrade, DataComponents.CONTAINER, 9) {
1919
@Override
2020
protected void onContentsChanged(int slot, ItemStack oldStack, ItemStack newStack) {
2121
super.onContentsChanged(slot, oldStack, newStack);
@@ -29,7 +29,7 @@ public boolean isItemValid(int slot, ItemStack stack) {
2929
};
3030
}
3131

32-
public ComponentItemHandler getInventory() {
32+
public StatefulComponentItemHandler getInventory() {
3333
return inventory;
3434
}
3535

src/main/java/net/p3pp3rf1y/sophisticatedcore/upgrades/jukebox/JukeboxUpgradeWrapper.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import net.minecraft.world.item.JukeboxSong;
1111
import net.minecraft.world.level.Level;
1212
import net.minecraft.world.phys.Vec3;
13-
import net.neoforged.neoforge.items.ComponentItemHandler;
1413
import net.neoforged.neoforge.items.IItemHandler;
1514
import net.p3pp3rf1y.sophisticatedcore.api.IStorageWrapper;
1615
import net.p3pp3rf1y.sophisticatedcore.init.ModCoreDataComponents;
16+
import net.p3pp3rf1y.sophisticatedcore.inventory.StatefulComponentItemHandler;
1717
import net.p3pp3rf1y.sophisticatedcore.upgrades.ITickableUpgrade;
1818
import net.p3pp3rf1y.sophisticatedcore.upgrades.UpgradeWrapperBase;
1919

@@ -23,7 +23,7 @@
2323

2424
public class JukeboxUpgradeWrapper extends UpgradeWrapperBase<JukeboxUpgradeWrapper, JukeboxUpgradeItem> implements ITickableUpgrade {
2525
private static final int KEEP_ALIVE_SEND_INTERVAL = 5;
26-
private final ComponentItemHandler discInventory;
26+
private final StatefulComponentItemHandler discInventory;
2727
private long lastKeepAliveSendTime = 0;
2828
private boolean isPlaying;
2929

@@ -44,7 +44,7 @@ public class JukeboxUpgradeWrapper extends UpgradeWrapperBase<JukeboxUpgradeWrap
4444

4545
protected JukeboxUpgradeWrapper(IStorageWrapper storageWrapper, ItemStack upgrade, Consumer<ItemStack> upgradeSaveHandler) {
4646
super(storageWrapper, upgrade, upgradeSaveHandler);
47-
discInventory = new ComponentItemHandler(upgrade, DataComponents.CONTAINER, upgradeItem.getNumberOfSlots()) {
47+
discInventory = new StatefulComponentItemHandler(upgrade, DataComponents.CONTAINER, upgradeItem.getNumberOfSlots()) {
4848
@Override
4949
protected void onContentsChanged(int slot, ItemStack oldStack, ItemStack newStack) {
5050
super.onContentsChanged(slot, oldStack, newStack);

0 commit comments

Comments
 (0)