Skip to content

Commit

Permalink
feat: task status listeners are properly called
Browse files Browse the repository at this point in the history
  • Loading branch information
raoulvdberge committed Jan 26, 2025
1 parent 06c9026 commit 5579509
Show file tree
Hide file tree
Showing 15 changed files with 464 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public record Item(
) {
}

// TODO: crafter logic doesn't know what to do with these
public enum ItemType {
NORMAL,
MACHINE_DOES_NOT_ACCEPT_RESOURCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ protected AbstractTaskPattern(final Pattern pattern, final TaskPlan.PatternPlan
}
}

abstract boolean step(MutableResourceList internalStorage,
RootStorage rootStorage,
ExternalPatternInputSink externalPatternInputSink);
abstract PatternStepResult step(MutableResourceList internalStorage,
RootStorage rootStorage,
ExternalPatternInputSink externalPatternInputSink);

abstract RootStorageListener.InterceptResult interceptInsertion(ResourceKey resource, long amount);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class ExternalTaskPattern extends AbstractTaskPattern {
private final long originalIterationsToSendToSink;
private long iterationsToSendToSink;
private long iterationsReceived;
private boolean interceptedAnythingSinceLastStep;

ExternalTaskPattern(final Pattern pattern, final TaskPlan.PatternPlan plan) {
super(pattern, plan);
Expand All @@ -34,21 +35,25 @@ class ExternalTaskPattern extends AbstractTaskPattern {
}

@Override
boolean step(final MutableResourceList internalStorage,
final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink) {
PatternStepResult step(final MutableResourceList internalStorage,
final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink) {
if (expectedOutputs.isEmpty()) {
return true;
return PatternStepResult.COMPLETED;
}
if (interceptedAnythingSinceLastStep) {
interceptedAnythingSinceLastStep = false;
return PatternStepResult.RUNNING;
}
if (iterationsToSendToSink == 0) {
return false;
return PatternStepResult.IDLE;
}
if (!acceptsIterationInputs(internalStorage, externalPatternInputSink)) {
return false;
return PatternStepResult.IDLE;
}
LOGGER.debug("Stepped {} with {} iterations remaining", pattern, iterationsToSendToSink);
iterationsToSendToSink--;
return false;
return PatternStepResult.RUNNING;
}

@Override
Expand Down Expand Up @@ -76,6 +81,7 @@ private void updateIterationsReceived() {
}
}
this.iterationsReceived = result;
this.interceptedAnythingSinceLastStep = true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ class InternalTaskPattern extends AbstractTaskPattern {
}

@Override
boolean step(final MutableResourceList internalStorage,
final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink) {
PatternStepResult step(final MutableResourceList internalStorage,
final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink) {
final ResourceList iterationInputsSimulated = calculateIterationInputs(Action.SIMULATE);
if (!extractAll(iterationInputsSimulated, internalStorage, Action.SIMULATE)) {
return false;
return PatternStepResult.IDLE;
}
LOGGER.debug("Stepping {}", pattern);
final ResourceList iterationInputs = calculateIterationInputs(Action.EXECUTE);
Expand Down Expand Up @@ -84,9 +84,9 @@ long getWeight() {
return iterationsCompleted / originalIterationsRemaining;
}

protected boolean useIteration() {
protected PatternStepResult useIteration() {
iterationsRemaining--;
LOGGER.debug("Stepped {} with {} iterations remaining", pattern, iterationsRemaining);
return iterationsRemaining == 0;
return iterationsRemaining == 0 ? PatternStepResult.COMPLETED : PatternStepResult.RUNNING;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.refinedmods.refinedstorage.api.autocrafting.task;

enum PatternStepResult {
COMPLETED,
RUNNING,
IDLE;

PatternStepResult and(final PatternStepResult stepResult) {
if (this == IDLE) {
return stepResult;
} else if (this == COMPLETED) {
return COMPLETED;
} else {
return stepResult == COMPLETED ? COMPLETED : RUNNING;
}
}

boolean isChanged() {
return this != IDLE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public interface Task extends RootStorageListener {

Collection<ResourceAmount> copyInternalStorageState();

void step(RootStorage rootStorage, ExternalPatternInputSink externalPatternInputSink, StepBehavior stepBehavior);
boolean step(RootStorage rootStorage, ExternalPatternInputSink externalPatternInputSink, StepBehavior stepBehavior);

void cancel();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,16 @@ private void updateState(final TaskState newState) {
}

@Override
public void step(final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink,
final StepBehavior stepBehavior) {
switch (state) {
public boolean step(final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink,
final StepBehavior stepBehavior) {
return switch (state) {
case READY -> startTask(rootStorage);
case EXTRACTING_INITIAL_RESOURCES -> extractInitialResourcesAndTryStartRunningTask(rootStorage);
case RUNNING -> stepPatterns(rootStorage, externalPatternInputSink, stepBehavior);
case RETURNING_INTERNAL_STORAGE -> returnInternalStorageAndTryCompleteTask(rootStorage);
}
case COMPLETED -> false;
};
}

@Override
Expand All @@ -112,86 +113,95 @@ public TaskStatus getStatus() {
return builder.build(totalWeightedCompleted / totalWeight);
}

private void startTask(final RootStorage rootStorage) {
private boolean startTask(final RootStorage rootStorage) {
updateState(TaskState.EXTRACTING_INITIAL_RESOURCES);
extractInitialResourcesAndTryStartRunningTask(rootStorage);
return extractInitialResourcesAndTryStartRunningTask(rootStorage);
}

private void extractInitialResourcesAndTryStartRunningTask(final RootStorage rootStorage) {
if (extractInitialResources(rootStorage)) {
private boolean extractInitialResourcesAndTryStartRunningTask(final RootStorage rootStorage) {
boolean extractedAll = true;
boolean extractedAny = false;
final Set<ResourceKey> initialRequirementResources = new HashSet<>(initialRequirements.getAll());
for (final ResourceKey initialRequirementResource : initialRequirementResources) {
final long needed = initialRequirements.get(initialRequirementResource);
final long extracted = rootStorage.extract(initialRequirementResource, needed, Action.EXECUTE, Actor.EMPTY);
if (extracted > 0) {
extractedAny = true;
}
LOGGER.debug("Extracted {}x {} from storage", extracted, initialRequirementResource);
if (extracted != needed) {
extractedAll = false;
}
if (extracted > 0) {
initialRequirements.remove(initialRequirementResource, extracted);
internalStorage.add(initialRequirementResource, extracted);
}
}
if (extractedAll) {
updateState(TaskState.RUNNING);
}
}

private void stepPatterns(final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink,
final StepBehavior stepBehavior) {
patterns.entrySet().removeIf(
pattern -> stepPattern(rootStorage, externalPatternInputSink, stepBehavior, pattern)
);
return extractedAny;
}

private boolean stepPatterns(final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink,
final StepBehavior stepBehavior) {
final var it = patterns.entrySet().iterator();
boolean changed = false;
while (it.hasNext()) {
final var pattern = it.next();
final PatternStepResult result = stepPattern(rootStorage, externalPatternInputSink, stepBehavior, pattern);
if (result == PatternStepResult.COMPLETED) {
it.remove();
}
changed |= result.isChanged();
}
if (patterns.isEmpty()) {
if (internalStorage.isEmpty()) {
updateState(TaskState.COMPLETED);
} else {
updateState(TaskState.RETURNING_INTERNAL_STORAGE);
}
}
return changed;
}

private boolean stepPattern(final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink,
final StepBehavior stepBehavior,
final Map.Entry<Pattern, AbstractTaskPattern> pattern) {
private PatternStepResult stepPattern(final RootStorage rootStorage,
final ExternalPatternInputSink externalPatternInputSink,
final StepBehavior stepBehavior,
final Map.Entry<Pattern, AbstractTaskPattern> pattern) {
PatternStepResult result = PatternStepResult.IDLE;
if (!stepBehavior.canStep(pattern.getKey())) {
return false;
return result;
}
final int steps = stepBehavior.getSteps(pattern.getKey());
for (int i = 0; i < steps; ++i) {
final boolean completed = pattern.getValue().step(internalStorage, rootStorage, externalPatternInputSink);
if (completed) {
final PatternStepResult stepResult = pattern.getValue().step(
internalStorage,
rootStorage,
externalPatternInputSink
);
if (stepResult == PatternStepResult.COMPLETED) {
LOGGER.debug("{} completed", pattern.getKey());
completedPatterns.add(pattern.getValue());
return true;
}
}
return false;
}

private void returnInternalStorageAndTryCompleteTask(final RootStorage rootStorage) {
if (returnInternalStorage(rootStorage)) {
updateState(TaskState.COMPLETED);
}
}

@Override
public Collection<ResourceAmount> copyInternalStorageState() {
return internalStorage.copyState();
}

private boolean extractInitialResources(final RootStorage rootStorage) {
boolean extractedAll = true;
final Set<ResourceKey> initialRequirementResources = new HashSet<>(initialRequirements.getAll());
for (final ResourceKey initialRequirementResource : initialRequirementResources) {
final long needed = initialRequirements.get(initialRequirementResource);
final long extracted = rootStorage.extract(initialRequirementResource, needed, Action.EXECUTE, Actor.EMPTY);
LOGGER.debug("Extracted {}x {} from storage", extracted, initialRequirementResource);
if (extracted != needed) {
extractedAll = false;
}
if (extracted > 0) {
initialRequirements.remove(initialRequirementResource, extracted);
internalStorage.add(initialRequirementResource, extracted);
return stepResult;
} else {
result = result.and(stepResult);
}
}
return extractedAll;
return result;
}

private boolean returnInternalStorage(final RootStorage rootStorage) {
private boolean returnInternalStorageAndTryCompleteTask(final RootStorage rootStorage) {
boolean returnedAll = true;
boolean returnedAny = false;
final Set<ResourceKey> internalResources = new HashSet<>(internalStorage.getAll());
for (final ResourceKey internalResource : internalResources) {
final long internalAmount = internalStorage.get(internalResource);
final long inserted = rootStorage.insert(internalResource, internalAmount, Action.EXECUTE, Actor.EMPTY);
if (inserted > 0) {
returnedAny = true;
}
LOGGER.debug("Returned {}x {} into storage", inserted, internalResource);
if (inserted != internalAmount) {
returnedAll = false;
Expand All @@ -200,7 +210,15 @@ private boolean returnInternalStorage(final RootStorage rootStorage) {
internalStorage.remove(internalResource, inserted);
}
}
return returnedAll;
if (returnedAll) {
updateState(TaskState.COMPLETED);
}
return returnedAny;
}

@Override
public Collection<ResourceAmount> copyInternalStorageState() {
return internalStorage.copyState();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.refinedmods.refinedstorage.api.network.autocrafting;

import com.refinedmods.refinedstorage.api.autocrafting.Pattern;
import com.refinedmods.refinedstorage.api.autocrafting.task.Task;

import org.apiguardian.api.API;

Expand All @@ -11,4 +12,10 @@ public interface ParentContainer {
void remove(PatternProvider provider, Pattern pattern);

void update(Pattern pattern, int priority);

void taskAdded(Task task);

void taskRemoved(Task task);

void taskChanged(Task task);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.refinedmods.refinedstorage.api.network.autocrafting;

import com.refinedmods.refinedstorage.api.autocrafting.status.TaskStatus;
import com.refinedmods.refinedstorage.api.autocrafting.task.StepBehavior;
import com.refinedmods.refinedstorage.api.autocrafting.task.Task;
import com.refinedmods.refinedstorage.api.autocrafting.task.TaskId;

import java.util.List;

import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.8")
Expand All @@ -19,4 +22,6 @@ default boolean contains(AutocraftingNetworkComponent component) {
void addTask(Task task);

void cancelTask(TaskId taskId);

List<TaskStatus> getTaskStatuses();
}
Loading

0 comments on commit 5579509

Please sign in to comment.