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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -42,11 +42,6 @@ public interface ICraftingTask {
|
||||
*/
|
||||
int getQuantity();
|
||||
|
||||
/**
|
||||
* @return the amount that this task gives back
|
||||
*/
|
||||
int getQuantityPerCraft();
|
||||
|
||||
/**
|
||||
* @return the completion percentage
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -938,7 +938,7 @@ public class CraftingTask implements ICraftingTask {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public int getQuantityPerCraft() {
|
||||
int qty = 0;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v6;
|
||||
|
||||
enum ProcessingState {
|
||||
READY,
|
||||
MACHINE_NONE,
|
||||
MACHINE_DOES_NOT_ACCEPT,
|
||||
PROCESSED,
|
||||
LOCKED
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user