Skip to content

Commit

Permalink
feat: processing status now identifies sink result types
Browse files Browse the repository at this point in the history
  • Loading branch information
raoulvdberge committed Jan 26, 2025
1 parent 5579509 commit cfd2cdd
Show file tree
Hide file tree
Showing 22 changed files with 243 additions and 69 deletions.
6 changes: 4 additions & 2 deletions config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="FileLength">
<property name="max" value="800"/>
<property name="max" value="1200"/>
</module>
<module name="NewlineAtEndOfFile"/>
<module name="JavadocPackage"/>
Expand Down Expand Up @@ -106,7 +106,9 @@
<module name="IllegalIdentifierName"/>
<module name="AnonInnerLength"/>
<module name="MethodCount"/>
<module name="MethodLength"/>
<module name="MethodLength">
<property name="max" value="200"/>
</module>
<module name="OuterTypeNumber"/>
<module name="RecordComponentNumber">
<property name="max" value="20"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ public record Item(
) {
}

// TODO: crafter logic doesn't know what to do with these
public enum ItemType {
NORMAL,
MACHINE_DOES_NOT_ACCEPT_RESOURCE,
NO_MACHINE_FOUND,
AUTOCRAFTER_IS_LOCKED
REJECTED,
NONE_FOUND,
LOCKED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ public TaskStatusBuilder crafting(final ResourceKey resource, final long craftin
return this;
}

public TaskStatusBuilder rejected(final ResourceKey resource) {
get(resource).type = TaskStatus.ItemType.REJECTED;
return this;
}

public TaskStatusBuilder noneFound(final ResourceKey resource) {
get(resource).type = TaskStatus.ItemType.NONE_FOUND;
return this;
}

public TaskStatusBuilder locked(final ResourceKey resource) {
get(resource).type = TaskStatus.ItemType.LOCKED;
return this;
}

private MutableItem get(final ResourceKey resource) {
return items.computeIfAbsent(resource, key -> new MutableItem(TaskStatus.ItemType.NORMAL));
}
Expand All @@ -55,7 +70,7 @@ public TaskStatus build(final double percentageCompleted) {
}

private static class MutableItem {
private final TaskStatus.ItemType type;
private TaskStatus.ItemType type;
private long stored;
private long processing;
private long scheduled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,22 @@
@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.12")
@FunctionalInterface
public interface ExternalPatternInputSink {
boolean accept(Pattern pattern, Collection<ResourceAmount> resources, Action action);
Result accept(Pattern pattern, Collection<ResourceAmount> resources, Action action);

enum Result {
ACCEPTED,
REJECTED,
SKIPPED,
LOCKED;

public Result and(final Result other) {
if (this == SKIPPED) {
return other;
} else if (this == REJECTED || other == REJECTED) {
return REJECTED;
} else {
return ACCEPTED;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.refinedmods.refinedstorage.api.storage.root.RootStorage;
import com.refinedmods.refinedstorage.api.storage.root.RootStorageListener;

import javax.annotation.Nullable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -23,6 +25,8 @@ class ExternalTaskPattern extends AbstractTaskPattern {
private long iterationsToSendToSink;
private long iterationsReceived;
private boolean interceptedAnythingSinceLastStep;
@Nullable
private ExternalPatternInputSink.Result lastSinkResult;

ExternalTaskPattern(final Pattern pattern, final TaskPlan.PatternPlan plan) {
super(pattern, plan);
Expand All @@ -41,21 +45,25 @@ PatternStepResult step(final MutableResourceList internalStorage,
if (expectedOutputs.isEmpty()) {
return PatternStepResult.COMPLETED;
}
if (interceptedAnythingSinceLastStep) {
interceptedAnythingSinceLastStep = false;
return PatternStepResult.RUNNING;
}
if (iterationsToSendToSink == 0) {
return PatternStepResult.IDLE;
return idleOrRunning();
}
if (!acceptsIterationInputs(internalStorage, externalPatternInputSink)) {
return PatternStepResult.IDLE;
return idleOrRunning();
}
LOGGER.debug("Stepped {} with {} iterations remaining", pattern, iterationsToSendToSink);
iterationsToSendToSink--;
return PatternStepResult.RUNNING;
}

private PatternStepResult idleOrRunning() {
if (interceptedAnythingSinceLastStep) {
interceptedAnythingSinceLastStep = false;
return PatternStepResult.RUNNING;
}
return PatternStepResult.IDLE;
}

@Override
RootStorageListener.InterceptResult interceptInsertion(final ResourceKey resource, final long amount) {
final long needed = expectedOutputs.get(resource);
Expand Down Expand Up @@ -98,6 +106,13 @@ void appendStatus(final TaskStatusBuilder builder) {
builder.processing(input, simulatedIterationInputs.get(input) * iterationsProcessing);
}
}
if (lastSinkResult != null) {
switch (lastSinkResult) {
case REJECTED -> pattern.outputs().stream().map(ResourceAmount::resource).forEach(builder::rejected);
case SKIPPED -> pattern.outputs().stream().map(ResourceAmount::resource).forEach(builder::noneFound);
case LOCKED -> pattern.outputs().stream().map(ResourceAmount::resource).forEach(builder::locked);
}
}
}

@Override
Expand All @@ -116,7 +131,13 @@ private boolean acceptsIterationInputs(final MutableResourceList internalStorage
if (!extractAll(iterationInputsSimulated, internalStorage, Action.SIMULATE)) {
return false;
}
if (!externalPatternInputSink.accept(pattern, iterationInputsSimulated.copyState(), Action.SIMULATE)) {
final ExternalPatternInputSink.Result simulatedResult = externalPatternInputSink.accept(
pattern,
iterationInputsSimulated.copyState(),
Action.SIMULATE
);
lastSinkResult = simulatedResult;
if (simulatedResult != ExternalPatternInputSink.Result.ACCEPTED) {
return false;
}
final ResourceList iterationInputs = calculateIterationInputs(Action.EXECUTE);
Expand All @@ -130,7 +151,8 @@ private boolean acceptsIterationInputs(final MutableResourceList internalStorage
// across the sink and the internal storage.
// The end result is that we lie, do as if the insertion was successful,
// and potentially void the extracted resources from the internal storage.
if (!externalPatternInputSink.accept(pattern, iterationInputs.copyState(), Action.EXECUTE)) {
if (externalPatternInputSink.accept(pattern, iterationInputs.copyState(), Action.EXECUTE)
!= ExternalPatternInputSink.Result.ACCEPTED) {
LOGGER.warn("External sink {} did not accept all inputs for pattern {}", externalPatternInputSink, pattern);
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ private PatternStepResult stepPattern(final RootStorage rootStorage,
LOGGER.debug("{} completed", pattern.getKey());
completedPatterns.add(pattern.getValue());
return stepResult;
} else {
result = result.and(stepResult);
} else if (stepResult != PatternStepResult.IDLE) {
result = PatternStepResult.RUNNING;
}
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ Sink storageSink(final Pattern pattern) {
ExternalPatternInputSink build() {
return (pattern, resources, action) -> {
final Sink sink = sinks.get(pattern);
return sink != null && sink.accept(resources, action);
return sink != null && sink.accept(resources, action)
? ExternalPatternInputSink.Result.ACCEPTED
: ExternalPatternInputSink.Result.REJECTED;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class TaskImplTest {
private static final RecursiveComparisonConfiguration STATUS_CONFIG = RecursiveComparisonConfiguration.builder()
.withIgnoredFields("info.startTime")
.build();
private static final ExternalPatternInputSink EMPTY_SINK = (pattern, resources, action) -> false;
private static final ExternalPatternInputSink EMPTY_SINK = (pattern, resources, action) ->
ExternalPatternInputSink.Result.SKIPPED;

@Test
void testInitialState() {
Expand Down Expand Up @@ -661,7 +662,9 @@ void shouldNotCompleteTaskWithExternalPatternIfSinkDoesNotAcceptResourcesOnlyWhe
);
final PatternRepository patterns = patterns(IRON_INGOT_PATTERN, IRON_PICKAXE_PATTERN);
final ExternalPatternInputSink sink = (pattern, resources, action) ->
action == Action.SIMULATE;
action == Action.SIMULATE
? ExternalPatternInputSink.Result.ACCEPTED
: ExternalPatternInputSink.Result.REJECTED;
final Task task = getRunningTask(storage, patterns, sink, IRON_PICKAXE, 1);

assertThat(storage.getAll()).isEmpty();
Expand Down Expand Up @@ -946,6 +949,100 @@ void shouldReportStatusCorrectly() {
);
}

@Test
void shouldReportWhetherSinkIsRejectingInputsOnStatus() {
// Arrange
final RootStorage storage = storage(new ResourceAmount(IRON_ORE, 10));
final PatternRepository patterns = patterns(IRON_INGOT_PATTERN);
final ExternalPatternInputSinkBuilder sinkBuilder = externalPatternInputSink();
final ExternalPatternInputSinkBuilder.Sink ironOreSink = sinkBuilder.storageSink(IRON_INGOT_PATTERN);
final ExternalPatternInputSink sink = sinkBuilder.build();
final Task task = getRunningTask(storage, patterns, EMPTY_SINK, IRON_INGOT, 2);

// Act & assert
task.step(storage, sink, StepBehavior.DEFAULT);
assertThat(task.getStatus()).usingRecursiveComparison(STATUS_CONFIG).isEqualTo(
new TaskStatusBuilder(task.getId(), IRON_INGOT, 2, 0)
.scheduled(IRON_INGOT, 1)
.stored(IRON_ORE, 1)
.processing(IRON_ORE, 1)
.build(0));

ironOreSink.setEnabled(false);
task.step(storage, sink, StepBehavior.DEFAULT);
assertThat(task.getStatus()).usingRecursiveComparison(STATUS_CONFIG).isEqualTo(
new TaskStatusBuilder(task.getId(), IRON_INGOT, 2, 0)
.scheduled(IRON_INGOT, 1)
.stored(IRON_ORE, 1)
.processing(IRON_ORE, 1)
.rejected(IRON_INGOT)
.build(0));
}

@Test
void shouldReportWhetherSinkIsNotFoundOnStatus() {
// Arrange
final RootStorage storage = storage(new ResourceAmount(IRON_ORE, 10));
final PatternRepository patterns = patterns(IRON_INGOT_PATTERN);
final ExternalPatternInputSinkBuilder sinkBuilder = externalPatternInputSink();
final ExternalPatternInputSinkBuilder.Sink ironOreSink = sinkBuilder.storageSink(IRON_INGOT_PATTERN);
final ExternalPatternInputSink sink = sinkBuilder.build();
final Task task = getRunningTask(storage, patterns, EMPTY_SINK, IRON_INGOT, 2);

// Act & assert
task.step(storage, sink, StepBehavior.DEFAULT);
assertThat(task.getStatus()).usingRecursiveComparison(STATUS_CONFIG).isEqualTo(
new TaskStatusBuilder(task.getId(), IRON_INGOT, 2, 0)
.scheduled(IRON_INGOT, 1)
.stored(IRON_ORE, 1)
.processing(IRON_ORE, 1)
.build(0));

ironOreSink.setEnabled(false);
task.step(storage, EMPTY_SINK, StepBehavior.DEFAULT);
assertThat(task.getStatus()).usingRecursiveComparison(STATUS_CONFIG).isEqualTo(
new TaskStatusBuilder(task.getId(), IRON_INGOT, 2, 0)
.scheduled(IRON_INGOT, 1)
.stored(IRON_ORE, 1)
.processing(IRON_ORE, 1)
.noneFound(IRON_INGOT)
.build(0));
}

@Test
void shouldReportWhetherSinkIsLockedFoundOnStatus() {
// Arrange
final RootStorage storage = storage(new ResourceAmount(IRON_ORE, 10));
final PatternRepository patterns = patterns(IRON_INGOT_PATTERN);
final ExternalPatternInputSinkBuilder sinkBuilder = externalPatternInputSink();
final ExternalPatternInputSinkBuilder.Sink ironOreSink = sinkBuilder.storageSink(IRON_INGOT_PATTERN);
final ExternalPatternInputSink sink = sinkBuilder.build();
final Task task = getRunningTask(storage, patterns, EMPTY_SINK, IRON_INGOT, 2);

// Act & assert
task.step(storage, sink, StepBehavior.DEFAULT);
assertThat(task.getStatus()).usingRecursiveComparison(STATUS_CONFIG).isEqualTo(
new TaskStatusBuilder(task.getId(), IRON_INGOT, 2, 0)
.scheduled(IRON_INGOT, 1)
.stored(IRON_ORE, 1)
.processing(IRON_ORE, 1)
.build(0));

ironOreSink.setEnabled(false);
task.step(
storage,
(pattern, resources, action) -> ExternalPatternInputSink.Result.LOCKED,
StepBehavior.DEFAULT
);
assertThat(task.getStatus()).usingRecursiveComparison(STATUS_CONFIG).isEqualTo(
new TaskStatusBuilder(task.getId(), IRON_INGOT, 2, 0)
.scheduled(IRON_INGOT, 1)
.stored(IRON_ORE, 1)
.processing(IRON_ORE, 1)
.locked(IRON_INGOT)
.build(0));
}

private static Task getTask(final RootStorage storage,
final PatternRepository patterns,
final ResourceKey resource,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.refinedmods.refinedstorage.common.autocrafting;

import com.refinedmods.refinedstorage.api.autocrafting.task.ExternalPatternInputSink;
import com.refinedmods.refinedstorage.api.core.Action;
import com.refinedmods.refinedstorage.api.network.autocrafting.PatternProviderExternalPatternInputSink;
import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
Expand All @@ -16,12 +17,15 @@ class CompositePatternProviderExternalPatternInputSink
}

@Override
public boolean accept(final Collection<ResourceAmount> resources, final Action action) {
public ExternalPatternInputSink.Result accept(final Collection<ResourceAmount> resources, final Action action) {
ExternalPatternInputSink.Result result = ExternalPatternInputSink.Result.SKIPPED;
for (final PatternProviderExternalPatternInputSink sink : sinks) {
if (!sink.accept(resources, action)) {
return false;
final ExternalPatternInputSink.Result sinkResult = sink.accept(resources, action);
if (sinkResult == ExternalPatternInputSink.Result.REJECTED) {
return sinkResult;
}
result = result.and(sinkResult);
}
return true;
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,9 @@ private List<FormattedCharSequence> getItemTooltip(final TaskStatus.Item item, f

private Component getErrorTooltip(final TaskStatus.ItemType type) {
return switch (type) {
case MACHINE_DOES_NOT_ACCEPT_RESOURCE -> MACHINE_DOES_NOT_ACCEPT_RESOURCE;
case NO_MACHINE_FOUND -> NO_MACHINE_FOUND;
case AUTOCRAFTER_IS_LOCKED -> AUTOCRAFTER_IS_LOCKED;
case REJECTED -> MACHINE_DOES_NOT_ACCEPT_RESOURCE;
case NONE_FOUND -> NO_MACHINE_FOUND;
case LOCKED -> AUTOCRAFTER_IS_LOCKED;
default -> Component.empty();
};
}
Expand Down
Loading

0 comments on commit cfd2cdd

Please sign in to comment.