Skip to content

Commit

Permalink
feat: starting and running crafting tasks in a pattern provider
Browse files Browse the repository at this point in the history
  • Loading branch information
raoulvdberge committed Jan 10, 2025
1 parent 97149aa commit 5237fea
Show file tree
Hide file tree
Showing 90 changed files with 2,005 additions and 448 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
import com.refinedmods.refinedstorage.api.resource.ResourceAmount;

import java.util.List;
import java.util.UUID;

import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.6")
public record Pattern(List<Ingredient> ingredients, List<ResourceAmount> outputs, PatternType type) {
public Pattern(final List<Ingredient> ingredients, final List<ResourceAmount> outputs, final PatternType type) {
public record Pattern(UUID id, List<Ingredient> ingredients, List<ResourceAmount> outputs, PatternType type) {
public Pattern(final UUID id,
final List<Ingredient> ingredients,
final List<ResourceAmount> outputs,
final PatternType type) {
CoreValidations.validateNotNull(id, "ID cannot be null");
CoreValidations.validateNotEmpty(ingredients, "Ingredients cannot be empty");
CoreValidations.validateNotEmpty(outputs, "Outputs cannot be empty");
CoreValidations.validateNotNull(type, "Type cannot be null");
this.id = id;
this.ingredients = List.copyOf(ingredients);
this.outputs = List.copyOf(outputs);
this.type = type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.12")
public class PatternBuilder {
private final PatternType type;
private final UUID id;
private final List<Ingredient> ingredients = new ArrayList<>();
private final List<ResourceAmount> outputs = new ArrayList<>();

private PatternBuilder(final PatternType type) {
private PatternBuilder(final UUID id, final PatternType type) {
this.id = id;
this.type = type;
}

Expand All @@ -23,16 +26,15 @@ public static PatternBuilder pattern() {
}

public static PatternBuilder pattern(final PatternType type) {
return new PatternBuilder(type);
return pattern(UUID.randomUUID(), type);
}

public IngredientBuilder ingredient(final long amount) {
return new IngredientBuilder(amount);
public static PatternBuilder pattern(final UUID id, final PatternType type) {
return new PatternBuilder(id, type);
}

public PatternBuilder ingredient(final Ingredient ingredient) {
ingredients.add(ingredient);
return this;
public IngredientBuilder ingredient(final long amount) {
return new IngredientBuilder(amount);
}

public PatternBuilder ingredient(final ResourceKey input, final long amount) {
Expand All @@ -46,7 +48,7 @@ public PatternBuilder output(final ResourceKey output, final long amount) {
}

public Pattern build() {
return new Pattern(ingredients, outputs, type);
return new Pattern(id, ingredients, outputs, type);
}

public class IngredientBuilder {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package com.refinedmods.refinedstorage.api.autocrafting.calculation;

import com.refinedmods.refinedstorage.api.autocrafting.Pattern;
import com.refinedmods.refinedstorage.api.core.CoreValidations;
import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
import com.refinedmods.refinedstorage.api.resource.ResourceKey;

public record Amount(long iterations, long amountPerIteration) {
public Amount {
CoreValidations.validateLargerThanZero(iterations, "Iterations");
CoreValidations.validateLargerThanZero(amountPerIteration, "Amount per iteration");
}

public long getTotal() {
return iterations * amountPerIteration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.12")
public interface CraftingCalculatorListener<T> {
CraftingCalculatorListener<T> childCalculationStarted(Pattern pattern, ResourceKey resource, Amount amount);
CraftingCalculatorListener<T> childCalculationStarted(Pattern childPattern, ResourceKey resource, Amount amount);

void childCalculationCompleted(CraftingCalculatorListener<T> childListener);

void ingredientsExhausted(ResourceKey resource, long amount);

void ingredientUsed(Pattern pattern, int ingredientIndex, ResourceKey resource, long amount);
void ingredientUsed(Pattern ingredientPattern, int ingredientIndex, ResourceKey resource, long amount);

void ingredientExtractedFromStorage(ResourceKey resource, long amount);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ boolean isMissingResources() {
}

@Override
public CraftingCalculatorListener<Boolean> childCalculationStarted(final Pattern pattern,
public CraftingCalculatorListener<Boolean> childCalculationStarted(final Pattern childPattern,
final ResourceKey resource,
final Amount amount) {
return new MissingResourcesCraftingCalculatorListener(missingResources);
Expand All @@ -37,7 +37,7 @@ public void ingredientsExhausted(final ResourceKey resource, final long amount)
}

@Override
public void ingredientUsed(final Pattern pattern,
public void ingredientUsed(final Pattern ingredientPattern,
final int ingredientIndex,
final ResourceKey resource,
final long amount) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static Preview calculatePreview(final CraftingCalculator calculator,
}

@Override
public CraftingCalculatorListener<PreviewBuilder> childCalculationStarted(final Pattern pattern,
public CraftingCalculatorListener<PreviewBuilder> childCalculationStarted(final Pattern childPattern,
final ResourceKey resource,
final Amount amount) {
LOGGER.debug("{} - Child calculation starting for {}x {}", listenerId, amount, resource);
Expand All @@ -64,7 +64,7 @@ public void ingredientsExhausted(final ResourceKey resource, final long amount)
}

@Override
public void ingredientUsed(final Pattern pattern,
public void ingredientUsed(final Pattern ingredientPattern,
final int ingredientIndex,
final ResourceKey resource,
final long amount) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ public interface PreviewProvider {

CompletableFuture<Long> getMaxAmount(ResourceKey resource);

boolean startTask(ResourceKey resource, long amount, Actor actor, boolean notify);
CompletableFuture<Boolean> startTask(ResourceKey resource, long amount, Actor actor, boolean notify);
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected final boolean extractAll(final ResourceList inputs,
}
if (action == Action.EXECUTE) {
internalStorage.remove(inputResource, inputAmount);
LOGGER.info("Extracted {}x {} from internal storage", inputAmount, inputResource);
LOGGER.debug("Extracted {}x {} from internal storage", inputAmount, inputResource);
}
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,5 @@
@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.12")
@FunctionalInterface
public interface ExternalPatternInputSink {
ExternalPatternInputSink EMPTY = (pattern, resources, action) -> false;

boolean accept(Pattern pattern, Collection<ResourceAmount> resources, Action action);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@ boolean step(final MutableResourceList internalStorage, final ExternalPatternInp
return true;
}
if (iterationsToSendToSink == 0) {
// TODO: coverage
return false;
}
if (!acceptsIterationInputs(internalStorage, externalPatternInputSink)) {
// TODO: coverage
return false;
}
LOGGER.info("Stepped {} with {} iterations remaining", pattern, iterationsToSendToSink);
LOGGER.debug("Stepped {} with {} iterations remaining", pattern, iterationsToSendToSink);
iterationsToSendToSink--;
return false;
}
Expand All @@ -50,26 +48,31 @@ long interceptInsertion(final ResourceKey resource, final long amount) {
expectedOutputs.remove(resource, available);
return available;
}
// TODO: coverage
return 0;
}

private boolean acceptsIterationInputs(final MutableResourceList internalStorage,
final ExternalPatternInputSink externalPatternInputSink) {
final ResourceList iterationInputsSimulated = calculateIterationInputs(Action.SIMULATE);
if (!extractAll(iterationInputsSimulated, internalStorage, Action.SIMULATE)) {
// TODO: coverage
return false;
}
if (!externalPatternInputSink.accept(pattern, iterationInputsSimulated.copyState(), Action.SIMULATE)) {
// TODO: coverage
return false;
}
final ResourceList iterationInputs = calculateIterationInputs(Action.EXECUTE);
extractAll(iterationInputs, internalStorage, Action.EXECUTE);
// If the sink does not accept the inputs
// we cannot return the extracted resources to the internal storage
// because we have already deducted from the iteration inputs
// and because the sink might have still accepted some resources halfway.
// If we returned the extracted resources to the internal storage and correct the
// iteration inputs, it would potentially duplicate the resources
// 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)) {
// TODO: coverage
return false;
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 @@ -25,11 +25,11 @@ boolean step(final MutableResourceList internalStorage, final ExternalPatternInp
if (!extractAll(iterationInputsSimulated, internalStorage, Action.SIMULATE)) {
return false;
}
LOGGER.info("Stepping {}", pattern);
LOGGER.debug("Stepping {}", pattern);
final ResourceList iterationInputs = calculateIterationInputs(Action.EXECUTE);
extractAll(iterationInputs, internalStorage, Action.EXECUTE);
pattern.outputs().forEach(output -> {
LOGGER.info("Inserting {}x {} into internal storage", output.amount(), output.resource());
LOGGER.debug("Inserting {}x {} into internal storage", output.amount(), output.resource());
internalStorage.add(output);
});
return useIteration();
Expand All @@ -42,7 +42,7 @@ long interceptInsertion(final ResourceKey resource, final long amount) {

protected boolean useIteration() {
iterationsRemaining--;
LOGGER.info("Stepped {} with {} iterations remaining", pattern, iterationsRemaining);
LOGGER.debug("Stepped {} with {} iterations remaining", pattern, iterationsRemaining);
return iterationsRemaining == 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,62 @@
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

import static java.util.Objects.requireNonNull;

public class MutableTaskPlan {
@Nullable
private final Pattern pattern;
private final Map<Pattern, MutablePatternPlan> patterns;
private final MutableResourceList initialRequirements;
private boolean missing;

MutableTaskPlan() {
this(new LinkedHashMap<>(), MutableResourceListImpl.create(), false);
this(null, new LinkedHashMap<>(), MutableResourceListImpl.create(), false);
}

private MutableTaskPlan(final Map<Pattern, MutablePatternPlan> patterns,
private MutableTaskPlan(@Nullable final Pattern pattern,
final Map<Pattern, MutablePatternPlan> patterns,
final MutableResourceList initialRequirements,
final boolean missing) {
this.pattern = pattern;
this.patterns = patterns;
this.initialRequirements = initialRequirements;
this.missing = missing;
}

void addOrUpdatePattern(final Pattern pattern, final long iterations) {
patterns.computeIfAbsent(pattern, MutablePatternPlan::new).addIterations(iterations);
void addOrUpdatePattern(final Pattern usedPattern, final long iterations) {
patterns.computeIfAbsent(usedPattern, MutablePatternPlan::new).addIterations(iterations);
}

void addToExtract(final ResourceKey resource, final long amount) {
initialRequirements.add(resource, amount);
}

void addUsedIngredient(final Pattern pattern,
void addUsedIngredient(final Pattern ingredientPattern,
final int ingredientIndex,
final ResourceKey resource,
final long amount) {
final MutablePatternPlan patternPlan = requireNonNull(patterns.get(pattern));
final MutablePatternPlan patternPlan = requireNonNull(patterns.get(ingredientPattern));
patternPlan.addUsedIngredient(ingredientIndex, resource, amount);
}

MutableTaskPlan copy() {
MutableTaskPlan copy(final Pattern childPattern) {
final Map<Pattern, MutablePatternPlan> patternsCopy = new LinkedHashMap<>();
for (final Map.Entry<Pattern, MutablePatternPlan> entry : patterns.entrySet()) {
patternsCopy.put(entry.getKey(), entry.getValue().copy());
}
return new MutableTaskPlan(patternsCopy, initialRequirements.copy(), missing);
return new MutableTaskPlan(
pattern == null ? childPattern : pattern,
patternsCopy,
initialRequirements.copy(),
missing
);
}

Optional<TaskPlan> getPlan() {
if (missing) {
if (missing || pattern == null) {
return Optional.empty();
}
final Map<Pattern, TaskPlan.PatternPlan> finalPatterns = Collections.unmodifiableMap(patterns.entrySet()
Expand All @@ -66,7 +76,7 @@ Optional<TaskPlan> getPlan() {
(a, b) -> a,
LinkedHashMap::new
)));
return Optional.of(new TaskPlan(finalPatterns, initialRequirements.copyState()));
return Optional.of(new TaskPlan(pattern, finalPatterns, initialRequirements.copyState()));
}

void setMissing() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package com.refinedmods.refinedstorage.api.autocrafting.task;

import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
import com.refinedmods.refinedstorage.api.storage.root.RootStorage;
import com.refinedmods.refinedstorage.api.storage.root.RootStorageListener;

import java.util.Collection;

import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.12")
public interface Task {
public interface Task extends RootStorageListener {
TaskId getId();

TaskState getState();

Collection<ResourceAmount> copyInternalStorageState();

void step(RootStorage rootStorage, ExternalPatternInputSink externalPatternInputSink);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ public record TaskId(UUID id) {
public static TaskId create() {
return new TaskId(UUID.randomUUID());
}

@Override
public String toString() {
return id.toString();
}
}
Loading

0 comments on commit 5237fea

Please sign in to comment.