Skip to content

Commit ab35342

Browse files
committed
Further adapt the current bridge system to the 1.21.1 one, support scripts from 1.21.1 without changes
1 parent 5ba38b4 commit ab35342

File tree

14 files changed

+1077
-268
lines changed

14 files changed

+1077
-268
lines changed

src/main/java/de/srendi/advancedperipherals/common/addons/ae2/AEApi.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@
1919
import appeng.api.storage.MEStorage;
2020
import appeng.api.storage.cells.IBasicCellItem;
2121
import appeng.blockentity.storage.DriveBlockEntity;
22+
import appeng.crafting.execution.CraftingCpuLogic;
2223
import appeng.crafting.pattern.EncodedPatternItem;
2324
import appeng.helpers.iface.PatternContainer;
2425
import appeng.items.storage.BasicStorageCell;
2526
import appeng.me.cells.BasicCellHandler;
2627
import appeng.me.cells.BasicCellInventory;
28+
import appeng.me.cluster.implementations.CraftingCPUCluster;
2729
import appeng.parts.storagebus.StorageBusPart;
2830
import com.the9grounds.aeadditions.item.storage.StorageCell;
2931
import com.the9grounds.aeadditions.item.storage.SuperStorageCell;
@@ -290,6 +292,14 @@ public static Map<String, Object> parseGenericStack(GenericStack stack) {
290292
return Collections.emptyMap();
291293
}
292294

295+
public static List<Object> parseKeyCounter(KeyCounter counter) {
296+
List<Object> parsedKeys = new ArrayList<>();
297+
for (AEKey key : counter.keySet()) {
298+
parsedKeys.add(parseGenericStack(new GenericStack(key, counter.get(key))));
299+
}
300+
301+
return parsedKeys;
302+
}
293303

294304
public static Map<Object, Object> parseDrive(DriveBlockEntity drive) {
295305
Map<Object, Object> map = new HashMap<>();
@@ -393,24 +403,34 @@ public static Map<String, Object> parseCraftingCPU(ICraftingCPU cpu, boolean rec
393403
map.put("coProcessors", coProcessors);
394404
map.put("isBusy", isBusy);
395405
if (!recursive)
396-
map.put("craftingJob", cpu.getJobStatus() != null ? parseCraftingJob(cpu.getJobStatus(), null) : null);
406+
map.put("craftingJob", cpu.getJobStatus() != null ? parseCraftingJob(cpu.getJobStatus(), null, null) : null);
397407
map.put("name", cpu.getName() != null ? cpu.getName().getString() : "Unnamed");
398408
map.put("selectionMode", cpu.getSelectionMode().toString());
399409

400410
return map;
401411
}
402412

403-
public static Map<String, Object> parseCraftingJob(CraftingJobStatus job, @Nullable ICraftingCPU cpu) {
404-
Map<String, Object> map = new HashMap<>();
405-
map.put("requestedItem", parseGenericStack(job.crafting()));
406-
map.put("elapsedTimeNanos", job.elapsedTimeNanos());
407-
map.put("totalItem", job.totalItems());
408-
map.put("progress", job.progress());
413+
public static Object parseCraftingJob(CraftingJobStatus status, AECraftJob craftJob, @Nullable ICraftingCPU cpu) {
414+
Map<String, Object> properties = new HashMap<>();
409415

410-
if (cpu != null)
411-
map.put("cpu", parseCraftingCPU(cpu, true));
416+
properties.put("bridge_id", craftJob == null ? -1 : craftJob.getId());
417+
properties.put("quantity", status.crafting().amount());
418+
properties.put("resource", parseGenericStack(status.crafting()));
412419

413-
return map;
420+
if (cpu != null) {
421+
CraftingCpuLogic craftingCpuLogic = ((CraftingCPUCluster) cpu).craftingLogic;
422+
long pending = craftingCpuLogic.getPendingOutputs(status.crafting().what());
423+
long active = craftingCpuLogic.getWaitingFor(status.crafting().what());
424+
long crafted = status.crafting().amount() - (pending + active);
425+
properties.put("completion", crafted / (double) status.crafting().amount());
426+
properties.put("crafted", crafted);
427+
428+
properties.put("id", craftingCpuLogic.getLastLink().getCraftingID().toString());
429+
430+
properties.put("cpu", parseCraftingCPU(cpu, true));
431+
}
432+
433+
return properties;
414434
}
415435

416436
public static MEStorage getMonitor(IGridNode node) {
@@ -419,6 +439,7 @@ public static MEStorage getMonitor(IGridNode node) {
419439

420440
public static boolean isCrafting(ICraftingService grid, GenericFilter<?> filter,
421441
@Nullable ICraftingCPU craftingCPU) {
442+
422443
// If the passed cpu is null, check all cpus
423444
if (craftingCPU == null) {
424445
// Loop through all crafting cpus and check if the item is being crafted.
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
package de.srendi.advancedperipherals.common.addons.ae2;
2+
3+
import appeng.api.networking.IGrid;
4+
import appeng.api.networking.IGridNode;
5+
import appeng.api.networking.crafting.CalculationStrategy;
6+
import appeng.api.networking.crafting.CraftingJobStatus;
7+
import appeng.api.networking.crafting.ICraftingCPU;
8+
import appeng.api.networking.crafting.ICraftingLink;
9+
import appeng.api.networking.crafting.ICraftingPlan;
10+
import appeng.api.networking.crafting.ICraftingRequester;
11+
import appeng.api.networking.crafting.ICraftingService;
12+
import appeng.api.networking.crafting.ICraftingSimulationRequester;
13+
import appeng.api.networking.crafting.ICraftingSubmitResult;
14+
import appeng.api.networking.security.IActionSource;
15+
import appeng.api.stacks.AEKey;
16+
import appeng.api.stacks.KeyCounter;
17+
import appeng.me.cluster.implementations.CraftingCPUCluster;
18+
import dan200.computercraft.api.lua.LuaFunction;
19+
import dan200.computercraft.api.peripheral.IComputerAccess;
20+
import de.srendi.advancedperipherals.AdvancedPeripherals;
21+
import de.srendi.advancedperipherals.common.blocks.blockentities.MeBridgeEntity;
22+
import de.srendi.advancedperipherals.common.util.BasicCraftJob;
23+
import de.srendi.advancedperipherals.common.util.StatusConstants;
24+
import net.minecraft.world.level.Level;
25+
import org.jetbrains.annotations.Nullable;
26+
27+
import java.util.concurrent.ExecutionException;
28+
import java.util.concurrent.Future;
29+
import java.util.function.Supplier;
30+
31+
//TODO needs to persistent - should be stored in the me bridge
32+
// We also need to do the same for the rs bridge. So we want to create a proper interface to keep the lua functions the same
33+
public class AECraftJob extends BasicCraftJob {
34+
35+
private final IGridNode node;
36+
private final IActionSource source;
37+
private final ICraftingSimulationRequester simulationRequester;
38+
private final ICraftingRequester requester;
39+
private ICraftingCPU targetCpu;
40+
private final AEKey toCraft;
41+
42+
private Future<ICraftingPlan> futureJob;
43+
private ICraftingPlan currentJob;
44+
@Nullable
45+
private ICraftingLink jobLink; // Job after calculation was done
46+
// Because the properties in `CraftingJobStatus` are set when the object is created, we need to create a supplier which
47+
// always re-fetches the object from the cpu
48+
private Supplier<CraftingJobStatus> jobStatus;
49+
// In the case the job is done and would return null, we have this cached one.
50+
private CraftingJobStatus cachedStatus;
51+
52+
public AECraftJob(Level world, final IComputerAccess computer, IGridNode node, AEKey item, long amount, MeBridgeEntity bridge, ICraftingCPU target) {
53+
super(computer, "ae", world, amount);
54+
this.node = node;
55+
this.source = bridge;
56+
this.toCraft = item;
57+
this.simulationRequester = bridge;
58+
this.requester = bridge;
59+
this.targetCpu = target;
60+
}
61+
62+
@LuaFunction
63+
public final Object getCraftingCPU() {
64+
return AEApi.parseCraftingCPU(targetCpu, true);
65+
}
66+
67+
@Nullable
68+
public ICraftingLink getJobLink() {
69+
return jobLink;
70+
}
71+
72+
public ICraftingCPU getTargetCpu() {
73+
return targetCpu;
74+
}
75+
76+
public AEKey getToCraft() {
77+
return toCraft;
78+
}
79+
80+
@Override
81+
protected boolean isJobDone() {
82+
return jobLink != null && jobLink.isDone();
83+
}
84+
85+
@Override
86+
protected boolean isJobCanceled() {
87+
return jobLink != null && jobLink.isCanceled();
88+
}
89+
90+
@Override
91+
public Object getParsedRequestedItem() {
92+
if (getJobStatus() == null) {
93+
return null;
94+
}
95+
return AEApi.parseGenericStack(getJobStatus().crafting());
96+
}
97+
98+
@Override
99+
public long getElapsedTime() {
100+
if (getJobStatus() == null) {
101+
return -1;
102+
}
103+
return getJobStatus().elapsedTimeNanos();
104+
}
105+
106+
@Override
107+
public long getTotalItems() {
108+
if (getJobStatus() == null) {
109+
return -1;
110+
}
111+
return getJobStatus().totalItems();
112+
}
113+
114+
@Override
115+
public long getItemProgress() {
116+
if (getJobStatus() == null) {
117+
return -1;
118+
}
119+
return getJobStatus().progress();
120+
}
121+
122+
@Override
123+
public Object getEmittedItems() {
124+
if (currentJob == null) {
125+
return null;
126+
}
127+
return AEApi.parseKeyCounter(currentJob.emittedItems());
128+
}
129+
130+
@Override
131+
public Object getUsedItems() {
132+
if (currentJob == null) {
133+
return null;
134+
}
135+
return AEApi.parseKeyCounter(currentJob.usedItems());
136+
}
137+
138+
@Override
139+
public Object getMissingItems() {
140+
if (currentJob == null) {
141+
return null;
142+
}
143+
return AEApi.parseKeyCounter(currentJob.missingItems());
144+
}
145+
146+
@Override
147+
public boolean hasMultiplePaths() {
148+
if (currentJob == null) {
149+
return false;
150+
}
151+
return currentJob.multiplePaths();
152+
}
153+
154+
@Override
155+
public Object getFinalOutput() {
156+
if (currentJob == null) {
157+
return null;
158+
}
159+
return AEApi.parseGenericStack(currentJob.finalOutput());
160+
}
161+
162+
@Override
163+
public boolean cancel() {
164+
if (targetCpu instanceof CraftingCPUCluster cluster) {
165+
if (cluster.isBusy()) {
166+
cluster.cancel();
167+
return true;
168+
}
169+
}
170+
return false;
171+
}
172+
173+
@LuaFunction
174+
public long getUsedBytes() {
175+
if (currentJob == null) {
176+
return -1;
177+
}
178+
return currentJob.bytes();
179+
}
180+
181+
public AECraftJob withJobStatus(Supplier<CraftingJobStatus> jobStatus) {
182+
this.jobStatus = jobStatus;
183+
return this;
184+
}
185+
186+
public AECraftJob withCPU(ICraftingCPU craftingCpu) {
187+
if (this.targetCpu == null) {
188+
this.targetCpu = craftingCpu;
189+
}
190+
return this;
191+
}
192+
193+
public void startCalculation() {
194+
if (startedCalculation) {
195+
return;
196+
}
197+
startedCalculation = true;
198+
199+
IGrid grid = node.getGrid();
200+
201+
ICraftingService craftingService = grid.getService(ICraftingService.class);
202+
203+
if (!craftingService.isCraftable(toCraft)) {
204+
fireEvent(true, StatusConstants.NOT_CRAFTABLE);
205+
calculationNotSuccessful = true;
206+
return;
207+
}
208+
209+
futureJob = craftingService.beginCraftingCalculation(world, this.simulationRequester, toCraft, amount, CalculationStrategy.REPORT_MISSING_ITEMS);
210+
fireEvent(false, StatusConstants.CALCULATION_STARTED);
211+
}
212+
213+
public void maybeCraft() {
214+
if (startedCrafting || futureJob == null || !futureJob.isDone()) {
215+
return;
216+
}
217+
ICraftingPlan job;
218+
219+
try {
220+
job = futureJob.get();
221+
} catch (ExecutionException | InterruptedException ex) {
222+
AdvancedPeripherals.debug("Tried to get job, but job calculation is not done. Should be done.", org.apache.logging.log4j.Level.ERROR);
223+
ex.printStackTrace();
224+
fireEvent(true, StatusConstants.UNKNOWN_ERROR);
225+
return;
226+
}
227+
228+
if (job == null) {
229+
AdvancedPeripherals.debug("Job is null, should not be null.", org.apache.logging.log4j.Level.ERROR);
230+
fireEvent(true, StatusConstants.UNKNOWN_ERROR);
231+
return;
232+
}
233+
this.currentJob = job;
234+
235+
KeyCounter missing = job.missingItems();
236+
if (!missing.isEmpty()) {
237+
fireEvent(true, StatusConstants.MISSING_ITEMS);
238+
calculationNotSuccessful = true;
239+
return;
240+
}
241+
242+
IGrid grid = node.getGrid();
243+
244+
ICraftingService craftingService = grid.getService(ICraftingService.class);
245+
ICraftingSubmitResult submitResult = craftingService.submitJob(job, requester, targetCpu, false, this.source);
246+
if (!submitResult.successful()) {
247+
calculationNotSuccessful = true;
248+
fireEvent(true, submitResult.errorCode().toString());
249+
return;
250+
}
251+
252+
this.jobLink = submitResult.link();
253+
this.futureJob = null;
254+
setStartedCrafting();
255+
prepareCPUAndStatus(craftingService);
256+
}
257+
258+
public void jobStateChanged() {
259+
ICraftingLink jobLink = this.jobLink;
260+
if (jobLink == null) {
261+
fireEvent(true, StatusConstants.UNKNOWN_ERROR);
262+
return;
263+
}
264+
265+
if (jobLink.isCanceled() && !isJobCanceled) {
266+
fireEvent(false, StatusConstants.JOB_CANCELED);
267+
setJobCanceled();
268+
return;
269+
}
270+
271+
if (jobLink.isDone() && !isJobDone) {
272+
fireEvent(false, StatusConstants.JOB_DONE);
273+
setJobDone();
274+
}
275+
}
276+
277+
private void prepareCPUAndStatus(ICraftingService service) {
278+
if (jobLink == null || jobStatus != null || !startedCrafting) {
279+
return;
280+
}
281+
for (ICraftingCPU cpu : service.getCpus()) {
282+
if (cpu instanceof CraftingCPUCluster cpuCluster) {
283+
if (cpuCluster.craftingLogic.getLastLink() != null && cpuCluster.craftingLogic.getLastLink().getCraftingID().equals(jobLink.getCraftingID())) {
284+
this.jobStatus = () -> {
285+
// Compare the id of the job in the cpu. This job object can exist longer than the job needs time to complete. So the cpu could have a new job
286+
if (cpuCluster.craftingLogic.getLastLink() != null && cpuCluster.craftingLogic.getLastLink().getCraftingID().equals(jobLink.getCraftingID()))
287+
return cpuCluster.getJobStatus();
288+
return null;
289+
};
290+
cpuCluster.craftingLogic.addListener((key) -> {
291+
// The last time the listeners are called from the cpu logic is when the job is finished
292+
// These listeners are not intended by ae2 to be used like this, but it works, and we don't modify the key
293+
if (cpuCluster.getJobStatus() != null) {
294+
this.cachedStatus = cpuCluster.getJobStatus();
295+
}
296+
});
297+
this.targetCpu = cpu;
298+
return;
299+
}
300+
}
301+
}
302+
AdvancedPeripherals.debug("Could not find CPU or job link even after job started", org.apache.logging.log4j.Level.WARN);
303+
}
304+
305+
private CraftingJobStatus getJobStatus() {
306+
if (jobStatus == null || jobStatus.get() == null && cachedStatus != null) {
307+
return cachedStatus;
308+
}
309+
cachedStatus = jobStatus.get();
310+
return jobStatus.get();
311+
}
312+
}

0 commit comments

Comments
 (0)