Autocrafting engine v6 (#2406)

* change CraftingPreviewScreen from full resourcelocation to just the version

* added v6 engine for autocrafting

* fix craftingpreview count for requested items

* fix crafting monitor not displaying errors
and displaying empty crafts in some cases

* fix fluid crafting not working for multiple iterations

* Revert "change CraftingPreviewScreen from full resourcelocation to just the version"

This reverts commit 7dd90c47

This should really have been it's own PR/issue

* fix crash with craftingMonitor
This commit is contained in:
Darkere
2020-04-25 22:35:44 +02:00
committed by GitHub
parent 552d89f5a8
commit 6724969c1b
21 changed files with 1948 additions and 17 deletions

View File

@@ -10,10 +10,7 @@ import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* The crafting manager handles the storing, updating, adding and deleting of crafting tasks in a network.
@@ -171,4 +168,11 @@ public interface ICraftingManager {
* Calls all {@link ICraftingMonitorListener}s.
*/
void onTaskChanged();
/**
* @param pattern to look for
* @return a LinkedHashSet with all container that have this pattern
*/
Set<ICraftingPatternContainer> getAllContainer(ICraftingPattern pattern);
}

View File

@@ -1,6 +1,7 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor;
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
@@ -20,6 +21,14 @@ public interface ICraftingMonitorElement {
@OnlyIn(Dist.CLIENT)
void draw(int x, int y, IElementDrawers drawers);
/**
* Returns the id for the base of this element, used for sorting in the {@link CraftingMonitorElementList}
*
* @return the id
*/
ResourceLocation getBaseId();
/**
* Returns the id of this element, used for serialization and deserialization over the network.
*
@@ -49,6 +58,10 @@ public interface ICraftingMonitorElement {
* @return true if merge was successful, false otherwise
*/
boolean merge(ICraftingMonitorElement element);
/**
* @return the hash code for the underlying base item/fluid element
*/
int baseElementHashCode();
/**
* @return the hash code for the underlying element

View File

@@ -9,6 +9,21 @@ public interface ICraftingMonitorElementList {
* @param element the {@link ICraftingMonitorElement}
*/
void directAdd(ICraftingMonitorElement element);
/**
* Add a element to the Storage list, similar elements will be merged.
* A {@link #commit()} will stop any following adds to be merged with previous ones.
*
* @param element the {@link ICraftingMonitorElement}
*/
void addStorage(ICraftingMonitorElement element);
/**
* Add a element to the Processing or Crafting list, similar elements will be merged.
* 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
*/
void add(ICraftingMonitorElement element, boolean isProcessing);
/**
* Add a element to the list, similar elements will be merged.

View File

@@ -42,11 +42,6 @@ public interface ICraftingTask {
*/
int getQuantity();
/**
* @return the amount that this task gives back
*/
int getQuantityPerCraft();
/**
* @return the completion percentage
*/

View File

@@ -40,6 +40,7 @@ public class CraftingManager implements ICraftingManager {
private INetwork network;
private Map<ITextComponent, List<IItemHandlerModifiable>> containerInventories = new LinkedHashMap<>();
private Map<ICraftingPattern, Set<ICraftingPatternContainer>> patternToContainer = new HashMap<>();
private List<ICraftingPattern> patterns = new ArrayList<>();
@@ -367,6 +368,7 @@ public class CraftingManager implements ICraftingManager {
this.patterns.clear();
this.containerInventories.clear();
this.patternToContainer.clear();
List<ICraftingPatternContainer> containers = new ArrayList<>();
@@ -389,6 +391,13 @@ public class CraftingManager implements ICraftingManager {
for (FluidStack output : pattern.getFluidOutputs()) {
network.getFluidStorageCache().getCraftablesList().add(output);
}
Set<ICraftingPatternContainer> list = this.patternToContainer.get(pattern);
if (list == null) {
list = new LinkedHashSet<>();
}
list.add(container);
this.patternToContainer.put(pattern, list);
}
IItemHandlerModifiable handler = container.getPatternInventory();
@@ -401,6 +410,11 @@ public class CraftingManager implements ICraftingManager {
this.network.getFluidStorageCache().reAttachListeners();
}
@Override
public Set<ICraftingPatternContainer> getAllContainer(ICraftingPattern pattern) {
return patternToContainer.getOrDefault(pattern, new LinkedHashSet<>());
}
@Nullable
@Override
public ICraftingPattern getPattern(ItemStack pattern) {

View File

@@ -1,10 +1,10 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTaskFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.inventory.container.Container;
@@ -165,7 +165,8 @@ public class CraftingPattern implements ICraftingPattern {
@Override
public ResourceLocation getCraftingTaskFactoryId() {
return CraftingTaskFactory.ID;
return RS.SERVER_CONFIG.getAutocrafting().useExperimentalAutocrafting() ? com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory.ID :
com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTaskFactory.ID;
}
@Override
@@ -272,6 +273,19 @@ 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) {

View File

@@ -9,12 +9,78 @@ import java.util.*;
public class CraftingMonitorElementList implements ICraftingMonitorElementList {
private List<ICraftingMonitorElement> elements = new LinkedList<>();
private Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentLists = new LinkedHashMap<>();
private Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentCraftingLists = new LinkedHashMap<>();
private Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentProcessingLists = new LinkedHashMap<>();
private Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentStorageLists = new LinkedHashMap<>();
@Override
public void directAdd(ICraftingMonitorElement element) {
elements.add(element);
}
@Override
public void addStorage(ICraftingMonitorElement element) {
Map<Integer, ICraftingMonitorElement> craftingElements = currentCraftingLists.get(element.getBaseId());
Map<Integer, ICraftingMonitorElement> processingElements = currentProcessingLists.get(element.getBaseId());
Map<Integer, ICraftingMonitorElement> storedElements = currentStorageLists.get(element.getBaseId());
boolean merged = false;
if (craftingElements != null) {
ICraftingMonitorElement existingElement = craftingElements.get(element.baseElementHashCode());
if (existingElement != null) {
if(existingElement instanceof ErrorCraftingMonitorElement){
((ErrorCraftingMonitorElement)existingElement).mergeBases(element);
} else {
existingElement.merge(element);
}
merged = true;
}
}
if (processingElements != null) {
ICraftingMonitorElement existingElement = processingElements.get(element.baseElementHashCode());
if (existingElement != null) {
if(existingElement instanceof ErrorCraftingMonitorElement){
((ErrorCraftingMonitorElement)existingElement).mergeBases(element);
} else {
existingElement.merge(element);
}
merged = true;
}
}
if (!merged) {
if (storedElements == null) {
storedElements = new HashMap<>();
}
storedElements.put(element.baseElementHashCode(), element);
currentStorageLists.put(element.getBaseId(), storedElements);
}
}
@Override
public void add(ICraftingMonitorElement element, boolean isProcessing) {
Map<Integer, ICraftingMonitorElement> currentElements = isProcessing ? currentProcessingLists.get(element.getBaseId()) : currentCraftingLists.get(element.getBaseId());
if (currentElements == null) {
currentElements = new LinkedHashMap<>();
}
ICraftingMonitorElement existingElement = currentElements.get(element.baseElementHashCode());
if (existingElement == null) {
existingElement = element;
} else {
existingElement.merge(element);
}
currentElements.put(existingElement.baseElementHashCode(), existingElement);
if (isProcessing) {
currentProcessingLists.put(existingElement.getBaseId(), currentElements);
} else {
currentCraftingLists.put(existingElement.getBaseId(), currentElements);
}
}
@Override
public void add(ICraftingMonitorElement element) {
Map<Integer, ICraftingMonitorElement> currentElements = currentLists.get(element.getId());
@@ -39,11 +105,17 @@ public class CraftingMonitorElementList implements ICraftingMonitorElementList {
public void commit() {
currentLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
currentLists.clear();
currentCraftingLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
currentCraftingLists.clear();
currentProcessingLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
currentProcessingLists.clear();
currentStorageLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
currentStorageLists.clear();
}
@Override
public List<ICraftingMonitorElement> getElements() {
if (!currentLists.isEmpty()) {
if (!currentLists.isEmpty()||!currentCraftingLists.isEmpty() || !currentProcessingLists.isEmpty() || !currentStorageLists.isEmpty()) {
commit();
}

View File

@@ -41,6 +41,11 @@ public class ErrorCraftingMonitorElement implements ICraftingMonitorElement {
return ID;
}
@Override
public ResourceLocation getBaseId() {
return base.getId();
}
@Override
public void write(PacketBuffer buf) {
buf.writeResourceLocation(base.getId());
@@ -64,8 +69,17 @@ public class ErrorCraftingMonitorElement implements ICraftingMonitorElement {
return elementHashCode() == element.elementHashCode() && base.merge(((ErrorCraftingMonitorElement) element).base);
}
@Override
public int baseElementHashCode() {
return base.elementHashCode();
}
@Override
public int elementHashCode() {
return base.elementHashCode() ^ message.hashCode();
}
public void mergeBases(ICraftingMonitorElement element) {
this.base.merge(element);
}
}

View File

@@ -94,6 +94,11 @@ public class FluidCraftingMonitorElement implements ICraftingMonitorElement {
RenderSystem.popMatrix();
}
@Override
public ResourceLocation getBaseId() {
return ID;
}
@Override
public ResourceLocation getId() {
return ID;
@@ -141,6 +146,11 @@ public class FluidCraftingMonitorElement implements ICraftingMonitorElement {
return false;
}
@Override
public int baseElementHashCode() {
return elementHashCode();
}
@Override
public int elementHashCode() {
return API.instance().getFluidStackHashCode(stack);

View File

@@ -95,6 +95,11 @@ public class ItemCraftingMonitorElement implements ICraftingMonitorElement {
RenderSystem.popMatrix();
}
@Override
public ResourceLocation getBaseId() {
return ID;
}
@Override
public ResourceLocation getId() {
return ID;
@@ -142,6 +147,11 @@ public class ItemCraftingMonitorElement implements ICraftingMonitorElement {
return false;
}
@Override
public int baseElementHashCode() {
return elementHashCode();
}
@Override
public int elementHashCode() {
return API.instance().getItemStackHashCode(stack);

View File

@@ -938,7 +938,7 @@ public class CraftingTask implements ICraftingTask {
return quantity;
}
@Override
public int getQuantityPerCraft() {
int qty = 0;

View File

@@ -18,11 +18,11 @@ public class CraftingTaskFactory implements ICraftingTaskFactory {
@Nonnull
@Override
public ICraftingTask create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {
return new CraftingTask(network, requested, quantity, pattern);
return new com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTask(network, requested, quantity, pattern);
}
@Override
public ICraftingTask createFromNbt(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
return new CraftingTask(network, tag);
return new com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTask(network, tag);
}
}

View File

@@ -0,0 +1,141 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6;
import com.google.common.primitives.Ints;
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.api.util.StackListEntry;
import com.raoulvdberge.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 boolean root;
protected int quantity;
private ICraftingPattern pattern;
private Map<Integer, IStackList<ItemStack>> itemsToUse = new LinkedHashMap<>();
private 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 com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6.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;
}
}

View File

@@ -0,0 +1,50 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6;
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.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 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;
}
}

View File

@@ -0,0 +1,32 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
import javax.annotation.Nullable;
public class CraftingTaskError implements ICraftingTaskError {
private 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;
}
}

View File

@@ -0,0 +1,28 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskReadException;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingRequestInfo;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskFactory;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
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 com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTask(network, requested, quantity, pattern);
}
@Override
public ICraftingTask createFromNbt(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
return new com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTask(network, tag);
}
}

View File

@@ -0,0 +1,188 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6;
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.api.util.StackListEntry;
import com.raoulvdberge.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));
}
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;
}
}

View File

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

View File

@@ -914,15 +914,19 @@ public class ServerConfig {
public class Autocrafting {
private final ForgeConfigSpec.IntValue calculationTimeoutMs;
private final ForgeConfigSpec.BooleanValue useExperimental;
public Autocrafting() {
builder.push("autocrafting");
useExperimental = builder.comment("Use the experimental autocrafting engine").define("useExperimental", true);
calculationTimeoutMs = builder.comment("The autocrafting calculation timeout in milliseconds, crafting tasks taking longer than this to calculate are cancelled to avoid server strain").defineInRange("calculationTimeoutMs", 5000, 5000, Integer.MAX_VALUE);
builder.pop();
}
public boolean useExperimentalAutocrafting(){
return useExperimental.get();
}
public int getCalculationTimeoutMs() {
return calculationTimeoutMs.get();
}

View File

@@ -130,7 +130,8 @@ public class CommonSetup {
API.instance().getCraftingMonitorElementRegistry().add(FluidCraftingMonitorElement.ID, FluidCraftingMonitorElement::read);
API.instance().getCraftingMonitorElementRegistry().add(ErrorCraftingMonitorElement.ID, ErrorCraftingMonitorElement::read);
API.instance().getCraftingTaskRegistry().add(CraftingTaskFactory.ID, new CraftingTaskFactory());
API.instance().getCraftingTaskRegistry().add( com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTaskFactory.ID, new com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTaskFactory());
API.instance().getCraftingTaskRegistry().add( com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory.ID, new com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory());
LootFunctionManager.registerFunction(new StorageBlockLootFunctionSerializer());
LootFunctionManager.registerFunction(new PortableGridBlockLootFunctionSerializer());