New autocrafting system, again.

This commit is contained in:
raoulvdberge
2018-08-09 21:28:19 +02:00
parent d20fcdf2b1
commit 7596239b32
18 changed files with 511 additions and 1136 deletions

View File

@@ -101,14 +101,14 @@ public interface ICraftingManager {
*
* @param stack the stack
*/
void track(ItemStack stack, int size);
int track(ItemStack stack, int size);
/**
* Tracks an incoming stack.
*
* @param stack the stack
*/
void track(FluidStack stack, int size);
int track(FluidStack stack, int size);
/**
* @return a list of crafting patterns in this network, do NOT modify this list

View File

@@ -56,7 +56,6 @@ public interface ICraftingTask {
* Called when a stack is inserted into the system through {@link com.raoulvdberge.refinedstorage.api.network.INetwork#insertItemTracked(ItemStack, int)}.
*
* @param stack the stack
* @return the size remaining, decremented by the crafting task when it was relevant to it
*/
int onTrackedInsert(ItemStack stack, int size);
@@ -64,7 +63,6 @@ public interface ICraftingTask {
* Called when a stack is inserted into the system through {@link com.raoulvdberge.refinedstorage.api.network.INetwork#insertFluidTracked(FluidStack, int)}.
*
* @param stack the stack
* @return the size remaining, decremented by the crafting task when it was relevant to it
*/
int onTrackedInsert(FluidStack stack, int size);
@@ -95,14 +93,6 @@ public interface ICraftingTask {
*/
ICraftingPattern getPattern();
/**
* Used to check if the crafting task has recursive elements (eg. block needs 9 ingots, ingots are crafted by a block).
* {@link ICraftingTask#calculate()} must be run before this!
*
* @return true if no recursion was found, false otherwise
*/
boolean isValid();
/**
* @return the time in ms when this task has started
*/

View File

@@ -108,14 +108,15 @@ public interface INetwork {
* @param size the amount of that prototype that has to be inserted
* @return null if the insert was successful, or a stack with the remainder
*/
@Nullable
default ItemStack insertItemTracked(@Nonnull ItemStack stack, int size) {
ItemStack remainder = insertItem(stack, size, Action.PERFORM);
int remainder = getCraftingManager().track(stack, size);
int inserted = remainder == null ? size : (size - remainder.getCount());
if (remainder == 0) {
return null;
}
getCraftingManager().track(stack, inserted);
return remainder;
return insertItem(stack, remainder, Action.PERFORM);
}
/**
@@ -178,13 +179,13 @@ public interface INetwork {
*/
@Nullable
default FluidStack insertFluidTracked(@Nonnull FluidStack stack, int size) {
FluidStack remainder = insertFluid(stack, size, Action.PERFORM);
int remainder = getCraftingManager().track(stack, size);
int inserted = remainder == null ? size : (size - remainder.amount);
if (remainder == 0) {
return null;
}
getCraftingManager().track(stack, inserted);
return remainder;
return insertFluid(stack, remainder, Action.PERFORM);
}
/**

View File

@@ -152,7 +152,9 @@ public class CraftingManager implements ICraftingManager {
}
this.tasksToCancel.clear();
this.tasksToAdd.stream().filter(ICraftingTask::isValid).forEach(t -> tasks.put(t.getId(), t));
for (ICraftingTask task : this.tasksToAdd) {
this.tasks.put(task.getId(), task);
}
this.tasksToAdd.clear();
boolean anyFinished = false;
@@ -275,37 +277,29 @@ public class CraftingManager implements ICraftingManager {
}
@Override
public void track(ItemStack stack, int size) {
int initialSize = size;
public int track(ItemStack stack, int size) {
for (ICraftingTask task : tasks.values()) {
size = task.onTrackedInsert(stack, size);
if (size == 0) {
break;
return 0;
}
}
if (size != initialSize) {
this.onTaskChanged();
}
return size;
}
@Override
public void track(FluidStack stack, int size) {
int initialSize = size;
public int track(FluidStack stack, int size) {
for (ICraftingTask task : tasks.values()) {
size = task.onTrackedInsert(stack, size);
if (size == 0) {
break;
return 0;
}
}
if (size != initialSize) {
this.onTaskChanged();
}
return size;
}
@Override

View File

@@ -22,6 +22,6 @@ public class CraftingTaskFactory implements ICraftingTaskFactory {
@Override
public ICraftingTask createFromNbt(INetwork network, NBTTagCompound tag) throws CraftingTaskReadException {
return new CraftingTask(network, tag);
throw new CraftingTaskReadException("Persistence isn't implemented yet, ignoring..."); // TODO: Persistence
}
}

View File

@@ -0,0 +1,30 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
class Crafting {
private ICraftingPattern pattern;
private NonNullList<ItemStack> took;
private IStackList<ItemStack> toExtract;
public Crafting(ICraftingPattern pattern, NonNullList<ItemStack> took, IStackList<ItemStack> toExtract) {
this.pattern = pattern;
this.took = took;
this.toExtract = toExtract;
}
public ICraftingPattern getPattern() {
return pattern;
}
public NonNullList<ItemStack> getTook() {
return took;
}
public IStackList<ItemStack> getToExtract() {
return toExtract;
}
}

View File

@@ -1,12 +1,17 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.*;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternChain;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternChainList;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.*;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.storage.IStorage;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
@@ -16,57 +21,34 @@ import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.Craf
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementText;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementFluidStack;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementItemStack;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractor;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStack;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStatus;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserter;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserterItem;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserterItemStatus;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step.CraftingStep;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step.CraftingStepCraft;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step.CraftingStepProcess;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import com.raoulvdberge.refinedstorage.apiimpl.storage.disk.StorageDiskFluid;
import com.raoulvdberge.refinedstorage.apiimpl.storage.disk.StorageDiskItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemHandlerHelper;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.*;
public class CraftingTask implements ICraftingTask {
private static final long CALCULATION_TIMEOUT_MS = 5000;
private static final String NBT_REQUESTED = "Requested";
private static final String NBT_QUANTITY = "Quantity";
private static final String NBT_PATTERN = "Pattern";
private static final String NBT_STEPS = "Steps";
private static final String NBT_INSERTER = "Inserter";
private static final String NBT_TICKS = "Ticks";
private static final String NBT_ID = "Id";
private static final String NBT_MISSING = "Missing";
private static final String NBT_EXECUTION_STARTED = "ExecutionStarted";
private static final String NBT_PATTERN_STACK = "Stack";
private static final String NBT_PATTERN_CONTAINER_POS = "ContainerPos";
private INetwork network;
private ICraftingRequestInfo requested;
private int quantity;
private ICraftingPattern pattern;
private List<CraftingStep> steps = new LinkedList<>();
private CraftingInserter inserter;
private Set<ICraftingPattern> patternsUsed = new HashSet<>();
private int ticks = 0;
private long calculationStarted = -1;
private long executionStarted = -1;
private UUID id = UUID.randomUUID();
private int ticks;
private long executionStarted = -1;
private IStorage<ItemStack> internalStorage;
private IStorage<FluidStack> internalFluidStorage;
private IStackList<ItemStack> toExtractInitial = API.instance().createItemStackList();
private IStackList<FluidStack> toExtractInitialFluids = API.instance().createFluidStackList();
private List<Crafting> crafting = new ArrayList<>();
private List<Processing> processing = new ArrayList<>();
private IStackList<ItemStack> toTake = API.instance().createItemStackList();
private IStackList<FluidStack> toTakeFluids = API.instance().createFluidStackList();
@@ -79,58 +61,17 @@ public class CraftingTask implements ICraftingTask {
public CraftingTask(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {
this.network = network;
this.inserter = new CraftingInserter(network);
this.requested = requested;
this.quantity = quantity;
this.pattern = pattern;
}
public CraftingTask(INetwork network, NBTTagCompound tag) throws CraftingTaskReadException {
this.network = network;
this.requested = API.instance().createCraftingRequestInfo(tag.getCompoundTag(NBT_REQUESTED));
this.quantity = tag.getInteger(NBT_QUANTITY);
this.pattern = readPatternFromNbt(tag.getCompoundTag(NBT_PATTERN), network.world());
this.inserter = new CraftingInserter(network, tag.getTagList(NBT_INSERTER, Constants.NBT.TAG_COMPOUND));
this.ticks = tag.getInteger(NBT_TICKS);
this.id = tag.getUniqueId(NBT_ID);
NBTTagList steps = tag.getTagList(NBT_STEPS, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < steps.tagCount(); ++i) {
NBTTagCompound stepTag = steps.getCompoundTagAt(i);
this.steps.add(CraftingStep.readFromNbt(network, inserter, stepTag));
}
NBTTagList missing = tag.getTagList(NBT_MISSING, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < missing.tagCount(); ++i) {
ItemStack missingItem = StackUtils.deserializeStackFromNbt(missing.getCompoundTagAt(i));
if (missingItem.isEmpty()) {
throw new CraftingTaskReadException("Missing item is empty");
}
this.missing.add(missingItem);
}
if (tag.hasKey(NBT_EXECUTION_STARTED)) {
this.executionStarted = tag.getLong(NBT_EXECUTION_STARTED);
}
this.internalStorage = new StorageDiskItem(network.world(), -1);
this.internalFluidStorage = new StorageDiskFluid(network.world(), -1);
}
@Override
@Nullable
public ICraftingTaskError calculate() {
if (calculationStarted != -1) {
throw new IllegalStateException("Task already calculated!");
}
if (executionStarted != -1) {
throw new IllegalStateException("Task already started!");
}
this.calculationStarted = System.currentTimeMillis();
int qty = this.quantity;
int qtyPerCraft = getQuantityPerCraft();
int crafted = 0;
@@ -141,52 +82,17 @@ public class CraftingTask implements ICraftingTask {
IStackList<ItemStack> storage = network.getItemStorageCache().getList().copy();
IStackList<FluidStack> fluidStorage = network.getFluidStorageCache().getList().copy();
// Items that are being handled in other tasks aren't available to us.
for (ICraftingTask task : network.getCraftingManager().getTasks()) {
if (task instanceof CraftingTask) {
for (CraftingStep step : ((CraftingTask) task).steps) {
CraftingExtractor extractor = null;
if (step instanceof CraftingStepCraft) {
extractor = ((CraftingStepCraft) step).getExtractor();
} else if (step instanceof CraftingStepProcess) {
extractor = ((CraftingStepProcess) step).getExtractor();
}
if (extractor != null) {
for (CraftingExtractorStack inUse : extractor.getStacks()) {
ItemStack inUseItem = inUse.getItem();
if (inUseItem != null) {
storage.remove(inUseItem);
} else {
FluidStack inUseFluid = inUse.getFluid();
if (inUseFluid != null) {
fluidStorage.remove(inUseFluid);
} else {
throw new IllegalStateException("Extractor stack is neither a fluid or an item!");
}
}
}
}
}
}
}
ICraftingPatternChainList patternChainList = network.getCraftingManager().createPatternChainList();
ICraftingPatternChain patternChain = patternChainList.getChain(pattern);
while (qty > 0) {
Pair<CraftingStep, ICraftingTaskError> result = calculateInternal(storage, fluidStorage, results, fluidResults, patternChainList, patternChain.current());
ICraftingTaskError result = calculateInternal(storage, fluidStorage, results, fluidResults, patternChainList, patternChain.current());
if (result.getRight() != null) {
return result.getRight();
if (result != null) {
return result;
}
this.steps.add(result.getLeft());
qty -= qtyPerCraft;
crafted += qtyPerCraft;
@@ -203,7 +109,8 @@ public class CraftingTask implements ICraftingTask {
return null;
}
private Pair<CraftingStep, ICraftingTaskError> calculateInternal(
@Nullable
private ICraftingTaskError calculateInternal(
IStackList<ItemStack> mutatedStorage,
IStackList<FluidStack> mutatedFluidStorage,
IStackList<ItemStack> results,
@@ -211,14 +118,6 @@ public class CraftingTask implements ICraftingTask {
ICraftingPatternChainList patternChainList,
ICraftingPattern pattern) {
if (System.currentTimeMillis() - calculationStarted > CALCULATION_TIMEOUT_MS) {
return Pair.of(null, new CraftingTaskError(CraftingTaskErrorType.TOO_COMPLEX));
}
if (!patternsUsed.add(pattern)) {
return Pair.of(null, new CraftingTaskError(CraftingTaskErrorType.RECURSIVE, pattern));
}
IStackList<ItemStack> itemsToExtract = API.instance().createItemStackList();
IStackList<FluidStack> fluidsToExtract = API.instance().createFluidStackList();
@@ -292,6 +191,8 @@ public class CraftingTask implements ICraftingTask {
took.set(took.size() - 1, ItemHandlerHelper.copyStackWithSize(fromNetwork, possibleInput.getCount()));
fromNetwork = mutatedStorage.get(possibleInput, flags);
toExtractInitial.add(took.get(took.size() - 1));
} else {
ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput);
@@ -299,14 +200,12 @@ public class CraftingTask implements ICraftingTask {
ICraftingPatternChain subPatternChain = patternChainList.getChain(subPattern);
while ((fromSelf == null ? 0 : fromSelf.getCount()) < remaining) {
Pair<CraftingStep, ICraftingTaskError> result = calculateInternal(mutatedStorage, mutatedFluidStorage, results, fluidResults, patternChainList, subPatternChain.current());
ICraftingTaskError result = calculateInternal(mutatedStorage, mutatedFluidStorage, results, fluidResults, patternChainList, subPatternChain.current());
if (result.getRight() != null) {
return Pair.of(null, result.getRight());
if (result != null) {
return result;
}
this.steps.add(result.getLeft());
fromSelf = results.get(possibleInput, flags);
if (fromSelf == null) {
throw new IllegalStateException("Recursive calculation didn't yield anything");
@@ -359,6 +258,8 @@ public class CraftingTask implements ICraftingTask {
remaining -= toTake;
fromNetwork = mutatedFluidStorage.get(input, IComparer.COMPARE_NBT);
toExtractInitialFluids.add(input);
} else {
ICraftingPattern subPattern = network.getCraftingManager().getPattern(input);
@@ -366,14 +267,12 @@ public class CraftingTask implements ICraftingTask {
ICraftingPatternChain subPatternChain = patternChainList.getChain(subPattern);
while ((fromSelf == null ? 0 : fromSelf.amount) < remaining) {
Pair<CraftingStep, ICraftingTaskError> result = calculateInternal(mutatedStorage, mutatedFluidStorage, results, fluidResults, patternChainList, subPatternChain.current());
ICraftingTaskError result = calculateInternal(mutatedStorage, mutatedFluidStorage, results, fluidResults, patternChainList, subPatternChain.current());
if (result.getRight() != null) {
return Pair.of(null, result.getRight());
if (result != null) {
return result;
}
this.steps.add(result.getLeft());
fromSelf = fluidResults.get(input, IComparer.COMPARE_NBT);
if (fromSelf == null) {
throw new IllegalStateException("Recursive fluid calculation didn't yield anything");
@@ -397,31 +296,307 @@ public class CraftingTask implements ICraftingTask {
}
}
patternsUsed.remove(pattern);
if (pattern.isProcessing()) {
IStackList<ItemStack> itemsToReceive = API.instance().createItemStackList();
IStackList<FluidStack> fluidsToReceive = API.instance().createFluidStackList();
for (ItemStack output : pattern.getOutputs()) {
results.add(output);
itemsToReceive.add(output);
}
for (FluidStack output : pattern.getFluidOutputs()) {
fluidResults.add(output);
fluidsToReceive.add(output);
}
return Pair.of(new CraftingStepProcess(pattern, network, new ArrayList<>(itemsToExtract.getStacks()), new ArrayList<>(fluidsToExtract.getStacks())), null);
processing.add(new Processing(pattern, itemsToReceive, fluidsToReceive, new ArrayList<>(itemsToExtract.getStacks()), new ArrayList<>(fluidsToExtract.getStacks())));
} else {
if (!fluidsToExtract.isEmpty()) {
throw new IllegalStateException("Cannot extract fluids in normal pattern!");
}
crafting.add(new Crafting(pattern, took, itemsToExtract));
results.add(pattern.getOutput(took));
for (ItemStack byproduct : pattern.getByproducts(took)) {
results.add(byproduct);
}
return Pair.of(new CraftingStepCraft(pattern, inserter, network, new ArrayList<>(itemsToExtract.getStacks()), took), null);
}
return null;
}
private static int getTickInterval(int speedUpgrades) {
switch (speedUpgrades) {
case 0:
return 10;
case 1:
return 8;
case 2:
return 6;
case 3:
return 4;
case 4:
return 2;
default:
return 2;
}
}
private void extractInitial() {
if (!toExtractInitial.isEmpty()) {
List<ItemStack> toRemove = new ArrayList<>();
for (ItemStack toExtract : toExtractInitial.getStacks()) {
ItemStack result = network.extractItem(toExtract, toExtract.getCount(), getFlags(toExtract), Action.PERFORM);
if (result != null) {
internalStorage.insert(toExtract, toExtract.getCount(), Action.PERFORM);
toRemove.add(result);
}
}
for (ItemStack stack : toRemove) {
toExtractInitial.remove(stack);
}
if (!toRemove.isEmpty()) {
network.getCraftingManager().onTaskChanged();
}
}
if (!toExtractInitialFluids.isEmpty()) {
List<FluidStack> toRemove = new ArrayList<>();
for (FluidStack toExtract : toExtractInitialFluids.getStacks()) {
FluidStack result = network.extractFluid(toExtract, toExtract.amount, Action.PERFORM);
if (result != null) {
internalFluidStorage.insert(toExtract, toExtract.amount, Action.PERFORM);
toRemove.add(result);
}
}
for (FluidStack stack : toRemove) {
toExtractInitialFluids.remove(stack);
}
if (!toRemove.isEmpty()) {
network.getCraftingManager().onTaskChanged();
}
}
}
private void updateCrafting() {
Iterator<Crafting> it = crafting.iterator();
while (it.hasNext()) {
Crafting c = it.next();
if (ticks % getTickInterval(c.getPattern().getContainer().getSpeedUpgradeCount()) == 0) {
boolean hasAll = true;
for (ItemStack need : c.getToExtract().getStacks()) {
ItemStack result = this.internalStorage.extract(need, need.getCount(), getFlags(need), Action.SIMULATE);
if (result == null || result.getCount() != need.getCount()) {
hasAll = false;
break;
}
}
if (hasAll) {
for (ItemStack need : c.getToExtract().getStacks()) {
ItemStack result = this.internalStorage.extract(need, need.getCount(), getFlags(need), Action.PERFORM);
if (result == null || result.getCount() != need.getCount()) {
throw new IllegalStateException("Extractor check lied");
}
}
ItemStack output = c.getPattern().getOutput(c.getTook());
this.internalStorage.insert(output, output.getCount(), Action.PERFORM);
for (ItemStack byp : c.getPattern().getByproducts(c.getTook())) {
this.internalStorage.insert(byp, byp.getCount(), Action.PERFORM);
}
it.remove();
network.getCraftingManager().onTaskChanged();
return;
}
}
}
}
private void updateProcessing() {
Iterator<Processing> it = processing.iterator();
while (it.hasNext()) {
Processing p = it.next();
if (p.getState() == ProcessingState.PROCESSED) {
it.remove();
network.getCraftingManager().onTaskChanged();
continue;
}
if (p.getState() == ProcessingState.EXTRACTED_ALL) {
continue;
}
if (ticks % getTickInterval(p.getPattern().getContainer().getSpeedUpgradeCount()) == 0) {
ProcessingState originalState = p.getState();
boolean hasAll = true;
for (ItemStack need : p.getItemsToPut()) {
if (p.getPattern().getContainer().getConnectedInventory() == null) {
p.setState(ProcessingState.MACHINE_NONE);
} else {
ItemStack result = this.internalStorage.extract(need, need.getCount(), getFlags(need), Action.SIMULATE);
if (result == null || result.getCount() != need.getCount()) {
hasAll = false;
break;
} else if (!ItemHandlerHelper.insertItem(p.getPattern().getContainer().getConnectedInventory(), result, true).isEmpty()) {
p.setState(ProcessingState.MACHINE_DOES_NOT_ACCEPT);
break;
} else {
p.setState(ProcessingState.READY);
}
}
}
for (FluidStack need : p.getFluidsToPut()) {
if (p.getPattern().getContainer().getConnectedFluidInventory() == null) {
p.setState(ProcessingState.MACHINE_NONE);
} else {
FluidStack result = this.internalFluidStorage.extract(need, need.amount, IComparer.COMPARE_NBT, Action.SIMULATE);
if (result == null || result.amount != need.amount) {
hasAll = false;
break;
} else if (p.getPattern().getContainer().getConnectedFluidInventory().fill(result, false) != result.amount) {
p.setState(ProcessingState.MACHINE_DOES_NOT_ACCEPT);
break;
} else if (p.getState() == ProcessingState.READY) { // If the items were ok.
p.setState(ProcessingState.READY);
}
}
}
if (p.getState() == ProcessingState.READY && hasAll) {
for (ItemStack need : p.getItemsToPut()) {
ItemStack result = this.internalStorage.extract(need, need.getCount(), getFlags(need), Action.PERFORM);
if (result == null || result.getCount() != need.getCount()) {
throw new IllegalStateException("Could not extract from the internal inventory even though we could");
}
if (!ItemHandlerHelper.insertItem(p.getPattern().getContainer().getConnectedInventory(), result, false).isEmpty()) {
throw new IllegalStateException("Can't fill up inventory even though we could");
}
}
for (FluidStack need : p.getFluidsToPut()) {
FluidStack result = this.internalFluidStorage.extract(need, need.amount, IComparer.COMPARE_NBT, Action.PERFORM);
if (result == null || result.amount != need.amount) {
throw new IllegalStateException("Could not extract from the internal inventory even though we could");
}
if (p.getPattern().getContainer().getConnectedFluidInventory().fill(result, true) != result.amount) {
throw new IllegalStateException("Can't fill up inventory even though we could");
}
}
p.setState(ProcessingState.EXTRACTED_ALL);
}
if (originalState != p.getState()) {
network.getCraftingManager().onTaskChanged();
}
}
}
}
@Override
public boolean update() {
if (executionStarted == -1) {
executionStarted = System.currentTimeMillis();
}
++ticks;
extractInitial();
if (this.crafting.isEmpty() && this.processing.isEmpty()) {
List<Runnable> toPerform = new ArrayList<>();
for (ItemStack stack : internalStorage.getStacks()) {
ItemStack remainder = network.insertItem(stack, stack.getCount(), Action.PERFORM);
toPerform.add(() -> {
if (remainder == null) {
internalStorage.extract(stack, stack.getCount(), IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT, Action.PERFORM);
} else {
internalStorage.extract(stack, stack.getCount() - remainder.getCount(), IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT, Action.PERFORM);
}
});
}
for (FluidStack stack : internalFluidStorage.getStacks()) {
FluidStack remainder = network.insertFluid(stack, stack.amount, Action.PERFORM);
toPerform.add(() -> {
if (remainder == null) {
internalFluidStorage.extract(stack, stack.amount, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT, Action.PERFORM);
} else {
internalFluidStorage.extract(stack, stack.amount - remainder.amount, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT, Action.PERFORM);
}
});
}
// Prevent CME.
toPerform.forEach(Runnable::run);
return internalStorage.getStacks().isEmpty() && internalFluidStorage.getStacks().isEmpty();
} else {
updateCrafting();
updateProcessing();
return false;
}
}
@Override
public void onCancelled() {
for (ItemStack remainder : internalStorage.getStacks()) {
network.insertItem(remainder, remainder.getCount(), Action.PERFORM);
}
for (FluidStack remainder : internalFluidStorage.getStacks()) {
network.insertFluid(remainder, remainder.amount, Action.PERFORM);
}
}
@Override
public int getQuantity() {
return quantity;
}
@Override
@@ -449,43 +624,12 @@ public class CraftingTask implements ICraftingTask {
return qty;
}
@Override
public boolean update() {
if (executionStarted == -1) {
executionStarted = System.currentTimeMillis();
private static int getFlags(ItemStack stack) {
if (stack.getItem().isDamageable()) {
return IComparer.COMPARE_NBT;
}
boolean allCompleted = true;
if (ticks % getTickInterval(pattern.getContainer().getSpeedUpgradeCount()) == 0) {
inserter.insertOne();
}
for (CraftingStep step : steps) {
if (!step.isCompleted()) {
allCompleted = false;
if (ticks % getTickInterval(step.getPattern().getContainer().getSpeedUpgradeCount()) == 0 && step.canExecute() && step.execute()) {
step.setCompleted();
network.getCraftingManager().onTaskChanged();
}
}
}
ticks++;
return allCompleted && inserter.getItems().isEmpty();
}
@Override
public void onCancelled() {
inserter.insertAll();
}
@Override
public int getQuantity() {
return quantity;
return IComparer.COMPARE_NBT | IComparer.COMPARE_DAMAGE;
}
@Override
@@ -495,12 +639,32 @@ public class CraftingTask implements ICraftingTask {
@Override
public int onTrackedInsert(ItemStack stack, int size) {
for (CraftingStep step : steps) {
if (step instanceof CraftingStepProcess) {
size = ((CraftingStepProcess) step).onTrackedItemInserted(stack, size);
for (Processing p : this.processing) {
if (p.getState() != ProcessingState.EXTRACTED_ALL) {
continue;
}
ItemStack content = p.getItemsToReceive().get(stack);
if (content != null) {
int needed = content.getCount();
if (needed > size) {
needed = size;
}
p.getItemsToReceive().remove(stack, needed);
size -= needed;
if (p.getItemsToReceive().isEmpty() && p.getFluidsToReceive().isEmpty()) {
p.setState(ProcessingState.PROCESSED);
}
internalStorage.insert(stack, needed, Action.PERFORM);
if (size == 0) {
break;
return 0;
}
}
}
@@ -510,12 +674,32 @@ public class CraftingTask implements ICraftingTask {
@Override
public int onTrackedInsert(FluidStack stack, int size) {
for (CraftingStep step : steps) {
if (step instanceof CraftingStepProcess) {
size = ((CraftingStepProcess) step).onTrackedFluidInserted(stack, size);
for (Processing p : this.processing) {
if (p.getState() != ProcessingState.EXTRACTED_ALL) {
continue;
}
FluidStack content = p.getFluidsToReceive().get(stack);
if (content != null) {
int needed = content.amount;
if (needed > size) {
needed = size;
}
p.getFluidsToReceive().remove(stack, needed);
size -= needed;
if (p.getItemsToReceive().isEmpty() && p.getFluidsToReceive().isEmpty()) {
p.setState(ProcessingState.PROCESSED);
}
internalFluidStorage.insert(stack, needed, Action.PERFORM);
if (size == 0) {
break;
return 0;
}
}
}
@@ -523,11 +707,16 @@ public class CraftingTask implements ICraftingTask {
return size;
}
@Override
public NBTTagCompound writeToNbt(NBTTagCompound tag) {
return new NBTTagCompound();
}
@Override
public List<ICraftingMonitorElement> getCraftingMonitorElements() {
ICraftingMonitorElementList elements = API.instance().createCraftingMonitorElementList();
if (!missing.isEmpty() || !missingFluids.isEmpty()) {
if (!missing.isEmpty() && !missingFluids.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.missing", 5));
}
@@ -547,81 +736,32 @@ public class CraftingTask implements ICraftingTask {
elements.commit();
}
if (!inserter.getItems().isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 5));
for (CraftingInserterItem item : inserter.getItems()) {
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(item.getStack(), item.getStack().getCount(), 0);
if (item.getStatus() == CraftingInserterItemStatus.FULL) {
element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.network_full", CraftingMonitorElementColor.COLOR_ERROR);
}
elements.add(element);
}
elements.commit();
}
if (steps.stream().anyMatch(s -> s instanceof CraftingStepCraft && !s.isCompleted() && !((CraftingStepCraft) s).getExtractor().getStacks().isEmpty())) {
if (!this.crafting.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_crafting", 5));
for (CraftingStep step : steps) {
if (step instanceof CraftingStepCraft && !step.isCompleted()) {
CraftingExtractor extractor = ((CraftingStepCraft) step).getExtractor();
for (int i = 0; i < extractor.getStacks().size(); ++i) {
// Assume we have an item here.
CraftingExtractorStack stack = extractor.getStacks().get(i);
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(stack.getItem(), stack.getItem().getCount(), 0);
if (stack.getStatus() == CraftingExtractorStatus.MISSING) {
element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.waiting_for_items", CraftingMonitorElementColor.COLOR_INFO);
}
elements.add(element);
}
for (Crafting c : this.crafting) {
for (ItemStack s : c.getToExtract().getStacks()) {
elements.add(new CraftingMonitorElementItemRender(s, s.getCount(), 0));
}
}
elements.commit();
}
if (steps.stream().anyMatch(s -> s instanceof CraftingStepProcess && !s.isCompleted())) {
if (!this.processing.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.processing", 5));
for (CraftingStep step : steps) {
if (step instanceof CraftingStepProcess && !step.isCompleted()) {
CraftingExtractor extractor = ((CraftingStepProcess) step).getExtractor();
for (int i = 0; i < extractor.getStacks().size(); ++i) {
CraftingExtractorStack stack = extractor.getStacks().get(i);
if (stack.getItem() == null) {
continue;
}
elements.add(wrapAccordingToStatus(new CraftingMonitorElementItemRender(stack.getItem(), stack.getItem().getCount(), 0), stack));
}
for (Processing p : this.processing) {
for (ItemStack s : p.getItemsToReceive().getStacks()) {
elements.add(wrapAccordingToState(new CraftingMonitorElementItemRender(s, s.getCount(), 0), p.getState(), false));
}
}
elements.commit();
for (CraftingStep step : steps) {
if (step instanceof CraftingStepProcess && !step.isCompleted()) {
CraftingExtractor extractor = ((CraftingStepProcess) step).getExtractor();
for (int i = 0; i < extractor.getStacks().size(); ++i) {
CraftingExtractorStack stack = extractor.getStacks().get(i);
if (stack.getItem() != null) {
continue;
}
elements.add(wrapAccordingToStatus(new CraftingMonitorElementFluidRender(stack.getFluid(), stack.getFluid().amount, 0), stack));
}
for (Processing p : this.processing) {
for (FluidStack s : p.getFluidsToReceive().getStacks()) {
elements.add(wrapAccordingToState(new CraftingMonitorElementFluidRender(s, s.amount, 0), p.getState(), true));
}
}
@@ -631,15 +771,14 @@ public class CraftingTask implements ICraftingTask {
return elements.getElements();
}
private ICraftingMonitorElement wrapAccordingToStatus(ICraftingMonitorElement element, CraftingExtractorStack stack) {
if (stack.getStatus() == CraftingExtractorStatus.MISSING) {
element = new CraftingMonitorElementColor(element, stack.getFluid() != null ? "gui.refinedstorage:crafting_monitor.waiting_for_fluids" : "gui.refinedstorage:crafting_monitor.waiting_for_items", CraftingMonitorElementColor.COLOR_INFO);
} else if (stack.getStatus() == CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT) {
element = new CraftingMonitorElementColor(element, stack.getFluid() != null ? "gui.refinedstorage:crafting_monitor.machine_does_not_accept_fluid" : "gui.refinedstorage:crafting_monitor.machine_does_not_accept_item", CraftingMonitorElementColor.COLOR_ERROR);
} else if (stack.getStatus() == CraftingExtractorStatus.MACHINE_NONE) {
element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.machine_none", CraftingMonitorElementColor.COLOR_ERROR);
} else if (stack.getStatus() == CraftingExtractorStatus.EXTRACTED) {
element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.inserted_into_machine", CraftingMonitorElementColor.COLOR_SUCCESS);
private ICraftingMonitorElement wrapAccordingToState(ICraftingMonitorElement element, ProcessingState state, boolean fluid) {
switch (state) {
case MACHINE_NONE:
element = new CraftingMonitorElementColor(element, "gui.refinedstorage:crafting_monitor.machine_none", CraftingMonitorElementColor.COLOR_ERROR);
break;
case MACHINE_DOES_NOT_ACCEPT:
element = new CraftingMonitorElementColor(element, fluid ? "gui.refinedstorage:crafting_monitor.machine_does_not_accept_fluid" : "gui.refinedstorage:crafting_monitor.machine_does_not_accept_item", CraftingMonitorElementColor.COLOR_ERROR);
break;
}
return element;
@@ -749,11 +888,6 @@ public class CraftingTask implements ICraftingTask {
return pattern;
}
@Override
public boolean isValid() {
return true;
}
@Override
public long getExecutionStarted() {
return executionStarted;
@@ -768,83 +902,4 @@ public class CraftingTask implements ICraftingTask {
public UUID getId() {
return id;
}
@Override
public NBTTagCompound writeToNbt(NBTTagCompound tag) {
tag.setTag(NBT_REQUESTED, requested.writeToNbt());
tag.setInteger(NBT_QUANTITY, quantity);
tag.setTag(NBT_PATTERN, writePatternToNbt(pattern));
tag.setTag(NBT_INSERTER, inserter.writeToNbt());
tag.setInteger(NBT_TICKS, ticks);
tag.setUniqueId(NBT_ID, id);
tag.setLong(NBT_EXECUTION_STARTED, executionStarted);
NBTTagList steps = new NBTTagList();
for (CraftingStep step : this.steps) {
steps.appendTag(step.writeToNbt());
}
tag.setTag(NBT_STEPS, steps);
NBTTagList missing = new NBTTagList();
for (ItemStack missingItem : this.missing.getStacks()) {
missing.appendTag(StackUtils.serializeStackToNbt(missingItem));
}
tag.setTag(NBT_MISSING, missing);
return tag;
}
private int getTickInterval(int speedUpgrades) {
switch (speedUpgrades) {
case 0:
return 10;
case 1:
return 8;
case 2:
return 6;
case 3:
return 4;
case 4:
return 2;
default:
return 2;
}
}
public static NBTTagCompound writePatternToNbt(ICraftingPattern pattern) {
NBTTagCompound tag = new NBTTagCompound();
tag.setTag(NBT_PATTERN_STACK, pattern.getStack().serializeNBT());
tag.setLong(NBT_PATTERN_CONTAINER_POS, pattern.getContainer().getPosition().toLong());
return tag;
}
public static ICraftingPattern readPatternFromNbt(NBTTagCompound tag, World world) throws CraftingTaskReadException {
BlockPos containerPos = BlockPos.fromLong(tag.getLong(NBT_PATTERN_CONTAINER_POS));
INetworkNode node = API.instance().getNetworkNodeManager(world).getNode(containerPos);
if (node instanceof ICraftingPatternContainer) {
ItemStack stack = new ItemStack(tag.getCompoundTag(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");
}
}
public static int getFlags(ItemStack stack) {
if (stack.getItem().isDamageable()) {
return IComparer.COMPARE_NBT;
}
return IComparer.COMPARE_NBT | IComparer.COMPARE_DAMAGE;
}
}

View File

@@ -0,0 +1,53 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import java.util.List;
class Processing {
private ICraftingPattern pattern;
private IStackList<ItemStack> itemsToReceive;
private IStackList<FluidStack> fluidsToReceive;
private List<ItemStack> itemsToPut;
private List<FluidStack> fluidsToPut;
private ProcessingState state = ProcessingState.READY;
public Processing(ICraftingPattern pattern, IStackList<ItemStack> itemsToReceive, IStackList<FluidStack> fluidsToReceive, List<ItemStack> itemsToPut, List<FluidStack> fluidsToPut) {
this.pattern = pattern;
this.itemsToReceive = itemsToReceive;
this.fluidsToReceive = fluidsToReceive;
this.itemsToPut = itemsToPut;
this.fluidsToPut = fluidsToPut;
}
public ICraftingPattern getPattern() {
return pattern;
}
public IStackList<ItemStack> getItemsToReceive() {
return itemsToReceive;
}
public IStackList<FluidStack> getFluidsToReceive() {
return fluidsToReceive;
}
public List<ItemStack> getItemsToPut() {
return itemsToPut;
}
public List<FluidStack> getFluidsToPut() {
return fluidsToPut;
}
public void setState(ProcessingState state) {
this.state = state;
}
public ProcessingState getState() {
return state;
}
}

View File

@@ -0,0 +1,9 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
enum ProcessingState {
READY,
EXTRACTED_ALL,
MACHINE_NONE,
MACHINE_DOES_NOT_ACCEPT,
PROCESSED
}

View File

@@ -1,179 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public class CraftingExtractor {
private INetwork network;
private List<CraftingExtractorStack> stacks;
private boolean processing;
public CraftingExtractor(INetwork network, List<CraftingExtractorStack> stacks, boolean processing) {
this.network = network;
this.stacks = stacks;
this.processing = processing;
}
public CraftingExtractor(INetwork network, NBTTagList tag, boolean processing) throws CraftingTaskReadException {
this.network = network;
this.processing = processing;
this.stacks = new ArrayList<>();
for (int i = 0; i < tag.tagCount(); ++i) {
this.stacks.add(new CraftingExtractorStack(tag.getCompoundTagAt(i)));
}
}
public List<CraftingExtractorStack> getStacks() {
return stacks;
}
public void updateStatus(@Nullable IItemHandler processingInventory, @Nullable IFluidHandler processingFluidInventory) {
boolean updated = false;
for (CraftingExtractorStack stack : stacks) {
if (stack.getStatus() != CraftingExtractorStatus.EXTRACTED) {
CraftingExtractorStatus previousStatus = stack.getStatus();
if (stack.getItem() != null) {
ItemStack item = stack.getItem();
ItemStack inNetwork = network.extractItem(item, item.getCount(), CraftingTask.getFlags(item), Action.SIMULATE);
if (inNetwork == null || inNetwork.getCount() < item.getCount()) {
stack.setStatus(CraftingExtractorStatus.MISSING);
} else {
stack.setStatus(CraftingExtractorStatus.AVAILABLE);
if (processing) {
if (processingInventory == null) {
stack.setStatus(CraftingExtractorStatus.MACHINE_NONE);
} else if (!ItemHandlerHelper.insertItem(processingInventory, item, true).isEmpty()) {
stack.setStatus(CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT);
}
}
}
} else {
FluidStack fluid = stack.getFluid();
FluidStack inNetwork = network.extractFluid(fluid, fluid.amount, IComparer.COMPARE_NBT, Action.SIMULATE);
if (inNetwork == null || inNetwork.amount < fluid.amount) {
stack.setStatus(CraftingExtractorStatus.MISSING);
} else {
stack.setStatus(CraftingExtractorStatus.AVAILABLE);
if (processingFluidInventory == null) {
stack.setStatus(CraftingExtractorStatus.MACHINE_NONE);
} else if (processingFluidInventory.fill(fluid, false) != fluid.amount) {
stack.setStatus(CraftingExtractorStatus.MACHINE_DOES_NOT_ACCEPT);
}
}
}
if (previousStatus != stack.getStatus()) {
updated = true;
}
}
}
if (updated) {
network.getCraftingManager().onTaskChanged();
}
}
public boolean isAllAvailable() {
return !stacks.isEmpty() && stacks.stream().allMatch(s -> s.getStatus() == CraftingExtractorStatus.AVAILABLE || s.getStatus() == CraftingExtractorStatus.EXTRACTED);
}
public boolean isAllExtracted() {
return !stacks.isEmpty() && stacks.stream().allMatch(s -> s.getStatus() == CraftingExtractorStatus.EXTRACTED);
}
public void extractOne(@Nullable IItemHandler processingInventory, @Nullable IFluidHandler processingFluidInventory) {
boolean changed = false;
for (CraftingExtractorStack stack : stacks) {
if (stack.getStatus() == CraftingExtractorStatus.AVAILABLE) {
if (stack.getItem() != null) {
ItemStack item = stack.getItem();
ItemStack extracted = network.extractItem(item, item.getCount(), CraftingTask.getFlags(item), Action.PERFORM);
if (extracted == null) {
throw new IllegalStateException("Did not extract anything while available");
}
if (processing) {
if (processingInventory == null) {
throw new IllegalStateException("Processing inventory is null");
}
ItemStack remainder = ItemHandlerHelper.insertItem(processingInventory, extracted, false);
if (!remainder.isEmpty()) {
throw new IllegalStateException("The processing inventory gave back a remainder while it previously stated it could handle all");
}
}
stack.setStatus(CraftingExtractorStatus.EXTRACTED);
changed = true;
} else {
FluidStack fluid = stack.getFluid();
FluidStack extracted = network.extractFluid(fluid, fluid.amount, IComparer.COMPARE_NBT, Action.PERFORM);
if (extracted == null) {
throw new IllegalStateException("Did not extract any fluids while available");
}
if (processingFluidInventory == null) {
throw new IllegalStateException("Processing fluid inventory is null");
}
int filled = processingFluidInventory.fill(fluid, true);
if (filled != fluid.amount) {
throw new IllegalStateException("The processing fluid inventory gave back a remainder while it previously stated it could handle all");
}
stack.setStatus(CraftingExtractorStatus.EXTRACTED);
changed = true;
}
// For processing patterns we want to insert all items at once to avoid conflicts with other crafting steps.
if (!processing) {
return;
} else {
updateStatus(processingInventory, processingFluidInventory);
}
}
}
if (changed) {
network.getCraftingManager().onTaskChanged();
}
}
public NBTTagList writeToNbt() {
NBTTagList list = new NBTTagList();
for (CraftingExtractorStack stack : stacks) {
list.appendTag(stack.writeToNbt());
}
return list;
}
}

View File

@@ -1,79 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nullable;
public class CraftingExtractorStack {
private static final String NBT_FLUID = "Fluid";
private static final String NBT_STACK = "Stack";
private static final String NBT_STATUS = "Status";
private ItemStack item;
private FluidStack fluid;
private CraftingExtractorStatus status = CraftingExtractorStatus.MISSING;
public CraftingExtractorStack(ItemStack item) {
this.item = item;
}
public CraftingExtractorStack(FluidStack fluid) {
this.fluid = fluid;
}
public CraftingExtractorStack(NBTTagCompound tag) throws CraftingTaskReadException {
if (!tag.getBoolean(NBT_FLUID)) {
item = StackUtils.deserializeStackFromNbt(tag.getCompoundTag(NBT_STACK));
if (item.isEmpty()) {
throw new CraftingTaskReadException("Extractor stack is empty");
}
} else {
fluid = FluidStack.loadFluidStackFromNBT(tag.getCompoundTag(NBT_STACK));
if (fluid == null) {
throw new CraftingTaskReadException("Extractor fluid stack is empty");
}
}
status = CraftingExtractorStatus.values()[tag.getInteger(NBT_STATUS)];
}
@Nullable
public ItemStack getItem() {
return item;
}
@Nullable
public FluidStack getFluid() {
return fluid;
}
public NBTTagCompound writeToNbt() {
NBTTagCompound tag = new NBTTagCompound();
tag.setBoolean(NBT_FLUID, fluid != null);
if (fluid != null) {
tag.setTag(NBT_STACK, fluid.writeToNBT(new NBTTagCompound()));
} else {
tag.setTag(NBT_STACK, StackUtils.serializeStackToNbt(item));
}
tag.setInteger(NBT_STATUS, status.ordinal());
return tag;
}
public CraftingExtractorStatus getStatus() {
return status;
}
public void setStatus(CraftingExtractorStatus status) {
this.status = status;
}
}

View File

@@ -1,9 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor;
public enum CraftingExtractorStatus {
AVAILABLE,
MISSING,
EXTRACTED,
MACHINE_NONE,
MACHINE_DOES_NOT_ACCEPT
}

View File

@@ -1,101 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
public class CraftingInserter {
private static final String NBT_ITEM = "Item";
private static final String NBT_STATUS = "Status";
private INetwork network;
private Deque<CraftingInserterItem> items = new ArrayDeque<>();
public CraftingInserter(INetwork network) {
this.network = network;
}
public CraftingInserter(INetwork network, NBTTagList list) throws CraftingTaskReadException {
this(network);
for (int i = 0; i < list.tagCount(); ++i) {
NBTTagCompound itemTag = list.getCompoundTagAt(i);
ItemStack stack = StackUtils.deserializeStackFromNbt(itemTag.getCompoundTag(NBT_ITEM));
if (stack.isEmpty()) {
throw new CraftingTaskReadException("Inserter has empty stack");
}
CraftingInserterItemStatus status = CraftingInserterItemStatus.values()[itemTag.getInteger(NBT_STATUS)];
items.push(new CraftingInserterItem(stack, status));
}
}
public void insert(ItemStack stack) {
items.addLast(new CraftingInserterItem(stack, CraftingInserterItemStatus.WAITING));
network.getCraftingManager().onTaskChanged();
}
public void insertOne() {
CraftingInserterItem item = items.peekFirst();
if (item != null) {
CraftingInserterItemStatus currentStatus = item.getStatus();
if (network.insertItem(item.getStack(), item.getStack().getCount(), Action.SIMULATE) == null) {
ItemStack inserted = network.insertItem(item.getStack(), item.getStack().getCount(), Action.PERFORM);
if (inserted != null) {
throw new IllegalStateException("Could not insert item");
}
items.pop();
network.getCraftingManager().onTaskChanged();
} else if (currentStatus != CraftingInserterItemStatus.FULL) {
item.setStatus(CraftingInserterItemStatus.FULL);
network.getCraftingManager().onTaskChanged();
}
}
}
public void insertAll() {
while (!items.isEmpty()) {
CraftingInserterItem item = items.pop();
network.insertItem(item.getStack(), item.getStack().getCount(), Action.PERFORM);
}
network.getCraftingManager().onTaskChanged();
}
public Collection<CraftingInserterItem> getItems() {
return items;
}
public NBTTagList writeToNbt() {
NBTTagList list = new NBTTagList();
for (CraftingInserterItem item : items) {
NBTTagCompound tag = new NBTTagCompound();
tag.setTag(NBT_ITEM, StackUtils.serializeStackToNbt(item.getStack()));
tag.setInteger(NBT_STATUS, item.getStatus().ordinal());
list.appendTag(tag);
}
return list;
}
}

View File

@@ -1,25 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter;
import net.minecraft.item.ItemStack;
public class CraftingInserterItem {
private ItemStack stack;
private CraftingInserterItemStatus status;
public CraftingInserterItem(ItemStack stack, CraftingInserterItemStatus status) {
this.stack = stack;
this.status = status;
}
public ItemStack getStack() {
return stack;
}
public CraftingInserterItemStatus getStatus() {
return status;
}
public void setStatus(CraftingInserterItemStatus status) {
this.status = status;
}
}

View File

@@ -1,6 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter;
public enum CraftingInserterItemStatus {
WAITING,
FULL
}

View File

@@ -1,74 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserter;
import net.minecraft.nbt.NBTTagCompound;
public abstract class CraftingStep {
private static final String NBT_PATTERN = "Pattern";
private static final String NBT_COMPLETED = "Completed";
private static final String NBT_TYPE = "Type";
protected ICraftingPattern pattern;
private boolean completed;
public CraftingStep(ICraftingPattern pattern) {
this.pattern = pattern;
}
public abstract boolean canExecute();
public abstract boolean execute();
public ICraftingPattern getPattern() {
return pattern;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted() {
this.completed = true;
}
public abstract String getType();
public NBTTagCompound writeToNbt() {
NBTTagCompound tag = new NBTTagCompound();
tag.setTag(NBT_PATTERN, CraftingTask.writePatternToNbt(pattern));
tag.setBoolean(NBT_COMPLETED, completed);
tag.setString(NBT_TYPE, getType());
return tag;
}
public static CraftingStep readFromNbt(INetwork network, CraftingInserter inserter, NBTTagCompound tag) throws CraftingTaskReadException {
ICraftingPattern pattern = CraftingTask.readPatternFromNbt(tag.getCompoundTag(NBT_PATTERN), network.world());
boolean completed = tag.getBoolean(NBT_COMPLETED);
String type = tag.getString(NBT_TYPE);
CraftingStep step;
switch (type) {
case CraftingStepCraft.TYPE:
step = new CraftingStepCraft(pattern, inserter, network, tag);
break;
case CraftingStepProcess.TYPE:
step = new CraftingStepProcess(pattern, network, tag);
break;
default:
throw new CraftingTaskReadException("Unknown crafting step type");
}
if (completed) {
step.setCompleted();
}
return step;
}
}

View File

@@ -1,109 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractor;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStack;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.inserter.CraftingInserter;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.util.Constants;
import java.util.List;
import java.util.stream.Collectors;
public class CraftingStepCraft extends CraftingStep {
public static final String TYPE = "craft";
private static final String NBT_EXTRACTOR = "Extractor";
private static final String NBT_TOOK = "Took";
private CraftingInserter inserter;
private CraftingExtractor extractor;
private NonNullList<ItemStack> took;
public CraftingStepCraft(ICraftingPattern pattern, CraftingInserter inserter, INetwork network, List<ItemStack> toExtract, NonNullList<ItemStack> took) {
super(pattern);
if (pattern.isProcessing()) {
throw new IllegalArgumentException("Cannot pass processing pattern to craft handler");
}
this.inserter = inserter;
this.extractor = new CraftingExtractor(network, toExtract.stream().map(CraftingExtractorStack::new).collect(Collectors.toList()), false);
this.took = took;
}
public CraftingStepCraft(ICraftingPattern pattern, CraftingInserter inserter, INetwork network, NBTTagCompound tag) throws CraftingTaskReadException {
super(pattern);
if (pattern.isProcessing()) {
throw new IllegalArgumentException("Cannot pass processing pattern to craft handler");
}
this.inserter = inserter;
this.extractor = new CraftingExtractor(network, tag.getTagList(NBT_EXTRACTOR, Constants.NBT.TAG_COMPOUND), false);
this.took = NonNullList.create();
NBTTagList tookList = tag.getTagList(NBT_TOOK, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < tookList.tagCount(); ++i) {
took.add(StackUtils.deserializeStackFromNbt(tookList.getCompoundTagAt(i))); // Took stack can be empty
}
}
@Override
public boolean canExecute() {
extractor.updateStatus(null, null);
return extractor.isAllAvailable();
}
@Override
public boolean execute() {
extractor.extractOne(null, null);
boolean allExtracted = extractor.isAllExtracted();
if (allExtracted) {
inserter.insert(pattern.getOutput(took));
for (ItemStack byproduct : pattern.getByproducts(took)) {
inserter.insert(byproduct);
}
}
return allExtracted;
}
@Override
public String getType() {
return TYPE;
}
@Override
public NBTTagCompound writeToNbt() {
NBTTagCompound tag = super.writeToNbt();
tag.setTag(NBT_EXTRACTOR, extractor.writeToNbt());
NBTTagList took = new NBTTagList();
for (ItemStack stack : this.took) {
took.appendTag(StackUtils.serializeStackToNbt(stack));
}
tag.setTag(NBT_TOOK, took);
return tag;
}
public CraftingExtractor getExtractor() {
return extractor;
}
}

View File

@@ -1,175 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractor;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.extractor.CraftingExtractorStack;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import java.util.List;
public class CraftingStepProcess extends CraftingStep {
public static final String TYPE = "process";
private static final String NBT_EXTRACTOR = "Extractor";
private static final String NBT_TO_RECEIVE = "ToReceive";
private static final String NBT_TO_RECEIVE_FLUIDS = "ToReceiveFluids";
private CraftingExtractor extractor;
private IStackList<ItemStack> itemsToReceive = API.instance().createItemStackList();
private IStackList<FluidStack> fluidsToReceive = API.instance().createFluidStackList();
public CraftingStepProcess(ICraftingPattern pattern, INetwork network, List<ItemStack> toExtract, List<FluidStack> fluidsToExtract) {
super(pattern);
if (!pattern.isProcessing()) {
throw new IllegalArgumentException("Cannot pass non-processing pattern to processing handler");
}
List<CraftingExtractorStack> stacks = new ArrayList<>();
for (ItemStack item : toExtract) {
stacks.add(new CraftingExtractorStack(item));
}
for (FluidStack fluid : fluidsToExtract) {
stacks.add(new CraftingExtractorStack(fluid));
}
this.extractor = new CraftingExtractor(network, stacks, true);
for (ItemStack output : pattern.getOutputs()) {
this.itemsToReceive.add(output);
}
for (FluidStack output : pattern.getFluidOutputs()) {
this.fluidsToReceive.add(output);
}
}
public CraftingStepProcess(ICraftingPattern pattern, INetwork network, NBTTagCompound tag) throws CraftingTaskReadException {
super(pattern);
if (!pattern.isProcessing()) {
throw new IllegalArgumentException("Cannot pass non-processing pattern to processing handler");
}
this.extractor = new CraftingExtractor(network, tag.getTagList(NBT_EXTRACTOR, Constants.NBT.TAG_COMPOUND), true);
NBTTagList toReceiveList = tag.getTagList(NBT_TO_RECEIVE, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < toReceiveList.tagCount(); ++i) {
ItemStack toReceive = StackUtils.deserializeStackFromNbt(toReceiveList.getCompoundTagAt(i));
if (toReceive.isEmpty()) {
throw new CraftingTaskReadException("Item to receive is empty");
}
this.itemsToReceive.add(toReceive);
}
NBTTagList toReceiveFluidsList = tag.getTagList(NBT_TO_RECEIVE_FLUIDS, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < toReceiveFluidsList.tagCount(); ++i) {
FluidStack toReceive = FluidStack.loadFluidStackFromNBT(toReceiveFluidsList.getCompoundTagAt(i));
if (toReceive == null) {
throw new CraftingTaskReadException("Fluid to receive is null");
}
this.fluidsToReceive.add(toReceive);
}
}
@Override
public boolean canExecute() {
extractor.updateStatus(pattern.getContainer().getConnectedInventory(), pattern.getContainer().getConnectedFluidInventory());
return extractor.isAllAvailable();
}
public int onTrackedItemInserted(ItemStack stack, int size) {
if (!extractor.isAllExtracted()) {
return size;
}
ItemStack inList = itemsToReceive.get(stack);
if (inList == null) {
return size;
}
int toExtract = Math.min(size, inList.getCount());
itemsToReceive.remove(stack, toExtract);
return size - toExtract;
}
public int onTrackedFluidInserted(FluidStack stack, int size) {
if (!extractor.isAllExtracted()) {
return size;
}
FluidStack inList = fluidsToReceive.get(stack);
if (inList == null) {
return size;
}
int toExtract = Math.min(size, inList.amount);
fluidsToReceive.remove(stack, toExtract);
return size - toExtract;
}
@Override
public boolean execute() {
if (!extractor.isAllExtracted()) {
extractor.extractOne(pattern.getContainer().getConnectedInventory(), pattern.getContainer().getConnectedFluidInventory());
}
return extractor.isAllExtracted() && itemsToReceive.isEmpty() && fluidsToReceive.isEmpty();
}
@Override
public String getType() {
return TYPE;
}
@Override
public NBTTagCompound writeToNbt() {
NBTTagCompound tag = super.writeToNbt();
tag.setTag(NBT_EXTRACTOR, extractor.writeToNbt());
NBTTagList toReceive = new NBTTagList();
for (ItemStack toReceiveStack : itemsToReceive.getStacks()) {
toReceive.appendTag(StackUtils.serializeStackToNbt(toReceiveStack));
}
tag.setTag(NBT_TO_RECEIVE, toReceive);
NBTTagList toReceiveFluids = new NBTTagList();
for (FluidStack toReceiveStack : fluidsToReceive.getStacks()) {
toReceiveFluids.appendTag(toReceiveStack.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_TO_RECEIVE_FLUIDS, toReceiveFluids);
return tag;
}
public CraftingExtractor getExtractor() {
return extractor;
}
}