rewrite of the autocrafting, hopefully this is the final form

This commit is contained in:
way2muchnoise
2016-10-23 14:47:36 +02:00
parent fcc4495303
commit 72de12142a
25 changed files with 651 additions and 361 deletions

View File

@@ -1,5 +1,6 @@
package com.raoulvdberge.refinedstorage.api;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry;
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry;
import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskRegistry;
@@ -59,6 +60,9 @@ public interface IRSAPI {
@Nonnull
IFluidStackList createFluidStackList();
@Nonnull
ICraftingMonitorElementList createCraftingMonitorElementList();
/**
* @param stack the stack
* @return a hashcode for the given stack

View File

@@ -11,11 +11,9 @@ import java.util.List;
*/
public interface ICraftingPatternContainer {
/**
* The speed that crafting tasks that have a pattern in this container can run.
*
* @return the speed of this container
* @return the amount of speed upgrades in the container.
*/
int getSpeed();
int getSpeedUpdateCount();
/**
* @return the inventory that this container is facing

View File

@@ -8,7 +8,7 @@ import net.minecraftforge.fml.relauncher.SideOnly;
/**
* Represents a crafting monitor element.
*/
public interface ICraftingMonitorElement<T> {
public interface ICraftingMonitorElement {
/**
* @param x position on the x axis to render
* @param y position on the y axis to render
@@ -50,4 +50,18 @@ public interface ICraftingMonitorElement<T> {
* @param buf the buffer
*/
void write(ByteBuf buf);
/**
* Merge an element into the current element
* Used to in {@link ICraftingMonitorElementList}
*
* @param element the element to merged with the current one
* @return true if merge was successful
*/
boolean merge(ICraftingMonitorElement element);
/**
* @return the hash code for the underlying element
*/
int elementHashCode();
}

View File

@@ -0,0 +1,41 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor;
import java.util.Collection;
import java.util.List;
public interface ICraftingMonitorElementList {
/**
* Directly add to the underlying list without trying to merge
*
* @param element the {@link ICraftingMonitorElement}
*/
void directAdd(ICraftingMonitorElement element);
/**
* Add a element to the 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 add(ICraftingMonitorElement element);
/**
* @param elements a {@link Collection} of {@link ICraftingMonitorElement}s to be added
*/
default void addAll(Collection<ICraftingMonitorElement> elements) {
elements.forEach(this::add);
}
/**
* Finish a current merge operation
*/
void commit();
/**
* This also commits the last changes
*
* @return Get the current list of elements
*/
List<ICraftingMonitorElement> getElements();
}

View File

@@ -0,0 +1,74 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.api.util.IItemStackList;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import java.util.Deque;
import java.util.List;
/**
* Represents a step in a crafting task that.
*/
public interface ICraftingStep {
/**
* @return the pattern
*/
ICraftingPattern getPattern();
/**
* @return the stacks to insert, no null entries
*/
List<ItemStack> getToInsert();
/**
* Check if the processing can start
*
* @param items a list to compare the needed {@link ItemStack} inputs against
* @param fluids a list to compare the needed {@link net.minecraftforge.fluids.FluidStack} inputs against (eg. a bucket, machine insert)
* @return true if processing can start
*/
boolean canStartProcessing(IItemStackList items, IFluidStackList fluids);
void setStartedProcessing();
boolean hasStartedProcessing();
/**
* Execute this step
* Any items to be added to the network should be inserting into these queues
* and they'll be managed by the {@link ICraftingTask}
*
* @param toInsertItems a queue of items to be inserted into the network
* @param toInsertFluids a queue of fluids to be inserted into the network
*/
void execute(Deque<ItemStack> toInsertItems, Deque<FluidStack> toInsertFluids);
/**
* @return true if we received all outputs, false otherwise
*/
boolean hasReceivedOutputs();
/**
* @param stack the output to check,
* @return true if we received the given output (based upon item and stacksize), false otherwise
*/
boolean hasReceivedOutput(ItemStack stack);
/**
* @param stack the stack that was inserted in the storage system
* @return true if this item belonged to the processable item, false otherwise
*/
boolean onReceiveOutput(ItemStack stack);
/**
* Writes the processable to NBT.
*
* @param tag the tag
* @return the written tag
*/
NBTTagCompound writeToNBT(NBTTagCompound tag);
}

View File

@@ -1,6 +1,7 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
import net.minecraft.item.ItemStack;
@@ -8,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
/**
* Represents a crafting task.
@@ -33,9 +35,10 @@ public interface ICraftingTask {
* Updates this task. Gets called every few ticks, depending on the speed of the pattern container.
* {@link ICraftingTask#calculate()} must be run before this
*
* @param usedContainers a map keeping track of used containers and how many times
* @return true if this crafting task is finished and can be deleted from the list, false otherwise
*/
boolean update();
boolean update(Map<ICraftingPatternContainer, Integer> usedContainers);
/**
* @return the amount of items that have to be crafted
@@ -92,7 +95,7 @@ public interface ICraftingTask {
*
* @return the processable items in this task
*/
List<IProcessable> getToProcess();
List<ICraftingStep> getSteps();
/**
* Used to check if the crafting task has recursive elements

View File

@@ -1,58 +0,0 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.util.IItemStackList;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
/**
* Represents a item in a crafting task that can be processed.
*/
public interface IProcessable {
/**
* @return the pattern
*/
ICraftingPattern getPattern();
/**
* @return the stacks to insert
*/
IItemStackList getToInsert();
/**
* Check if the processing can start
*
* @param list a list to compare the need inputs against
* @return true if processing can start
*/
boolean canStartProcessing(IItemStackList list);
void setStartedProcessing();
boolean hasStartedProcessing();
/**
* @return true if we received all outputs, false otherwise
*/
boolean hasReceivedOutputs();
/**
* @param i the output to check
* @return true if we received the given output, false otherwise
*/
boolean hasReceivedOutput(int i);
/**
* @param stack the stack that was inserted in the storage system
* @return true if this item belonged to the processable item, false otherwise
*/
boolean onReceiveOutput(ItemStack stack);
/**
* Writes the processable to NBT.
*
* @param tag the tag
* @return the written tag
*/
NBTTagCompound writeToNBT(NBTTagCompound tag);
}

View File

@@ -24,7 +24,7 @@ public interface IFluidStackList {
* @param stack the stack
* @param size the size to remove
* @param removeIfReachedZero true to remove the stack if the count reaches 0, false otherwise
* @return whether the remove was successful
* @return whether the remove was successful for the full amount
*/
boolean remove(@Nonnull FluidStack stack, int size, boolean removeIfReachedZero);
@@ -33,7 +33,7 @@ public interface IFluidStackList {
*
* @param stack the stack
* @param removeIfReachedZero true to remove the stack if the count reaches 0, false otherwise
* @return whether the remove was successful
* @return whether the remove was successful for the full amount
*/
default boolean remove(@Nonnull FluidStack stack, boolean removeIfReachedZero) {
return remove(stack, stack.amount, removeIfReachedZero);
@@ -74,6 +74,11 @@ public interface IFluidStackList {
*/
void clear();
/**
* Removes all stacks with size zero
*/
void clean();
/**
* @return true if the list is empty, false otherwise
*/

View File

@@ -24,7 +24,7 @@ public interface IItemStackList {
* @param stack the stack
* @param size the size to remove
* @param removeIfReachedZero true to remove the stack if the count reaches 0, false otherwise
* @return whether the remove was successful
* @return whether the remove was successful for the full amount
*/
boolean remove(@Nonnull ItemStack stack, int size, boolean removeIfReachedZero);
@@ -33,7 +33,7 @@ public interface IItemStackList {
*
* @param stack the stack
* @param removeIfReachedZero true to remove the stack if the count reaches 0, false otherwise
* @return whether the remove was successful
* @return whether the remove was successful for the full amount
*/
default boolean remove(@Nonnull ItemStack stack, boolean removeIfReachedZero) {
return remove(stack, stack.stackSize, removeIfReachedZero);

View File

@@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.apiimpl;
import com.raoulvdberge.refinedstorage.api.IRSAPI;
import com.raoulvdberge.refinedstorage.api.RSAPIInject;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry;
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry;
import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskRegistry;
@@ -9,6 +10,7 @@ import com.raoulvdberge.refinedstorage.api.solderer.ISoldererRegistry;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.api.util.IItemStackList;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementRegistry;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementRegistry;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry.CraftingTaskRegistry;
@@ -75,6 +77,12 @@ public class API implements IRSAPI {
return new FluidStackList();
}
@Nonnull
@Override
public ICraftingMonitorElementList createCraftingMonitorElementList() {
return new CraftingMonitorElementList();
}
@Override
public int getItemStackHashCode(ItemStack stack) {
return stack.getItem().hashCode() * (stack.getItemDamage() + 1) * (stack.hasTagCompound() ? stack.getTagCompound().hashCode() : 1);

View File

@@ -50,4 +50,14 @@ public class CraftingMonitorElementError implements ICraftingMonitorElement {
base.write(buf);
}
@Override
public boolean merge(ICraftingMonitorElement element) {
return element.getId().equals(getId()) && elementHashCode() == element.elementHashCode() && base.merge(((CraftingMonitorElementError)element).base);
}
@Override
public int elementHashCode() {
return base.elementHashCode() ^ tooltip.hashCode();
}
}

View File

@@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor;
import com.raoulvdberge.refinedstorage.RSUtils;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.gui.GuiBase;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.renderer.GlStateManager;
@@ -10,7 +11,7 @@ import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class CraftingMonitorElementFluidRender implements ICraftingMonitorElement<FluidStack> {
public class CraftingMonitorElementFluidRender implements ICraftingMonitorElement {
public static final String ID = "fluid_render";
private int taskId;
@@ -59,4 +60,18 @@ public class CraftingMonitorElementFluidRender implements ICraftingMonitorElemen
RSUtils.writeFluidStack(buf, stack);
buf.writeInt(offset);
}
@Override
public boolean merge(ICraftingMonitorElement element) {
if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) {
this.stack.amount += ((CraftingMonitorElementFluidRender) element).stack.amount;
return true;
}
return false;
}
@Override
public int elementHashCode() {
return API.instance().getFluidStackHashCode(stack);
}
}

View File

@@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.gui.GuiBase;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.renderer.GlStateManager;
@@ -10,7 +11,7 @@ import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class CraftingMonitorElementItemRender implements ICraftingMonitorElement<ItemStack> {
public class CraftingMonitorElementItemRender implements ICraftingMonitorElement {
public static final String ID = "item_render";
private int taskId;
@@ -62,4 +63,18 @@ public class CraftingMonitorElementItemRender implements ICraftingMonitorElement
buf.writeInt(quantity);
buf.writeInt(offset);
}
@Override
public boolean merge(ICraftingMonitorElement element) {
if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) {
this.quantity += ((CraftingMonitorElementItemRender) element).quantity;
return true;
}
return false;
}
@Override
public int elementHashCode() {
return API.instance().getItemStackHashCode(stack);
}
}

View File

@@ -0,0 +1,46 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
import java.util.*;
public class CraftingMonitorElementList implements ICraftingMonitorElementList {
public List<ICraftingMonitorElement> elements = new LinkedList<>();
public Map<String, Map<Integer, ICraftingMonitorElement>> currentLists = new LinkedHashMap<>();
@Override
public void directAdd(ICraftingMonitorElement element) {
elements.add(element);
}
@Override
public void add(ICraftingMonitorElement element) {
Map<Integer, ICraftingMonitorElement> currentElements = currentLists.get(element.getId());
if (currentElements == null) {
currentElements = new HashMap<>();
}
ICraftingMonitorElement exitingElement = currentElements.get(element.elementHashCode());
if (exitingElement == null) {
exitingElement = element;
} else {
exitingElement.merge(element);
}
currentElements.put(exitingElement.elementHashCode(), exitingElement);
currentLists.put(exitingElement.getId(), currentElements);
}
@Override
public void commit() {
currentLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add);
currentLists.clear();
}
@Override
public List<ICraftingMonitorElement> getElements() {
if (!currentLists.isEmpty()) {
commit();
}
return elements;
}
}

View File

@@ -10,7 +10,7 @@ import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class CraftingMonitorElementText implements ICraftingMonitorElement<String> {
public class CraftingMonitorElementText implements ICraftingMonitorElement {
public static final String ID = "text";
private String text;
@@ -62,4 +62,14 @@ public class CraftingMonitorElementText implements ICraftingMonitorElement<Strin
ByteBufUtils.writeUTF8String(buf, text);
buf.writeInt(offset);
}
@Override
public boolean merge(ICraftingMonitorElement element) {
return element.getId().equals(getId()) && elementHashCode() == element.elementHashCode();
}
@Override
public int elementHashCode() {
return text.hashCode();
}
}

View File

@@ -4,12 +4,13 @@ import com.raoulvdberge.refinedstorage.RSUtils;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskFactory;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.IProcessable;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.api.util.IItemStackList;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftCraftingStep;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.Processable;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.AbstractCraftingStep;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.ProcessCraftingStep;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
@@ -21,6 +22,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
public class CraftingTaskFactory implements ICraftingTaskFactory {
@@ -32,23 +34,33 @@ public class CraftingTaskFactory implements ICraftingTaskFactory {
if (tag != null) {
NBTTagList toProcessList = tag.getTagList(CraftingTask.NBT_TO_PROCESS, Constants.NBT.TAG_COMPOUND);
List<IProcessable> toProcess = new ArrayList<>();
List<ICraftingStep> toProcess = new ArrayList<>();
for (int i = 0; i < toProcessList.tagCount(); ++i) {
Processable processable = new Processable(network);
NBTTagCompound compound = toProcessList.getCompoundTagAt(i);
AbstractCraftingStep abstractCraftingStep;
switch (compound.getString(AbstractCraftingStep.NBT_CRAFTING_STEP_TYPE))
{
case CraftCraftingStep.ID:
abstractCraftingStep = new CraftCraftingStep(network);
break;
case ProcessCraftingStep.ID:
abstractCraftingStep = new ProcessCraftingStep(network);
break;
default:
abstractCraftingStep = null;
break;
}
if (processable.readFromNBT(toProcessList.getCompoundTagAt(i))) {
toProcess.add(processable);
if (abstractCraftingStep != null && abstractCraftingStep.readFromNBT(compound)) {
toProcess.add(abstractCraftingStep);
}
}
IItemStackList toTake = RSUtils.readItemStackList(tag.getTagList(CraftingTask.NBT_TO_TAKE, Constants.NBT.TAG_COMPOUND));
IItemStackList internalToTake = RSUtils.readItemStackList(tag.getTagList(CraftingTask.NBT_INTERNAL_TO_TAKE, Constants.NBT.TAG_COMPOUND));
IFluidStackList toTakeFluids = RSUtils.readFluidStackList(tag.getTagList(CraftingTask.NBT_TO_TAKE_FLUIDS, Constants.NBT.TAG_COMPOUND));
NBTTagList toInsertList = tag.getTagList(CraftingTask.NBT_TO_INSERT, Constants.NBT.TAG_COMPOUND);
NBTTagList toInsertList = tag.getTagList(CraftingTask.NBT_TO_INSERT_ITEMS, Constants.NBT.TAG_COMPOUND);
ArrayDeque<ItemStack> toInsert = new ArrayDeque<>();
Deque<ItemStack> toInsert = new ArrayDeque<>();
for (int i = 0; i < toInsertList.tagCount(); ++i) {
ItemStack insertStack = ItemStack.loadItemStackFromNBT(toInsertList.getCompoundTagAt(i));
@@ -58,23 +70,22 @@ public class CraftingTaskFactory implements ICraftingTaskFactory {
}
}
NBTTagList tookList = tag.getTagList(CraftingTask.NBT_TOOK, Constants.NBT.TAG_COMPOUND);
IFluidStackList toTakeFluids = RSUtils.readFluidStackList(tag.getTagList(CraftingTask.NBT_TO_TAKE_FLUIDS, Constants.NBT.TAG_COMPOUND));
IFluidStackList tookFluids = RSUtils.readFluidStackList(tag.getTagList(CraftingTask.NBT_TOOK_FLUIDS, Constants.NBT.TAG_COMPOUND));
IItemStackList took = RSUtils.readItemStackList(tookList);
NBTTagList toInsertFluidsList = tag.getTagList(CraftingTask.NBT_TO_INSERT_FLUIDS, Constants.NBT.TAG_COMPOUND);
NBTTagList tookFluidsList = tag.getTagList(CraftingTask.NBT_TOOK_FLUIDS, Constants.NBT.TAG_COMPOUND);
Deque<FluidStack> toInsertFluids = new ArrayDeque<>();
List<FluidStack> tookFluids = new ArrayList<>();
for (int i = 0; i < tookFluidsList.tagCount(); ++i) {
FluidStack tookStack = FluidStack.loadFluidStackFromNBT(tookList.getCompoundTagAt(i));
for (int i = 0; i < toInsertFluidsList.tagCount(); ++i) {
FluidStack tookStack = FluidStack.loadFluidStackFromNBT(toInsertFluidsList.getCompoundTagAt(i));
if (tookStack != null) {
tookFluids.add(tookStack);
toInsertFluids.add(tookStack);
}
}
return new CraftingTask(network, stack, pattern, quantity, toProcess, toTake, internalToTake, toTakeFluids, toInsert, took, tookFluids);
return new CraftingTask(network, stack, pattern, quantity, toProcess, toInsert, toTakeFluids, tookFluids, toInsertFluids);
}
return new CraftingTask(network, stack, pattern, quantity);

View File

@@ -1,46 +1,41 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.RSUtils;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternProvider;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.IProcessable;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.api.util.IItemStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagCompound;;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.util.Constants;
public class Processable implements IProcessable {
import java.util.*;
import java.util.stream.Collectors;
public abstract class AbstractCraftingStep implements ICraftingStep {
public static final String NBT_CRAFTING_STEP_TYPE = "CraftingStepType";
private static final String NBT_SATISFIED = "Satisfied_%d";
private static final String NBT_TO_INSERT = "ToInsert";
private static final String NBT_PATTERN = "Pattern";
private static final String NBT_PATTERN_CONTAINER = "PatternContainer";
private static final String NBT_STARTED_PROCESSING = "StartedProcessing";
private INetworkMaster network;
private ICraftingPattern pattern;
private IItemStackList toInsert = API.instance().createItemStackList();
private boolean satisfied[];
private boolean startedProcessing;
protected INetworkMaster network;
protected ICraftingPattern pattern;
protected Map<Integer, Integer> satisfied;
protected boolean startedProcessing;
public Processable(INetworkMaster network, ICraftingPattern pattern) {
public AbstractCraftingStep(INetworkMaster network, ICraftingPattern pattern) {
this.network = network;
this.pattern = pattern;
this.satisfied = new boolean[pattern.getOutputs().size()];
for (ItemStack input : pattern.getInputs()) {
if (input != null) {
toInsert.add(input.copy());
}
}
this.satisfied = new HashMap<>(getPattern().getOutputs().size());
}
public Processable(INetworkMaster network) {
public AbstractCraftingStep(INetworkMaster network) {
this.network = network;
}
@@ -52,17 +47,17 @@ public class Processable implements IProcessable {
if (container instanceof ICraftingPatternContainer) {
this.pattern = ((ICraftingPatternProvider) patternStack.getItem()).create(network.getNetworkWorld(), patternStack, (ICraftingPatternContainer) container);
this.satisfied = new boolean[pattern.getOutputs().size()];
this.satisfied = new HashMap<>(pattern.getOutputs().size());
for (int i = 0; i < satisfied.length; ++i) {
String id = String.format(NBT_SATISFIED, i);
for (ItemStack stack : pattern.getOutputs()) {
int hashcode = API.instance().getItemStackHashCode(stack);
String id = String.format(NBT_SATISFIED, hashcode);
if (tag.hasKey(id)) {
this.satisfied[i] = tag.getBoolean(id);
this.satisfied.put(hashcode, tag.getInteger(id));
}
}
this.toInsert = RSUtils.readItemStackList(tag.getTagList(NBT_TO_INSERT, Constants.NBT.TAG_COMPOUND));
this.startedProcessing = tag.getBoolean(NBT_STARTED_PROCESSING);
return true;
@@ -78,18 +73,18 @@ public class Processable implements IProcessable {
}
@Override
public IItemStackList getToInsert() {
return toInsert;
public List<ItemStack> getToInsert() {
return pattern.getInputs().stream().filter(Objects::nonNull).collect(Collectors.toList());
}
@Override
public boolean canStartProcessing(IItemStackList list) {
list = list.copy(); // So we can edit the list
public boolean canStartProcessing(IItemStackList items, IFluidStackList fluids) {
items = items.copy(); // So we can edit the list
for (ItemStack stack : toInsert.getStacks()) {
ItemStack actualStack = list.get(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0));
for (ItemStack stack : getToInsert()) {
ItemStack actualStack = items.get(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0));
if (actualStack == null || actualStack.stackSize == 0 || !list.remove(actualStack, true)) {
if (actualStack == null || actualStack.stackSize == 0 || !items.remove(actualStack, stack.stackSize, true)) {
return false;
}
}
@@ -109,8 +104,9 @@ public class Processable implements IProcessable {
@Override
public boolean hasReceivedOutputs() {
for (boolean item : satisfied) {
if (!item) {
for (ItemStack stack : pattern.getOutputs()) {
Integer received = satisfied.get(API.instance().getItemStackHashCode(stack));
if (received == null || stack.stackSize > received) {
return false;
}
}
@@ -119,18 +115,22 @@ public class Processable implements IProcessable {
}
@Override
public boolean hasReceivedOutput(int i) {
return satisfied[i];
public boolean hasReceivedOutput(ItemStack stack) {
Integer received = satisfied.get(API.instance().getItemStackHashCode(stack));
return received != null && received >= stack.stackSize;
}
@Override
public boolean onReceiveOutput(ItemStack stack) {
for (int i = 0; i < pattern.getOutputs().size(); ++i) {
if (!satisfied[i]) {
ItemStack item = pattern.getOutputs().get(i);
if (API.instance().getComparer().isEqualNoQuantity(stack, item)) {
satisfied[i] = true;
for (ItemStack output : pattern.getOutputs()) {
int hashcode = API.instance().getItemStackHashCode(output);
Integer received = satisfied.get(hashcode);
if (received == null) {
received = 0;
}
if (API.instance().getComparer().isEqual(stack, output, CraftingTask.DEFAULT_COMPARE | (getPattern().isOredict() ? IComparer.COMPARE_OREDICT : 0))) {
if (received < output.stackSize) {
satisfied.put(hashcode, received + stack.stackSize);
network.sendCraftingMonitorUpdate();
@@ -144,11 +144,10 @@ public class Processable implements IProcessable {
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
for (int i = 0; i < satisfied.length; ++i) {
tag.setBoolean(String.format(NBT_SATISFIED, i), satisfied[i]);
for (Map.Entry<Integer, Integer> entry : satisfied.entrySet()) {
tag.setInteger(String.format(NBT_SATISFIED, entry.getKey()), entry.getValue());
}
tag.setTag(NBT_TO_INSERT, RSUtils.serializeItemStackList(toInsert));
tag.setTag(NBT_PATTERN, pattern.getStack().serializeNBT());
tag.setLong(NBT_PATTERN_CONTAINER, pattern.getContainer().getPosition().toLong());
tag.setBoolean(NBT_STARTED_PROCESSING, startedProcessing);

View File

@@ -0,0 +1,94 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.RSUtils;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.api.util.IItemStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemHandlerHelper;
import java.util.Deque;
public class CraftCraftingStep extends AbstractCraftingStep {
public static final String ID = "CraftCraftingStep";
public CraftCraftingStep(INetworkMaster network, ICraftingPattern pattern) {
super(network, pattern);
}
public CraftCraftingStep(INetworkMaster network) {
super(network);
}
@Override
public boolean canStartProcessing(IItemStackList items, IFluidStackList fluids) {
// So we can edit the lists
items = items.copy();
fluids = fluids.copy();
int compare = IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0);
for (ItemStack stack : getToInsert()) {
ItemStack actualStack = items.get(stack, compare);
if (actualStack == null || actualStack.stackSize == 0 || !items.remove(actualStack, stack.stackSize, true)) {
FluidStack fluidInItem = RSUtils.getFluidFromStack(stack, true);
if (fluidInItem != null && RSUtils.hasFluidBucket(fluidInItem)) {
FluidStack fluidStack = fluids.get(fluidInItem, compare);
if (fluidStack != null && fluids.remove(fluidStack, fluidInItem.amount, true)) {
continue;
}
}
return false;
}
}
return true;
}
@Override
public void execute(Deque<ItemStack> toInsertItems, Deque<FluidStack> toInsertFluids) {
IItemStackList actualInputs = API.instance().createItemStackList();
int compare = CraftingTask.DEFAULT_COMPARE | (getPattern().isOredict() ? IComparer.COMPARE_OREDICT : 0);
for (ItemStack insertStack : getToInsert()) {
FluidStack fluidInItem = RSUtils.getFluidFromStack(insertStack, true);
if (fluidInItem != null) {
network.extractFluid(fluidInItem, fluidInItem.amount, compare);
actualInputs.add(insertStack.copy());
} else {
actualInputs.add(network.extractItem(insertStack, insertStack.stackSize, compare));
}
}
ItemStack[] took = new ItemStack[9];
for (int i = 0; i < pattern.getInputs().size(); i++) {
ItemStack input = pattern.getInputs().get(i);
if (input != null) {
ItemStack actualInput = actualInputs.get(input, compare);
ItemStack taken = ItemHandlerHelper.copyStackWithSize(actualInput, input.stackSize);
took[i] = taken;
actualInputs.remove(taken, true);
}
}
for (ItemStack byproduct : (pattern.isOredict()? pattern.getByproducts(took) : pattern.getByproducts())) {
toInsertItems.add(byproduct.copy());
}
for (ItemStack output : (pattern.isOredict() ? pattern.getOutputs(took) : pattern.getOutputs())) {
toInsertItems.add(output.copy());
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
tag.setString(NBT_CRAFTING_STEP_TYPE, ID);
return super.writeToNBT(tag);
}
}

View File

@@ -2,10 +2,12 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.RSUtils;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.IProcessable;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
@@ -21,7 +23,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nullable;
@@ -29,14 +30,12 @@ import java.util.*;
import java.util.stream.Collectors;
public class CraftingTask implements ICraftingTask {
private static final int DEFAULT_COMPARE = IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT;
protected static final int DEFAULT_COMPARE = IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT;
public static final String NBT_TO_PROCESS = "ToProcess";
public static final String NBT_TO_TAKE = "ToTake";
public static final String NBT_INTERNAL_TO_TAKE = "InternalToTake";
public static final String NBT_TO_TAKE_FLUIDS = "ToTakeFluids";
public static final String NBT_TO_INSERT = "ToInsert";
public static final String NBT_TOOK = "Took";
public static final String NBT_TO_INSERT_ITEMS = "ToInsertItems";
public static final String NBT_TO_INSERT_FLUIDS = "ToInsertFluids";
public static final String NBT_TOOK_FLUIDS = "TookFluids";
private INetworkMaster network;
@@ -44,17 +43,16 @@ public class CraftingTask implements ICraftingTask {
private ItemStack requested;
private ICraftingPattern pattern;
private int quantity;
private List<IProcessable> toProcess = new ArrayList<>();
private List<ICraftingStep> steps = new ArrayList<>();
private IItemStackList toTake = API.instance().createItemStackList();
private IItemStackList internalToTake = API.instance().createItemStackList();
private IItemStackList toCraft = API.instance().createItemStackList();
private IFluidStackList toTakeFluids = API.instance().createFluidStackList();
private IItemStackList missing = API.instance().createItemStackList();
private Set<ICraftingPattern> usedPatterns = new HashSet<>();
private boolean recurseFound = false;
private Deque<ItemStack> toInsert = new ArrayDeque<>();
private IItemStackList took = API.instance().createItemStackList();
private List<FluidStack> tookFluids = new ArrayList<>();
private Deque<ItemStack> toInsertItems = new ArrayDeque<>();
private Deque<FluidStack> toInsertFluids = new ArrayDeque<>();
private IFluidStackList toTakeFluids = API.instance().createFluidStackList();
private IFluidStackList tookFluids = API.instance().createFluidStackList();
public CraftingTask(INetworkMaster network, @Nullable ItemStack requested, ICraftingPattern pattern, int quantity) {
this.network = network;
@@ -63,16 +61,13 @@ public class CraftingTask implements ICraftingTask {
this.quantity = quantity;
}
public CraftingTask(INetworkMaster network, @Nullable ItemStack requested, ICraftingPattern pattern, int quantity, List<IProcessable> toProcess, IItemStackList toTake, IItemStackList internalToTake, IFluidStackList toTakeFluids, Deque<ItemStack> toInsert, IItemStackList took, List<FluidStack> tookFluids) {
public CraftingTask(INetworkMaster network, @Nullable ItemStack requested, ICraftingPattern pattern, int quantity, List<ICraftingStep> steps, Deque<ItemStack> toInsertItems, IFluidStackList toTakeFluids, IFluidStackList tookFluids, Deque<FluidStack> toInsertFluids) {
this(network, requested, pattern, quantity);
this.toProcess = toProcess;
this.toTake = toTake;
this.internalToTake = internalToTake;
this.steps = steps;
this.toInsertItems = toInsertItems;
this.toTakeFluids = toTakeFluids;
this.toInsert = toInsert;
this.took = took;
this.tookFluids = tookFluids;
this.toInsertFluids = toInsertFluids;
}
@Override
@@ -87,10 +82,6 @@ public class CraftingTask implements ICraftingTask {
quantity -= pattern.getQuantityPerRequest(requested);
}
if (!recurseFound) {
this.toInsert.addAll(toInsert.getStacks());
}
usedPatterns.clear();
}
@@ -122,6 +113,7 @@ public class CraftingTask implements ICraftingTask {
ItemStack inputStack = ItemHandlerHelper.copyStackWithSize(extraStack, takeQuantity);
actualInputs.add(inputStack.copy());
input.stackSize -= takeQuantity;
toCraft.add(inputStack);
toInsert.remove(inputStack, true);
} else if (networkStack != null && networkStack.stackSize > 0) {
int takeQuantity = Math.min(networkStack.stackSize, input.stackSize);
@@ -140,13 +132,9 @@ public class CraftingTask implements ICraftingTask {
actualInputs.add(inputCrafted.copy());
calculate(networkList, inputPattern, toInsert);
input.stackSize -= craftQuantity;
// Calculate added all the crafted outputs toInsert
// So we remove the ones we use from toInsert
// Calculate added all the crafted outputs toInsertItems
// So we remove the ones we use from toInsertItems
toInsert.remove(inputCrafted, true);
// If the pattern is processing the have to be taken.
if (pattern.isProcessing()) {
internalToTake.add(inputCrafted.copy());
}
} else if (doFluidCalculation(networkList, input, toInsert)) {
actualInputs.add(ItemHandlerHelper.copyStackWithSize(input, 1));
input.stackSize -= 1;
@@ -159,7 +147,9 @@ public class CraftingTask implements ICraftingTask {
}
if (pattern.isProcessing()) {
toProcess.add(new Processable(network, pattern));
steps.add(new ProcessCraftingStep(network, pattern));
} else {
steps.add(new CraftCraftingStep(network, pattern));
}
if (missing.isEmpty()) {
@@ -221,116 +211,79 @@ public class CraftingTask implements ICraftingTask {
@Override
public void onCancelled() {
for (ItemStack stack : took.getStacks()) {
for (ItemStack stack : toInsertItems) {
network.insertItem(stack, stack.stackSize, false);
}
for (FluidStack stack : tookFluids) {
for (FluidStack stack : tookFluids.getStacks()) {
network.insertFluid(stack, stack.amount, false);
}
network.sendCraftingMonitorUpdate();
}
@Override
public String toString() {
return "\nCraftingTask{quantity=" + quantity +
"\n, toTake=" + toTake +
"\n, internalToTake=" + internalToTake +
"\n, toTakeFluids=" + toTakeFluids +
"\n, toProcess=" + toProcess +
"\n, toCraft=" + toProcess +
"\n, toInsert=" + toInsert +
"\n, toCraft=" + toCraft +
"\n, toInsertItems=" + toInsertItems +
"\n, toInsertFluids=" + toInsertFluids +
"\n, steps=" + steps +
'}';
}
@Override
public boolean update() {
for (ItemStack stack : toTake.getStacks()) {
ItemStack stackExtracted = network.extractItem(stack, Math.min(stack.stackSize, 64));
if (stackExtracted != null) {
toTake.remove(stack, stackExtracted.stackSize, true);
took.add(stackExtracted);
network.sendCraftingMonitorUpdate();
break;
}
}
// Fetches results from processing patterns
for (ItemStack stack : internalToTake.getStacks()) {
ItemStack stackExtracted = network.extractItem(stack, Math.min(stack.stackSize, 64));
if (stackExtracted != null) {
internalToTake.remove(stack, stackExtracted.stackSize, false);
took.add(stackExtracted);
network.sendCraftingMonitorUpdate();
}
}
// Clean up zero stacks, cause we can't remove them in the loop (CME ahoy!)
internalToTake.clean();
for (IProcessable processable : toProcess) {
IItemHandler inventory = processable.getPattern().getContainer().getFacingInventory();
if (inventory != null && !processable.hasStartedProcessing() && processable.canStartProcessing(took) && canProcess(processable)) {
processable.setStartedProcessing();
for (ItemStack insertStack : processable.getToInsert().getStacks()) {
ItemStack tookStack = took.get(insertStack, DEFAULT_COMPARE | (processable.getPattern().isOredict() ? IComparer.COMPARE_OREDICT : 0));
ItemStack toInsert = ItemHandlerHelper.copyStackWithSize(tookStack, insertStack.stackSize);
if (ItemHandlerHelper.insertItem(inventory, toInsert, true) == null) {
ItemHandlerHelper.insertItem(inventory, toInsert, false);
took.remove(tookStack, toInsert.stackSize, true);
network.sendCraftingMonitorUpdate();
}
}
}
}
// If we took all the items, we can start taking fluids
if (toTake.isEmpty()) {
public boolean update(Map<ICraftingPatternContainer, Integer> usedContainers) {
for (FluidStack stack : toTakeFluids.getStacks()) {
FluidStack stackExtracted = network.extractFluid(stack, stack.amount);
if (stackExtracted != null) {
toTakeFluids.remove(stack, stack.amount, true);
toTakeFluids.remove(stack, stack.amount, false);
tookFluids.add(stackExtracted);
network.sendCraftingMonitorUpdate();
break;
}
}
}
if (isFinished()) {
ItemStack insert = toInsert.peek();
if (insert != null && network.insertItem(insert, insert.stackSize, true) == null) {
network.insertItem(insert, insert.stackSize, false);
toInsert.pop();
network.sendCraftingMonitorUpdate();
}
return toInsert.isEmpty();
}
return false;
toTakeFluids.clean();
for (ICraftingStep step : steps) {
ICraftingPatternContainer container = step.getPattern().getContainer();
Integer timesUsed = usedContainers.get(container);
if (timesUsed == null) timesUsed = 0;
if (timesUsed++ <= container.getSpeedUpdateCount()) {
if (!step.hasStartedProcessing() && step.canStartProcessing(network.getItemStorageCache().getList(), tookFluids) && canProcess(step)) {
step.setStartedProcessing();
step.execute(toInsertItems, toInsertFluids);
usedContainers.put(container, timesUsed);
network.sendCraftingMonitorUpdate();
}
}
}
private boolean canProcess(IProcessable processable) {
// We need to copy the size cause we'll readd unadded stacks to the queue
int times = toInsertItems.size();
for (int i = 0; i < times; i++)
{
ItemStack insert = toInsertItems.poll();
if (insert != null) {
ItemStack remainder = network.insertItem(insert, insert.stackSize, false);
if (remainder != null) {
toInsertItems.add(remainder);
}
}
}
steps.removeIf(ICraftingStep::hasReceivedOutputs);
return isFinished();
}
private boolean canProcess(ICraftingStep processable) {
if (processable.getPattern().isProcessing()) {
for (ICraftingTask otherTask : network.getCraftingTasks()) {
for (IProcessable otherProcessable : otherTask.getToProcess()) {
for (ICraftingStep otherProcessable : otherTask.getSteps()) {
if (otherProcessable.getPattern().isProcessing()) {
if (otherProcessable != processable && !otherProcessable.hasReceivedOutputs() && otherProcessable.hasStartedProcessing() && otherProcessable.getPattern().getContainer().getFacingTile() != null) {
if (!arePatternsEqual(processable.getPattern(), otherProcessable.getPattern())) {
if (processable.getPattern().getContainer().getFacingTile().getPos().equals(otherProcessable.getPattern().getContainer().getFacingTile().getPos())) {
@@ -340,6 +293,8 @@ public class CraftingTask implements ICraftingTask {
}
}
}
}
}
return true;
}
@@ -374,94 +329,84 @@ public class CraftingTask implements ICraftingTask {
NBTTagList processablesList = new NBTTagList();
for (IProcessable processable : toProcess) {
for (ICraftingStep processable : steps) {
processablesList.appendTag(processable.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_TO_PROCESS, processablesList);
tag.setTag(NBT_TO_TAKE, RSUtils.serializeItemStackList(toTake));
tag.setTag(NBT_INTERNAL_TO_TAKE, RSUtils.serializeItemStackList(internalToTake));
NBTTagList toInsertItemsList = new NBTTagList();
for (ItemStack insert : toInsertItems) {
toInsertItemsList.appendTag(insert.serializeNBT());
}
tag.setTag(NBT_TO_INSERT_ITEMS, toInsertItemsList);
tag.setTag(NBT_TO_TAKE_FLUIDS, RSUtils.serializeFluidStackList(toTakeFluids));
NBTTagList toInsertList = new NBTTagList();
NBTTagList toInsertFluidsList = new NBTTagList();
for (ItemStack insert : new ArrayList<>(toInsert)) {
toInsertList.appendTag(insert.serializeNBT());
for (FluidStack insert : toInsertFluids) {
toInsertFluidsList.appendTag(insert.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_TO_INSERT, toInsertList);
tag.setTag(NBT_TO_INSERT_FLUIDS, toInsertFluidsList);
tag.setTag(NBT_TOOK, RSUtils.serializeItemStackList(took));
NBTTagList fluidsTookList = new NBTTagList();
for (FluidStack took : this.tookFluids) {
fluidsTookList.appendTag(took.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_TOOK_FLUIDS, fluidsTookList);
tag.setTag(NBT_TOOK_FLUIDS, RSUtils.serializeFluidStackList(tookFluids));
return tag;
}
@Override
public List<ICraftingMonitorElement> getCraftingMonitorElements() {
List<ICraftingMonitorElement> elements = new ArrayList<>();
ICraftingMonitorElementList elements = API.instance().createCraftingMonitorElementList();
elements.add(new CraftingMonitorElementItemRender(
elements.directAdd(new CraftingMonitorElementItemRender(
network.getCraftingTasks().indexOf(this),
requested != null ? requested : pattern.getOutputs().get(0),
quantity,
0
));
if (isFinished() && !toInsert.isEmpty()) {
elements.add(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 16));
if (!toInsertItems.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 16));
elements.addAll(toInsert.stream()
toInsertItems.stream()
.map(stack -> new CraftingMonitorElementItemRender(
-1,
stack,
stack.stackSize,
32
))
.collect(Collectors.toList())
);
} else {
if (!toTake.isEmpty()) {
elements.add(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_taking", 16));
.forEach(elements::add);
elements.addAll(toTake.getStacks().stream()
.map(stack -> new CraftingMonitorElementItemRender(
-1,
stack,
stack.stackSize,
32
))
.collect(Collectors.toList())
);
elements.commit();
}
if (!toTakeFluids.isEmpty()) {
elements.add(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.fluids_taking", 16));
if (!isFinished()) {
if (steps.stream().filter(s -> !s.getPattern().isProcessing()).count() > 0) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_crafting", 16));
elements.addAll(toTakeFluids.getStacks().stream()
.map(stack -> new CraftingMonitorElementFluidRender(
-1,
stack,
32
))
.collect(Collectors.toList())
);
}
if (!hasProcessedItems()) {
elements.add(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_processing", 16));
for (IProcessable processable : toProcess) {
for (ICraftingStep processable : steps.stream().filter(s -> !s.getPattern().isProcessing()).collect(Collectors.toList())) {
for (int i = 0; i < processable.getPattern().getOutputs().size(); ++i) {
elements.add(new CraftingMonitorElementItemRender(
-1,
processable.getPattern().getOutputs().get(i),
processable.getPattern().getOutputs().get(i).stackSize,
32
));
}
}
elements.commit();
}
if (steps.stream().filter(s -> s.getPattern().isProcessing()).count() > 0) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_processing", 16));
for (ICraftingStep processable : steps.stream().filter(s -> s.getPattern().isProcessing()).collect(Collectors.toList())) {
for (int i = 0; i < processable.getPattern().getOutputs().size(); ++i) {
if (!processable.hasReceivedOutput(i)) {
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(
-1,
processable.getPattern().getOutputs().get(i),
@@ -478,11 +423,25 @@ public class CraftingTask implements ICraftingTask {
elements.add(element);
}
}
elements.commit();
}
if (!toTakeFluids.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.fluids_taking", 16));
toTakeFluids.getStacks().stream()
.map(stack -> new CraftingMonitorElementFluidRender(
-1,
stack,
32
)).forEach(elements::add);
elements.commit();
}
}
return elements;
return elements.getElements();
}
@Override
@@ -490,9 +449,8 @@ public class CraftingTask implements ICraftingTask {
return pattern;
}
@Override
public List<IProcessable> getToProcess() {
return toProcess;
public List<ICraftingStep> getSteps() {
return steps;
}
@Override
@@ -547,10 +505,6 @@ public class CraftingTask implements ICraftingTask {
}
private boolean isFinished() {
return toTake.isEmpty() && internalToTake.isEmpty() && toTakeFluids.isEmpty() && missing.isEmpty() && hasProcessedItems();
}
private boolean hasProcessedItems() {
return toProcess.stream().allMatch(IProcessable::hasReceivedOutputs);
return steps.stream().allMatch(ICraftingStep::hasReceivedOutputs);
}
}

View File

@@ -0,0 +1,40 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import java.util.Deque;
public class ProcessCraftingStep extends AbstractCraftingStep {
public static final String ID = "ProcessCraftingStep";
public ProcessCraftingStep(INetworkMaster network, ICraftingPattern pattern) {
super(network, pattern);
}
public ProcessCraftingStep(INetworkMaster network) {
super(network);
}
@Override
public void execute(Deque<ItemStack> toInsertItems, Deque<FluidStack> toInsertFluids) {
// TODO fluid handling
IItemHandler inventory = getPattern().getContainer().getFacingInventory();
for (ItemStack insertStack : getToInsert()) {
ItemStack tookStack = network.extractItem(insertStack, insertStack.stackSize, CraftingTask.DEFAULT_COMPARE | (getPattern().isOredict() ? IComparer.COMPARE_OREDICT : 0));
ItemHandlerHelper.insertItem(inventory, tookStack, false);
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
tag.setString(NBT_CRAFTING_STEP_TYPE, ID);
return super.writeToNBT(tag);
}
}

View File

@@ -3,12 +3,15 @@ package com.raoulvdberge.refinedstorage.apiimpl.util;
import com.google.common.collect.ArrayListMultimap;
import com.raoulvdberge.refinedstorage.api.util.IFluidStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
public class FluidStackList implements IFluidStackList {
private ArrayListMultimap<Fluid, FluidStack> stacks = ArrayListMultimap.create();
@@ -31,12 +34,13 @@ public class FluidStackList implements IFluidStackList {
for (FluidStack otherStack : stacks.get(stack.getFluid())) {
if (stack.isFluidEqual(otherStack)) {
otherStack.amount -= size;
boolean success = otherStack.amount >= 0;
if (otherStack.amount <= 0 && removeIfReachedZero) {
stacks.remove(otherStack.getFluid(), otherStack);
}
return true;
return success;
}
}
@@ -72,6 +76,14 @@ public class FluidStackList implements IFluidStackList {
stacks.clear();
}
@Override
public void clean() {
List<FluidStack> toRemove = stacks.values().stream()
.filter(stack -> stack.amount <= 0)
.collect(Collectors.toList());
toRemove.forEach(stack -> stacks.remove(stack.getFluid(), stack));
}
@Override
public boolean isEmpty() {
return stacks.isEmpty();

View File

@@ -38,12 +38,13 @@ public class ItemStackList implements IItemStackList {
for (ItemStack otherStack : stacks.get(stack.getItem())) {
if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) {
otherStack.stackSize -= size;
boolean success = otherStack.stackSize >= 0;
if (otherStack.stackSize <= 0 && removeIfReachedZero) {
stacks.remove(otherStack.getItem(), otherStack);
}
return true;
return success;
}
}

View File

@@ -10,7 +10,7 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContaine
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternProvider;
import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskFactory;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.IProcessable;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.network.INetworkNode;
import com.raoulvdberge.refinedstorage.api.network.INetworkNodeGraph;
@@ -290,14 +290,16 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR
craftingTasksToAdd.clear();
// Only run task updates every 5 ticks
if (ticks % 5 == 0) {
Iterator<ICraftingTask> craftingTaskIterator = craftingTasks.iterator();
Map<ICraftingPatternContainer, Integer> usedCrafters = new HashMap<>();
while (craftingTaskIterator.hasNext()) {
ICraftingTask task = craftingTaskIterator.next();
ICraftingPatternContainer container = task.getPattern().getContainer();
if (container != null && ticks % container.getSpeed() == 0 && task.update()) {
if (task.update(usedCrafters)) {
craftingTaskIterator.remove();
craftingTasksChanged = true;
@@ -311,6 +313,7 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR
if (!craftingTasks.isEmpty()) {
markDirty();
}
}
if (craftingMonitorUpdateRequested) {
craftingMonitorUpdateRequested = false;
@@ -321,6 +324,7 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR
}
}
}
}
wirelessGridHandler.update();
@@ -457,7 +461,7 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR
for (ItemStack input : patterns.get(i).getInputs()) {
if (input != null) {
ItemStack stored = itemStorage.getList().get(input, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT);
ItemStack stored = itemStorage.getList().get(input, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (patterns.get(i).isOredict() ? IComparer.COMPARE_OREDICT : 0));
score += stored != null ? stored.stackSize : 0;
}
@@ -578,20 +582,10 @@ public class TileController extends TileBase implements INetworkMaster, IEnergyR
if (!simulate && inserted > 0 && accessType != AccessType.WRITE) {
itemStorage.add(ItemHandlerHelper.copyStackWithSize(stack, inserted), false);
for (int i = 0; i < inserted; ++i) {
for (ICraftingTask task : craftingTasks) {
if (inserted == 0) {
break;
}
for (IProcessable processable : task.getToProcess()) {
if (inserted == 0) {
break;
}
for (ICraftingStep processable : task.getSteps()) {
if (processable.onReceiveOutput(stack)) {
inserted--;
}
break;
}
}
}

View File

@@ -152,8 +152,8 @@ public class TileCrafter extends TileNode implements ICraftingPatternContainer {
}
@Override
public int getSpeed() {
return 20 - (upgrades.getUpgradeCount(ItemUpgrade.TYPE_SPEED) * 4);
public int getSpeedUpdateCount() {
return upgrades.getUpgradeCount(ItemUpgrade.TYPE_SPEED);
}
@Override

View File

@@ -19,8 +19,8 @@ gui.refinedstorage:relay=Relay
gui.refinedstorage:interface.import=Interface Import
gui.refinedstorage:interface.export=Interface Export
gui.refinedstorage:crafting_monitor=Crafting Monitor
gui.refinedstorage:crafting_monitor.items_taking=Items taking
gui.refinedstorage:crafting_monitor.fluids_taking=Fluids taking
gui.refinedstorage:crafting_monitor.items_crafting=Items crafting
gui.refinedstorage:crafting_monitor.items_processing=Items processing
gui.refinedstorage:crafting_monitor.items_inserting=Items inserting
gui.refinedstorage:crafting_monitor.machine_in_use=Machine is in use