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.Nonnull;
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.UUID;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * The crafting manager handles the storing, updating, adding and deleting of crafting tasks in a network.
 | 
					 * 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.
 | 
					     * Calls all {@link ICraftingMonitorListener}s.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void onTaskChanged();
 | 
					    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;
 | 
					package com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
 | 
					import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
 | 
				
			||||||
 | 
					import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList;
 | 
				
			||||||
import net.minecraft.network.PacketBuffer;
 | 
					import net.minecraft.network.PacketBuffer;
 | 
				
			||||||
import net.minecraft.util.ResourceLocation;
 | 
					import net.minecraft.util.ResourceLocation;
 | 
				
			||||||
import net.minecraftforge.api.distmarker.Dist;
 | 
					import net.minecraftforge.api.distmarker.Dist;
 | 
				
			||||||
@@ -20,6 +21,14 @@ public interface ICraftingMonitorElement {
 | 
				
			|||||||
    @OnlyIn(Dist.CLIENT)
 | 
					    @OnlyIn(Dist.CLIENT)
 | 
				
			||||||
    void draw(int x, int y, IElementDrawers drawers);
 | 
					    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.
 | 
					     * 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
 | 
					     * @return true if merge was successful, false otherwise
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    boolean merge(ICraftingMonitorElement element);
 | 
					    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
 | 
					     * @return the hash code for the underlying element
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,21 @@ public interface ICraftingMonitorElementList {
 | 
				
			|||||||
     * @param element the {@link ICraftingMonitorElement}
 | 
					     * @param element the {@link ICraftingMonitorElement}
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    void directAdd(ICraftingMonitorElement element);
 | 
					    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.
 | 
					     * Add a element to the list, similar elements will be merged.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,11 +42,6 @@ public interface ICraftingTask {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    int getQuantity();
 | 
					    int getQuantity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return the amount that this task gives back
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    int getQuantityPerCraft();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @return the completion percentage
 | 
					     * @return the completion percentage
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,7 @@ public class CraftingManager implements ICraftingManager {
 | 
				
			|||||||
    private INetwork network;
 | 
					    private INetwork network;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Map<ITextComponent, List<IItemHandlerModifiable>> containerInventories = new LinkedHashMap<>();
 | 
					    private Map<ITextComponent, List<IItemHandlerModifiable>> containerInventories = new LinkedHashMap<>();
 | 
				
			||||||
 | 
					    private Map<ICraftingPattern, Set<ICraftingPatternContainer>> patternToContainer = new HashMap<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private List<ICraftingPattern> patterns = new ArrayList<>();
 | 
					    private List<ICraftingPattern> patterns = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -367,6 +368,7 @@ public class CraftingManager implements ICraftingManager {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        this.patterns.clear();
 | 
					        this.patterns.clear();
 | 
				
			||||||
        this.containerInventories.clear();
 | 
					        this.containerInventories.clear();
 | 
				
			||||||
 | 
					        this.patternToContainer.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        List<ICraftingPatternContainer> containers = new ArrayList<>();
 | 
					        List<ICraftingPatternContainer> containers = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -389,6 +391,13 @@ public class CraftingManager implements ICraftingManager {
 | 
				
			|||||||
                for (FluidStack output : pattern.getFluidOutputs()) {
 | 
					                for (FluidStack output : pattern.getFluidOutputs()) {
 | 
				
			||||||
                    network.getFluidStorageCache().getCraftablesList().add(output);
 | 
					                    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();
 | 
					            IItemHandlerModifiable handler = container.getPatternInventory();
 | 
				
			||||||
@@ -401,6 +410,11 @@ public class CraftingManager implements ICraftingManager {
 | 
				
			|||||||
        this.network.getFluidStorageCache().reAttachListeners();
 | 
					        this.network.getFluidStorageCache().reAttachListeners();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Set<ICraftingPatternContainer> getAllContainer(ICraftingPattern pattern) {
 | 
				
			||||||
 | 
					        return patternToContainer.getOrDefault(pattern, new LinkedHashSet<>());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Nullable
 | 
					    @Nullable
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public ICraftingPattern getPattern(ItemStack pattern) {
 | 
					    public ICraftingPattern getPattern(ItemStack pattern) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
 | 
					package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.raoulvdberge.refinedstorage.RS;
 | 
				
			||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
 | 
					import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
 | 
				
			||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
 | 
					import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
 | 
				
			||||||
import com.raoulvdberge.refinedstorage.api.util.IComparer;
 | 
					import com.raoulvdberge.refinedstorage.api.util.IComparer;
 | 
				
			||||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
 | 
					import com.raoulvdberge.refinedstorage.apiimpl.API;
 | 
				
			||||||
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.v5.CraftingTaskFactory;
 | 
					 | 
				
			||||||
import net.minecraft.entity.player.PlayerEntity;
 | 
					import net.minecraft.entity.player.PlayerEntity;
 | 
				
			||||||
import net.minecraft.inventory.CraftingInventory;
 | 
					import net.minecraft.inventory.CraftingInventory;
 | 
				
			||||||
import net.minecraft.inventory.container.Container;
 | 
					import net.minecraft.inventory.container.Container;
 | 
				
			||||||
@@ -165,7 +165,8 @@ public class CraftingPattern implements ICraftingPattern {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public ResourceLocation getCraftingTaskFactoryId() {
 | 
					    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
 | 
					    @Override
 | 
				
			||||||
@@ -272,6 +273,19 @@ public class CraftingPattern implements ICraftingPattern {
 | 
				
			|||||||
        return result;
 | 
					        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 static class DummyCraftingInventory extends CraftingInventory {
 | 
				
			||||||
        public DummyCraftingInventory() {
 | 
					        public DummyCraftingInventory() {
 | 
				
			||||||
            super(new Container(null, 0) {
 | 
					            super(new Container(null, 0) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,12 +9,78 @@ import java.util.*;
 | 
				
			|||||||
public class CraftingMonitorElementList implements ICraftingMonitorElementList {
 | 
					public class CraftingMonitorElementList implements ICraftingMonitorElementList {
 | 
				
			||||||
    private List<ICraftingMonitorElement> elements = new LinkedList<>();
 | 
					    private List<ICraftingMonitorElement> elements = new LinkedList<>();
 | 
				
			||||||
    private Map<ResourceLocation, Map<Integer, ICraftingMonitorElement>> currentLists = new LinkedHashMap<>();
 | 
					    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
 | 
					    @Override
 | 
				
			||||||
    public void directAdd(ICraftingMonitorElement element) {
 | 
					    public void directAdd(ICraftingMonitorElement element) {
 | 
				
			||||||
        elements.add(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
 | 
					    @Override
 | 
				
			||||||
    public void add(ICraftingMonitorElement element) {
 | 
					    public void add(ICraftingMonitorElement element) {
 | 
				
			||||||
        Map<Integer, ICraftingMonitorElement> currentElements = currentLists.get(element.getId());
 | 
					        Map<Integer, ICraftingMonitorElement> currentElements = currentLists.get(element.getId());
 | 
				
			||||||
@@ -39,11 +105,17 @@ public class CraftingMonitorElementList implements ICraftingMonitorElementList {
 | 
				
			|||||||
    public void commit() {
 | 
					    public void commit() {
 | 
				
			||||||
        currentLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
 | 
					        currentLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
 | 
				
			||||||
        currentLists.clear();
 | 
					        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
 | 
					    @Override
 | 
				
			||||||
    public List<ICraftingMonitorElement> getElements() {
 | 
					    public List<ICraftingMonitorElement> getElements() {
 | 
				
			||||||
        if (!currentLists.isEmpty()) {
 | 
					        if (!currentLists.isEmpty()||!currentCraftingLists.isEmpty() || !currentProcessingLists.isEmpty() || !currentStorageLists.isEmpty()) {
 | 
				
			||||||
            commit();
 | 
					            commit();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,11 @@ public class ErrorCraftingMonitorElement implements ICraftingMonitorElement {
 | 
				
			|||||||
        return ID;
 | 
					        return ID;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public ResourceLocation getBaseId() {
 | 
				
			||||||
 | 
					        return base.getId();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void write(PacketBuffer buf) {
 | 
					    public void write(PacketBuffer buf) {
 | 
				
			||||||
        buf.writeResourceLocation(base.getId());
 | 
					        buf.writeResourceLocation(base.getId());
 | 
				
			||||||
@@ -64,8 +69,17 @@ public class ErrorCraftingMonitorElement implements ICraftingMonitorElement {
 | 
				
			|||||||
        return elementHashCode() == element.elementHashCode() && base.merge(((ErrorCraftingMonitorElement) element).base);
 | 
					        return elementHashCode() == element.elementHashCode() && base.merge(((ErrorCraftingMonitorElement) element).base);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int baseElementHashCode() {
 | 
				
			||||||
 | 
					        return base.elementHashCode();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int elementHashCode() {
 | 
					    public int elementHashCode() {
 | 
				
			||||||
        return base.elementHashCode() ^ message.hashCode();
 | 
					        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();
 | 
					        RenderSystem.popMatrix();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public ResourceLocation getBaseId() {
 | 
				
			||||||
 | 
					        return ID;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public ResourceLocation getId() {
 | 
					    public ResourceLocation getId() {
 | 
				
			||||||
        return ID;
 | 
					        return ID;
 | 
				
			||||||
@@ -141,6 +146,11 @@ public class FluidCraftingMonitorElement implements ICraftingMonitorElement {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int baseElementHashCode() {
 | 
				
			||||||
 | 
					        return elementHashCode();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int elementHashCode() {
 | 
					    public int elementHashCode() {
 | 
				
			||||||
        return API.instance().getFluidStackHashCode(stack);
 | 
					        return API.instance().getFluidStackHashCode(stack);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,6 +95,11 @@ public class ItemCraftingMonitorElement implements ICraftingMonitorElement {
 | 
				
			|||||||
        RenderSystem.popMatrix();
 | 
					        RenderSystem.popMatrix();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public ResourceLocation getBaseId() {
 | 
				
			||||||
 | 
					        return ID;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public ResourceLocation getId() {
 | 
					    public ResourceLocation getId() {
 | 
				
			||||||
        return ID;
 | 
					        return ID;
 | 
				
			||||||
@@ -142,6 +147,11 @@ public class ItemCraftingMonitorElement implements ICraftingMonitorElement {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public int baseElementHashCode() {
 | 
				
			||||||
 | 
					        return elementHashCode();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int elementHashCode() {
 | 
					    public int elementHashCode() {
 | 
				
			||||||
        return API.instance().getItemStackHashCode(stack);
 | 
					        return API.instance().getItemStackHashCode(stack);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -938,7 +938,7 @@ public class CraftingTask implements ICraftingTask {
 | 
				
			|||||||
        return quantity;
 | 
					        return quantity;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					
 | 
				
			||||||
    public int getQuantityPerCraft() {
 | 
					    public int getQuantityPerCraft() {
 | 
				
			||||||
        int qty = 0;
 | 
					        int qty = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,11 +18,11 @@ public class CraftingTaskFactory implements ICraftingTaskFactory {
 | 
				
			|||||||
    @Nonnull
 | 
					    @Nonnull
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public ICraftingTask create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) {
 | 
					    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
 | 
					    @Override
 | 
				
			||||||
    public ICraftingTask createFromNbt(INetwork network, CompoundNBT tag) throws CraftingTaskReadException {
 | 
					    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 {
 | 
					    public class Autocrafting {
 | 
				
			||||||
        private final ForgeConfigSpec.IntValue calculationTimeoutMs;
 | 
					        private final ForgeConfigSpec.IntValue calculationTimeoutMs;
 | 
				
			||||||
 | 
					        private final ForgeConfigSpec.BooleanValue useExperimental;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Autocrafting() {
 | 
					        public Autocrafting() {
 | 
				
			||||||
            builder.push("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);
 | 
					            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();
 | 
					            builder.pop();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        public boolean useExperimentalAutocrafting(){
 | 
				
			||||||
 | 
					            return useExperimental.get();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        public int getCalculationTimeoutMs() {
 | 
					        public int getCalculationTimeoutMs() {
 | 
				
			||||||
            return calculationTimeoutMs.get();
 | 
					            return calculationTimeoutMs.get();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,7 +130,8 @@ public class CommonSetup {
 | 
				
			|||||||
        API.instance().getCraftingMonitorElementRegistry().add(FluidCraftingMonitorElement.ID, FluidCraftingMonitorElement::read);
 | 
					        API.instance().getCraftingMonitorElementRegistry().add(FluidCraftingMonitorElement.ID, FluidCraftingMonitorElement::read);
 | 
				
			||||||
        API.instance().getCraftingMonitorElementRegistry().add(ErrorCraftingMonitorElement.ID, ErrorCraftingMonitorElement::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 StorageBlockLootFunctionSerializer());
 | 
				
			||||||
        LootFunctionManager.registerFunction(new PortableGridBlockLootFunctionSerializer());
 | 
					        LootFunctionManager.registerFunction(new PortableGridBlockLootFunctionSerializer());
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user