diff --git a/src/main/java/com/almostreliable/merequester/requester/RequesterBlockEntity.java b/src/main/java/com/almostreliable/merequester/requester/RequesterBlockEntity.java index d7dda2c..2002ddb 100644 --- a/src/main/java/com/almostreliable/merequester/requester/RequesterBlockEntity.java +++ b/src/main/java/com/almostreliable/merequester/requester/RequesterBlockEntity.java @@ -179,31 +179,26 @@ private boolean handleRequests() { var tickRateModulation = TickRateModulation.IDLE; for (var i = 0; i < requestStatus.length; i++) { var state = requestStatus[i]; - var result = handleRequest(i); - if (!Objects.equals(state, result)) { + + // if we change multiple states per tick then the client will never see us in "missing ingredients" + // we can either special case that state, or only transition once per tick, and once-per-tick is + // significantly less code :) + var nextState = state.handle(this, i); + + if (state.type().translateToClient() != nextState.type().translateToClient()) { changed = true; } - var resultTickRateModulation = result.getTickRateModulation(); + var resultTickRateModulation = nextState.getTickRateModulation(); if (resultTickRateModulation.ordinal() > tickRateModulation.ordinal()) { tickRateModulation = resultTickRateModulation; } - updateRequestStatus(i, result); + updateRequestStatus(i, nextState); } currentTickRate = tickRateModulation; return changed; } - private StatusState handleRequest(int slot) { - var state = requestStatus[slot]; - updateRequestStatus(slot, state.handle(this, slot)); - if (requestStatus[slot].type() != RequestStatus.IDLE && !Objects.equals(requestStatus[slot], state)) { - return handleRequest(slot); - } - - return requestStatus[slot]; - } - private void updateRequestStatus(int slot, StatusState state) { requestStatus[slot] = state; if (state.type().translateToClient() != requests.get(slot).getClientStatus()) { diff --git a/src/main/java/com/almostreliable/merequester/requester/status/MissingState.java b/src/main/java/com/almostreliable/merequester/requester/status/MissingState.java index 8ecf13c..1308d68 100644 --- a/src/main/java/com/almostreliable/merequester/requester/status/MissingState.java +++ b/src/main/java/com/almostreliable/merequester/requester/status/MissingState.java @@ -3,23 +3,12 @@ import appeng.api.networking.ticking.TickRateModulation; import com.almostreliable.merequester.requester.RequesterBlockEntity; -import javax.annotation.Nullable; - public class MissingState implements StatusState { - @Nullable private PlanState simulatedPlanState; - MissingState() {} @Override public StatusState handle(RequesterBlockEntity host, int slot) { - // re-run the crafting job plan to see if we are still missing ingredients - if (simulatedPlanState != null) { - var planSim = simulatedPlanState.handle(host, slot); - simulatedPlanState = null; - return planSim; - } - var idleSim = StatusState.IDLE.handle(host, slot); if (idleSim == StatusState.IDLE || idleSim == StatusState.EXPORT) { // idle simulation returning idle means a request is no @@ -30,14 +19,7 @@ public StatusState handle(RequesterBlockEntity host, int slot) { } // idle sim returned that we can request - var requestSim = StatusState.REQUEST.handle(host, slot); - if (requestSim == StatusState.IDLE) { - return StatusState.IDLE; - } - - // request sim returned that we can start planning - simulatedPlanState = (PlanState) requestSim; - return this; + return PlanState.BuildPlan(host, slot, true); } @Override diff --git a/src/main/java/com/almostreliable/merequester/requester/status/PlanState.java b/src/main/java/com/almostreliable/merequester/requester/status/PlanState.java index 313eb99..78381c8 100644 --- a/src/main/java/com/almostreliable/merequester/requester/status/PlanState.java +++ b/src/main/java/com/almostreliable/merequester/requester/status/PlanState.java @@ -1,5 +1,6 @@ package com.almostreliable.merequester.requester.status; +import appeng.api.networking.crafting.CalculationStrategy; import appeng.api.networking.crafting.CraftingSubmitErrorCode; import appeng.api.networking.crafting.ICraftingPlan; import appeng.api.networking.ticking.TickRateModulation; @@ -11,12 +12,33 @@ public final class PlanState implements StatusState { + private final boolean wasMissing; private final Future future; - PlanState(Future future) { + PlanState(boolean wasMissing, Future future) { + this.wasMissing = wasMissing; this.future = future; } + static PlanState BuildPlan(RequesterBlockEntity host, int slot, boolean wasMissing) + { + // Once BuildPlan is invoked, we're crafting no matter what, rather than returning a null PlanState + var amountToCraft = Math.max(1, host.getStorageManager().computeAmountToCraft(slot)); + var key = host.getRequests().getKey(slot); + + var future = host.getMainNodeGrid() + .getCraftingService() + .beginCraftingCalculation( + host.getLevel(), + host::getActionSource, + key, + amountToCraft, + CalculationStrategy.CRAFT_LESS + ); + + return new PlanState(wasMissing, future); + } + @Override public StatusState handle(RequesterBlockEntity host, int index) { if (!future.isDone()) return this; @@ -45,7 +67,7 @@ public StatusState handle(RequesterBlockEntity host, int index) { @Override public RequestStatus type() { - return RequestStatus.PLAN; + return wasMissing ? RequestStatus.MISSING : RequestStatus.PLAN; } @Override diff --git a/src/main/java/com/almostreliable/merequester/requester/status/RequestState.java b/src/main/java/com/almostreliable/merequester/requester/status/RequestState.java index 2aa1c4d..246ccd4 100644 --- a/src/main/java/com/almostreliable/merequester/requester/status/RequestState.java +++ b/src/main/java/com/almostreliable/merequester/requester/status/RequestState.java @@ -9,22 +9,8 @@ public class RequestState implements StatusState { RequestState() {} @Override - public StatusState handle(RequesterBlockEntity owner, int index) { - var amountToCraft = owner.getStorageManager().computeAmountToCraft(index); - if (amountToCraft <= 0) return StatusState.IDLE; - var key = owner.getRequests().getKey(index); - - var future = owner.getMainNodeGrid() - .getCraftingService() - .beginCraftingCalculation( - owner.getLevel(), - owner::getActionSource, - key, - amountToCraft, - CalculationStrategy.CRAFT_LESS - ); - - return new PlanState(future); + public StatusState handle(RequesterBlockEntity host, int slot) { + return PlanState.BuildPlan(host, slot, false); } @Override