Autocrafting refactor (#2625)
* Extract some methods to other classes to reduce LOC, rename Craft/Crafting/Processing. * Remove CraftingTaskState as it's unused. * Move creation of preview elements. * Move creation of monitor elements. * Move node management. * Move recipe node update. * Move processing node update. * Clean up List<Pair<NonNullList<ItemStack>, Integer>> mess. * Introduce CraftingPreviewInfo * CraftingTask#calculate returns non-null value now * Split calculate method up some more. * Rename nodes a bit for readability. * Make sure that no CraftingTask instance exists that has missing items. * More cleanup. * More cleanup. * Rename some stuff. * Introduce a NodeListener. * Improve ProcessingNode a bit. * Improve some naming. * Add missing doc * Merge PossibleInputs. * Fix breaking out of wrong loop. * Remove crafting pattern chain stuff and fix forgotten changes to IoUtil calls.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
@@ -54,25 +55,18 @@ public interface ICraftingManager {
|
||||
*
|
||||
* @param stack the stack to craft
|
||||
* @param quantity the quantity to craft
|
||||
* @return the crafting task, or null if no pattern was found for the given stack
|
||||
* @return the calculation result
|
||||
*/
|
||||
@Nullable
|
||||
ICraftingTask create(ItemStack stack, int quantity);
|
||||
ICalculationResult create(ItemStack stack, int quantity);
|
||||
|
||||
/**
|
||||
* Creates a crafting task for a given stack, but doesn't add it to the list.
|
||||
*
|
||||
* @param stack the stack to craft
|
||||
* @param quantity the quantity to craft
|
||||
* @return the crafting task, or null if no pattern was found for the given stack
|
||||
* @return the calculation result
|
||||
*/
|
||||
@Nullable
|
||||
ICraftingTask create(FluidStack stack, int quantity);
|
||||
|
||||
/**
|
||||
* @return a new pattern chain list
|
||||
*/
|
||||
ICraftingPatternChainList createPatternChainList();
|
||||
ICalculationResult create(FluidStack stack, int quantity);
|
||||
|
||||
/**
|
||||
* Schedules a crafting task if the task isn't scheduled yet.
|
||||
@@ -170,9 +164,8 @@ public interface ICraftingManager {
|
||||
void onTaskChanged();
|
||||
|
||||
/**
|
||||
* @param pattern to look for
|
||||
* @return a LinkedHashSet with all container that have this pattern
|
||||
* @param pattern pattern to look for
|
||||
* @return a set with all containers that have this pattern
|
||||
*/
|
||||
|
||||
Set<ICraftingPatternContainer> getAllContainer(ICraftingPattern pattern);
|
||||
Set<ICraftingPatternContainer> getAllContainers(ICraftingPattern pattern);
|
||||
}
|
||||
|
@@ -81,15 +81,4 @@ public interface ICraftingPattern {
|
||||
* @return the id of the factory that creates a crafting task for this pattern, as defined in the {@link ICraftingTaskRegistry}
|
||||
*/
|
||||
ResourceLocation getCraftingTaskFactoryId();
|
||||
|
||||
/**
|
||||
* @param other the other pattern
|
||||
* @return true if this pattern chain be in a chain with the other pattern, false otherwise
|
||||
*/
|
||||
boolean canBeInChainWith(ICraftingPattern other);
|
||||
|
||||
/**
|
||||
* @return the hashcode used to store the pattern chains
|
||||
*/
|
||||
int getChainHashCode();
|
||||
}
|
||||
|
@@ -1,18 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting;
|
||||
|
||||
/**
|
||||
* A crafting pattern chain, which stores equivalent patterns.
|
||||
*/
|
||||
public interface ICraftingPatternChain {
|
||||
/**
|
||||
* @return the current pattern in the chain
|
||||
*/
|
||||
ICraftingPattern current();
|
||||
|
||||
/**
|
||||
* Cycles the pattern in the chain.
|
||||
*
|
||||
* @return the cycled (and now current) pattern
|
||||
*/
|
||||
ICraftingPattern cycle();
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting;
|
||||
|
||||
/**
|
||||
* A list of pattern chains per pattern.
|
||||
*/
|
||||
public interface ICraftingPatternChainList {
|
||||
/**
|
||||
* @param pattern the pattern
|
||||
* @return a chain for the pattern
|
||||
*/
|
||||
ICraftingPatternChain getChain(ICraftingPattern pattern);
|
||||
}
|
@@ -23,7 +23,7 @@ public interface ICraftingMonitorElementList {
|
||||
* A {@link #commit()} will stop any following adds to be merged with previous ones.
|
||||
*
|
||||
* @param element the {@link ICraftingMonitorElement}
|
||||
* @param isProcessing wether to add to the processing list or the crafting list
|
||||
* @param isProcessing whether to add to the processing list or the crafting list
|
||||
*/
|
||||
void add(ICraftingMonitorElement element, boolean isProcessing);
|
||||
|
||||
|
@@ -1,9 +1,21 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting.task;
|
||||
|
||||
/**
|
||||
* The error type.
|
||||
* The result type.
|
||||
*/
|
||||
public enum CraftingTaskErrorType {
|
||||
public enum CalculationResultType {
|
||||
/**
|
||||
* No problems.
|
||||
*/
|
||||
OK,
|
||||
/**
|
||||
* Some requirements are missing.
|
||||
*/
|
||||
MISSING,
|
||||
/**
|
||||
* There is no pattern for the requested stack.
|
||||
*/
|
||||
NO_PATTERN,
|
||||
/**
|
||||
* When the crafting task would cause too much server strain or is too complex.
|
||||
*/
|
||||
@@ -11,5 +23,5 @@ public enum CraftingTaskErrorType {
|
||||
/**
|
||||
* When one of the used patterns during the calculation reuses itself again and would cause an infinite loop.
|
||||
*/
|
||||
RECURSIVE
|
||||
RECURSIVE;
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting.task;
|
||||
|
||||
public enum CraftingTaskState {
|
||||
UNKNOWN,
|
||||
CALCULATING,
|
||||
CALCULATED,
|
||||
RUNNING,
|
||||
DONE
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting.task;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The result of the crafting calculation.
|
||||
*/
|
||||
public interface ICalculationResult {
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
CalculationResultType getType();
|
||||
|
||||
/**
|
||||
* @return get a list of {@link ICraftingPreviewElement}s
|
||||
*/
|
||||
List<ICraftingPreviewElement<?>> getPreviewElements();
|
||||
|
||||
/**
|
||||
* @return the task if the calculation {@link #isOk()}, otherwise null
|
||||
*/
|
||||
@Nullable
|
||||
ICraftingTask getTask();
|
||||
|
||||
/**
|
||||
* @return whether the calculation succeeded
|
||||
*/
|
||||
boolean isOk();
|
||||
|
||||
/**
|
||||
* If this result type is a {@link CalculationResultType#RECURSIVE}, the recursed pattern will be returned here.
|
||||
*
|
||||
* @return the recursed pattern, or null if this result is not {@link CalculationResultType#RECURSIVE}
|
||||
*/
|
||||
@Nullable
|
||||
ICraftingPattern getRecursedPattern();
|
||||
}
|
@@ -2,14 +2,11 @@ package com.refinedmods.refinedstorage.api.autocrafting.task;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -17,19 +14,10 @@ import java.util.UUID;
|
||||
* Represents a crafting task.
|
||||
*/
|
||||
public interface ICraftingTask {
|
||||
/**
|
||||
* Calculates what this task will do, but doesn't run the task yet.
|
||||
*
|
||||
* @return the error, or null if there was no error
|
||||
*/
|
||||
@Nullable
|
||||
ICraftingTaskError calculate();
|
||||
|
||||
/**
|
||||
* Updates this task.
|
||||
* {@link ICraftingTask#calculate()} must be run before this!
|
||||
*
|
||||
* @return true if this crafting task is finished and can be deleted from the list, false otherwise
|
||||
* @return true if this crafting task is finished, false otherwise
|
||||
*/
|
||||
boolean update();
|
||||
|
||||
@@ -57,6 +45,7 @@ public interface ICraftingTask {
|
||||
* Called when a stack is inserted into the system through {@link INetwork#insertItemTracked(ItemStack, int)}.
|
||||
*
|
||||
* @param stack the stack
|
||||
* @return the remainder of this stack after processing of the task
|
||||
*/
|
||||
int onTrackedInsert(ItemStack stack, int size);
|
||||
|
||||
@@ -64,6 +53,7 @@ public interface ICraftingTask {
|
||||
* Called when a stack is inserted into the system through {@link INetwork#insertFluidTracked(FluidStack, int)}.
|
||||
*
|
||||
* @param stack the stack
|
||||
* @return the remainder of this stack after processing of the task
|
||||
*/
|
||||
int onTrackedInsert(FluidStack stack, int size);
|
||||
|
||||
@@ -76,56 +66,25 @@ public interface ICraftingTask {
|
||||
CompoundNBT writeToNbt(CompoundNBT tag);
|
||||
|
||||
/**
|
||||
* {@link ICraftingTask#calculate()} must be run before this!
|
||||
*
|
||||
* @return the elements of this task for display in the crafting monitor
|
||||
*/
|
||||
List<ICraftingMonitorElement> getCraftingMonitorElements();
|
||||
|
||||
/**
|
||||
* {@link ICraftingTask#calculate()} must be run before this!
|
||||
*
|
||||
* @return get a list of {@link ICraftingPreviewElement}s
|
||||
*/
|
||||
List<ICraftingPreviewElement<?>> getPreviewStacks();
|
||||
|
||||
/**
|
||||
* @return the crafting pattern corresponding to this task
|
||||
*/
|
||||
ICraftingPattern getPattern();
|
||||
|
||||
/**
|
||||
* @return the time in ms when this task has started
|
||||
* @return the unix time in ms when this task has started
|
||||
*/
|
||||
long getExecutionStarted();
|
||||
|
||||
/**
|
||||
* @return the missing items
|
||||
*/
|
||||
IStackList<ItemStack> getMissing();
|
||||
|
||||
/**
|
||||
* @return the missing fluids
|
||||
*/
|
||||
IStackList<FluidStack> getMissingFluids();
|
||||
|
||||
/**
|
||||
* @return true if any items or fluids are missing, false otherwise
|
||||
*/
|
||||
default boolean hasMissing() {
|
||||
return !getMissing().isEmpty() || !getMissingFluids().isEmpty();
|
||||
}
|
||||
long getStartTime();
|
||||
|
||||
/**
|
||||
* @return the id of this task
|
||||
*/
|
||||
UUID getId();
|
||||
|
||||
/**
|
||||
* @return the state of this crafting task
|
||||
*/
|
||||
CraftingTaskState getState();
|
||||
|
||||
/**
|
||||
* Start the CraftingTask
|
||||
*/
|
||||
|
@@ -1,23 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.api.autocrafting.task;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Returned from {@link ICraftingTask#calculate()} when an error occurs during the calculation.
|
||||
*/
|
||||
public interface ICraftingTaskError {
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
CraftingTaskErrorType getType();
|
||||
|
||||
/**
|
||||
* If this error type is a {@link CraftingTaskErrorType#RECURSIVE}, the recursed pattern will be returned here.
|
||||
*
|
||||
* @return the recursed pattern, or null if this error is not {@link CraftingTaskErrorType#RECURSIVE}
|
||||
*/
|
||||
@Nullable
|
||||
ICraftingPattern getRecursedPattern();
|
||||
}
|
@@ -4,8 +4,6 @@ import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A factory that creates a crafting task.
|
||||
* Register this factory in the {@link ICraftingTaskRegistry}.
|
||||
@@ -18,10 +16,9 @@ public interface ICraftingTaskFactory {
|
||||
* @param requested the request info
|
||||
* @param pattern the pattern
|
||||
* @param quantity the quantity
|
||||
* @return the crafting task
|
||||
* @return the calculation result
|
||||
*/
|
||||
@Nonnull
|
||||
ICraftingTask create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern);
|
||||
ICalculationResult create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern);
|
||||
|
||||
/**
|
||||
* Returns a crafting task for a given NBT tag.
|
||||
|
@@ -56,6 +56,23 @@ public interface IStackList<T> {
|
||||
return get(stack, IComparer.COMPARE_NBT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount in this list, based on the stack and the flags.
|
||||
*
|
||||
* @param stack the stack
|
||||
* @param flags the flags
|
||||
* @return the count, 0 if not found
|
||||
*/
|
||||
int getCount(@Nonnull T stack, int flags);
|
||||
|
||||
/**
|
||||
* @param stack the stack
|
||||
* @return the count, 0 if not found
|
||||
*/
|
||||
default int getCount(@Nonnull T stack) {
|
||||
return getCount(stack, IComparer.COMPARE_NBT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stack.
|
||||
*
|
||||
|
@@ -2,18 +2,14 @@ package com.refinedmods.refinedstorage.apiimpl.autocrafting;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternChainList;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskFactory;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.*;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.network.node.INetworkNode;
|
||||
import com.refinedmods.refinedstorage.api.util.IComparer;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTask;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator.CalculationResult;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
@@ -94,40 +90,33 @@ public class CraftingManager implements ICraftingManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ICraftingTask create(ItemStack stack, int quantity) {
|
||||
public ICalculationResult create(ItemStack stack, int quantity) {
|
||||
ICraftingPattern pattern = getPattern(stack);
|
||||
if (pattern == null) {
|
||||
return null;
|
||||
return new CalculationResult(CalculationResultType.NO_PATTERN);
|
||||
}
|
||||
|
||||
ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId());
|
||||
if (factory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return factory.create(network, API.instance().createCraftingRequestInfo(stack), quantity, pattern);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ICraftingTask create(FluidStack stack, int quantity) {
|
||||
ICraftingPattern pattern = getPattern(stack);
|
||||
if (pattern == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId());
|
||||
if (factory == null) {
|
||||
return null;
|
||||
return new CalculationResult(CalculationResultType.NO_PATTERN);
|
||||
}
|
||||
|
||||
return factory.create(network, API.instance().createCraftingRequestInfo(stack), quantity, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICraftingPatternChainList createPatternChainList() {
|
||||
return new CraftingPatternChainList(patterns);
|
||||
public ICalculationResult create(FluidStack stack, int quantity) {
|
||||
ICraftingPattern pattern = getPattern(stack);
|
||||
if (pattern == null) {
|
||||
return new CalculationResult(CalculationResultType.NO_PATTERN);
|
||||
}
|
||||
|
||||
ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId());
|
||||
if (factory == null) {
|
||||
return new CalculationResult(CalculationResultType.NO_PATTERN);
|
||||
}
|
||||
|
||||
return factory.create(network, API.instance().createCraftingRequestInfo(stack), quantity, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -249,18 +238,10 @@ public class CraftingManager implements ICraftingManager {
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
ICraftingTask task = create(stack, amount);
|
||||
ICalculationResult result = create(stack, amount);
|
||||
|
||||
if (task != null) {
|
||||
ICraftingTaskError error = task.calculate();
|
||||
|
||||
if (error == null && !task.hasMissing()) {
|
||||
this.start(task);
|
||||
|
||||
return task;
|
||||
} else {
|
||||
throttle(source);
|
||||
}
|
||||
if (result.isOk()) {
|
||||
start(result.getTask());
|
||||
} else {
|
||||
throttle(source);
|
||||
}
|
||||
@@ -285,18 +266,10 @@ public class CraftingManager implements ICraftingManager {
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
ICraftingTask task = create(stack, amount);
|
||||
ICalculationResult result = create(stack, amount);
|
||||
|
||||
if (task != null) {
|
||||
ICraftingTaskError error = task.calculate();
|
||||
|
||||
if (error == null && !task.hasMissing()) {
|
||||
this.start(task);
|
||||
|
||||
return task;
|
||||
} else {
|
||||
throttle(source);
|
||||
}
|
||||
if (result.isOk()) {
|
||||
start(result.getTask());
|
||||
} else {
|
||||
throttle(source);
|
||||
}
|
||||
@@ -413,8 +386,8 @@ public class CraftingManager implements ICraftingManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ICraftingPatternContainer> getAllContainer(ICraftingPattern pattern) {
|
||||
return patternToContainer.getOrDefault(pattern, new LinkedHashSet<>());
|
||||
public Set<ICraftingPatternContainer> getAllContainers(ICraftingPattern pattern) {
|
||||
return patternToContainer.getOrDefault(pattern, Collections.emptySet());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@@ -169,7 +169,13 @@ public class CraftingPattern implements ICraftingPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeInChainWith(ICraftingPattern other) {
|
||||
public boolean equals(Object otherObj) {
|
||||
if (!(otherObj instanceof ICraftingPattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ICraftingPattern other = (ICraftingPattern) otherObj;
|
||||
|
||||
if (other.isProcessing() != processing) {
|
||||
return false;
|
||||
}
|
||||
@@ -239,7 +245,7 @@ public class CraftingPattern implements ICraftingPattern {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChainHashCode() {
|
||||
public int hashCode() {
|
||||
int result = 0;
|
||||
|
||||
result = 31 * result + (processing ? 1 : 0);
|
||||
@@ -272,19 +278,6 @@ public class CraftingPattern implements ICraftingPattern {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getChainHashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof CraftingPattern) {
|
||||
return canBeInChainWith((CraftingPattern) obj);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class DummyCraftingInventory extends CraftingInventory {
|
||||
public DummyCraftingInventory() {
|
||||
super(new Container(null, 0) {
|
||||
|
@@ -1,32 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternChain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingPatternChain implements ICraftingPatternChain {
|
||||
private final List<ICraftingPattern> patterns = new ArrayList<>();
|
||||
private int pos;
|
||||
|
||||
public void addPattern(ICraftingPattern pattern) {
|
||||
patterns.add(pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICraftingPattern current() {
|
||||
return patterns.get(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICraftingPattern cycle() {
|
||||
if (pos + 1 >= patterns.size()) {
|
||||
this.pos = 0;
|
||||
} else {
|
||||
this.pos++;
|
||||
}
|
||||
|
||||
return current();
|
||||
}
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternChain;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternChainList;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CraftingPatternChainList implements ICraftingPatternChainList {
|
||||
private final Map<Key, CraftingPatternChain> map = new HashMap<>();
|
||||
|
||||
public CraftingPatternChainList(Collection<ICraftingPattern> patterns) {
|
||||
for (ICraftingPattern pattern : patterns) {
|
||||
Key key = new Key(pattern);
|
||||
|
||||
CraftingPatternChain chain = map.get(key);
|
||||
|
||||
if (chain == null) {
|
||||
map.put(key, chain = new CraftingPatternChain());
|
||||
}
|
||||
|
||||
chain.addPattern(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICraftingPatternChain getChain(ICraftingPattern pattern) {
|
||||
ICraftingPatternChain chain = map.get(new Key(pattern));
|
||||
|
||||
if (chain == null) {
|
||||
throw new IllegalStateException("Pattern was not found in pattern chain");
|
||||
}
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
private static class Key {
|
||||
private final ICraftingPattern pattern;
|
||||
|
||||
public Key(ICraftingPattern pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other instanceof Key && pattern.canBeInChainWith(((Key) other).pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return pattern.getChainHashCode();
|
||||
}
|
||||
}
|
||||
}
|
@@ -158,4 +158,50 @@ public class FluidCraftingMonitorElement implements ICraftingMonitorElement {
|
||||
public int elementHashCode() {
|
||||
return API.instance().getFluidStackHashCode(stack);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final FluidStack stack;
|
||||
private int stored;
|
||||
private int missing;
|
||||
private int processing;
|
||||
private int scheduled;
|
||||
private int crafting;
|
||||
|
||||
public Builder(FluidStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public FluidCraftingMonitorElement.Builder stored(int stored) {
|
||||
this.stored = stored;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FluidCraftingMonitorElement.Builder missing(int missing) {
|
||||
this.missing = missing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FluidCraftingMonitorElement.Builder processing(int processing) {
|
||||
this.processing = processing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FluidCraftingMonitorElement.Builder scheduled(int scheduled) {
|
||||
this.scheduled = scheduled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FluidCraftingMonitorElement.Builder crafting(int crafting) {
|
||||
this.crafting = crafting;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FluidCraftingMonitorElement build() {
|
||||
return new FluidCraftingMonitorElement(stack, stored, missing, processing, scheduled, crafting);
|
||||
}
|
||||
|
||||
public static FluidCraftingMonitorElement.Builder forStack(FluidStack stack) {
|
||||
return new FluidCraftingMonitorElement.Builder(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -158,4 +158,50 @@ public class ItemCraftingMonitorElement implements ICraftingMonitorElement {
|
||||
public int elementHashCode() {
|
||||
return API.instance().getItemStackHashCode(stack);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final ItemStack stack;
|
||||
private int stored;
|
||||
private int missing;
|
||||
private int processing;
|
||||
private int scheduled;
|
||||
private int crafting;
|
||||
|
||||
public Builder(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public Builder stored(int stored) {
|
||||
this.stored = stored;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder missing(int missing) {
|
||||
this.missing = missing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder processing(int processing) {
|
||||
this.processing = processing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder scheduled(int scheduled) {
|
||||
this.scheduled = scheduled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder crafting(int crafting) {
|
||||
this.crafting = crafting;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemCraftingMonitorElement build() {
|
||||
return new ItemCraftingMonitorElement(stack, stored, missing, processing, scheduled, crafting);
|
||||
}
|
||||
|
||||
public static Builder forStack(ItemStack stack) {
|
||||
return new Builder(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.refinedmods.refinedstorage.RS;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
import com.refinedmods.refinedstorage.api.render.IElementDrawers;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
@@ -12,10 +12,10 @@ import net.minecraft.util.ResourceLocation;
|
||||
public class ErrorCraftingPreviewElement implements ICraftingPreviewElement<ItemStack> {
|
||||
public static final ResourceLocation ID = new ResourceLocation(RS.ID, "error");
|
||||
|
||||
private final CraftingTaskErrorType type;
|
||||
private final CalculationResultType type;
|
||||
private final ItemStack stack;
|
||||
|
||||
public ErrorCraftingPreviewElement(CraftingTaskErrorType type, ItemStack stack) {
|
||||
public ErrorCraftingPreviewElement(CalculationResultType type, ItemStack stack) {
|
||||
this.type = type;
|
||||
this.stack = stack;
|
||||
}
|
||||
@@ -51,13 +51,13 @@ public class ErrorCraftingPreviewElement implements ICraftingPreviewElement<Item
|
||||
buf.writeItemStack(stack);
|
||||
}
|
||||
|
||||
public CraftingTaskErrorType getType() {
|
||||
public CalculationResultType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static ErrorCraftingPreviewElement read(PacketBuffer buf) {
|
||||
int errorIdx = buf.readInt();
|
||||
CraftingTaskErrorType error = errorIdx >= 0 && errorIdx < CraftingTaskErrorType.values().length ? CraftingTaskErrorType.values()[errorIdx] : CraftingTaskErrorType.TOO_COMPLEX;
|
||||
CalculationResultType error = errorIdx >= 0 && errorIdx < CalculationResultType.values().length ? CalculationResultType.values()[errorIdx] : CalculationResultType.TOO_COMPLEX;
|
||||
ItemStack stack = buf.readItemStack();
|
||||
|
||||
return new ErrorCraftingPreviewElement(error, stack);
|
||||
|
@@ -1,145 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public abstract class Craft {
|
||||
private static final String NBT_PATTERN = "Pattern";
|
||||
private static final String NBT_ROOT = "Root";
|
||||
private static final String NBT_IS_PROCESSING = "IsProcessing";
|
||||
private static final String NBT_ITEMS_TO_USE = "ItemsToUse";
|
||||
private static final String NBT_QUANTITY = "Quantity";
|
||||
private static final String NBT_NEEDED_PER_CRAFT = "NeededPerCraft";
|
||||
|
||||
private final boolean root;
|
||||
protected int quantity;
|
||||
private final ICraftingPattern pattern;
|
||||
private final Map<Integer, IStackList<ItemStack>> itemsToUse = new LinkedHashMap<>();
|
||||
private final Map<Integer, Integer> neededPerCraft = new LinkedHashMap<>();
|
||||
|
||||
Craft(ICraftingPattern pattern, boolean root) {
|
||||
this.pattern = pattern;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
Craft(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
this.quantity = tag.getInt(NBT_QUANTITY);
|
||||
this.pattern = CraftingTask.readPatternFromNbt(tag.getCompound(NBT_PATTERN), network.getWorld());
|
||||
this.root = tag.getBoolean(NBT_ROOT);
|
||||
ListNBT list = tag.getList(NBT_ITEMS_TO_USE, Constants.NBT.TAG_LIST);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
this.itemsToUse.put(i, CraftingTask.readItemStackList(list.getList(i)));
|
||||
}
|
||||
List<Integer> perCraftList = Ints.asList(tag.getIntArray(NBT_NEEDED_PER_CRAFT));
|
||||
for (int i = 0; i < perCraftList.size(); i++) {
|
||||
neededPerCraft.put(i, perCraftList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
static Craft createCraftFromNBT(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
return tag.getBoolean(NBT_IS_PROCESSING) ? new Processing(network, tag) : new Crafting(network, tag);
|
||||
}
|
||||
|
||||
ICraftingPattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
void addQuantity(int quantity) {
|
||||
this.quantity += quantity;
|
||||
}
|
||||
|
||||
void next() {
|
||||
quantity--;
|
||||
}
|
||||
|
||||
boolean isRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
boolean hasItems() {
|
||||
return !itemsToUse.isEmpty();
|
||||
}
|
||||
|
||||
IStackList<ItemStack> getItemsToUse(boolean simulate) {
|
||||
IStackList<ItemStack> toReturn = API.instance().createItemStackList();
|
||||
for (int i = 0; i < itemsToUse.size(); i++) {
|
||||
int needed = neededPerCraft.get(i);
|
||||
if (!itemsToUse.get(i).isEmpty()) {
|
||||
Iterator<StackListEntry<ItemStack>> it = itemsToUse.get(i).getStacks().iterator();
|
||||
while (needed > 0 && it.hasNext()) {
|
||||
ItemStack toUse = it.next().getStack();
|
||||
if (needed < toUse.getCount()) {
|
||||
if (!simulate) {
|
||||
itemsToUse.get(i).remove(toUse, needed);
|
||||
}
|
||||
toReturn.add(toUse, needed);
|
||||
needed = 0;
|
||||
} else {
|
||||
if (!simulate) {
|
||||
it.remove();
|
||||
}
|
||||
needed -= toUse.getCount();
|
||||
toReturn.add(toUse);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LogManager.getLogger(Craft.class).warn("Craft requested more Items than available");
|
||||
this.quantity = 0; // stop crafting
|
||||
break;
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void addItemsToUse(int ingredientNumber, ItemStack stack, int size, int perCraft) {
|
||||
if (!neededPerCraft.containsKey(ingredientNumber)) {
|
||||
neededPerCraft.put(ingredientNumber, perCraft);
|
||||
}
|
||||
if (!itemsToUse.containsKey(ingredientNumber)) {
|
||||
itemsToUse.put(ingredientNumber, API.instance().createItemStackList());
|
||||
}
|
||||
itemsToUse.get(ingredientNumber).add(stack, size);
|
||||
}
|
||||
|
||||
CompoundNBT writeToNbt() {
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
tag.putInt(NBT_QUANTITY, quantity);
|
||||
tag.putBoolean(NBT_IS_PROCESSING, this instanceof Processing);
|
||||
tag.putBoolean(NBT_ROOT, root);
|
||||
tag.put(NBT_PATTERN, CraftingTask.writePatternToNbt(pattern));
|
||||
ListNBT list = new ListNBT();
|
||||
for (IStackList<ItemStack> stackList : itemsToUse.values()) {
|
||||
list.add(CraftingTask.writeItemStackList(stackList));
|
||||
}
|
||||
tag.put(NBT_ITEMS_TO_USE, list);
|
||||
tag.putIntArray(NBT_NEEDED_PER_CRAFT, Ints.toArray(neededPerCraft.values()));
|
||||
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
void finishCalculation() {
|
||||
//NOOP
|
||||
}
|
||||
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.util.StackUtils;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
|
||||
class Crafting extends Craft {
|
||||
private static final String NBT_RECIPE = "Recipe";
|
||||
private final NonNullList<ItemStack> recipe;
|
||||
|
||||
Crafting(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe) {
|
||||
super(pattern, root);
|
||||
this.recipe = recipe;
|
||||
}
|
||||
|
||||
Crafting(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
super(network, tag);
|
||||
this.recipe = NonNullList.create();
|
||||
ListNBT tookList = tag.getList(NBT_RECIPE, Constants.NBT.TAG_COMPOUND);
|
||||
for (int i = 0; i < tookList.size(); ++i) {
|
||||
ItemStack stack = StackUtils.deserializeStackFromNbt(tookList.getCompound(i));
|
||||
|
||||
// Can be empty.
|
||||
recipe.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
NonNullList<ItemStack> getRecipe() {
|
||||
return recipe;
|
||||
}
|
||||
|
||||
CompoundNBT writeToNbt() {
|
||||
CompoundNBT tag = super.writeToNbt();
|
||||
|
||||
ListNBT tookList = new ListNBT();
|
||||
for (ItemStack took : this.recipe) {
|
||||
tookList.add(StackUtils.serializeStackToNbt(took));
|
||||
}
|
||||
|
||||
tag.put(NBT_RECIPE, tookList);
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.util.IComparer;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingPatternInputs {
|
||||
private final NonNullList<ItemStack> recipe = NonNullList.create();
|
||||
private final List<Ingredient<ItemStack>> itemIngredients = new ArrayList<>();
|
||||
private final List<Ingredient<FluidStack>> fluidIngredients = new ArrayList<>();
|
||||
|
||||
public CraftingPatternInputs(ICraftingPattern pattern) {
|
||||
fillOutRecipe(pattern);
|
||||
combineItemInputs(pattern);
|
||||
combineFluidInputs(pattern);
|
||||
}
|
||||
|
||||
private void fillOutRecipe(ICraftingPattern pattern) {
|
||||
for (NonNullList<ItemStack> inputsForSlot : pattern.getInputs()) {
|
||||
if (inputsForSlot.isEmpty()) {
|
||||
recipe.add(ItemStack.EMPTY);
|
||||
} else {
|
||||
recipe.add(inputsForSlot.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void combineItemInputs(ICraftingPattern pattern) {
|
||||
for (NonNullList<ItemStack> inputsForSlot : pattern.getInputs()) {
|
||||
if (inputsForSlot.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ingredient<ItemStack> matchingIngredient = findMatchingItemIngredient(inputsForSlot);
|
||||
|
||||
if (matchingIngredient == null) {
|
||||
itemIngredients.add(new Ingredient<>(inputsForSlot, inputsForSlot.get(0).getCount()));
|
||||
} else {
|
||||
matchingIngredient.increaseCount(inputsForSlot.get(0).getCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void combineFluidInputs(ICraftingPattern pattern) {
|
||||
for (NonNullList<FluidStack> inputsForSlot : pattern.getFluidInputs()) {
|
||||
if (inputsForSlot.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Ingredient<FluidStack> matchingIngredient = findMatchingFluidIngredient(inputsForSlot);
|
||||
|
||||
if (matchingIngredient == null) {
|
||||
fluidIngredients.add(new Ingredient<>(inputsForSlot, inputsForSlot.get(0).getAmount()));
|
||||
} else {
|
||||
matchingIngredient.increaseCount(inputsForSlot.get(0).getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Ingredient<ItemStack> findMatchingItemIngredient(NonNullList<ItemStack> inputsForSlot) {
|
||||
for (Ingredient<ItemStack> existingIngredient : itemIngredients) {
|
||||
if (existingIngredient.getInputs().size() == inputsForSlot.size()) {
|
||||
boolean found = true;
|
||||
|
||||
for (int i = 0; i < inputsForSlot.size(); i++) {
|
||||
if (!API.instance().getComparer().isEqualNoQuantity(existingIngredient.getInputs().get(i), inputsForSlot.get(i))) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
return existingIngredient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Ingredient<FluidStack> findMatchingFluidIngredient(NonNullList<FluidStack> inputsForSlot) {
|
||||
for (Ingredient<FluidStack> existingIngredient : fluidIngredients) {
|
||||
if (existingIngredient.getInputs().size() == inputsForSlot.size()) {
|
||||
boolean found = true;
|
||||
|
||||
for (int i = 0; i < inputsForSlot.size(); i++) {
|
||||
if (!API.instance().getComparer().isEqual(existingIngredient.getInputs().get(i), inputsForSlot.get(i), IComparer.COMPARE_NBT)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
return existingIngredient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public NonNullList<ItemStack> getRecipe() {
|
||||
return recipe;
|
||||
}
|
||||
|
||||
public List<Ingredient<ItemStack>> getItemIngredients() {
|
||||
return itemIngredients;
|
||||
}
|
||||
|
||||
public List<Ingredient<FluidStack>> getFluidIngredients() {
|
||||
return fluidIngredients;
|
||||
}
|
||||
|
||||
public static class Ingredient<T> {
|
||||
private final NonNullList<T> inputs;
|
||||
private int count;
|
||||
|
||||
public Ingredient(NonNullList<T> inputs, int count) {
|
||||
this.inputs = inputs;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public NonNullList<T> getInputs() {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void increaseCount(int count) {
|
||||
this.count += count;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CraftingTaskError implements ICraftingTaskError {
|
||||
private final CraftingTaskErrorType type;
|
||||
private ICraftingPattern recursedPattern;
|
||||
|
||||
public CraftingTaskError(CraftingTaskErrorType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public CraftingTaskError(CraftingTaskErrorType type, ICraftingPattern recursedPattern) {
|
||||
this.type = type;
|
||||
this.recursedPattern = recursedPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftingTaskErrorType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ICraftingPattern getRecursedPattern() {
|
||||
return recursedPattern;
|
||||
}
|
||||
}
|
@@ -2,23 +2,19 @@ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.RS;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskFactory;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.*;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator.CraftingCalculator;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CraftingTaskFactory implements ICraftingTaskFactory {
|
||||
public static final ResourceLocation ID = new ResourceLocation(RS.ID, "v6");
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ICraftingTask create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {
|
||||
return new CraftingTask(network, requested, quantity, pattern);
|
||||
public ICalculationResult create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {
|
||||
CraftingCalculator calculator = new CraftingCalculator(network, requested, quantity, pattern);
|
||||
return calculator.calculate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,187 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;
|
||||
import com.refinedmods.refinedstorage.api.util.Action;
|
||||
import com.refinedmods.refinedstorage.api.util.IComparer;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class IoUtil {
|
||||
private static final Logger LOGGER = LogManager.getLogger(IoUtil.class);
|
||||
|
||||
private static final int DEFAULT_EXTRACT_FLAGS = IComparer.COMPARE_NBT;
|
||||
|
||||
public static IStackList<ItemStack> extractFromInternalItemStorage(IStackList<ItemStack> list, IStorageDisk<ItemStack> storage, Action action) {
|
||||
IStackList<ItemStack> extracted = API.instance().createItemStackList();
|
||||
|
||||
for (StackListEntry<ItemStack> entry : list.getStacks()) {
|
||||
ItemStack result = storage.extract(entry.getStack(), entry.getStack().getCount(), DEFAULT_EXTRACT_FLAGS, action);
|
||||
|
||||
if (result.isEmpty() || result.getCount() != entry.getStack().getCount()) {
|
||||
if (action == Action.PERFORM) {
|
||||
throw new IllegalStateException("The internal crafting inventory reported that " + entry.getStack() + " was available but we got " + result);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
extracted.add(result);
|
||||
}
|
||||
|
||||
return extracted;
|
||||
}
|
||||
|
||||
public static IStackList<FluidStack> extractFromInternalFluidStorage(IStackList<FluidStack> list, IStorageDisk<FluidStack> storage, Action action) {
|
||||
IStackList<FluidStack> extracted = API.instance().createFluidStackList();
|
||||
|
||||
for (StackListEntry<FluidStack> entry : list.getStacks()) {
|
||||
FluidStack result = storage.extract(entry.getStack(), entry.getStack().getAmount(), DEFAULT_EXTRACT_FLAGS, action);
|
||||
|
||||
if (result.isEmpty() || result.getAmount() != entry.getStack().getAmount()) {
|
||||
if (action == Action.PERFORM) {
|
||||
throw new IllegalStateException("The internal crafting inventory reported that " + entry.getStack() + " was available but we got " + result);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
extracted.add(result);
|
||||
}
|
||||
|
||||
return extracted;
|
||||
}
|
||||
|
||||
public static boolean insertIntoInventory(@Nullable IItemHandler dest, Collection<StackListEntry<ItemStack>> toInsert, Action action) {
|
||||
if (dest == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (toInsert.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Deque<StackListEntry<ItemStack>> stacks = new ArrayDeque<>(toInsert);
|
||||
|
||||
StackListEntry<ItemStack> currentEntry = stacks.poll();
|
||||
|
||||
ItemStack current = currentEntry != null ? currentEntry.getStack() : null;
|
||||
|
||||
List<Integer> availableSlots = IntStream.range(0, dest.getSlots()).boxed().collect(Collectors.toList());
|
||||
|
||||
while (current != null && !availableSlots.isEmpty()) {
|
||||
ItemStack remainder = ItemStack.EMPTY;
|
||||
|
||||
for (int i = 0; i < availableSlots.size(); ++i) {
|
||||
int slot = availableSlots.get(i);
|
||||
|
||||
// .copy() is mandatory!
|
||||
remainder = dest.insertItem(slot, current.copy(), action == Action.SIMULATE);
|
||||
|
||||
// If we inserted *something*
|
||||
if (remainder.isEmpty() || current.getCount() != remainder.getCount()) {
|
||||
availableSlots.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (remainder.isEmpty()) { // If we inserted successfully, get a next stack.
|
||||
currentEntry = stacks.poll();
|
||||
|
||||
current = currentEntry != null ? currentEntry.getStack() : null;
|
||||
} else if (current.getCount() == remainder.getCount()) { // If we didn't insert anything over ALL these slots, stop here.
|
||||
break;
|
||||
} else { // If we didn't insert all, continue with other slots and use our remainder.
|
||||
current = remainder;
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = current == null && stacks.isEmpty();
|
||||
|
||||
if (!success && action == Action.PERFORM) {
|
||||
LOGGER.warn("Inventory unexpectedly didn't accept " + (current != null ? current.getTranslationKey() : null) + ", the remainder has been voided!");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public static boolean insertIntoInventory(IFluidHandler dest, Collection<StackListEntry<FluidStack>> toInsert, Action action) {
|
||||
for (StackListEntry<FluidStack> entry : toInsert) {
|
||||
int filled = dest.fill(entry.getStack(), action == Action.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE);
|
||||
|
||||
if (filled != entry.getStack().getAmount()) {
|
||||
if (action == Action.PERFORM) {
|
||||
LOGGER.warn("Inventory unexpectedly didn't accept all of " + entry.getStack().getTranslationKey() + ", the remainder has been voided!");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void extractItemsFromNetwork(IStackList<ItemStack> toExtractInitial, INetwork network, IStorageDisk<ItemStack> internalStorage) {
|
||||
if (toExtractInitial.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemStack> toRemove = new ArrayList<>();
|
||||
|
||||
for (StackListEntry<ItemStack> toExtract : toExtractInitial.getStacks()) {
|
||||
ItemStack result = network.extractItem(toExtract.getStack(), toExtract.getStack().getCount(), Action.PERFORM);
|
||||
|
||||
if (!result.isEmpty()) {
|
||||
internalStorage.insert(toExtract.getStack(), result.getCount(), Action.PERFORM);
|
||||
|
||||
toRemove.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemStack stack : toRemove) {
|
||||
toExtractInitial.remove(stack);
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
network.getCraftingManager().onTaskChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public static void extractFluidsFromNetwork(IStackList<FluidStack> toExtractInitial, INetwork network, IStorageDisk<FluidStack> internalStorage) {
|
||||
if (toExtractInitial.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<FluidStack> toRemove = new ArrayList<>();
|
||||
|
||||
for (StackListEntry<FluidStack> toExtract : toExtractInitial.getStacks()) {
|
||||
FluidStack result = network.extractFluid(toExtract.getStack(), toExtract.getStack().getAmount(), Action.PERFORM);
|
||||
|
||||
if (!result.isEmpty()) {
|
||||
internalStorage.insert(toExtract.getStack(), result.getAmount(), Action.PERFORM);
|
||||
|
||||
toRemove.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
for (FluidStack stack : toRemove) {
|
||||
toExtractInitial.remove(stack);
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) {
|
||||
network.getCraftingManager().onTaskChanged();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,189 +0,0 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
class Processing extends Craft {
|
||||
private static final String NBT_ITEMS_TO_RECEIVE = "ItemsToReceive";
|
||||
private static final String NBT_FLUIDS_TO_RECEIVE = "FluidsToReceive";
|
||||
private static final String NBT_FLUIDS_TO_USE = "FluidsToUse";
|
||||
private static final String NBT_STATE = "State";
|
||||
private static final String NBT_QUANTITY_TOTAL = "TotalQuantity";
|
||||
private static final String NBT_ITEMS_RECEIVED = "ItemsReceived";
|
||||
private static final String NBT_FLUIDS_RECEIVED = "FluidsReceived";
|
||||
private static final String NBT_ITEMS_TO_DISPLAY = "ItemsToDisplay";
|
||||
|
||||
private IStackList<ItemStack> itemsToReceive = API.instance().createItemStackList();
|
||||
private IStackList<ItemStack> itemsReceived = API.instance().createItemStackList();
|
||||
private IStackList<FluidStack> fluidsToReceive = API.instance().createFluidStackList();
|
||||
private IStackList<FluidStack> fluidsReceived = API.instance().createFluidStackList();
|
||||
private IStackList<FluidStack> fluidsToUse = API.instance().createFluidStackList();
|
||||
private IStackList<ItemStack> itemsToDisplay;
|
||||
private ProcessingState state = ProcessingState.READY;
|
||||
|
||||
private int finished;
|
||||
private int totalQuantity;
|
||||
|
||||
Processing(ICraftingPattern pattern, boolean root) {
|
||||
super(pattern, root);
|
||||
}
|
||||
|
||||
Processing(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
super(network, tag);
|
||||
this.itemsToReceive = CraftingTask.readItemStackList(tag.getList(NBT_ITEMS_TO_RECEIVE, Constants.NBT.TAG_COMPOUND));
|
||||
this.fluidsToReceive = CraftingTask.readFluidStackList(tag.getList(NBT_FLUIDS_TO_RECEIVE, Constants.NBT.TAG_COMPOUND));
|
||||
this.state = ProcessingState.values()[tag.getInt(NBT_STATE)];
|
||||
this.totalQuantity = tag.getInt(NBT_QUANTITY_TOTAL);
|
||||
this.itemsReceived = CraftingTask.readItemStackList(tag.getList(NBT_ITEMS_RECEIVED, Constants.NBT.TAG_COMPOUND));
|
||||
this.fluidsReceived = CraftingTask.readFluidStackList(tag.getList(NBT_FLUIDS_RECEIVED, Constants.NBT.TAG_COMPOUND));
|
||||
this.fluidsToUse = CraftingTask.readFluidStackList(tag.getList(NBT_FLUIDS_TO_USE, Constants.NBT.TAG_COMPOUND));
|
||||
this.itemsToDisplay = CraftingTask.readItemStackList(tag.getList(NBT_ITEMS_TO_DISPLAY, Constants.NBT.TAG_COMPOUND));
|
||||
}
|
||||
|
||||
@Override
|
||||
void finishCalculation() {
|
||||
this.totalQuantity = quantity;
|
||||
updateItemsToDisplay();
|
||||
}
|
||||
|
||||
int getNeeded(ItemStack stack) {
|
||||
if (itemsToReceive.get(stack) != null) {
|
||||
int needed = itemsToReceive.get(stack).getCount() * totalQuantity;
|
||||
if (itemsReceived.get(stack) != null) {
|
||||
needed -= itemsReceived.get(stack).getCount();
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getNeeded(FluidStack stack) {
|
||||
if (fluidsToReceive.get(stack) != null) {
|
||||
int needed = fluidsToReceive.get(stack).getAmount() * totalQuantity;
|
||||
if (fluidsReceived.get(stack) != null) {
|
||||
needed -= fluidsReceived.get(stack).getAmount();
|
||||
}
|
||||
return needed;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean updateFinished() {
|
||||
int fin = finished;
|
||||
updateFinishedPatterns();
|
||||
if (finished == totalQuantity) {
|
||||
this.setState(ProcessingState.PROCESSED);
|
||||
}
|
||||
return fin != finished;
|
||||
}
|
||||
|
||||
/*
|
||||
Calculates how many patterns were already finished
|
||||
by calculating the number finished patterns for every output
|
||||
and then taking the minimum of those
|
||||
*/
|
||||
private void updateFinishedPatterns() {
|
||||
int temp = totalQuantity;
|
||||
if (!itemsToReceive.isEmpty()) {
|
||||
for (StackListEntry<ItemStack> stack : itemsToReceive.getStacks()) {
|
||||
if (itemsReceived.get(stack.getStack()) != null) {
|
||||
if (temp > itemsReceived.get(stack.getStack()).getCount() / (itemsToReceive.get(stack.getStack()).getCount())) {
|
||||
temp = itemsReceived.get(stack.getStack()).getCount() / (itemsToReceive.get(stack.getStack()).getCount());
|
||||
}
|
||||
} else {
|
||||
temp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fluidsToReceive.isEmpty()) {
|
||||
for (StackListEntry<FluidStack> stack : fluidsToReceive.getStacks()) {
|
||||
if (fluidsReceived.get(stack.getStack()) != null) {
|
||||
if (temp > fluidsReceived.get(stack.getStack()).getAmount() / (fluidsToReceive.get(stack.getStack()).getAmount())) {
|
||||
temp = fluidsReceived.get(stack.getStack()).getAmount() / (fluidsToReceive.get(stack.getStack()).getAmount());
|
||||
}
|
||||
} else {
|
||||
temp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
finished = temp;
|
||||
}
|
||||
|
||||
IStackList<ItemStack> getItemsToReceive() {
|
||||
return itemsToReceive;
|
||||
}
|
||||
|
||||
IStackList<FluidStack> getFluidsToReceive() {
|
||||
return fluidsToReceive;
|
||||
}
|
||||
|
||||
IStackList<ItemStack> getItemsToDisplay() {
|
||||
return itemsToDisplay;
|
||||
}
|
||||
|
||||
private void updateItemsToDisplay() {
|
||||
itemsToDisplay = getItemsToUse(true);
|
||||
}
|
||||
|
||||
IStackList<FluidStack> getFluidsToUse() {
|
||||
return fluidsToUse;
|
||||
}
|
||||
|
||||
void addFluidsToUse(FluidStack stack) {
|
||||
fluidsToUse.add(stack);
|
||||
}
|
||||
|
||||
void addItemsToReceive(ItemStack stack) {
|
||||
itemsToReceive.add(stack);
|
||||
}
|
||||
|
||||
void addFluidsToReceive(FluidStack stack) {
|
||||
fluidsToReceive.add(stack);
|
||||
}
|
||||
|
||||
int getProcessing() {
|
||||
return totalQuantity - quantity - finished;
|
||||
}
|
||||
|
||||
void addFinished(ItemStack received, int size) {
|
||||
itemsReceived.add(received, size);
|
||||
}
|
||||
|
||||
void addFinished(FluidStack received, int size) {
|
||||
fluidsReceived.add(received, size);
|
||||
}
|
||||
|
||||
void setState(ProcessingState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
ProcessingState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
boolean hasFluids() {
|
||||
return !fluidsToUse.isEmpty();
|
||||
}
|
||||
|
||||
CompoundNBT writeToNbt() {
|
||||
CompoundNBT tag = super.writeToNbt();
|
||||
tag.put(NBT_ITEMS_TO_RECEIVE, CraftingTask.writeItemStackList(itemsToReceive));
|
||||
tag.put(NBT_FLUIDS_TO_RECEIVE, CraftingTask.writeFluidStackList(fluidsToReceive));
|
||||
tag.putInt(NBT_STATE, state.ordinal());
|
||||
tag.putInt(NBT_QUANTITY_TOTAL, totalQuantity);
|
||||
tag.put(NBT_ITEMS_RECEIVED, CraftingTask.writeItemStackList(itemsReceived));
|
||||
tag.put(NBT_FLUIDS_RECEIVED, CraftingTask.writeFluidStackList(fluidsReceived));
|
||||
tag.put(NBT_FLUIDS_TO_USE, CraftingTask.writeFluidStackList(fluidsToUse));
|
||||
tag.put(NBT_ITEMS_TO_DISPLAY, CraftingTask.writeItemStackList(itemsToDisplay));
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.node.INetworkNode;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.util.StackUtils;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class SerializationUtil {
|
||||
private static final String NBT_PATTERN_STACK = "Stack";
|
||||
private static final String NBT_PATTERN_CONTAINER_POS = "ContainerPos";
|
||||
|
||||
public static ListNBT writeItemStackList(IStackList<ItemStack> stacks) {
|
||||
ListNBT list = new ListNBT();
|
||||
|
||||
for (StackListEntry<ItemStack> entry : stacks.getStacks()) {
|
||||
list.add(StackUtils.serializeStackToNbt(entry.getStack()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static IStackList<ItemStack> readItemStackList(ListNBT list) throws CraftingTaskReadException {
|
||||
IStackList<ItemStack> stacks = API.instance().createItemStackList();
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
ItemStack stack = StackUtils.deserializeStackFromNbt(list.getCompound(i));
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
throw new CraftingTaskReadException("Empty stack!");
|
||||
}
|
||||
|
||||
stacks.add(stack);
|
||||
}
|
||||
|
||||
return stacks;
|
||||
}
|
||||
|
||||
public static ListNBT writeFluidStackList(IStackList<FluidStack> stacks) {
|
||||
ListNBT list = new ListNBT();
|
||||
|
||||
for (StackListEntry<FluidStack> entry : stacks.getStacks()) {
|
||||
list.add(entry.getStack().writeToNBT(new CompoundNBT()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static IStackList<FluidStack> readFluidStackList(ListNBT list) throws CraftingTaskReadException {
|
||||
IStackList<FluidStack> stacks = API.instance().createFluidStackList();
|
||||
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
FluidStack stack = FluidStack.loadFluidStackFromNBT(list.getCompound(i));
|
||||
|
||||
if (stack.isEmpty()) {
|
||||
throw new CraftingTaskReadException("Empty stack!");
|
||||
}
|
||||
|
||||
stacks.add(stack);
|
||||
}
|
||||
|
||||
return stacks;
|
||||
}
|
||||
|
||||
public static CompoundNBT writePatternToNbt(ICraftingPattern pattern) {
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
|
||||
tag.put(NBT_PATTERN_STACK, pattern.getStack().serializeNBT());
|
||||
tag.putLong(NBT_PATTERN_CONTAINER_POS, pattern.getContainer().getPosition().toLong());
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static ICraftingPattern readPatternFromNbt(CompoundNBT tag, World world) throws CraftingTaskReadException {
|
||||
BlockPos containerPos = BlockPos.fromLong(tag.getLong(NBT_PATTERN_CONTAINER_POS));
|
||||
|
||||
INetworkNode node = API.instance().getNetworkNodeManager((ServerWorld) world).getNode(containerPos);
|
||||
|
||||
if (node instanceof ICraftingPatternContainer) {
|
||||
ItemStack stack = ItemStack.read(tag.getCompound(NBT_PATTERN_STACK));
|
||||
|
||||
if (stack.getItem() instanceof ICraftingPatternProvider) {
|
||||
return ((ICraftingPatternProvider) stack.getItem()).create(world, stack, (ICraftingPatternContainer) node);
|
||||
} else {
|
||||
throw new CraftingTaskReadException("Pattern stack is not a crafting pattern provider");
|
||||
}
|
||||
} else {
|
||||
throw new CraftingTaskReadException("Crafting pattern container doesn't exist anymore");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CalculationResult implements ICalculationResult {
|
||||
private final CalculationResultType type;
|
||||
private final ICraftingPattern recursedPattern;
|
||||
private final List<ICraftingPreviewElement<?>> previewElements;
|
||||
private final ICraftingTask craftingTask;
|
||||
|
||||
public CalculationResult(CalculationResultType type) {
|
||||
this.type = type;
|
||||
this.recursedPattern = null;
|
||||
this.previewElements = Collections.emptyList();
|
||||
this.craftingTask = null;
|
||||
}
|
||||
|
||||
public CalculationResult(CalculationResultType type, ICraftingPattern recursedPattern) {
|
||||
this.type = type;
|
||||
this.recursedPattern = recursedPattern;
|
||||
this.previewElements = Collections.emptyList();
|
||||
this.craftingTask = null;
|
||||
}
|
||||
|
||||
public CalculationResult(CalculationResultType type, List<ICraftingPreviewElement<?>> previewElements, @Nullable ICraftingTask craftingTask) {
|
||||
this.type = type;
|
||||
this.recursedPattern = null;
|
||||
this.previewElements = previewElements;
|
||||
this.craftingTask = craftingTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculationResultType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ICraftingPreviewElement<?>> getPreviewElements() {
|
||||
return previewElements;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ICraftingTask getTask() {
|
||||
return craftingTask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOk() {
|
||||
return type == CalculationResultType.OK;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ICraftingPattern getRecursedPattern() {
|
||||
return recursedPattern;
|
||||
}
|
||||
}
|
@@ -0,0 +1,360 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;
|
||||
|
||||
import com.refinedmods.refinedstorage.RS;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.util.IComparer;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingPatternInputs;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTask;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.CraftingNode;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview.CraftingPreviewElementFactory;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview.CraftingPreviewInfo;
|
||||
import com.refinedmods.refinedstorage.util.StackUtils;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class CraftingCalculator {
|
||||
private final INetwork network;
|
||||
private final ICraftingRequestInfo requested;
|
||||
private final int quantity;
|
||||
private final ICraftingPattern pattern;
|
||||
|
||||
private final Set<ICraftingPattern> patternsUsed = new HashSet<>();
|
||||
|
||||
private final CraftingPreviewInfo craftingPreviewInfo = new CraftingPreviewInfo();
|
||||
|
||||
private final NodeList nodes = new NodeList();
|
||||
|
||||
private final IStackList<ItemStack> toExtractInitial = API.instance().createItemStackList();
|
||||
private final IStackList<FluidStack> toExtractInitialFluids = API.instance().createFluidStackList();
|
||||
|
||||
private long calculationStarted = -1;
|
||||
|
||||
public CraftingCalculator(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {
|
||||
this.network = network;
|
||||
this.requested = requested;
|
||||
this.quantity = quantity;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public ICalculationResult calculate() {
|
||||
this.calculationStarted = System.currentTimeMillis();
|
||||
|
||||
IStackList<ItemStack> results = API.instance().createItemStackList();
|
||||
IStackList<FluidStack> fluidResults = API.instance().createFluidStackList();
|
||||
|
||||
IStackList<ItemStack> storageSource = network.getItemStorageCache().getList().copy();
|
||||
IStackList<FluidStack> fluidStorageSource = network.getFluidStorageCache().getList().copy();
|
||||
|
||||
int qtyPerCraft = getQuantityPerCraft(requested.getItem(), requested.getFluid(), pattern);
|
||||
int qty = ((quantity - 1) / qtyPerCraft) + 1;
|
||||
|
||||
try {
|
||||
calculateInternal(qty, storageSource, fluidStorageSource, results, fluidResults, pattern, true);
|
||||
} catch (CraftingCalculatorException e) {
|
||||
return new CalculationResult(e.getType(), e.getRecursedPattern());
|
||||
}
|
||||
|
||||
if (requested.getItem() != null) {
|
||||
craftingPreviewInfo.getToCraft().add(ItemHandlerHelper.copyStackWithSize(requested.getItem(), qty * qtyPerCraft));
|
||||
} else if (requested.getFluid() != null) {
|
||||
craftingPreviewInfo.getToCraftFluids().add(StackUtils.copy(requested.getFluid(), qty * qtyPerCraft));
|
||||
}
|
||||
|
||||
List<ICraftingPreviewElement<?>> previewElements = new CraftingPreviewElementFactory().getElements(craftingPreviewInfo);
|
||||
|
||||
if (craftingPreviewInfo.hasMissing()) {
|
||||
return new CalculationResult(CalculationResultType.MISSING, previewElements, null);
|
||||
}
|
||||
|
||||
return new CalculationResult(
|
||||
CalculationResultType.OK,
|
||||
previewElements,
|
||||
new CraftingTask(network, requested, quantity, pattern, nodes, toExtractInitial, toExtractInitialFluids)
|
||||
);
|
||||
}
|
||||
|
||||
private void calculateInternal(
|
||||
int qty,
|
||||
IStackList<ItemStack> storageSource,
|
||||
IStackList<FluidStack> fluidStorageSource,
|
||||
IStackList<ItemStack> results,
|
||||
IStackList<FluidStack> fluidResults,
|
||||
ICraftingPattern pattern,
|
||||
boolean root) throws CraftingCalculatorException {
|
||||
|
||||
if (System.currentTimeMillis() - calculationStarted > RS.SERVER_CONFIG.getAutocrafting().getCalculationTimeoutMs()) {
|
||||
throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX, null);
|
||||
}
|
||||
|
||||
if (!patternsUsed.add(pattern)) {
|
||||
throw new CraftingCalculatorException(CalculationResultType.RECURSIVE, pattern);
|
||||
}
|
||||
|
||||
IStackList<ItemStack> itemsToExtract = API.instance().createItemStackList();
|
||||
IStackList<FluidStack> fluidsToExtract = API.instance().createFluidStackList();
|
||||
|
||||
CraftingPatternInputs inputs = new CraftingPatternInputs(pattern);
|
||||
|
||||
Node node = nodes.createOrAddToExistingNode(pattern, root, inputs.getRecipe(), qty);
|
||||
|
||||
calculateForItems(qty, storageSource, fluidStorageSource, results, fluidResults, itemsToExtract, inputs, node);
|
||||
|
||||
if (node instanceof CraftingNode) {
|
||||
ItemStack output = pattern.getOutput(inputs.getRecipe());
|
||||
results.add(output, output.getCount() * qty);
|
||||
|
||||
for (ItemStack byproduct : pattern.getByproducts(inputs.getRecipe())) {
|
||||
results.add(byproduct, byproduct.getCount() * qty);
|
||||
}
|
||||
} else if (node instanceof ProcessingNode) {
|
||||
ProcessingNode processing = (ProcessingNode) node;
|
||||
|
||||
calculateForFluids(qty, storageSource, fluidStorageSource, results, fluidResults, pattern, inputs, fluidsToExtract, processing);
|
||||
|
||||
for (ItemStack output : pattern.getOutputs()) {
|
||||
results.add(output, output.getCount() * qty);
|
||||
}
|
||||
|
||||
for (FluidStack output : pattern.getFluidOutputs()) {
|
||||
fluidResults.add(output, output.getAmount() * qty);
|
||||
}
|
||||
}
|
||||
|
||||
patternsUsed.remove(pattern);
|
||||
}
|
||||
|
||||
private void calculateForItems(int qty,
|
||||
IStackList<ItemStack> storageSource,
|
||||
IStackList<FluidStack> fluidStorageSource,
|
||||
IStackList<ItemStack> results,
|
||||
IStackList<FluidStack> fluidResults,
|
||||
IStackList<ItemStack> itemsToExtract,
|
||||
CraftingPatternInputs inputs,
|
||||
Node node) throws CraftingCalculatorException {
|
||||
int ingredientNumber = -1;
|
||||
|
||||
for (CraftingPatternInputs.Ingredient<ItemStack> ingredient : inputs.getItemIngredients()) {
|
||||
ingredientNumber++;
|
||||
|
||||
PossibleInputs<ItemStack> possibleInputs = new PossibleInputs<>(ingredient.getInputs());
|
||||
possibleInputs.sort(storageSource, results);
|
||||
|
||||
ItemStack possibleInput = possibleInputs.get();
|
||||
|
||||
ItemStack fromSelf = results.get(possibleInput);
|
||||
ItemStack fromNetwork = storageSource.get(possibleInput);
|
||||
|
||||
int remaining = ingredient.getCount() * qty;
|
||||
|
||||
if (remaining < 0) { // int overflow
|
||||
throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX);
|
||||
}
|
||||
|
||||
while (remaining > 0) {
|
||||
if (fromSelf != null) {
|
||||
int toTake = Math.min(remaining, fromSelf.getCount());
|
||||
|
||||
node.getRequirements().addItemRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());
|
||||
|
||||
results.remove(fromSelf, toTake);
|
||||
|
||||
remaining -= toTake;
|
||||
|
||||
fromSelf = results.get(possibleInput);
|
||||
}
|
||||
|
||||
if (fromNetwork != null && remaining > 0) {
|
||||
int toTake = Math.min(remaining, fromNetwork.getCount());
|
||||
|
||||
craftingPreviewInfo.getToTake().add(possibleInput, toTake);
|
||||
|
||||
node.getRequirements().addItemRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());
|
||||
|
||||
storageSource.remove(fromNetwork, toTake);
|
||||
|
||||
remaining -= toTake;
|
||||
|
||||
fromNetwork = storageSource.get(possibleInput);
|
||||
|
||||
toExtractInitial.add(possibleInput, toTake);
|
||||
}
|
||||
|
||||
if (remaining > 0) {
|
||||
ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput);
|
||||
|
||||
if (subPattern != null) {
|
||||
int qtyPerCraft = getQuantityPerCraft(possibleInput, null, subPattern);
|
||||
int subQty = ((remaining - 1) / qtyPerCraft) + 1;
|
||||
|
||||
calculateInternal(subQty, storageSource, fluidStorageSource, results, fluidResults, subPattern, false);
|
||||
|
||||
fromSelf = results.get(possibleInput);
|
||||
if (fromSelf == null) {
|
||||
throw new IllegalStateException("Recursive calculation didn't yield anything");
|
||||
}
|
||||
|
||||
fromNetwork = storageSource.get(possibleInput);
|
||||
|
||||
// fromSelf contains the amount crafted after the loop.
|
||||
craftingPreviewInfo.getToCraft().add(fromSelf.copy());
|
||||
} else {
|
||||
if (!possibleInputs.cycle()) {
|
||||
// Give up.
|
||||
possibleInput = possibleInputs.get(); // Revert back to 0.
|
||||
|
||||
craftingPreviewInfo.getMissing().add(possibleInput, remaining);
|
||||
|
||||
itemsToExtract.add(possibleInput, remaining);
|
||||
|
||||
remaining = 0;
|
||||
} else {
|
||||
// Retry with new input...
|
||||
possibleInput = possibleInputs.get();
|
||||
|
||||
fromSelf = results.get(possibleInput);
|
||||
fromNetwork = storageSource.get(possibleInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateForFluids(int qty,
|
||||
IStackList<ItemStack> storageSource,
|
||||
IStackList<FluidStack> fluidStorageSource,
|
||||
IStackList<ItemStack> results,
|
||||
IStackList<FluidStack> fluidResults,
|
||||
ICraftingPattern pattern,
|
||||
CraftingPatternInputs inputs,
|
||||
IStackList<FluidStack> fluidsToExtract,
|
||||
ProcessingNode node) throws CraftingCalculatorException {
|
||||
int ingredientNumber = -1;
|
||||
|
||||
for (CraftingPatternInputs.Ingredient<FluidStack> ingredient : inputs.getFluidIngredients()) {
|
||||
ingredientNumber++;
|
||||
|
||||
PossibleInputs<FluidStack> possibleInputs = new PossibleInputs<>(ingredient.getInputs());
|
||||
possibleInputs.sort(fluidStorageSource, fluidResults);
|
||||
|
||||
FluidStack possibleInput = possibleInputs.get();
|
||||
|
||||
FluidStack fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT);
|
||||
FluidStack fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT);
|
||||
|
||||
int remaining = possibleInput.getAmount() * qty;
|
||||
|
||||
if (remaining < 0) { // int overflow
|
||||
throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX);
|
||||
}
|
||||
|
||||
while (remaining > 0) {
|
||||
if (fromSelf != null) {
|
||||
int toTake = Math.min(remaining, fromSelf.getAmount());
|
||||
|
||||
node.getRequirements().addFluidRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());
|
||||
|
||||
fluidResults.remove(possibleInput, toTake);
|
||||
|
||||
remaining -= toTake;
|
||||
|
||||
fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT);
|
||||
}
|
||||
|
||||
if (fromNetwork != null && remaining > 0) {
|
||||
int toTake = Math.min(remaining, fromNetwork.getAmount());
|
||||
|
||||
node.getRequirements().addFluidRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount());
|
||||
|
||||
craftingPreviewInfo.getToTakeFluids().add(possibleInput, toTake);
|
||||
|
||||
fluidStorageSource.remove(fromNetwork, toTake);
|
||||
|
||||
remaining -= toTake;
|
||||
|
||||
fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT);
|
||||
|
||||
toExtractInitialFluids.add(possibleInput, toTake);
|
||||
}
|
||||
|
||||
if (remaining > 0) {
|
||||
ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput);
|
||||
|
||||
if (subPattern != null) {
|
||||
int qtyPerCraft = getQuantityPerCraft(null, possibleInput, subPattern);
|
||||
int subQty = ((remaining - 1) / qtyPerCraft) + 1;
|
||||
|
||||
calculateInternal(subQty, storageSource, fluidStorageSource, results, fluidResults, subPattern, false);
|
||||
|
||||
fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT);
|
||||
if (fromSelf == null) {
|
||||
throw new IllegalStateException("Recursive fluid calculation didn't yield anything");
|
||||
}
|
||||
|
||||
fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT);
|
||||
|
||||
// fromSelf contains the amount crafted after the loop.
|
||||
craftingPreviewInfo.getToCraftFluids().add(fromSelf.copy());
|
||||
} else {
|
||||
if (!possibleInputs.cycle()) {
|
||||
// Give up.
|
||||
possibleInput = possibleInputs.get(); // Revert back to 0.
|
||||
|
||||
craftingPreviewInfo.getMissingFluids().add(possibleInput, remaining);
|
||||
|
||||
fluidsToExtract.add(possibleInput, remaining);
|
||||
|
||||
remaining = 0;
|
||||
} else {
|
||||
// Retry with new input...
|
||||
possibleInput = possibleInputs.get();
|
||||
|
||||
fromSelf = fluidResults.get(possibleInput);
|
||||
fromNetwork = fluidStorageSource.get(possibleInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getQuantityPerCraft(@Nullable ItemStack item, @Nullable FluidStack fluid, ICraftingPattern pattern) {
|
||||
int qty = 0;
|
||||
|
||||
if (item != null) {
|
||||
for (ItemStack output : pattern.getOutputs()) {
|
||||
if (API.instance().getComparer().isEqualNoQuantity(output, item)) {
|
||||
qty += output.getCount();
|
||||
|
||||
if (!pattern.isProcessing()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (fluid != null) {
|
||||
for (FluidStack output : pattern.getFluidOutputs()) {
|
||||
if (API.instance().getComparer().isEqual(output, fluid, IComparer.COMPARE_NBT)) {
|
||||
qty += output.getAmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qty;
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CraftingCalculatorException extends Exception {
|
||||
private final CalculationResultType type;
|
||||
@Nullable
|
||||
private final ICraftingPattern recursedPattern;
|
||||
|
||||
public CraftingCalculatorException(CalculationResultType type) {
|
||||
this.type = type;
|
||||
this.recursedPattern = null;
|
||||
}
|
||||
|
||||
public CraftingCalculatorException(CalculationResultType type, @Nullable ICraftingPattern recursedPattern) {
|
||||
this.type = type;
|
||||
this.recursedPattern = recursedPattern;
|
||||
}
|
||||
|
||||
public CalculationResultType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ICraftingPattern getRecursedPattern() {
|
||||
return recursedPattern;
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PossibleInputs<T> {
|
||||
private final List<T> possibilities;
|
||||
private int pos;
|
||||
|
||||
public PossibleInputs(List<T> possibilities) {
|
||||
this.possibilities = new ArrayList<>(possibilities);
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return possibilities.get(pos);
|
||||
}
|
||||
|
||||
// Return false if we're exhausted.
|
||||
public boolean cycle() {
|
||||
if (pos + 1 >= possibilities.size()) {
|
||||
pos = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pos++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void sort(IStackList<T> mutatedStorage, IStackList<T> results) {
|
||||
possibilities.sort((a, b) -> {
|
||||
int ar = mutatedStorage.getCount(a);
|
||||
int br = mutatedStorage.getCount(b);
|
||||
|
||||
return br - ar;
|
||||
});
|
||||
|
||||
possibilities.sort((a, b) -> {
|
||||
int ar = results.getCount(a);
|
||||
int br = results.getCount(b);
|
||||
|
||||
return br - ar;
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,123 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.monitor;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ErrorCraftingMonitorElement;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.FluidCraftingMonitorElement;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ItemCraftingMonitorElement;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.CraftingNode;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingMonitorElementFactory {
|
||||
public List<ICraftingMonitorElement> getElements(Collection<Node> nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage) {
|
||||
ICraftingMonitorElementList list = API.instance().createCraftingMonitorElementList();
|
||||
|
||||
for (Node node : nodes) {
|
||||
if (node instanceof CraftingNode) {
|
||||
addForRecipe(list, (CraftingNode) node);
|
||||
} else {
|
||||
addForProcessing(list, (ProcessingNode) node);
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemStack stack : internalStorage.getStacks()) {
|
||||
list.addStorage(new ItemCraftingMonitorElement(stack, stack.getCount(), 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
for (FluidStack stack : internalFluidStorage.getStacks()) {
|
||||
list.addStorage(new FluidCraftingMonitorElement(stack, stack.getAmount(), 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
list.commit();
|
||||
|
||||
return list.getElements();
|
||||
}
|
||||
|
||||
private void addForProcessing(ICraftingMonitorElementList list, ProcessingNode node) {
|
||||
if (node.getState() == ProcessingState.PROCESSED) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (StackListEntry<ItemStack> requirement : node.getSingleItemSetToRequire().getStacks()) {
|
||||
if (node.getCurrentlyProcessing() > 0) {
|
||||
ICraftingMonitorElement element = ItemCraftingMonitorElement.Builder
|
||||
.forStack(requirement.getStack())
|
||||
.processing(requirement.getStack().getCount() * node.getCurrentlyProcessing())
|
||||
.build();
|
||||
|
||||
list.add(element, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (StackListEntry<ItemStack> toReceive : node.getSingleItemSetToReceive().getStacks()) {
|
||||
int needed = node.getNeeded(toReceive.getStack());
|
||||
|
||||
if (needed > 0) {
|
||||
ICraftingMonitorElement element = ItemCraftingMonitorElement.Builder
|
||||
.forStack(toReceive.getStack())
|
||||
.scheduled(needed)
|
||||
.build();
|
||||
|
||||
element = wrapWithProcessingState(element, node.getState(), "item");
|
||||
|
||||
list.add(element, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (StackListEntry<FluidStack> requirement : node.getSingleFluidSetToRequire().getStacks()) {
|
||||
if (node.getCurrentlyProcessing() > 0) {
|
||||
ICraftingMonitorElement element = FluidCraftingMonitorElement.Builder
|
||||
.forStack(requirement.getStack())
|
||||
.processing(requirement.getStack().getAmount() * node.getCurrentlyProcessing())
|
||||
.build();
|
||||
|
||||
list.add(element, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (StackListEntry<FluidStack> toReceive : node.getSingleFluidSetToReceive().getStacks()) {
|
||||
int needed = node.getNeeded(toReceive.getStack());
|
||||
|
||||
if (needed > 0) {
|
||||
ICraftingMonitorElement element = FluidCraftingMonitorElement.Builder
|
||||
.forStack(toReceive.getStack())
|
||||
.scheduled(needed)
|
||||
.build();
|
||||
|
||||
element = wrapWithProcessingState(element, node.getState(), "fluid");
|
||||
|
||||
list.add(element, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ICraftingMonitorElement wrapWithProcessingState(ICraftingMonitorElement element, ProcessingState state, String type) {
|
||||
if (state == ProcessingState.MACHINE_DOES_NOT_ACCEPT) {
|
||||
return new ErrorCraftingMonitorElement(element, "gui.refinedstorage.crafting_monitor.machine_does_not_accept_" + type);
|
||||
} else if (state == ProcessingState.MACHINE_NONE) {
|
||||
return new ErrorCraftingMonitorElement(element, "gui.refinedstorage.crafting_monitor.machine_none");
|
||||
} else if (state == ProcessingState.LOCKED) {
|
||||
return new ErrorCraftingMonitorElement(element, "gui.refinedstorage.crafting_monitor.crafter_is_locked");
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
private void addForRecipe(ICraftingMonitorElementList list, CraftingNode node) {
|
||||
if (node.getQuantity() > 0) {
|
||||
for (ItemStack receive : node.getPattern().getOutputs()) {
|
||||
list.add(new ItemCraftingMonitorElement(receive, 0, 0, 0, 0, receive.getCount() * node.getQuantity()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;
|
||||
import com.refinedmods.refinedstorage.api.util.Action;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.IoUtil;
|
||||
import com.refinedmods.refinedstorage.util.StackUtils;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class CraftingNode extends Node {
|
||||
private static final String NBT_RECIPE = "Recipe";
|
||||
|
||||
private final NonNullList<ItemStack> recipe;
|
||||
|
||||
public CraftingNode(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe) {
|
||||
super(pattern, root);
|
||||
|
||||
this.recipe = recipe;
|
||||
}
|
||||
|
||||
public CraftingNode(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
super(network, tag);
|
||||
|
||||
this.recipe = NonNullList.create();
|
||||
|
||||
ListNBT tookList = tag.getList(NBT_RECIPE, Constants.NBT.TAG_COMPOUND);
|
||||
for (int i = 0; i < tookList.size(); ++i) {
|
||||
recipe.add(StackUtils.deserializeStackFromNbt(tookList.getCompound(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(INetwork network, int ticks, NodeList nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage, NodeListener listener) {
|
||||
for (ICraftingPatternContainer container : network.getCraftingManager().getAllContainers(getPattern())) {
|
||||
int interval = container.getUpdateInterval();
|
||||
if (interval < 0) {
|
||||
throw new IllegalStateException(container + " has an update interval of < 0");
|
||||
}
|
||||
|
||||
if (interval == 0 || ticks % interval == 0) {
|
||||
for (int i = 0; i < container.getMaximumSuccessfulCraftingUpdates(); i++) {
|
||||
if (IoUtil.extractFromInternalItemStorage(requirements.getSingleItemRequirementSet(true), internalStorage, Action.SIMULATE) != null) {
|
||||
IoUtil.extractFromInternalItemStorage(requirements.getSingleItemRequirementSet(false), internalStorage, Action.PERFORM);
|
||||
|
||||
ItemStack output = getPattern().getOutput(recipe);
|
||||
|
||||
if (!isRoot()) {
|
||||
internalStorage.insert(output, output.getCount(), Action.PERFORM);
|
||||
} else {
|
||||
ItemStack remainder = network.insertItem(output, output.getCount(), Action.PERFORM);
|
||||
|
||||
internalStorage.insert(remainder, remainder.getCount(), Action.PERFORM);
|
||||
}
|
||||
|
||||
// Byproducts need to always be inserted in the internal storage for later reuse further in the task.
|
||||
// Regular outputs can be inserted into the network *IF* it's a root since it's *NOT* expected to be used later on.
|
||||
for (ItemStack byp : getPattern().getByproducts(recipe)) {
|
||||
internalStorage.insert(byp, byp.getCount(), Action.PERFORM);
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
listener.onSingleDone(this);
|
||||
|
||||
if (getQuantity() <= 0) {
|
||||
listener.onAllDone(this);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToNbt() {
|
||||
CompoundNBT tag = super.writeToNbt();
|
||||
|
||||
ListNBT tookList = new ListNBT();
|
||||
for (ItemStack took : this.recipe) {
|
||||
tookList.add(StackUtils.serializeStackToNbt(took));
|
||||
}
|
||||
|
||||
tag.put(NBT_RECIPE, tookList);
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public abstract class Node {
|
||||
private static final String NBT_PATTERN = "Pattern";
|
||||
private static final String NBT_ROOT = "Root";
|
||||
private static final String NBT_IS_PROCESSING = "IsProcessing";
|
||||
private static final String NBT_QUANTITY = "Quantity";
|
||||
private static final String NBT_QUANTITY_TOTAL = "TotalQuantity";
|
||||
|
||||
private final boolean root;
|
||||
private final ICraftingPattern pattern;
|
||||
|
||||
protected int quantity;
|
||||
protected int totalQuantity;
|
||||
|
||||
protected final NodeRequirements requirements = new NodeRequirements();
|
||||
|
||||
public Node(ICraftingPattern pattern, boolean root) {
|
||||
this.pattern = pattern;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public Node(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
this.quantity = tag.getInt(NBT_QUANTITY);
|
||||
this.totalQuantity = tag.getInt(NBT_QUANTITY_TOTAL);
|
||||
this.pattern = SerializationUtil.readPatternFromNbt(tag.getCompound(NBT_PATTERN), network.getWorld());
|
||||
this.root = tag.getBoolean(NBT_ROOT);
|
||||
this.requirements.readFromNbt(tag);
|
||||
}
|
||||
|
||||
public static Node fromNbt(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
return tag.getBoolean(NBT_IS_PROCESSING) ? new ProcessingNode(network, tag) : new CraftingNode(network, tag);
|
||||
}
|
||||
|
||||
public abstract void update(INetwork network, int ticks, NodeList nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage, NodeListener listener);
|
||||
|
||||
public void onCalculationFinished() {
|
||||
this.totalQuantity = quantity;
|
||||
}
|
||||
|
||||
public ICraftingPattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void addQuantity(int quantity) {
|
||||
this.quantity += quantity;
|
||||
}
|
||||
|
||||
protected void next() {
|
||||
quantity--;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
public NodeRequirements getRequirements() {
|
||||
return requirements;
|
||||
}
|
||||
|
||||
public CompoundNBT writeToNbt() {
|
||||
CompoundNBT tag = new CompoundNBT();
|
||||
|
||||
tag.putInt(NBT_QUANTITY, quantity);
|
||||
tag.putInt(NBT_QUANTITY_TOTAL, totalQuantity);
|
||||
tag.putBoolean(NBT_IS_PROCESSING, this instanceof ProcessingNode);
|
||||
tag.putBoolean(NBT_ROOT, root);
|
||||
tag.put(NBT_PATTERN, SerializationUtil.writePatternToNbt(pattern));
|
||||
tag = requirements.writeToNbt(tag);
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class NodeList {
|
||||
private final Map<ICraftingPattern, Node> nodes = new LinkedHashMap<>();
|
||||
private final List<Node> nodesToRemove = new ArrayList<>();
|
||||
|
||||
public void removeMarkedForRemoval() {
|
||||
for (Node node : nodesToRemove) {
|
||||
nodes.remove(node.getPattern());
|
||||
}
|
||||
nodesToRemove.clear();
|
||||
}
|
||||
|
||||
public Collection<Node> all() {
|
||||
return nodes.values();
|
||||
}
|
||||
|
||||
public void unlockAll(INetwork network) {
|
||||
for (Node node : nodes.values()) {
|
||||
if (node instanceof ProcessingNode) {
|
||||
network.getCraftingManager().getAllContainers(node.getPattern()).forEach(ICraftingPatternContainer::unlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return nodes.isEmpty();
|
||||
}
|
||||
|
||||
public void remove(Node node) {
|
||||
nodesToRemove.add(node);
|
||||
}
|
||||
|
||||
public Node createOrAddToExistingNode(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe, int qty) {
|
||||
Node node = nodes.get(pattern);
|
||||
if (node == null) {
|
||||
nodes.put(pattern, node = createNode(pattern, root, recipe));
|
||||
}
|
||||
|
||||
node.addQuantity(qty);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
private Node createNode(ICraftingPattern pattern, boolean root, NonNullList<ItemStack> recipe) {
|
||||
return pattern.isProcessing() ? new ProcessingNode(pattern, root) : new CraftingNode(pattern, root, recipe);
|
||||
}
|
||||
|
||||
public void put(ICraftingPattern pattern, Node node) {
|
||||
nodes.put(pattern, node);
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
public interface NodeListener {
|
||||
void onAllDone(Node node);
|
||||
|
||||
void onSingleDone(Node node);
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class NodeRequirements {
|
||||
private static final String NBT_ITEMS_TO_USE = "ItemsToUse";
|
||||
private static final String NBT_FLUIDS_TO_USE = "FluidsToUse";
|
||||
|
||||
private static final String NBT_ITEMS_NEEDED_PER_CRAFT = "ItemsNeededPerCraft";
|
||||
private static final String NBT_FLUIDS_NEEDED_PER_CRAFT = "FluidsNeededPerCraft";
|
||||
|
||||
private final Map<Integer, IStackList<ItemStack>> itemRequirements = new LinkedHashMap<>();
|
||||
private final Map<Integer, Integer> itemsNeededPerCraft = new LinkedHashMap<>();
|
||||
|
||||
private final Map<Integer, IStackList<FluidStack>> fluidRequirements = new LinkedHashMap<>();
|
||||
private final Map<Integer, Integer> fluidsNeededPerCraft = new LinkedHashMap<>();
|
||||
|
||||
public void addItemRequirement(int ingredientNumber, ItemStack stack, int size, int perCraft) {
|
||||
if (!itemsNeededPerCraft.containsKey(ingredientNumber)) {
|
||||
itemsNeededPerCraft.put(ingredientNumber, perCraft);
|
||||
}
|
||||
|
||||
IStackList<ItemStack> list = itemRequirements.get(ingredientNumber);
|
||||
if (list == null) {
|
||||
itemRequirements.put(ingredientNumber, list = API.instance().createItemStackList());
|
||||
}
|
||||
|
||||
list.add(stack, size);
|
||||
}
|
||||
|
||||
public void addFluidRequirement(int ingredientNumber, FluidStack stack, int size, int perCraft) {
|
||||
if (!fluidsNeededPerCraft.containsKey(ingredientNumber)) {
|
||||
fluidsNeededPerCraft.put(ingredientNumber, perCraft);
|
||||
}
|
||||
|
||||
IStackList<FluidStack> list = fluidRequirements.get(ingredientNumber);
|
||||
if (list == null) {
|
||||
fluidRequirements.put(ingredientNumber, list = API.instance().createFluidStackList());
|
||||
}
|
||||
|
||||
list.add(stack, size);
|
||||
}
|
||||
|
||||
public IStackList<ItemStack> getSingleItemRequirementSet(boolean simulate) {
|
||||
IStackList<ItemStack> toReturn = API.instance().createItemStackList();
|
||||
|
||||
for (int i = 0; i < itemRequirements.size(); i++) {
|
||||
int needed = itemsNeededPerCraft.get(i);
|
||||
|
||||
if (!itemRequirements.get(i).isEmpty()) {
|
||||
Iterator<StackListEntry<ItemStack>> it = itemRequirements.get(i).getStacks().iterator();
|
||||
|
||||
while (needed > 0 && it.hasNext()) {
|
||||
ItemStack toUse = it.next().getStack();
|
||||
|
||||
if (needed < toUse.getCount()) {
|
||||
if (!simulate) {
|
||||
itemRequirements.get(i).remove(toUse, needed);
|
||||
}
|
||||
|
||||
toReturn.add(toUse, needed);
|
||||
|
||||
needed = 0;
|
||||
} else {
|
||||
if (!simulate) {
|
||||
it.remove();
|
||||
}
|
||||
|
||||
toReturn.add(toUse);
|
||||
|
||||
needed -= toUse.getCount();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Bad!");
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public IStackList<FluidStack> getSingleFluidRequirementSet(boolean simulate) {
|
||||
IStackList<FluidStack> toReturn = API.instance().createFluidStackList();
|
||||
|
||||
for (int i = 0; i < fluidRequirements.size(); i++) {
|
||||
int needed = fluidsNeededPerCraft.get(i);
|
||||
|
||||
if (!fluidRequirements.get(i).isEmpty()) {
|
||||
Iterator<StackListEntry<FluidStack>> it = fluidRequirements.get(i).getStacks().iterator();
|
||||
|
||||
while (needed > 0 && it.hasNext()) {
|
||||
FluidStack toUse = it.next().getStack();
|
||||
|
||||
if (needed < toUse.getAmount()) {
|
||||
if (!simulate) {
|
||||
fluidRequirements.get(i).remove(toUse, needed);
|
||||
}
|
||||
|
||||
toReturn.add(toUse, needed);
|
||||
|
||||
needed = 0;
|
||||
} else {
|
||||
if (!simulate) {
|
||||
it.remove();
|
||||
}
|
||||
|
||||
toReturn.add(toUse);
|
||||
|
||||
needed -= toUse.getAmount();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Bad!");
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public void readFromNbt(CompoundNBT tag) throws CraftingTaskReadException {
|
||||
ListNBT itemRequirements = tag.getList(NBT_ITEMS_TO_USE, Constants.NBT.TAG_LIST);
|
||||
for (int i = 0; i < itemRequirements.size(); i++) {
|
||||
this.itemRequirements.put(i, SerializationUtil.readItemStackList(itemRequirements.getList(i)));
|
||||
}
|
||||
|
||||
List<Integer> itemsNeededPerCraft = Ints.asList(tag.getIntArray(NBT_ITEMS_NEEDED_PER_CRAFT));
|
||||
for (int i = 0; i < itemsNeededPerCraft.size(); i++) {
|
||||
this.itemsNeededPerCraft.put(i, itemsNeededPerCraft.get(i));
|
||||
}
|
||||
|
||||
ListNBT fluidRequirements = tag.getList(NBT_FLUIDS_TO_USE, Constants.NBT.TAG_LIST);
|
||||
for (int i = 0; i < fluidRequirements.size(); i++) {
|
||||
this.fluidRequirements.put(i, SerializationUtil.readFluidStackList(fluidRequirements.getList(i)));
|
||||
}
|
||||
|
||||
List<Integer> fluidsNeededPerCraft = Ints.asList(tag.getIntArray(NBT_FLUIDS_NEEDED_PER_CRAFT));
|
||||
for (int i = 0; i < fluidsNeededPerCraft.size(); i++) {
|
||||
this.fluidsNeededPerCraft.put(i, fluidsNeededPerCraft.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public CompoundNBT writeToNbt(CompoundNBT tag) {
|
||||
ListNBT itemRequirements = new ListNBT();
|
||||
for (IStackList<ItemStack> list : this.itemRequirements.values()) {
|
||||
itemRequirements.add(SerializationUtil.writeItemStackList(list));
|
||||
}
|
||||
tag.put(NBT_ITEMS_TO_USE, itemRequirements);
|
||||
|
||||
tag.putIntArray(NBT_ITEMS_NEEDED_PER_CRAFT, Ints.toArray(itemsNeededPerCraft.values()));
|
||||
|
||||
ListNBT fluidRequirements = new ListNBT();
|
||||
for (IStackList<FluidStack> list : this.fluidRequirements.values()) {
|
||||
fluidRequirements.add(SerializationUtil.writeFluidStackList(list));
|
||||
}
|
||||
tag.put(NBT_FLUIDS_TO_USE, fluidRequirements);
|
||||
|
||||
tag.putIntArray(NBT_FLUIDS_NEEDED_PER_CRAFT, Ints.toArray(fluidsNeededPerCraft.values()));
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,272 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk;
|
||||
import com.refinedmods.refinedstorage.api.util.Action;
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.IoUtil;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
public class ProcessingNode extends Node {
|
||||
private static final String NBT_ITEMS_RECEIVED = "ItemsReceived";
|
||||
private static final String NBT_FLUIDS_RECEIVED = "FluidsReceived";
|
||||
private static final String NBT_SINGLE_ITEM_SET_TO_REQUIRE = "SingleItemSetToRequire";
|
||||
private static final String NBT_SINGLE_FLUID_SET_TO_REQUIRE = "SingleFluidSetToRequire";
|
||||
private static final String NBT_STATE = "State";
|
||||
|
||||
private final IStackList<ItemStack> singleItemSetToReceive = API.instance().createItemStackList();
|
||||
private final IStackList<FluidStack> singleFluidSetToReceive = API.instance().createFluidStackList();
|
||||
|
||||
private IStackList<ItemStack> singleItemSetToRequire;
|
||||
private IStackList<FluidStack> singleFluidSetToRequire;
|
||||
|
||||
private IStackList<ItemStack> itemsReceived = API.instance().createItemStackList();
|
||||
private IStackList<FluidStack> fluidsReceived = API.instance().createFluidStackList();
|
||||
|
||||
private ProcessingState state;
|
||||
|
||||
private int quantityFinished;
|
||||
|
||||
public ProcessingNode(ICraftingPattern pattern, boolean root) {
|
||||
super(pattern, root);
|
||||
|
||||
initSetsToReceive();
|
||||
}
|
||||
|
||||
public ProcessingNode(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
|
||||
super(network, tag);
|
||||
|
||||
this.itemsReceived = SerializationUtil.readItemStackList(tag.getList(NBT_ITEMS_RECEIVED, Constants.NBT.TAG_COMPOUND));
|
||||
this.fluidsReceived = SerializationUtil.readFluidStackList(tag.getList(NBT_FLUIDS_RECEIVED, Constants.NBT.TAG_COMPOUND));
|
||||
|
||||
this.singleItemSetToRequire = SerializationUtil.readItemStackList(tag.getList(NBT_SINGLE_ITEM_SET_TO_REQUIRE, Constants.NBT.TAG_COMPOUND));
|
||||
this.singleFluidSetToRequire = SerializationUtil.readFluidStackList(tag.getList(NBT_SINGLE_FLUID_SET_TO_REQUIRE, Constants.NBT.TAG_COMPOUND));
|
||||
|
||||
this.state = ProcessingState.values()[tag.getInt(NBT_STATE)];
|
||||
|
||||
initSetsToReceive();
|
||||
}
|
||||
|
||||
private void initSetsToReceive() {
|
||||
for (ItemStack output : getPattern().getOutputs()) {
|
||||
singleItemSetToReceive.add(output, output.getCount());
|
||||
}
|
||||
|
||||
for (FluidStack output : getPattern().getFluidOutputs()) {
|
||||
singleFluidSetToReceive.add(output, output.getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(INetwork network, int ticks, NodeList nodes, IStorageDisk<ItemStack> internalStorage, IStorageDisk<FluidStack> internalFluidStorage, NodeListener listener) {
|
||||
if (state == ProcessingState.PROCESSED) {
|
||||
listener.onAllDone(this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (getQuantity() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allLocked = true;
|
||||
boolean allMissingMachine = true;
|
||||
boolean allRejected = true;
|
||||
|
||||
ProcessingState originalState = state;
|
||||
|
||||
for (ICraftingPatternContainer container : network.getCraftingManager().getAllContainers(getPattern())) {
|
||||
int interval = container.getUpdateInterval();
|
||||
|
||||
if (interval < 0) {
|
||||
throw new IllegalStateException(container + " has an update interval of < 0");
|
||||
}
|
||||
|
||||
if (interval == 0 || ticks % interval == 0) {
|
||||
for (int i = 0; i < container.getMaximumSuccessfulCraftingUpdates(); i++) {
|
||||
if (getQuantity() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (container.isLocked()) {
|
||||
if (allLocked) {
|
||||
this.state = ProcessingState.LOCKED;
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
allLocked = false;
|
||||
}
|
||||
|
||||
if ((!singleItemSetToReceive.isEmpty() && container.getConnectedInventory() == null) ||
|
||||
(!singleFluidSetToReceive.isEmpty() && container.getConnectedFluidInventory() == null)) {
|
||||
if (allMissingMachine) {
|
||||
this.state = ProcessingState.MACHINE_NONE;
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
allMissingMachine = false;
|
||||
}
|
||||
|
||||
boolean hasAllRequirements = false;
|
||||
|
||||
IStackList<ItemStack> extractedItems = IoUtil.extractFromInternalItemStorage(requirements.getSingleItemRequirementSet(true), internalStorage, Action.SIMULATE);
|
||||
IStackList<FluidStack> extractedFluids = null;
|
||||
if (extractedItems != null) {
|
||||
extractedFluids = IoUtil.extractFromInternalFluidStorage(requirements.getSingleFluidRequirementSet(true), internalFluidStorage, Action.SIMULATE);
|
||||
if (extractedFluids != null) {
|
||||
hasAllRequirements = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean canInsertFullAmount = false;
|
||||
if (hasAllRequirements) {
|
||||
canInsertFullAmount = IoUtil.insertIntoInventory(container.getConnectedInventory(), extractedItems.getStacks(), Action.SIMULATE);
|
||||
if (canInsertFullAmount) {
|
||||
canInsertFullAmount = IoUtil.insertIntoInventory(container.getConnectedFluidInventory(), extractedFluids.getStacks(), Action.SIMULATE);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAllRequirements && !canInsertFullAmount) {
|
||||
if (allRejected) {
|
||||
this.state = ProcessingState.MACHINE_DOES_NOT_ACCEPT;
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
allRejected = false;
|
||||
}
|
||||
|
||||
if (hasAllRequirements && canInsertFullAmount) {
|
||||
this.state = ProcessingState.READY;
|
||||
|
||||
extractedItems = IoUtil.extractFromInternalItemStorage(requirements.getSingleItemRequirementSet(false), internalStorage, Action.PERFORM);
|
||||
extractedFluids = IoUtil.extractFromInternalFluidStorage(requirements.getSingleFluidRequirementSet(false), internalFluidStorage, Action.PERFORM);
|
||||
|
||||
IoUtil.insertIntoInventory(container.getConnectedInventory(), extractedItems.getStacks(), Action.PERFORM);
|
||||
IoUtil.insertIntoInventory(container.getConnectedFluidInventory(), extractedFluids.getStacks(), Action.PERFORM);
|
||||
|
||||
next();
|
||||
|
||||
listener.onSingleDone(this);
|
||||
|
||||
container.onUsedForProcessing();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (originalState != state) {
|
||||
network.getCraftingManager().onTaskChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public ProcessingState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public IStackList<ItemStack> getSingleItemSetToReceive() {
|
||||
return singleItemSetToReceive;
|
||||
}
|
||||
|
||||
public IStackList<FluidStack> getSingleFluidSetToReceive() {
|
||||
return singleFluidSetToReceive;
|
||||
}
|
||||
|
||||
public IStackList<ItemStack> getSingleItemSetToRequire() {
|
||||
return singleItemSetToRequire;
|
||||
}
|
||||
|
||||
public IStackList<FluidStack> getSingleFluidSetToRequire() {
|
||||
return singleFluidSetToRequire;
|
||||
}
|
||||
|
||||
public int getNeeded(ItemStack stack) {
|
||||
return (singleItemSetToReceive.getCount(stack) * totalQuantity) - itemsReceived.getCount(stack);
|
||||
}
|
||||
|
||||
public int getNeeded(FluidStack stack) {
|
||||
return (singleFluidSetToReceive.getCount(stack) * totalQuantity) - fluidsReceived.getCount(stack);
|
||||
}
|
||||
|
||||
public int getCurrentlyProcessing() {
|
||||
int unprocessed = totalQuantity - quantity;
|
||||
return unprocessed - quantityFinished;
|
||||
}
|
||||
|
||||
public void markReceived(ItemStack stack, int count) {
|
||||
itemsReceived.add(stack, count);
|
||||
updateFinishedQuantity();
|
||||
}
|
||||
|
||||
public void markReceived(FluidStack stack, int count) {
|
||||
fluidsReceived.add(stack, count);
|
||||
updateFinishedQuantity();
|
||||
}
|
||||
|
||||
public void updateFinishedQuantity() {
|
||||
int quantityFinished = totalQuantity;
|
||||
|
||||
for (StackListEntry<ItemStack> toReceive : singleItemSetToReceive.getStacks()) {
|
||||
if (itemsReceived.get(toReceive.getStack()) != null) {
|
||||
int ratioReceived = itemsReceived.get(toReceive.getStack()).getCount() / toReceive.getStack().getCount();
|
||||
|
||||
if (quantityFinished > ratioReceived) {
|
||||
quantityFinished = ratioReceived;
|
||||
}
|
||||
} else {
|
||||
quantityFinished = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (StackListEntry<FluidStack> toReceive : singleFluidSetToReceive.getStacks()) {
|
||||
if (fluidsReceived.get(toReceive.getStack()) != null) {
|
||||
int ratioReceived = fluidsReceived.get(toReceive.getStack()).getAmount() / toReceive.getStack().getAmount();
|
||||
|
||||
if (quantityFinished > ratioReceived) {
|
||||
quantityFinished = ratioReceived;
|
||||
}
|
||||
} else {
|
||||
quantityFinished = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.quantityFinished = quantityFinished;
|
||||
|
||||
if (this.quantityFinished == this.totalQuantity) {
|
||||
this.state = ProcessingState.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculationFinished() {
|
||||
super.onCalculationFinished();
|
||||
|
||||
this.singleItemSetToRequire = requirements.getSingleItemRequirementSet(true);
|
||||
this.singleFluidSetToRequire = requirements.getSingleFluidRequirementSet(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT writeToNbt() {
|
||||
CompoundNBT tag = super.writeToNbt();
|
||||
|
||||
tag.put(NBT_ITEMS_RECEIVED, SerializationUtil.writeItemStackList(itemsReceived));
|
||||
tag.put(NBT_FLUIDS_RECEIVED, SerializationUtil.writeFluidStackList(fluidsReceived));
|
||||
|
||||
tag.put(NBT_SINGLE_ITEM_SET_TO_REQUIRE, SerializationUtil.writeItemStackList(singleItemSetToRequire));
|
||||
tag.put(NBT_SINGLE_FLUID_SET_TO_REQUIRE, SerializationUtil.writeFluidStackList(singleFluidSetToRequire));
|
||||
|
||||
tag.putInt(NBT_STATE, state.ordinal());
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node;
|
||||
|
||||
enum ProcessingState {
|
||||
public enum ProcessingState {
|
||||
READY,
|
||||
MACHINE_NONE,
|
||||
MACHINE_DOES_NOT_ACCEPT,
|
@@ -0,0 +1,115 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.api.util.StackListEntry;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CraftingPreviewElementFactory {
|
||||
public List<ICraftingPreviewElement<?>> getElements(CraftingPreviewInfo info) {
|
||||
Map<Integer, ItemCraftingPreviewElement> map = new LinkedHashMap<>();
|
||||
Map<Integer, FluidCraftingPreviewElement> mapFluids = new LinkedHashMap<>();
|
||||
|
||||
for (StackListEntry<ItemStack> stack : info.getMissing().getStacks()) {
|
||||
int hash = API.instance().getItemStackHashCode(stack.getStack());
|
||||
|
||||
ItemCraftingPreviewElement previewStack = map.get(hash);
|
||||
|
||||
if (previewStack == null) {
|
||||
previewStack = new ItemCraftingPreviewElement(stack.getStack());
|
||||
}
|
||||
|
||||
previewStack.setMissing(true);
|
||||
previewStack.addToCraft(stack.getStack().getCount());
|
||||
|
||||
map.put(hash, previewStack);
|
||||
}
|
||||
|
||||
for (StackListEntry<FluidStack> stack : info.getMissingFluids().getStacks()) {
|
||||
int hash = API.instance().getFluidStackHashCode(stack.getStack());
|
||||
|
||||
FluidCraftingPreviewElement previewStack = mapFluids.get(hash);
|
||||
|
||||
if (previewStack == null) {
|
||||
previewStack = new FluidCraftingPreviewElement(stack.getStack());
|
||||
}
|
||||
|
||||
previewStack.setMissing(true);
|
||||
previewStack.addToCraft(stack.getStack().getAmount());
|
||||
|
||||
mapFluids.put(hash, previewStack);
|
||||
}
|
||||
|
||||
for (ItemStack stack : ImmutableList.copyOf(info.getToCraft()).reverse()) {
|
||||
int hash = API.instance().getItemStackHashCode(stack);
|
||||
|
||||
ItemCraftingPreviewElement previewStack = map.get(hash);
|
||||
|
||||
if (previewStack == null) {
|
||||
previewStack = new ItemCraftingPreviewElement(stack.getStack());
|
||||
}
|
||||
|
||||
previewStack.addToCraft(stack.getCount());
|
||||
|
||||
map.put(hash, previewStack);
|
||||
}
|
||||
|
||||
for (FluidStack stack : ImmutableList.copyOf(info.getToCraftFluids()).reverse()) {
|
||||
int hash = API.instance().getFluidStackHashCode(stack);
|
||||
|
||||
FluidCraftingPreviewElement previewStack = mapFluids.get(hash);
|
||||
|
||||
if (previewStack == null) {
|
||||
previewStack = new FluidCraftingPreviewElement(stack);
|
||||
}
|
||||
|
||||
previewStack.addToCraft(stack.getAmount());
|
||||
|
||||
mapFluids.put(hash, previewStack);
|
||||
}
|
||||
|
||||
for (StackListEntry<ItemStack> stack : info.getToTake().getStacks()) {
|
||||
int hash = API.instance().getItemStackHashCode(stack.getStack());
|
||||
|
||||
ItemCraftingPreviewElement previewStack = map.get(hash);
|
||||
|
||||
if (previewStack == null) {
|
||||
previewStack = new ItemCraftingPreviewElement(stack.getStack());
|
||||
}
|
||||
|
||||
previewStack.addAvailable(stack.getStack().getCount());
|
||||
|
||||
map.put(hash, previewStack);
|
||||
}
|
||||
|
||||
for (StackListEntry<FluidStack> stack : info.getToTakeFluids().getStacks()) {
|
||||
int hash = API.instance().getFluidStackHashCode(stack.getStack());
|
||||
|
||||
FluidCraftingPreviewElement previewStack = mapFluids.get(hash);
|
||||
|
||||
if (previewStack == null) {
|
||||
previewStack = new FluidCraftingPreviewElement(stack.getStack());
|
||||
}
|
||||
|
||||
previewStack.addAvailable(stack.getStack().getAmount());
|
||||
|
||||
mapFluids.put(hash, previewStack);
|
||||
}
|
||||
|
||||
List<ICraftingPreviewElement<?>> elements = new ArrayList<>();
|
||||
|
||||
elements.addAll(map.values());
|
||||
elements.addAll(mapFluids.values());
|
||||
|
||||
return elements;
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview;
|
||||
|
||||
import com.refinedmods.refinedstorage.api.util.IStackList;
|
||||
import com.refinedmods.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingPreviewInfo {
|
||||
private final IStackList<ItemStack> missing = API.instance().createItemStackList();
|
||||
private final IStackList<FluidStack> missingFluids = API.instance().createFluidStackList();
|
||||
|
||||
private final IStackList<ItemStack> toTake = API.instance().createItemStackList();
|
||||
private final IStackList<FluidStack> toTakeFluids = API.instance().createFluidStackList();
|
||||
|
||||
private final List<ItemStack> toCraft = new ArrayList<>();
|
||||
private final List<FluidStack> toCraftFluids = new ArrayList<>();
|
||||
|
||||
public IStackList<ItemStack> getMissing() {
|
||||
return missing;
|
||||
}
|
||||
|
||||
public IStackList<FluidStack> getMissingFluids() {
|
||||
return missingFluids;
|
||||
}
|
||||
|
||||
public boolean hasMissing() {
|
||||
return !missing.isEmpty() || !missingFluids.isEmpty();
|
||||
}
|
||||
|
||||
public IStackList<ItemStack> getToTake() {
|
||||
return toTake;
|
||||
}
|
||||
|
||||
public IStackList<FluidStack> getToTakeFluids() {
|
||||
return toTakeFluids;
|
||||
}
|
||||
|
||||
public List<ItemStack> getToCraft() {
|
||||
return toCraft;
|
||||
}
|
||||
|
||||
public List<FluidStack> getToCraftFluids() {
|
||||
return toCraftFluids;
|
||||
}
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.network.grid.handler;
|
||||
|
||||
import com.refinedmods.refinedstorage.RS;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler;
|
||||
import com.refinedmods.refinedstorage.api.network.security.Permission;
|
||||
@@ -15,7 +15,6 @@ import com.refinedmods.refinedstorage.util.StackUtils;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fluids.FluidAttributes;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
@@ -101,36 +100,30 @@ public class FluidGridHandler implements IFluidGridHandler {
|
||||
|
||||
if (stack != null) {
|
||||
Thread calculationThread = new Thread(() -> {
|
||||
ICraftingTask task = network.getCraftingManager().create(stack, quantity);
|
||||
if (task == null) {
|
||||
ICalculationResult result = network.getCraftingManager().create(stack, quantity);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ICraftingTaskError error = task.calculate();
|
||||
|
||||
ResourceLocation factoryId = task.getPattern().getCraftingTaskFactoryId();
|
||||
|
||||
if (error != null) {
|
||||
if (!result.isOk() && result.getType() != CalculationResultType.MISSING) {
|
||||
RS.NETWORK_HANDLER.sendTo(
|
||||
player,
|
||||
new GridCraftingPreviewResponseMessage(
|
||||
factoryId,
|
||||
Collections.singletonList(new ErrorCraftingPreviewElement(error.getType(), error.getRecursedPattern() == null ? ItemStack.EMPTY : error.getRecursedPattern().getStack())),
|
||||
Collections.singletonList(new ErrorCraftingPreviewElement(result.getType(), result.getRecursedPattern() == null ? ItemStack.EMPTY : result.getRecursedPattern().getStack())),
|
||||
id,
|
||||
quantity,
|
||||
true
|
||||
)
|
||||
);
|
||||
} else if (noPreview && !task.hasMissing()) {
|
||||
network.getCraftingManager().start(task);
|
||||
} else if (result.isOk() && noPreview) {
|
||||
network.getCraftingManager().start(result.getTask());
|
||||
|
||||
RS.NETWORK_HANDLER.sendTo(player, new GridCraftingStartResponseMessage());
|
||||
} else {
|
||||
RS.NETWORK_HANDLER.sendTo(
|
||||
player,
|
||||
new GridCraftingPreviewResponseMessage(
|
||||
factoryId,
|
||||
task.getPreviewStacks(),
|
||||
result.getPreviewElements(),
|
||||
id,
|
||||
quantity,
|
||||
true
|
||||
@@ -152,14 +145,9 @@ public class FluidGridHandler implements IFluidGridHandler {
|
||||
FluidStack stack = network.getFluidStorageCache().getCraftablesList().get(id);
|
||||
|
||||
if (stack != null) {
|
||||
ICraftingTask task = network.getCraftingManager().create(stack, quantity);
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ICraftingTaskError error = task.calculate();
|
||||
if (error == null && !task.hasMissing()) {
|
||||
network.getCraftingManager().start(task);
|
||||
ICalculationResult result = network.getCraftingManager().create(stack, quantity);
|
||||
if (result.isOk()) {
|
||||
network.getCraftingManager().start(result.getTask());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package com.refinedmods.refinedstorage.apiimpl.network.grid.handler;
|
||||
|
||||
import com.refinedmods.refinedstorage.RS;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult;
|
||||
import com.refinedmods.refinedstorage.api.network.INetwork;
|
||||
import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler;
|
||||
import com.refinedmods.refinedstorage.api.network.security.Permission;
|
||||
@@ -14,7 +14,6 @@ import com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMess
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
@@ -159,36 +158,27 @@ public class ItemGridHandler implements IItemGridHandler {
|
||||
|
||||
if (stack != null) {
|
||||
Thread calculationThread = new Thread(() -> {
|
||||
ICraftingTask task = network.getCraftingManager().create(stack, quantity);
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
ICalculationResult result = network.getCraftingManager().create(stack, quantity);
|
||||
|
||||
ICraftingTaskError error = task.calculate();
|
||||
|
||||
ResourceLocation factoryId = task.getPattern().getCraftingTaskFactoryId();
|
||||
|
||||
if (error != null) {
|
||||
if (!result.isOk() && result.getType() != CalculationResultType.MISSING) {
|
||||
RS.NETWORK_HANDLER.sendTo(
|
||||
player,
|
||||
new GridCraftingPreviewResponseMessage(
|
||||
factoryId,
|
||||
Collections.singletonList(new ErrorCraftingPreviewElement(error.getType(), error.getRecursedPattern() == null ? ItemStack.EMPTY : error.getRecursedPattern().getStack())),
|
||||
Collections.singletonList(new ErrorCraftingPreviewElement(result.getType(), result.getRecursedPattern() == null ? ItemStack.EMPTY : result.getRecursedPattern().getStack())),
|
||||
id,
|
||||
quantity,
|
||||
false
|
||||
)
|
||||
);
|
||||
} else if (noPreview && !task.hasMissing()) {
|
||||
network.getCraftingManager().start(task);
|
||||
} else if (result.isOk() && noPreview) {
|
||||
network.getCraftingManager().start(result.getTask());
|
||||
|
||||
RS.NETWORK_HANDLER.sendTo(player, new GridCraftingStartResponseMessage());
|
||||
} else {
|
||||
RS.NETWORK_HANDLER.sendTo(
|
||||
player,
|
||||
new GridCraftingPreviewResponseMessage(
|
||||
factoryId,
|
||||
task.getPreviewStacks(),
|
||||
result.getPreviewElements(),
|
||||
id,
|
||||
quantity,
|
||||
false
|
||||
@@ -210,14 +200,9 @@ public class ItemGridHandler implements IItemGridHandler {
|
||||
ItemStack stack = network.getItemStorageCache().getCraftablesList().get(id);
|
||||
|
||||
if (stack != null) {
|
||||
ICraftingTask task = network.getCraftingManager().create(stack, quantity);
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ICraftingTaskError error = task.calculate();
|
||||
if (error == null && !task.hasMissing()) {
|
||||
network.getCraftingManager().start(task);
|
||||
ICalculationResult result = network.getCraftingManager().create(stack, quantity);
|
||||
if (result.isOk()) {
|
||||
network.getCraftingManager().start(result.getTask());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -82,6 +82,16 @@ public class FluidStackList implements IStackList<FluidStack> {
|
||||
return remove(stack, stack.getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount(@Nonnull FluidStack stack, int flags) {
|
||||
FluidStack found = get(stack, flags);
|
||||
if (found == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return found.getAmount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public FluidStack get(@Nonnull FluidStack stack, int flags) {
|
||||
|
@@ -80,6 +80,16 @@ public class ItemStackList implements IStackList<ItemStack> {
|
||||
return remove(stack, stack.getCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount(@Nonnull ItemStack stack, int flags) {
|
||||
ItemStack found = get(stack, flags);
|
||||
if (found == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return found.getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ItemStack get(@Nonnull ItemStack stack, int flags) {
|
||||
|
@@ -20,8 +20,7 @@ public class ClientProxy {
|
||||
|
||||
Minecraft.getInstance().displayGuiScreen(new CraftingPreviewScreen(
|
||||
screen,
|
||||
message.getFactoryId(),
|
||||
message.getStacks(),
|
||||
message.getElements(),
|
||||
message.getId(),
|
||||
message.getQuantity(),
|
||||
message.isFluids(),
|
||||
|
@@ -83,7 +83,7 @@ public class CraftingMonitorUpdateMessage {
|
||||
buf.writeUniqueId(task.getId());
|
||||
buf.writeCompoundTag(task.getRequested().writeToNbt());
|
||||
buf.writeInt(task.getQuantity());
|
||||
buf.writeLong(task.getExecutionStarted());
|
||||
buf.writeLong(task.getStartTime());
|
||||
buf.writeInt(task.getCompletionPercentage());
|
||||
|
||||
List<ICraftingMonitorElement> elements = task.getCraftingMonitorElements();
|
||||
|
@@ -13,26 +13,20 @@ import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class GridCraftingPreviewResponseMessage {
|
||||
private final ResourceLocation factoryId;
|
||||
private final List<ICraftingPreviewElement<?>> stacks;
|
||||
private final List<ICraftingPreviewElement<?>> elements;
|
||||
private final UUID id;
|
||||
private final int quantity;
|
||||
private final boolean fluids;
|
||||
|
||||
public GridCraftingPreviewResponseMessage(ResourceLocation factoryId, List<ICraftingPreviewElement<?>> stacks, UUID id, int quantity, boolean fluids) {
|
||||
this.factoryId = factoryId;
|
||||
this.stacks = stacks;
|
||||
public GridCraftingPreviewResponseMessage(List<ICraftingPreviewElement<?>> elements, UUID id, int quantity, boolean fluids) {
|
||||
this.elements = elements;
|
||||
this.id = id;
|
||||
this.quantity = quantity;
|
||||
this.fluids = fluids;
|
||||
}
|
||||
|
||||
public ResourceLocation getFactoryId() {
|
||||
return factoryId;
|
||||
}
|
||||
|
||||
public List<ICraftingPreviewElement<?>> getStacks() {
|
||||
return stacks;
|
||||
public List<ICraftingPreviewElement<?>> getElements() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
@@ -48,7 +42,6 @@ public class GridCraftingPreviewResponseMessage {
|
||||
}
|
||||
|
||||
public static GridCraftingPreviewResponseMessage decode(PacketBuffer buf) {
|
||||
ResourceLocation factoryId = buf.readResourceLocation();
|
||||
UUID id = buf.readUniqueId();
|
||||
int quantity = buf.readInt();
|
||||
boolean fluids = buf.readBoolean();
|
||||
@@ -62,17 +55,16 @@ public class GridCraftingPreviewResponseMessage {
|
||||
stacks.add(API.instance().getCraftingPreviewElementRegistry().get(type).apply(buf));
|
||||
}
|
||||
|
||||
return new GridCraftingPreviewResponseMessage(factoryId, stacks, id, quantity, fluids);
|
||||
return new GridCraftingPreviewResponseMessage(stacks, id, quantity, fluids);
|
||||
}
|
||||
|
||||
public static void encode(GridCraftingPreviewResponseMessage message, PacketBuffer buf) {
|
||||
buf.writeResourceLocation(message.factoryId);
|
||||
buf.writeUniqueId(message.id);
|
||||
buf.writeInt(message.quantity);
|
||||
buf.writeBoolean(message.fluids);
|
||||
buf.writeInt(message.stacks.size());
|
||||
buf.writeInt(message.elements.size());
|
||||
|
||||
for (ICraftingPreviewElement<?> stack : message.stacks) {
|
||||
for (ICraftingPreviewElement<?> stack : message.elements) {
|
||||
buf.writeResourceLocation(stack.getId());
|
||||
stack.write(buf);
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.refinedmods.refinedstorage.RS;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||
import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType;
|
||||
import com.refinedmods.refinedstorage.api.render.IElementDrawers;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement;
|
||||
import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement;
|
||||
@@ -25,7 +25,6 @@ import net.minecraft.client.util.ITooltipFlag;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
@@ -36,14 +35,12 @@ import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CraftingPreviewScreen extends BaseScreen<Container> {
|
||||
private static final int VISIBLE_ROWS = 5;
|
||||
|
||||
private final List<ICraftingPreviewElement<?>> stacks;
|
||||
private final Screen parent;
|
||||
private final ResourceLocation factoryId;
|
||||
|
||||
private final ScrollbarWidget scrollbar;
|
||||
|
||||
@@ -56,7 +53,7 @@ public class CraftingPreviewScreen extends BaseScreen<Container> {
|
||||
|
||||
private final IElementDrawers drawers = new CraftingPreviewElementDrawers(this, font);
|
||||
|
||||
public CraftingPreviewScreen(Screen parent, ResourceLocation factoryId, List<ICraftingPreviewElement<?>> stacks, UUID id, int quantity, boolean fluids, ITextComponent title) {
|
||||
public CraftingPreviewScreen(Screen parent, List<ICraftingPreviewElement<?>> stacks, UUID id, int quantity, boolean fluids, ITextComponent title) {
|
||||
super(new Container(null, 0) {
|
||||
@Override
|
||||
public boolean canInteractWith(@Nonnull PlayerEntity player) {
|
||||
@@ -66,7 +63,6 @@ public class CraftingPreviewScreen extends BaseScreen<Container> {
|
||||
|
||||
this.stacks = new ArrayList<>(stacks);
|
||||
this.parent = parent;
|
||||
this.factoryId = factoryId;
|
||||
|
||||
this.id = id;
|
||||
this.quantity = quantity;
|
||||
@@ -90,7 +86,7 @@ public class CraftingPreviewScreen extends BaseScreen<Container> {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CraftingTaskErrorType getErrorType() {
|
||||
private CalculationResultType getErrorType() {
|
||||
if (stacks.size() == 1 && stacks.get(0) instanceof ErrorCraftingPreviewElement) {
|
||||
return ((ErrorCraftingPreviewElement) stacks.get(0)).getType();
|
||||
}
|
||||
@@ -135,8 +131,6 @@ public class CraftingPreviewScreen extends BaseScreen<Container> {
|
||||
|
||||
renderString(matrixStack, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 61, scale), I18n.format("gui.refinedstorage.crafting_preview.error.recursive.4"));
|
||||
|
||||
RenderSystem.popMatrix();
|
||||
|
||||
ICraftingPattern pattern = PatternItem.fromCache(parent.getMinecraft().world, (ItemStack) stacks.get(0).getElement());
|
||||
|
||||
int yy = 83;
|
||||
@@ -162,11 +156,11 @@ public class CraftingPreviewScreen extends BaseScreen<Container> {
|
||||
renderString(matrixStack, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), I18n.format("gui.refinedstorage.crafting_preview.error.too_complex.0"));
|
||||
renderString(matrixStack, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), I18n.format("gui.refinedstorage.crafting_preview.error.too_complex.1"));
|
||||
|
||||
RenderSystem.popMatrix();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RenderSystem.popMatrix();
|
||||
} else {
|
||||
int slot = scrollbar != null ? (scrollbar.getOffset() * 3) : 0;
|
||||
|
||||
|
Reference in New Issue
Block a user