diff --git a/src/main/java/com/raoulvdberge/refinedstorage/RSUtils.java b/src/main/java/com/raoulvdberge/refinedstorage/RSUtils.java index 9d3d7ae94..d4ea1eeea 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/RSUtils.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/RSUtils.java @@ -92,7 +92,7 @@ public final class RSUtils { if (network != null) { buf.writeInt(API.instance().getItemStackHashCode(stack)); - buf.writeBoolean(network.hasPattern(stack)); + buf.writeBoolean(network.getCraftingManager().hasPattern(stack)); buf.writeBoolean(displayCraftText); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java new file mode 100644 index 000000000..82b8825a4 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/autocrafting/ICraftingManager.java @@ -0,0 +1,120 @@ +package com.raoulvdberge.refinedstorage.api.autocrafting; + +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; +import com.raoulvdberge.refinedstorage.api.util.IComparer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public interface ICraftingManager { + /** + * @return the crafting tasks in this network, do NOT modify this list + */ + List getTasks(); + + /** + * Adds a crafting task. + * + * @param task the task to add + */ + void add(@Nonnull ICraftingTask task); + + /** + * Cancels a crafting task. + * + * @param task the task to cancel + */ + void cancel(@Nonnull ICraftingTask task); + + /** + * Creates a crafting task. + * + * @param stack the stack to create a task for + * @param pattern the pattern + * @param quantity the quantity + * @return the crafting task + */ + ICraftingTask create(@Nullable ItemStack stack, ICraftingPattern pattern, int quantity); + + /** + * Schedules a crafting task if the task isn't scheduled yet. + * + * @param stack the stack + * @param toSchedule the amount of tasks to schedule + * @param compare the compare value to find patterns + * @return the crafting task created, or null if no task is created + */ + @Nullable + ICraftingTask schedule(ItemStack stack, int toSchedule, int compare); + + /** + * Tracks an incoming stack. + * + * @param stack the stack + */ + void track(ItemStack stack, int size); + + /** + * @return a list of crafting patterns in this network, do NOT modify this list + */ + List getPatterns(); + + /** + * Rebuilds the pattern list. + */ + void rebuild(); + + /** + * Returns crafting patterns from an item stack. + * + * @param pattern the stack to get a pattern for + * @param flags the flags to compare on, see {@link IComparer} + * @return a list of crafting patterns where the given pattern is one of the outputs + */ + List getPatterns(ItemStack pattern, int flags); + + /** + * Returns a crafting pattern for an item stack. + * This returns a single crafting pattern, as opposed to {@link ICraftingManager#getPatterns(ItemStack, int)}. + * Internally, this makes a selection out of the available patterns. + * It makes this selection based on the item count of the pattern outputs in the system. + * + * @param pattern the stack to get a pattern for + * @param flags the flags to compare on, see {@link IComparer} + * @return the pattern, or null if the pattern is not found + */ + @Nullable + ICraftingPattern getPattern(ItemStack pattern, int flags); + + /** + * Returns a crafting pattern for an item stack. + * This returns a single crafting pattern, as opposed to {@link ICraftingManager#getPatterns(ItemStack, int)}. + * Internally, this makes a selection out of the available patterns. + * It makes this selection based on the item count of the pattern outputs in the system. + * + * @param pattern the stack to get a pattern for + * @return the pattern, or null if the pattern is not found + */ + default ICraftingPattern getPattern(ItemStack pattern) { + return getPattern(pattern, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT); + } + + /** + * Returns if there is a pattern with a given stack as output. + * + * @param stack the stack + * @return true if there is a pattern, false otherwise + */ + default boolean hasPattern(ItemStack stack) { + return getPattern(stack) != null; + } + + void update(); + + void readFromNBT(NBTTagCompound tag); + + NBTTagCompound writeToNBT(NBTTagCompound tag); +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java b/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java index 71a7388f5..e87e83d70 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/network/INetworkMaster.java @@ -1,7 +1,6 @@ package com.raoulvdberge.refinedstorage.api.network; -import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; -import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; +import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingManager; import com.raoulvdberge.refinedstorage.api.network.grid.IFluidGridHandler; import com.raoulvdberge.refinedstorage.api.network.grid.IItemGridHandler; import com.raoulvdberge.refinedstorage.api.network.item.INetworkItemHandler; @@ -9,7 +8,6 @@ import com.raoulvdberge.refinedstorage.api.network.readerwriter.IReaderWriterCha import com.raoulvdberge.refinedstorage.api.network.security.ISecurityManager; import com.raoulvdberge.refinedstorage.api.storage.IStorageCache; import com.raoulvdberge.refinedstorage.api.util.IComparer; -import com.raoulvdberge.refinedstorage.apiimpl.API; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; @@ -18,7 +16,6 @@ import net.minecraftforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.List; /** * Represents a network master, usually is a controller. @@ -49,6 +46,11 @@ public interface INetworkMaster { */ ISecurityManager getSecurityManager(); + /** + * @return the {@link ICraftingManager} of this network + */ + ICraftingManager getCraftingManager(); + /** * @return the {@link IItemGridHandler} of this network */ @@ -74,103 +76,6 @@ public interface INetworkMaster { */ IStorageCache getFluidStorageCache(); - /** - * @return the crafting tasks in this network, do NOT modify this list - */ - List getCraftingTasks(); - - /** - * Adds a crafting task. - * - * @param task the task to add - */ - void addCraftingTask(@Nonnull ICraftingTask task); - - /** - * Cancels a crafting task. - * - * @param task the task to cancel - */ - void cancelCraftingTask(@Nonnull ICraftingTask task); - - /** - * @return a list of crafting patterns in this network, do NOT modify this list - */ - List getPatterns(); - - /** - * Rebuilds the pattern list. - */ - void rebuildPatterns(); - - /** - * Returns crafting patterns from an item stack. - * - * @param pattern the stack to get a pattern for - * @param flags the flags to compare on, see {@link IComparer} - * @return a list of crafting patterns where the given pattern is one of the outputs - */ - List getPatterns(ItemStack pattern, int flags); - - /** - * Returns a crafting pattern for an item stack. - * This returns a single crafting pattern, as opposed to {@link INetworkMaster#getPatterns(ItemStack, int)}. - * Internally, this makes a selection out of the available patterns. - * It makes this selection based on the item count of the pattern outputs in the system. - * - * @param pattern the stack to get a pattern for - * @param flags the flags to compare on, see {@link IComparer} - * @return the pattern, or null if the pattern is not found - */ - @Nullable - ICraftingPattern getPattern(ItemStack pattern, int flags); - - /** - * Returns a crafting pattern for an item stack. - * This returns a single crafting pattern, as opposed to {@link INetworkMaster#getPatterns(ItemStack, int)}. - * Internally, this makes a selection out of the available patterns. - * It makes this selection based on the item count of the pattern outputs in the system. - * - * @param pattern the stack to get a pattern for - * @return the pattern, or null if the pattern is not found - */ - default ICraftingPattern getPattern(ItemStack pattern) { - return getPattern(pattern, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT); - } - - /** - * Returns if there is a pattern with a given stack as output. - * - * @param stack the stack - * @return true if there is a pattern, false otherwise - */ - default boolean hasPattern(ItemStack stack) { - return getPattern(stack) != null; - } - - /** - * Creates a crafting task. - * - * @param stack the stack to create a task for - * @param pattern the pattern - * @param quantity the quantity - * @return the crafting task - */ - default ICraftingTask createCraftingTask(@Nullable ItemStack stack, ICraftingPattern pattern, int quantity) { - return API.instance().getCraftingTaskRegistry().get(pattern.getId()).create(getNetworkWorld(), this, stack, pattern, quantity, null); - } - - /** - * Schedules a crafting task if the task isn't scheduled yet. - * - * @param stack the stack - * @param toSchedule the amount of tasks to schedule - * @param compare the compare value to find patterns - * @return the crafting task created, or null if no task is created - */ - @Nullable - ICraftingTask scheduleCraftingTask(ItemStack stack, int toSchedule, int compare); - /** * Sends a grid update packet with all the items to all clients that are watching a grid connected to this network. */ @@ -271,6 +176,16 @@ public interface INetworkMaster { @Nullable ItemStack insertItem(@Nonnull ItemStack stack, int size, boolean simulate); + default ItemStack insertItemTracked(@Nonnull ItemStack stack, int size) { + ItemStack remainder = insertItem(stack, size, false); + + int inserted = remainder == null ? size : (size - remainder.getCount()); + + getCraftingManager().track(stack, inserted); + + return remainder; + } + /** * Extracts an item from this network. * diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java new file mode 100644 index 000000000..689d0ed91 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/CraftingManager.java @@ -0,0 +1,271 @@ +package com.raoulvdberge.refinedstorage.apiimpl.autocrafting; + +import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingManager; +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.registry.ICraftingTaskFactory; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep; +import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; +import com.raoulvdberge.refinedstorage.api.network.INetworkMaster; +import com.raoulvdberge.refinedstorage.api.network.INetworkNode; +import com.raoulvdberge.refinedstorage.api.util.IComparer; +import com.raoulvdberge.refinedstorage.api.util.IStackList; +import com.raoulvdberge.refinedstorage.apiimpl.API; +import com.raoulvdberge.refinedstorage.tile.TileController; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.items.ItemHandlerHelper; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; + +public class CraftingManager implements ICraftingManager { + private static final String NBT_CRAFTING_TASKS = "CraftingTasks"; + + private TileController network; + + private List patterns = new ArrayList<>(); + + private List craftingTasks = new ArrayList<>(); + private List craftingTasksToAdd = new ArrayList<>(); + private List craftingTasksToCancel = new ArrayList<>(); + private List craftingTasksToRead = new ArrayList<>(); + + private int ticks; + + public CraftingManager(TileController network) { + this.network = network; + } + + @Override + public List getTasks() { + return craftingTasks; + } + + @Override + public void add(@Nonnull ICraftingTask task) { + craftingTasksToAdd.add(task); + + network.markDirty(); + } + + @Override + public void cancel(@Nonnull ICraftingTask task) { + craftingTasksToCancel.add(task); + + network.markDirty(); + } + + @Override + public ICraftingTask create(@Nullable ItemStack stack, ICraftingPattern pattern, int quantity) { + return API.instance().getCraftingTaskRegistry().get(pattern.getId()).create(network.getNetworkWorld(), network, stack, pattern, quantity, null); + } + + @Override + public List getPatterns() { + return patterns; + } + + @Override + public List getPatterns(ItemStack pattern, int flags) { + List patterns = new ArrayList<>(); + + for (ICraftingPattern craftingPattern : getPatterns()) { + for (ItemStack output : craftingPattern.getOutputs()) { + if (API.instance().getComparer().isEqual(output, pattern, flags)) { + patterns.add(craftingPattern); + } + } + } + + return patterns; + } + + @Override + public ICraftingPattern getPattern(ItemStack pattern, int flags) { + List patterns = getPatterns(pattern, flags); + + if (patterns.isEmpty()) { + return null; + } else if (patterns.size() == 1) { + return patterns.get(0); + } + + int highestScore = 0; + int highestPattern = 0; + + IStackList itemList = network.getItemStorageCache().getList().getOredicted(); + + for (int i = 0; i < patterns.size(); ++i) { + int score = 0; + + for (ItemStack input : patterns.get(i).getInputs()) { + if (input != null) { + ItemStack stored = itemList.get(input, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (patterns.get(i).isOredict() ? IComparer.COMPARE_OREDICT : 0)); + + score += stored != null ? stored.getCount() : 0; + } + } + + if (score > highestScore) { + highestScore = score; + highestPattern = i; + } + } + + return patterns.get(highestPattern); + } + + @Override + public void update() { + if (!craftingTasksToRead.isEmpty()) { + for (NBTTagCompound tag : craftingTasksToRead) { + ICraftingTask task = readCraftingTask(network.getNetworkWorld(), network, tag); + + if (task != null) { + add(task); + } + } + + craftingTasksToRead.clear(); + } + + if (network.canRun()) { + boolean craftingTasksChanged = !craftingTasksToAdd.isEmpty() || !craftingTasksToCancel.isEmpty(); + + craftingTasksToCancel.forEach(ICraftingTask::onCancelled); + craftingTasks.removeAll(craftingTasksToCancel); + craftingTasksToCancel.clear(); + + craftingTasksToAdd.stream().filter(ICraftingTask::isValid).forEach(craftingTasks::add); + craftingTasksToAdd.clear(); + + // Only run task updates every 5 ticks + if (ticks++ % 5 == 0) { + Iterator craftingTaskIterator = craftingTasks.iterator(); + Map usedCrafters = new HashMap<>(); + + while (craftingTaskIterator.hasNext()) { + ICraftingTask task = craftingTaskIterator.next(); + + if (task.update(usedCrafters)) { + craftingTaskIterator.remove(); + + craftingTasksChanged = true; + } else if (!task.getMissing().isEmpty() && ticks % 100 == 0 && Math.random() > 0.5) { + task.getMissing().clear(); + } + } + + if (craftingTasksChanged) { + network.getNetwork().markCraftingMonitorForUpdate(); + } + } + } + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + if (tag.hasKey(NBT_CRAFTING_TASKS)) { + NBTTagList taskList = tag.getTagList(NBT_CRAFTING_TASKS, Constants.NBT.TAG_COMPOUND); + + for (int i = 0; i < taskList.tagCount(); ++i) { + craftingTasksToRead.add(taskList.getCompoundTagAt(i)); + } + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound tag) { + NBTTagList craftingTaskList = new NBTTagList(); + + for (ICraftingTask task : craftingTasks) { + craftingTaskList.appendTag(task.writeToNBT(new NBTTagCompound())); + } + + tag.setTag(NBT_CRAFTING_TASKS, craftingTaskList); + + return tag; + } + + @Override + public ICraftingTask schedule(ItemStack stack, int toSchedule, int compare) { + for (ICraftingTask task : getTasks()) { + for (ItemStack output : task.getPattern().getOutputs()) { + if (API.instance().getComparer().isEqual(output, stack, compare)) { + toSchedule -= output.getCount() * task.getQuantity(); + } + } + } + + if (toSchedule > 0) { + ICraftingPattern pattern = getPattern(stack, compare); + + if (pattern != null) { + ICraftingTask task = create(stack, pattern, toSchedule); + + task.calculate(); + task.getMissing().clear(); + + add(task); + + network.markCraftingMonitorForUpdate(); + + return task; + } + } + + return null; + } + + @Override + public void track(ItemStack stack, int size) { + ItemStack inserted = ItemHandlerHelper.copyStackWithSize(stack, size); + + for (ICraftingTask task : craftingTasks) { + for (ICraftingStep processable : task.getSteps()) { + if (processable.onReceiveOutput(inserted)) { + return; + } + } + } + } + + @Override + public void rebuild() { + patterns.clear(); + + for (INetworkNode node : network.getNodeGraph().all()) { + if (node instanceof ICraftingPatternContainer && node.canUpdate()) { + patterns.addAll(((ICraftingPatternContainer) node).getPatterns()); + } + } + } + + private static ICraftingTask readCraftingTask(World world, INetworkMaster network, NBTTagCompound tag) { + ItemStack stack = new ItemStack(tag.getCompoundTag(ICraftingTask.NBT_PATTERN_STACK)); + + if (!stack.isEmpty() && stack.getItem() instanceof ICraftingPatternProvider) { + TileEntity container = world.getTileEntity(BlockPos.fromLong(tag.getLong(ICraftingTask.NBT_PATTERN_CONTAINER))); + + if (container instanceof ICraftingPatternContainer) { + ICraftingPattern pattern = ((ICraftingPatternProvider) stack.getItem()).create(world, stack, (ICraftingPatternContainer) container); + + ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(tag.getString(ICraftingTask.NBT_PATTERN_ID)); + + if (factory != null) { + return factory.create(world, network, tag.hasKey(ICraftingTask.NBT_REQUESTED) ? new ItemStack(tag.getCompoundTag(ICraftingTask.NBT_REQUESTED)) : null, pattern, tag.getInteger(ICraftingTask.NBT_QUANTITY), tag); + } + } + } + + return null; + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java index b24e11637..167d0282c 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/autocrafting/task/CraftingTask.java @@ -139,7 +139,7 @@ public class CraftingTask implements ICraftingTask { ICraftingPattern inputPattern = null; int available = (extraStack == null ? 0 : extraStack.getCount()) + (networkStack == null ? 0 : networkStack.getCount()); if (available < input.getCount()) { - inputPattern = network.getPattern(input, compare); + inputPattern = network.getCraftingManager().getPattern(input, compare); if (inputPattern != null) { if (inputPattern.getInputs().stream().anyMatch(s -> API.instance().getComparer().isEqual(s, input, lambdaCompare))) { int craftQuantity = inputPattern.getQuantityPerRequest(input, compare); @@ -179,7 +179,7 @@ public class CraftingTask implements ICraftingTask { } } else { if (inputPattern == null) { - inputPattern = network.getPattern(input, compare); + inputPattern = network.getCraftingManager().getPattern(input, compare); } if (inputPattern != null) { @@ -264,7 +264,7 @@ public class CraftingTask implements ICraftingTask { } } - ICraftingPattern bucketPattern = network.getPattern(RSUtils.EMPTY_BUCKET); + ICraftingPattern bucketPattern = network.getCraftingManager().getPattern(RSUtils.EMPTY_BUCKET); if (!hasBucket) { if (bucketPattern == null) { @@ -456,7 +456,7 @@ public class CraftingTask implements ICraftingTask { ICraftingMonitorElementList elements = API.instance().createCraftingMonitorElementList(); elements.directAdd(new CraftingMonitorElementItemRender( - network.getCraftingTasks().indexOf(this), + network.getCraftingManager().getTasks().indexOf(this), requested != null ? requested : pattern.getOutputs().get(0), quantity, 0 diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java index d43b893d1..e3f426a37 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/grid/ItemGridHandler.java @@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.apiimpl.network.grid; import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.RSUtils; +import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingManager; import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern; import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask; import com.raoulvdberge.refinedstorage.api.network.INetworkMaster; @@ -155,7 +156,7 @@ public class ItemGridHandler implements IItemGridHandler { IStackList cache = API.instance().createItemStackList(); - for (ICraftingPattern pattern : network.getPatterns()) { + for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) { for (ItemStack output : pattern.getOutputs()) { if (output != null) { cache.add(output); @@ -167,7 +168,7 @@ public class ItemGridHandler implements IItemGridHandler { if (stack != null) { Thread calculationThread = new Thread(() -> { - ICraftingTask task = new CraftingTask(network, stack, network.getPattern(stack), quantity); + ICraftingTask task = new CraftingTask(network, stack, network.getCraftingManager().getPattern(stack), quantity); task.calculate(); @@ -185,13 +186,13 @@ public class ItemGridHandler implements IItemGridHandler { } if (stack != null) { - ICraftingTask task = new CraftingTask(network, stack, network.getPattern(stack), quantity); + ICraftingTask task = new CraftingTask(network, stack, network.getCraftingManager().getPattern(stack), quantity); task.calculate(); task.getMissing().clear(); - network.addCraftingTask(task); + network.getCraftingManager().add(task); } } @@ -201,11 +202,13 @@ public class ItemGridHandler implements IItemGridHandler { return; } - if (id >= 0 && id < network.getCraftingTasks().size()) { - network.cancelCraftingTask(network.getCraftingTasks().get(id)); + ICraftingManager manager = network.getCraftingManager(); + + if (id >= 0 && id < manager.getTasks().size()) { + manager.cancel(manager.getTasks().get(id)); } else if (id == -1) { - for (ICraftingTask task : network.getCraftingTasks()) { - network.cancelCraftingTask(task); + for (ICraftingTask task : manager.getTasks()) { + manager.cancel(task); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java index dd1a3cac5..6f041d4b9 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java @@ -187,7 +187,7 @@ public class NetworkNodeConstructor extends NetworkNode implements IComparable, } else if (upgrades.hasUpgrade(ItemUpgrade.TYPE_CRAFTING)) { ItemStack craft = itemFilters.getStackInSlot(0); - network.scheduleCraftingTask(craft, 1, compare); + network.getCraftingManager().schedule(craft, 1, compare); } } } @@ -200,7 +200,7 @@ public class NetworkNodeConstructor extends NetworkNode implements IComparable, } else if (upgrades.hasUpgrade(ItemUpgrade.TYPE_CRAFTING)) { ItemStack craft = itemFilters.getStackInSlot(0); - network.scheduleCraftingTask(craft, 1, compare); + network.getCraftingManager().schedule(craft, 1, compare); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java index d81db905a..8e44ebad0 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCrafter.java @@ -44,7 +44,7 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC } if (network != null) { - network.rebuildPatterns(); + network.getCraftingManager().rebuild(); } } }; @@ -99,7 +99,7 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC if (network != null && triggeredAutocrafting && holder.world().isBlockPowered(holder.pos())) { for (ICraftingPattern pattern : actualPatterns) { for (ItemStack output : pattern.getOutputs()) { - network.scheduleCraftingTask(output, 1, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT); + network.getCraftingManager().schedule(output, 1, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT); } } } @@ -110,12 +110,12 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC super.onConnectedStateChange(network, state); if (!state) { - network.getCraftingTasks().stream() + network.getCraftingManager().getTasks().stream() .filter(task -> task.getPattern().getContainer().getPosition().equals(holder.pos())) - .forEach(network::cancelCraftingTask); + .forEach(task -> network.getCraftingManager().cancel(task)); } - network.rebuildPatterns(); + network.getCraftingManager().rebuild(); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java index 1c138c3a1..cfddcee78 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java @@ -85,7 +85,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I ItemStack droppedItem = ((EntityItem) entity).getEntityItem(); if (IFilterable.canTake(itemFilters, mode, compare, droppedItem) && network.insertItem(droppedItem, droppedItem.getCount(), true) == null) { - network.insertItem(droppedItem.copy(), droppedItem.getCount(), false); + network.insertItemTracked(droppedItem.copy(), droppedItem.getCount()); holder.world().removeEntity(entity); @@ -127,7 +127,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I if (network == null) { InventoryHelper.spawnItemStack(holder.world(), front.getX(), front.getY(), front.getZ(), drop); } else { - network.insertItem(drop, drop.getCount(), false); + network.insertItemTracked(drop, drop.getCount()); } } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDetector.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDetector.java index a53e68781..6383551f4 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDetector.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDetector.java @@ -73,7 +73,7 @@ public class NetworkNodeDetector extends NetworkNode implements IComparable, ITy if (mode == MODE_AUTOCRAFTING) { boolean found = false; - for (ICraftingTask task : network.getCraftingTasks()) { + for (ICraftingTask task : network.getCraftingManager().getTasks()) { for (ItemStack output : task.getPattern().getOutputs()) { if (API.instance().getComparer().isEqualNoQuantity(slot, output)) { found = true; @@ -94,7 +94,7 @@ public class NetworkNodeDetector extends NetworkNode implements IComparable, ITy powered = isPowered(stack == null ? null : stack.getCount()); } } else { - powered = mode == MODE_AUTOCRAFTING ? !network.getCraftingTasks().isEmpty() : isPowered(network.getItemStorageCache().getList().getStacks().stream().map(s -> s.getCount()).mapToInt(Number::intValue).sum()); + powered = mode == MODE_AUTOCRAFTING ? !network.getCraftingManager().getTasks().isEmpty() : isPowered(network.getItemStorageCache().getList().getStacks().stream().map(s -> s.getCount()).mapToInt(Number::intValue).sum()); } } else if (type == IType.FLUIDS) { FluidStack slot = fluidFilters.getFluidStackInSlot(0); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java index f5c2f77b9..d2d593bc9 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java @@ -68,7 +68,7 @@ public class NetworkNodeExporter extends NetworkNode implements IComparable, ITy if (craftOnly) { if (craftOnlyTask[i] == null) { - craftOnlyTask[i] = network.scheduleCraftingTask(slot, upgrades.getItemInteractCount(), compare); + craftOnlyTask[i] = network.getCraftingManager().schedule(slot, upgrades.getItemInteractCount(), compare); if (craftOnlyTask[i] != null) { craftOnlyToExtract[i] = craftOnlyTask[i].getPattern().getQuantityPerRequest(slot, compare); @@ -90,7 +90,7 @@ public class NetworkNodeExporter extends NetworkNode implements IComparable, ITy craftOnlyTask[i] = null; } } - } else if (!network.getCraftingTasks().contains(craftOnlyTask[i])) { + } else if (!network.getCraftingManager().getTasks().contains(craftOnlyTask[i])) { craftOnlyTask[i] = null; } } else { @@ -120,7 +120,7 @@ public class NetworkNodeExporter extends NetworkNode implements IComparable, ITy if (took == null) { if (upgrades.hasUpgrade(ItemUpgrade.TYPE_CRAFTING)) { - network.scheduleCraftingTask(slot, 1, compare); + network.getCraftingManager().schedule(slot, 1, compare); } } else if (ItemHandlerHelper.insertItem(handler, took, true).isEmpty()) { took = network.extractItem(slot, upgrades.getItemInteractCount(), compare, false); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java index 38c1eb452..824dc8f5d 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java @@ -72,7 +72,7 @@ public class NetworkNodeImporter extends NetworkNode implements IComparable, IFi ItemStack result = handler.extractItem(currentSlot, upgrades.getItemInteractCount(), true); if (!result.isEmpty() && network.insertItem(result, result.getCount(), true) == null) { - network.insertItem(result, result.getCount(), false); + network.insertItemTracked(result, result.getCount()); handler.extractItem(currentSlot, upgrades.getItemInteractCount(), false); } else { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java index b42b71744..c1a0ab287 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java @@ -59,7 +59,7 @@ public class NetworkNodeInterface extends NetworkNode implements IComparable { } else if (ticks % upgrades.getSpeed() == 0) { int size = Math.min(slot.getCount(), upgrades.getItemInteractCount()); - ItemStack remainder = network.insertItem(slot, size, false); + ItemStack remainder = network.insertItemTracked(slot, size); if (remainder == null) { importItems.extractItemInternal(currentSlot, size, false); @@ -76,7 +76,7 @@ public class NetworkNodeInterface extends NetworkNode implements IComparable { if (wanted.isEmpty()) { if (!got.isEmpty()) { - exportItems.setStackInSlot(i, RSUtils.getStack(network.insertItem(got, got.getCount(), false))); + exportItems.setStackInSlot(i, RSUtils.getStack(network.insertItemTracked(got, got.getCount()))); } } else { int delta = got.isEmpty() ? wanted.getCount() : (wanted.getCount() - got.getCount()); @@ -91,10 +91,10 @@ public class NetworkNodeInterface extends NetworkNode implements IComparable { exportItems.getStackInSlot(i).grow(result.getCount()); } } else if (upgrades.hasUpgrade(ItemUpgrade.TYPE_CRAFTING)) { - network.scheduleCraftingTask(wanted, delta, compare); + network.getCraftingManager().schedule(wanted, delta, compare); } } else if (delta < 0) { - ItemStack remainder = network.insertItem(got, Math.abs(delta), false); + ItemStack remainder = network.insertItemTracked(got, Math.abs(delta)); if (remainder == null) { exportItems.extractItem(i, Math.abs(delta), false); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java index d96f8bbbb..40ab3bca5 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/network/MessageGridItemUpdate.java @@ -45,7 +45,7 @@ public class MessageGridItemUpdate implements IMessage, IMessageHandler o != null).count(); } @@ -55,7 +55,7 @@ public class MessageGridItemUpdate implements IMessage, IMessageHandler itemStorage = new StorageCacheItem(this); @@ -170,13 +163,6 @@ public class TileController extends TileBase implements INetworkMaster, IRedston private Map readerWriterChannels = new HashMap<>(); - private List patterns = new ArrayList<>(); - - private List craftingTasks = new ArrayList<>(); - private List craftingTasksToAdd = new ArrayList<>(); - private List craftingTasksToCancel = new ArrayList<>(); - private List craftingTasksToRead = new ArrayList<>(); - private ControllerEnergyForge energy = new ControllerEnergyForge(); private ControllerEnergyTesla energyTesla; @@ -226,55 +212,19 @@ public class TileController extends TileBase implements INetworkMaster, IRedston return securityManager; } + @Override + public ICraftingManager getCraftingManager() { + return craftingManager; + } + @Override public void update() { if (!getWorld().isRemote) { - if (!craftingTasksToRead.isEmpty()) { - for (NBTTagCompound tag : craftingTasksToRead) { - ICraftingTask task = readCraftingTask(getWorld(), this, tag); - - if (task != null) { - addCraftingTask(task); - } - } - - craftingTasksToRead.clear(); - } - if (canRun()) { Collections.sort(itemStorage.getStorages(), STORAGE_COMPARATOR); Collections.sort(fluidStorage.getStorages(), STORAGE_COMPARATOR); - boolean craftingTasksChanged = !craftingTasksToAdd.isEmpty() || !craftingTasksToCancel.isEmpty(); - - craftingTasksToCancel.forEach(ICraftingTask::onCancelled); - craftingTasks.removeAll(craftingTasksToCancel); - craftingTasksToCancel.clear(); - - craftingTasksToAdd.stream().filter(ICraftingTask::isValid).forEach(craftingTasks::add); - craftingTasksToAdd.clear(); - - // Only run task updates every 5 ticks - if (ticks % 5 == 0) { - Iterator craftingTaskIterator = craftingTasks.iterator(); - Map usedCrafters = new HashMap<>(); - - while (craftingTaskIterator.hasNext()) { - ICraftingTask task = craftingTaskIterator.next(); - - if (task.update(usedCrafters)) { - craftingTaskIterator.remove(); - - craftingTasksChanged = true; - } else if (!task.getMissing().isEmpty() && ticks % 100 == 0 && Math.random() > 0.5) { - task.getMissing().clear(); - } - } - - if (craftingTasksChanged) { - craftingMonitorUpdateRequested = true; - } - } + craftingManager.update(); for (IReaderWriterChannel channel : readerWriterChannels.values()) { for (IReaderWriterHandler handler : channel.getHandlers()) { @@ -282,7 +232,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston } } - if (!craftingTasks.isEmpty() || !readerWriterChannels.isEmpty()) { + if (!craftingManager.getTasks().isEmpty() || !readerWriterChannels.isEmpty()) { markDirty(); } @@ -363,121 +313,6 @@ public class TileController extends TileBase implements INetworkMaster, IRedston return fluidStorage; } - @Override - public List getCraftingTasks() { - return craftingTasks; - } - - @Override - public void addCraftingTask(@Nonnull ICraftingTask task) { - craftingTasksToAdd.add(task); - - markDirty(); - } - - @Override - public void cancelCraftingTask(@Nonnull ICraftingTask task) { - craftingTasksToCancel.add(task); - - markDirty(); - } - - @Override - public List getPatterns() { - return patterns; - } - - @Override - public List getPatterns(ItemStack pattern, int flags) { - List patterns = new ArrayList<>(); - - for (ICraftingPattern craftingPattern : getPatterns()) { - for (ItemStack output : craftingPattern.getOutputs()) { - if (API.instance().getComparer().isEqual(output, pattern, flags)) { - patterns.add(craftingPattern); - } - } - } - - return patterns; - } - - @Override - public ICraftingPattern getPattern(ItemStack pattern, int flags) { - List patterns = getPatterns(pattern, flags); - - if (patterns.isEmpty()) { - return null; - } else if (patterns.size() == 1) { - return patterns.get(0); - } - - int highestScore = 0; - int highestPattern = 0; - - IStackList itemList = itemStorage.getList().getOredicted(); - - for (int i = 0; i < patterns.size(); ++i) { - int score = 0; - - for (ItemStack input : patterns.get(i).getInputs()) { - if (input != null) { - ItemStack stored = itemList.get(input, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (patterns.get(i).isOredict() ? IComparer.COMPARE_OREDICT : 0)); - - score += stored != null ? stored.getCount() : 0; - } - } - - if (score > highestScore) { - highestScore = score; - highestPattern = i; - } - } - - return patterns.get(highestPattern); - } - - @Override - public ICraftingTask scheduleCraftingTask(ItemStack stack, int toSchedule, int compare) { - for (ICraftingTask task : getCraftingTasks()) { - for (ItemStack output : task.getPattern().getOutputs()) { - if (API.instance().getComparer().isEqual(output, stack, compare)) { - toSchedule -= output.getCount() * task.getQuantity(); - } - } - } - - if (toSchedule > 0) { - ICraftingPattern pattern = getPattern(stack, compare); - - if (pattern != null) { - ICraftingTask task = createCraftingTask(stack, pattern, toSchedule); - - task.calculate(); - task.getMissing().clear(); - - addCraftingTask(task); - - markCraftingMonitorForUpdate(); - - return task; - } - } - - return null; - } - - @Override - public void rebuildPatterns() { - patterns.clear(); - - for (INetworkNode node : nodeGraph.all()) { - if (node instanceof ICraftingPatternContainer && node.canUpdate()) { - patterns.addAll(((ICraftingPatternContainer) node).getPatterns()); - } - } - } - @Override public void sendItemStorageToClient() { getWorld().getMinecraftServer().getPlayerList().getPlayers().stream() @@ -540,7 +375,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston .collect(Collectors.toList()); if (!watchers.isEmpty()) { - List elements = getElements(); + List elements = craftingManager.getTasks().stream().flatMap(t -> t.getCraftingMonitorElements().stream()).collect(Collectors.toList()); watchers.forEach(player -> RS.INSTANCE.network.sendTo(new MessageCraftingMonitorElements(elements), player)); } @@ -548,7 +383,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston @Override public void sendCraftingMonitorUpdate(EntityPlayerMP player) { - RS.INSTANCE.network.sendTo(new MessageCraftingMonitorElements(getElements()), player); + RS.INSTANCE.network.sendTo(new MessageCraftingMonitorElements(craftingManager.getTasks().stream().flatMap(t -> t.getCraftingMonitorElements().stream()).collect(Collectors.toList())), player); } @Nullable @@ -592,10 +427,6 @@ public class TileController extends TileBase implements INetworkMaster, IRedston RS.INSTANCE.network.sendTo(new MessageReaderWriterUpdate(readerWriterChannels.keySet()), player); } - private List getElements() { - return craftingTasks.stream().flatMap(t -> t.getCraftingMonitorElements().stream()).collect(Collectors.toList()); - } - @Override public ItemStack insertItem(@Nonnull ItemStack stack, int size, boolean simulate) { if (stack.isEmpty() || itemStorage.getStorages().isEmpty()) { @@ -641,22 +472,8 @@ public class TileController extends TileBase implements INetworkMaster, IRedston } } - if (!simulate) { - if (inserted - insertedExternally > 0) { - itemStorage.add(stack, inserted - insertedExternally, false); - } - - if (inserted > 0) { - ItemStack checkSteps = ItemHandlerHelper.copyStackWithSize(stack, inserted); - - for (ICraftingTask task : craftingTasks) { - for (ICraftingStep processable : task.getSteps()) { - if (processable.onReceiveOutput(checkSteps)) { - return remainder; // All done - } - } - } - } + if (!simulate && inserted - insertedExternally > 0) { + itemStorage.add(stack, inserted - insertedExternally, false); } return remainder; @@ -795,26 +612,6 @@ public class TileController extends TileBase implements INetworkMaster, IRedston return getWorld(); } - private static ICraftingTask readCraftingTask(World world, INetworkMaster network, NBTTagCompound tag) { - ItemStack stack = new ItemStack(tag.getCompoundTag(ICraftingTask.NBT_PATTERN_STACK)); - - if (!stack.isEmpty() && stack.getItem() instanceof ICraftingPatternProvider) { - TileEntity container = world.getTileEntity(BlockPos.fromLong(tag.getLong(ICraftingTask.NBT_PATTERN_CONTAINER))); - - if (container instanceof ICraftingPatternContainer) { - ICraftingPattern pattern = ((ICraftingPatternProvider) stack.getItem()).create(world, stack, (ICraftingPatternContainer) container); - - ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(tag.getString(ICraftingTask.NBT_PATTERN_ID)); - - if (factory != null) { - return factory.create(world, network, tag.hasKey(ICraftingTask.NBT_REQUESTED) ? new ItemStack(tag.getCompoundTag(ICraftingTask.NBT_REQUESTED)) : null, pattern, tag.getInteger(ICraftingTask.NBT_QUANTITY), tag); - } - } - } - - return null; - } - @Override public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); @@ -825,13 +622,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston redstoneMode = RedstoneMode.read(tag); - if (tag.hasKey(NBT_CRAFTING_TASKS)) { - NBTTagList taskList = tag.getTagList(NBT_CRAFTING_TASKS, Constants.NBT.TAG_COMPOUND); - - for (int i = 0; i < taskList.tagCount(); ++i) { - craftingTasksToRead.add(taskList.getCompoundTagAt(i)); - } - } + craftingManager.readFromNBT(tag); if (tag.hasKey(NBT_READER_WRITER_CHANNELS)) { NBTTagList readerWriterChannelsList = tag.getTagList(NBT_READER_WRITER_CHANNELS, Constants.NBT.TAG_COMPOUND); @@ -858,13 +649,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston redstoneMode.write(tag); - NBTTagList craftingTaskList = new NBTTagList(); - - for (ICraftingTask task : craftingTasks) { - craftingTaskList.appendTag(task.writeToNBT(new NBTTagCompound())); - } - - tag.setTag(NBT_CRAFTING_TASKS, craftingTaskList); + craftingManager.writeToNBT(tag); NBTTagList readerWriterChannelsList = new NBTTagList();