Skip to content

Commit 1a9e766

Browse files
committed
fix crafting
1 parent 987e3ac commit 1a9e766

File tree

5 files changed

+169
-31
lines changed

5 files changed

+169
-31
lines changed

src/main/java/com/cleanroommc/modularui/screen/ModularContainer.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.cleanroommc.modularui.core.mixin.ContainerAccessor;
55
import com.cleanroommc.modularui.factory.GuiData;
66
import com.cleanroommc.modularui.network.NetworkUtils;
7+
import com.cleanroommc.modularui.utils.Platform;
78
import com.cleanroommc.modularui.value.sync.ModularSyncManager;
89
import com.cleanroommc.modularui.value.sync.PanelSyncManager;
910
import com.cleanroommc.modularui.widgets.slot.ModularSlot;
@@ -218,7 +219,7 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
218219

219220
@Override
220221
public @NotNull ItemStack slotClick(int slotId, int mouseButton, @NotNull ClickType clickTypeIn, @NotNull EntityPlayer player) {
221-
ItemStack returnable = ItemStack.EMPTY;
222+
ItemStack returnable = Platform.EMPTY_STACK;
222223
InventoryPlayer inventoryplayer = player.inventory;
223224

224225
if (clickTypeIn == ClickType.QUICK_CRAFT || acc().getDragEvent() != 0) {
@@ -232,7 +233,7 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
232233
if (!inventoryplayer.getItemStack().isEmpty()) {
233234
if (mouseButton == LEFT_MOUSE) {
234235
player.dropItem(inventoryplayer.getItemStack(), true);
235-
inventoryplayer.setItemStack(ItemStack.EMPTY);
236+
inventoryplayer.setItemStack(Platform.EMPTY_STACK);
236237
}
237238

238239
if (mouseButton == RIGHT_MOUSE) {
@@ -243,16 +244,20 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
243244
}
244245

245246
// early return
246-
if (slotId < 0) return ItemStack.EMPTY;
247+
if (slotId < 0) return Platform.EMPTY_STACK;
247248

248249
if (clickTypeIn == ClickType.QUICK_MOVE) {
249250
Slot fromSlot = getSlot(slotId);
250251

251252
if (!fromSlot.canTakeStack(player)) {
252-
return ItemStack.EMPTY;
253+
return Platform.EMPTY_STACK;
253254
}
254-
// simpler code, but effectivly no difference
255-
returnable = transferStackInSlot(player, slotId);
255+
// looping so that crafting works properly
256+
ItemStack remainder;
257+
do {
258+
remainder = transferStackInSlot(player, slotId);
259+
returnable = Platform.copyStack(remainder);
260+
} while (!Platform.isStackEmpty(remainder) && ItemHandlerHelper.canItemStacksStack(fromSlot.getStack(), remainder));
256261
} else {
257262
Slot clickedSlot = getSlot(slotId);
258263

@@ -306,7 +311,7 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
306311
slotStack = clickedSlot.decrStackSize(stackCount);
307312

308313
if (slotStack.isEmpty()) {
309-
clickedSlot.putStack(ItemStack.EMPTY);
314+
clickedSlot.putStack(Platform.EMPTY_STACK);
310315
}
311316

312317
clickedSlot.onTake(player, inventoryplayer.getItemStack());
@@ -339,7 +344,7 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
339344
itemstack1.grow(i1);
340345

341346
if (itemstack3.isEmpty()) {
342-
slot1.putStack(ItemStack.EMPTY);
347+
slot1.putStack(Platform.EMPTY_STACK);
343348
}
344349

345350
slot1.onTake(player, itemstack3);
@@ -356,7 +361,7 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
356361
ItemStack hotbarStack = inventoryplayer.getStackInSlot(mouseButton);
357362
if (phantom.isPhantom()) {
358363
// insert stack from hotbar slot into phantom slot
359-
phantom.putStack(hotbarStack.isEmpty() ? ItemStack.EMPTY : hotbarStack.copy());
364+
phantom.putStack(hotbarStack.isEmpty() ? Platform.EMPTY_STACK : hotbarStack.copy());
360365
detectAndSendChanges();
361366
return returnable;
362367
}
@@ -375,20 +380,25 @@ public boolean canInteractWith(@NotNull EntityPlayer playerIn) {
375380
if (!slot.isPhantom()) {
376381
ItemStack stack = slot.getStack();
377382
if (!stack.isEmpty()) {
383+
ItemStack copy = stack.copy();
378384
stack = stack.copy();
379385
int base = 0;
380386
if (stack.getCount() > stack.getMaxStackSize()) {
381387
base = stack.getCount() - stack.getMaxStackSize();
382388
stack.setCount(stack.getMaxStackSize());
383389
}
384390
ItemStack remainder = transferItem(slot, stack.copy());
385-
if (base == 0 && remainder.isEmpty()) stack = ItemStack.EMPTY;
391+
if (ItemStack.areItemStacksEqual(remainder, stack)) return Platform.EMPTY_STACK;
392+
if (base == 0 && remainder.isEmpty()) stack = Platform.EMPTY_STACK;
386393
else stack.setCount(base + remainder.getCount());
387394
slot.putStack(stack);
388-
return ItemStack.EMPTY;
395+
slot.onSlotChange(remainder, copy);
396+
slot.onTake(playerIn, remainder);
397+
slot.onCraftShiftClick(playerIn, remainder);
398+
return copy; // return a non-empty stack if insertion was successful, this causes this function to be called again, important for crafting
389399
}
390400
}
391-
return ItemStack.EMPTY;
401+
return Platform.EMPTY_STACK;
392402
}
393403

394404
protected ItemStack transferItem(ModularSlot fromSlot, ItemStack fromStack) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.cleanroommc.modularui.utils;
2+
3+
import net.minecraft.item.ItemStack;
4+
5+
/**
6+
* Version specific code is supposed to go here.
7+
* Ideally only the body of methods and value of fields should be changed and no signatures.
8+
*/
9+
public class Platform {
10+
11+
public static final ItemStack EMPTY_STACK = ItemStack.EMPTY;
12+
13+
public static boolean isStackEmpty(ItemStack stack) {
14+
return stack == null || stack.isEmpty();
15+
}
16+
17+
public static ItemStack copyStack(ItemStack stack) {
18+
return isStackEmpty(stack) ? EMPTY_STACK : stack.copy();
19+
}
20+
}
Lines changed: 112 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.cleanroommc.modularui.widgets.slot;
22

33
import com.cleanroommc.modularui.core.mixin.InventoryCraftingAccessor;
4+
import com.cleanroommc.modularui.utils.Platform;
45

6+
import net.minecraft.client.util.RecipeItemHelper;
57
import net.minecraft.inventory.Container;
68
import net.minecraft.inventory.InventoryCrafting;
79
import net.minecraft.item.ItemStack;
@@ -10,47 +12,62 @@
1012
import net.minecraftforge.items.IItemHandlerModifiable;
1113
import net.minecraftforge.items.ItemHandlerHelper;
1214

15+
import org.jetbrains.annotations.NotNull;
16+
17+
/**
18+
* A crafting inventory which wraps a {@link IItemHandlerModifiable}. This inventory creates a content list which is here used to detect
19+
* changes from the item handler. This is required as interacting with a slot will update the content, but will not notify the container
20+
* to check for new recipes.
21+
*/
1322
public class InventoryCraftingWrapper extends InventoryCrafting {
1423

15-
private final IItemHandler delegate;
24+
private final IItemHandlerModifiable delegate;
25+
private final int size;
1626
private final int startIndex;
17-
private final ItemStack[] snapshot;
1827

1928
public InventoryCraftingWrapper(Container eventHandlerIn, int width, int height, IItemHandlerModifiable delegate, int startIndex) {
2029
super(eventHandlerIn, width, height);
30+
this.size = width * height + 1;
31+
if (startIndex + this.size < delegate.getSlots()) {
32+
throw new IllegalArgumentException("Inventory does not have enough slots for given size. Requires " + (startIndex + this.size) + " slots, but only has " + delegate.getSlots() + " slots!");
33+
}
2134
this.delegate = delegate;
2235
this.startIndex = startIndex;
23-
this.snapshot = new ItemStack[width * height];
24-
// save inventory snapshot
25-
for (int i = 0; i < snapshot.length; i++) {
36+
for (int i = 0; i < this.size - 1; i++) {
2637
ItemStack stack = this.delegate.getStackInSlot(i + this.startIndex);
2738
updateSnapshot(i, stack);
28-
getBackingList().set(i, stack.isEmpty() ? ItemStack.EMPTY : stack.copy());
2939
}
3040
}
3141

3242
private NonNullList<ItemStack> getBackingList() {
3343
return ((InventoryCraftingAccessor) this).getStackList();
3444
}
3545

36-
public Container getEventHandler() {
46+
public Container getContainer() {
3747
return ((InventoryCraftingAccessor) this).getEventHandler();
3848
}
3949

4050
private void updateSnapshot(int index, ItemStack stack) {
41-
this.snapshot[index] = stack.isEmpty() ? ItemStack.EMPTY : stack.copy();
51+
getBackingList().set(index, Platform.copyStack(stack));
4252
}
4353

4454
public void detectChanges() {
4555
// detect changes from snapshot and notify container
46-
for (int i = 0; i < snapshot.length; i++) {
47-
ItemStack stack = snapshot[i];
56+
boolean notify = false;
57+
for (int i = 0; i < this.size - 1; i++) {
58+
ItemStack stack = getBackingList().get(i);
4859
ItemStack current = this.delegate.getStackInSlot(i + this.startIndex);
49-
if (stack.isEmpty() != current.isEmpty() || (!stack.isEmpty() && !ItemHandlerHelper.canItemStacksStack(stack, current))) {
50-
setInventorySlotContents(i, current);
60+
if (Platform.isStackEmpty(current) && current != Platform.EMPTY_STACK) {
61+
current = Platform.EMPTY_STACK;
62+
this.delegate.setStackInSlot(i + this.startIndex, Platform.EMPTY_STACK);
63+
}
64+
if (Platform.isStackEmpty(stack) != Platform.isStackEmpty(current) ||
65+
(!Platform.isStackEmpty(stack) && !ItemHandlerHelper.canItemStacksStack(stack, current))) {
5166
updateSnapshot(i, current);
67+
notify = true;
5268
}
5369
}
70+
if (notify) notifyContainer();
5471
}
5572

5673
public IItemHandler getDelegate() {
@@ -60,4 +77,87 @@ public IItemHandler getDelegate() {
6077
public int getStartIndex() {
6178
return startIndex;
6279
}
80+
81+
@Override
82+
public int getSizeInventory() {
83+
return size;
84+
}
85+
86+
@Override
87+
public boolean isEmpty() {
88+
for (int i = 0; i < this.size; i++) {
89+
if (!Platform.isStackEmpty(getStackInSlot(i))) {
90+
return false;
91+
}
92+
}
93+
return true;
94+
}
95+
96+
@Override
97+
public @NotNull ItemStack getStackInSlot(int index) {
98+
index += this.startIndex;
99+
return index >= 0 && index < this.size ? this.delegate.getStackInSlot(index) : Platform.EMPTY_STACK;
100+
}
101+
102+
@Override
103+
public void setInventorySlotContents(int index, @NotNull ItemStack stack) {
104+
setSlot(index, stack, true);
105+
}
106+
107+
public void setSlot(int index, @NotNull ItemStack stack, boolean notifyContainer) {
108+
this.delegate.setStackInSlot(this.startIndex + index, stack);
109+
if (notifyContainer) notifyContainer();
110+
}
111+
112+
@Override
113+
public @NotNull ItemStack decrStackSize(int index, int count) {
114+
return decrStackSize(index, count, true);
115+
}
116+
117+
public ItemStack decrStackSize(int index, int count, boolean notifyContainer) {
118+
index += this.startIndex;
119+
if (index < 0 || index >= this.size || count <= 0) return Platform.EMPTY_STACK;
120+
ItemStack stack = getStackInSlot(index);
121+
if (Platform.isStackEmpty(stack)) return Platform.EMPTY_STACK;
122+
stack.splitStack(count);
123+
if (Platform.isStackEmpty(stack)) {
124+
setSlot(index, Platform.EMPTY_STACK, false);
125+
}
126+
if (notifyContainer) {
127+
notifyContainer();
128+
}
129+
return stack;
130+
}
131+
132+
@Override
133+
public @NotNull ItemStack removeStackFromSlot(int index) {
134+
return removeStackFromSlot(index, true);
135+
}
136+
137+
public @NotNull ItemStack removeStackFromSlot(int index, boolean notifyContainer) {
138+
index += this.startIndex;
139+
if (index < 0 || index >= this.size) return Platform.EMPTY_STACK;
140+
ItemStack stack = getStackInSlot(index);
141+
this.delegate.setStackInSlot(index, Platform.EMPTY_STACK);
142+
if (notifyContainer) notifyContainer();
143+
return stack;
144+
}
145+
146+
@Override
147+
public void clear() {
148+
for (int i = 0; i < this.size; i++) {
149+
setSlot(i, Platform.EMPTY_STACK, false);
150+
}
151+
}
152+
153+
@Override
154+
public void fillStackedContents(@NotNull RecipeItemHelper helper) {
155+
for (int i = 0; i < this.size; i++) {
156+
helper.accountStack(getStackInSlot(i));
157+
}
158+
}
159+
160+
public void notifyContainer() {
161+
getContainer().onCraftMatrixChanged(this);
162+
}
63163
}

src/main/java/com/cleanroommc/modularui/widgets/slot/ModularCraftingSlot.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.cleanroommc.modularui.widgets.slot;
22

33
import net.minecraft.entity.player.EntityPlayer;
4-
import net.minecraft.inventory.InventoryCrafting;
54
import net.minecraft.item.ItemStack;
65
import net.minecraft.item.crafting.CraftingManager;
76
import net.minecraft.item.crafting.IRecipe;
@@ -17,7 +16,7 @@
1716
*/
1817
public class ModularCraftingSlot extends ModularSlot {
1918

20-
private InventoryCrafting craftMatrix;
19+
private InventoryCraftingWrapper craftMatrix;
2120
private IRecipe recipeUsed;
2221
private int amountCrafted;
2322

@@ -74,6 +73,13 @@ protected void onCrafting(@NotNull ItemStack stack) {
7473
}
7574
}
7675

76+
@Override
77+
public void onCraftShiftClick(EntityPlayer player, ItemStack stack) {
78+
if (!stack.isEmpty()) {
79+
player.dropItem(stack, false);
80+
}
81+
}
82+
7783
@Override
7884
public @NotNull ItemStack onTake(@NotNull EntityPlayer thePlayer, @NotNull ItemStack stack) {
7985
net.minecraftforge.common.ForgeHooks.setCraftingPlayer(thePlayer);
@@ -85,22 +91,22 @@ protected void onCrafting(@NotNull ItemStack stack) {
8591
ItemStack itemstack1 = nonnulllist.get(i);
8692

8793
if (!itemstack.isEmpty()) {
88-
this.craftMatrix.decrStackSize(i, 1);
94+
this.craftMatrix.decrStackSize(i, 1, false);
8995
itemstack = this.craftMatrix.getStackInSlot(i);
9096
}
9197

9298
if (!itemstack1.isEmpty()) {
9399
if (itemstack.isEmpty()) {
94-
this.craftMatrix.setInventorySlotContents(i, itemstack1);
100+
this.craftMatrix.setSlot(i, itemstack1, false);
95101
} else if (ItemStack.areItemsEqual(itemstack, itemstack1) && ItemStack.areItemStackTagsEqual(itemstack, itemstack1)) {
96102
itemstack1.grow(itemstack.getCount());
97-
this.craftMatrix.setInventorySlotContents(i, itemstack1);
103+
this.craftMatrix.setSlot(i, itemstack1, false);
98104
} else if (!thePlayer.inventory.addItemStackToInventory(itemstack1)) {
99105
thePlayer.dropItem(itemstack1, false);
100106
}
101107
}
102108
}
103-
109+
this.craftMatrix.notifyContainer();
104110
return stack;
105111
}
106112

@@ -113,7 +119,7 @@ public void setRecipeUsed(IRecipe recipeUsed) {
113119
this.recipeUsed = recipeUsed;
114120
}
115121

116-
public void setCraftMatrix(InventoryCrafting craftMatrix) {
122+
public void setCraftMatrix(InventoryCraftingWrapper craftMatrix) {
117123
this.craftMatrix = craftMatrix;
118124
}
119125
}

src/main/java/com/cleanroommc/modularui/widgets/slot/ModularSlot.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ public void onSlotChangedReal(ItemStack itemStack, boolean onlyChangedAmount, bo
8383
if (!init && isInitialized()) getSyncHandler().getSyncManager().getContainer().onSlotChanged(this, itemStack, onlyChangedAmount);
8484
}
8585

86+
public void onCraftShiftClick(EntityPlayer player, ItemStack stack) {}
87+
8688
@Override
8789
public void putStack(@NotNull ItemStack stack) {
8890
if (ItemStack.areItemStacksEqual(stack, getStack())) return;

0 commit comments

Comments
 (0)