Skip to content

Commit 449db11

Browse files
committed
Fix Issues with Sticky Card and Crafting
Impl AE2-UEL/Applied-Energistics-2#533
1 parent 4860fc7 commit 449db11

2 files changed

Lines changed: 177 additions & 1 deletion

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
package com.nomiceu.nomilabs.mixin.ae2;
2+
3+
import java.util.*;
4+
5+
import org.spongepowered.asm.mixin.Final;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.Shadow;
8+
import org.spongepowered.asm.mixin.Unique;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Inject;
11+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
13+
14+
import appeng.api.config.Actionable;
15+
import appeng.api.config.SecurityPermissions;
16+
import appeng.api.networking.crafting.ICraftingGrid;
17+
import appeng.api.networking.security.IActionSource;
18+
import appeng.api.storage.IMEInventoryHandler;
19+
import appeng.api.storage.data.IAEStack;
20+
import appeng.api.storage.data.IItemList;
21+
import appeng.me.storage.NetworkInventoryHandler;
22+
23+
/**
24+
* Apply <a href="https://github.com/AE2-UEL/Applied-Energistics-2/pull/533">AE2 #533</a> for v0.56.5.
25+
*/
26+
@Mixin(value = NetworkInventoryHandler.class, remap = false)
27+
public abstract class NetworkInventoryHandlerMixin<T extends IAEStack<T>> {
28+
29+
@Shadow
30+
@Final
31+
private static Comparator<Integer> PRIORITY_SORTER;
32+
33+
@Shadow
34+
@Final
35+
private NavigableMap<Integer, List<IMEInventoryHandler<T>>> priorityInventory;
36+
37+
@Shadow
38+
@Final
39+
private NavigableMap<Integer, List<IMEInventoryHandler<T>>> stickyPriorityInventory;
40+
41+
@Shadow
42+
protected abstract boolean diveList(NetworkInventoryHandler<T> networkInventoryHandler, Actionable type);
43+
44+
@Shadow
45+
protected abstract boolean testPermission(IActionSource src, SecurityPermissions permission);
46+
47+
@Shadow
48+
protected abstract void surface(NetworkInventoryHandler<T> networkInventoryHandler, Actionable type);
49+
50+
@Shadow
51+
protected abstract IItemList<T> iterateInventories(IItemList<T> out,
52+
NavigableMap<Integer, List<IMEInventoryHandler<T>>> map);
53+
54+
@Unique
55+
private final NavigableMap<Integer, List<IMEInventoryHandler<T>>> labs$craftingPriorityInventory = new TreeMap<>(
56+
PRIORITY_SORTER);
57+
58+
@Inject(method = "addNewStorage", at = @At("HEAD"), cancellable = true)
59+
private void handleCrafting(IMEInventoryHandler<T> h, CallbackInfo ci) {
60+
int priority = h.getPriority();
61+
62+
NavigableMap<Integer, List<IMEInventoryHandler<T>>> map;
63+
if (h instanceof ICraftingGrid) {
64+
map = labs$craftingPriorityInventory;
65+
} else if (h.isSticky()) {
66+
map = stickyPriorityInventory;
67+
} else {
68+
map = priorityInventory;
69+
}
70+
71+
map.computeIfAbsent(priority, _priority -> new ArrayList<>()).add(h);
72+
ci.cancel();
73+
}
74+
75+
/**
76+
* The fix presents some issues to implement neatly, since it modifies a parameter. Just overwrite it.
77+
*/
78+
@Inject(method = "injectItems", at = @At("HEAD"), cancellable = true)
79+
private void checkCraftingInv(T input, Actionable type, IActionSource src, CallbackInfoReturnable<T> cir) {
80+
if (diveList(labs$this(), type)) {
81+
cir.setReturnValue(input);
82+
return;
83+
} else if (testPermission(src, SecurityPermissions.INJECT)) {
84+
surface(labs$this(), type);
85+
cir.setReturnValue(input);
86+
return;
87+
}
88+
89+
// First pass. Check if the crafting grid is awaiting the input.
90+
for (List<IMEInventoryHandler<T>> invList : labs$craftingPriorityInventory.values()) {
91+
Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
92+
while (ii.hasNext() && input != null) {
93+
IMEInventoryHandler<T> inv = ii.next();
94+
95+
if (inv.canAccept(input) &&
96+
(inv.isPrioritized(input) || inv.extractItems(input, Actionable.SIMULATE, src) != null)) {
97+
input = inv.injectItems(input, type, src);
98+
}
99+
}
100+
}
101+
102+
// If everything got stored in the crafting storage, no need to continue.
103+
if (input == null) {
104+
surface(labs$this(), type);
105+
cir.setReturnValue(null);
106+
return;
107+
}
108+
109+
boolean stickyInventoryFound = false;
110+
111+
// For this pass we do return input if the item is able to go into a sticky inventory. We NEVER want to try and
112+
// insert the item into a non-sticky inventory if it could already go into a sticky inventory.
113+
for (List<IMEInventoryHandler<T>> stickyInvList : stickyPriorityInventory.values()) {
114+
Iterator<IMEInventoryHandler<T>> ii = stickyInvList.iterator();
115+
while (ii.hasNext() && input != null) {
116+
IMEInventoryHandler<T> inv = ii.next();
117+
if (inv.validForPass(1) && inv.canAccept(input) &&
118+
(inv.isPrioritized(input) || inv.extractItems(input, Actionable.SIMULATE, src) != null)) {
119+
input = inv.injectItems(input, type, src);
120+
stickyInventoryFound = true;
121+
}
122+
}
123+
}
124+
125+
if (stickyInventoryFound) {
126+
surface(labs$this(), type);
127+
cir.setReturnValue(input);
128+
return;
129+
}
130+
131+
for (List<IMEInventoryHandler<T>> invList : priorityInventory.values()) {
132+
Iterator<IMEInventoryHandler<T>> ii = invList.iterator();
133+
while (ii.hasNext() && input != null) {
134+
IMEInventoryHandler<T> inv = ii.next();
135+
136+
if (inv.validForPass(1) && inv
137+
.canAccept(input) &&
138+
(inv.isPrioritized(input) || inv.extractItems(input, Actionable.SIMULATE, src) != null)) {
139+
input = inv.injectItems(input, type, src);
140+
}
141+
}
142+
143+
// We need to ignore prioritized inventories in the second pass. If they were not able to store everything
144+
// during the first pass, they will do so in the second, but as this is stateless we will just report twice
145+
// the amount of storable items.
146+
ii = invList.iterator();
147+
while (ii.hasNext() && input != null) {
148+
IMEInventoryHandler<T> inv = ii.next();
149+
150+
if (inv.validForPass(2) && inv.canAccept(input) && !inv.isPrioritized(input)) {
151+
input = inv.injectItems(input, type, src);
152+
}
153+
}
154+
}
155+
156+
surface(labs$this(), type);
157+
158+
cir.setReturnValue(input);
159+
}
160+
161+
@Inject(method = "getAvailableItems",
162+
at = @At(value = "INVOKE",
163+
target = "Lappeng/me/storage/NetworkInventoryHandler;surface(Lappeng/me/storage/NetworkInventoryHandler;Lappeng/api/config/Actionable;)V"),
164+
require = 1,
165+
remap = false)
166+
private void iterateCrafting(IItemList<T> out, CallbackInfoReturnable<IItemList<T>> cir) {
167+
iterateInventories(out, labs$craftingPriorityInventory);
168+
}
169+
170+
@Unique
171+
private NetworkInventoryHandler<T> labs$this() {
172+
// noinspection unchecked
173+
return (NetworkInventoryHandler<T>) (Object) this;
174+
}
175+
}

src/main/resources/mixins.nomilabs.appliedenergistics2.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"DualityFluidInterfaceMixin",
1212
"DualityInterfaceMixin",
1313
"FluidHandlerAdapterInventoryCacheMixin",
14-
"InscriberRecipeMixin"
14+
"InscriberRecipeMixin",
15+
"NetworkInventoryHandlerMixin"
1516
],
1617
"client": [
1718
"AEBaseGuiMixin",

0 commit comments

Comments
 (0)