Remove all autocrafting logic. Improve the ICraftingPattern interface. Remove blocking mode.

This commit is contained in:
raoulvdberge
2018-05-27 20:15:20 +02:00
parent 3d8cdfcc0c
commit 1827831fbf
48 changed files with 243 additions and 2875 deletions

View File

@@ -1,36 +0,0 @@
package com.raoulvdberge.refinedstorage.api.autocrafting;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.items.ItemHandlerHelper;
/**
* Event fired upon completion of an auto crafting task.
*/
public class EventAutocraftingComplete extends Event {
private ItemStack crafted;
private INetwork network;
private EventAutocraftingComplete(INetwork network, ItemStack crafted) {
this.crafted = crafted;
this.network = network;
}
public ItemStack getCrafted() {
return crafted;
}
public INetwork getNetwork() {
return network;
}
public static void fire(INetwork network, ItemStack crafted) {
MinecraftForge.EVENT_BUS.post(new EventAutocraftingComplete(network, crafted));
}
public static void fire(INetwork network, ItemStack crafted, int quantity) {
fire(network, ItemHandlerHelper.copyStackWithSize(crafted, quantity));
}
}

View File

@@ -2,7 +2,6 @@ package com.raoulvdberge.refinedstorage.api.autocrafting;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -12,7 +11,6 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* The crafting manager handles the storing, updating, adding and deleting of crafting tasks in a network.
@@ -23,39 +21,11 @@ public interface ICraftingManager {
*/
List<ICraftingTask> getTasks();
/**
* @return all the crafting pattern containers
*/
List<ICraftingPatternContainer> getContainers();
/**
* @return named crafting pattern containers
*/
Map<String, List<IItemHandlerModifiable>> getNamedContainers();
/**
* @param blocker the container that is blocking another container
* @param blockee the container being blocked, may be the same as blocker
*/
void addContainerBlock(UUID blocker, UUID blockee);
/**
* @param blocker the container that is blocking another container
*/
void removeContainerBlock(UUID blocker);
/**
* @param blockee the container to check
* @return whether the container is blocked
*/
boolean isContainerBlocked(UUID blockee);
/**
* @param container the container to set the blocking state for
* @param blocked whether the container should be blocked
*/
void setContainerBlocked(ICraftingPatternContainer container, boolean blocked);
/**
* Adds a crafting task.
*
@@ -70,27 +40,8 @@ public interface ICraftingManager {
*/
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
* @param automated whether this crafting task is created in an automated way
* @return the crafting task
*/
ICraftingTask create(@Nullable ItemStack stack, ICraftingPattern pattern, int quantity, boolean automated);
/**
* Creates a crafting task.
*
* @param stack the stack to create a task for
* @param patternChain the pattern
* @param quantity the quantity
* @param automated whether this crafting task is created in an automated way
* @return the crafting task
*/
ICraftingTask create(@Nullable ItemStack stack, ICraftingPatternChain patternChain, int quantity, boolean automated);
@Nullable
ICraftingTask create(ItemStack stack, int quantity);
/**
* Schedules a crafting task if the task isn't scheduled yet.
@@ -121,122 +72,14 @@ public interface ICraftingManager {
void rebuild();
/**
* Returns crafting patterns from an item stack.
* Return a crafting pattern 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<ICraftingPattern> 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
* @return the crafting pattern, or null if none is found
*/
@Nullable
default ICraftingPattern getPattern(ItemStack pattern, int flags) {
ICraftingPatternChain chain = getPatternChain(pattern, flags);
return chain == null ? null : chain.cycle();
}
/**
* 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 {@link IStackList<ItemStack>} provided.
*
* @param pattern the stack to get a pattern for
* @param flags the flags to compare on, see {@link IComparer}
* @param itemList the {@link IStackList<ItemStack>} used to calculate the best fitting pattern
* @return the pattern, or null if the pattern is not found
*/
@Nullable
default ICraftingPattern getPattern(ItemStack pattern, int flags, IStackList<ItemStack> itemList) {
ICraftingPatternChain chain = getPatternChain(pattern, flags, itemList);
return chain == null ? null : chain.cycle();
}
/**
* 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
*/
@Nullable
default ICraftingPattern getPattern(ItemStack pattern) {
return getPattern(pattern, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT);
}
/**
* Returns a crafting pattern chain 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 chain, or null if the pattern chain is not found
*/
@Nullable
ICraftingPatternChain getPatternChain(ItemStack pattern, int flags);
/**
* Returns a crafting pattern chain 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 {@link IStackList<ItemStack>} provided.
*
* @param pattern the stack to get a pattern for
* @param flags the flags to compare on, see {@link IComparer}
* @param itemList the {@link IStackList<ItemStack>} used to calculate the best fitting pattern
* @return the pattern chain, or null if the pattern chain is not found
*/
@Nullable
ICraftingPatternChain getPatternChain(ItemStack pattern, int flags, IStackList<ItemStack> itemList);
/**
* 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 chain, or null if the pattern chain is not found
*/
@Nullable
default ICraftingPatternChain getPatternChain(ItemStack pattern) {
return getPatternChain(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 hasPattern(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT);
}
/**
* Returns if there is a pattern with a given stack as output.
*
* @param stack the stack
* @param flags the flags to compare on, see {@link IComparer}
* @return true if there is a pattern, false otherwise
*/
boolean hasPattern(ItemStack stack, int flags);
ICraftingPattern getPattern(ItemStack pattern, int flags);
/**
* Updates the tasks in this manager.

View File

@@ -1,9 +1,8 @@
package com.raoulvdberge.refinedstorage.api.autocrafting;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import javax.annotation.Nullable;
import java.util.List;
/**
@@ -36,82 +35,34 @@ public interface ICraftingPattern {
boolean isOredict();
/**
* @return true if the crafting pattern may block other crafting tasks that are the same, false otherwise
* @return the inputs per slot
*/
boolean isBlocking();
/**
* @return the inputs, can contain nulls
*/
List<ItemStack> getInputs();
/**
* @return the possible inputs per slot, empty list means null slot
*/
List<List<ItemStack>> getOreInputs();
/**
* @param took the items took
* @return the outputs based on the items took, null when failed
*/
@Nullable
List<ItemStack> getOutputs(ItemStack[] took);
List<NonNullList<ItemStack>> getInputs();
/**
* @return the outputs
*/
List<ItemStack> getOutputs();
NonNullList<ItemStack> getOutputs();
/**
* @param took the items took
* @param took the items took per slot
* @return the outputs based on the items took
*/
List<ItemStack> getByproducts(ItemStack[] took);
NonNullList<ItemStack> getOutputs(NonNullList<ItemStack> took);
/**
* @return the byproducts
* @return the outputs
*/
List<ItemStack> getByproducts();
NonNullList<ItemStack> getByproducts();
/**
* @param took the items took per slot
* @return the outputs based on the items took
*/
NonNullList<ItemStack> getByproducts(NonNullList<ItemStack> took);
/**
* @return the id of the factory that creates a crafting task for this pattern, as defined in the {@link com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskRegistry}
*/
String getId();
/**
* Returns the quantity of items that this crafting task yields per request.
*
* @param requested the item requested
* @return the quantity
*/
default int getQuantityPerRequest(ItemStack requested) {
return getQuantityPerRequest(requested, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT);
}
/**
* Returns the quantity of items that this crafting task yields per request.
*
* @param requested the item requested
* @param compare the {@link IComparer} flags
* @return the quantity
*/
int getQuantityPerRequest(ItemStack requested, int compare);
/**
* Returns the actual outputted {@link ItemStack}
*
* @param requested an item requested
* @param compare the {@link IComparer} flags
* @return the actual {@link ItemStack} with quantity
*/
ItemStack getActualOutput(ItemStack requested, int compare);
/**
* Compares with an other pattern if it is alike
* Used to balance out {@link com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep}s over alike {@link ICraftingPattern}s
*
* @param pattern the {@link ICraftingPattern} to compare against
* @return true if the patterns are alike, false otherwise
*/
boolean alike(ICraftingPattern pattern);
}

View File

@@ -1,32 +0,0 @@
package com.raoulvdberge.refinedstorage.api.autocrafting;
import java.util.Collection;
/**
* Represents a chain of {@link ICraftingPattern}s, used to balance crafts over those patterns.
*/
public interface ICraftingPatternChain extends Collection<ICraftingPattern> {
/**
* Check whether a pattern belongs in the chain.
*
* @param compare the {@link ICraftingPattern} to check
* @return true if the chains {@link #getPrototype()} is {@link ICraftingPattern#alike(ICraftingPattern)}, false otherwise
*/
default boolean isValidForChain(ICraftingPattern compare) {
return getPrototype() == compare || getPrototype().alike(compare);
}
/**
* Cycles the list and returns use you the pattern that was used the longest time ago.
*
* @return an {@link ICraftingPattern}
*/
ICraftingPattern cycle();
/**
* The prototype used for this {@link ICraftingPatternChain}.
*
* @return an {@link ICraftingPattern} that represents all patterns in the chain
*/
ICraftingPattern getPrototype();
}

View File

@@ -7,7 +7,6 @@ import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nullable;
import java.util.List;
import java.util.UUID;
@@ -76,11 +75,6 @@ public interface ICraftingPatternContainer {
@Nullable
ICraftingPatternContainer getRootContainer();
/**
* @return true if this container or its proxy is blocked, false otherwise
*/
boolean isBlocked();
/**
* @return the UUID of this container
*/

View File

@@ -1,7 +1,6 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.registry;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternChain;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import net.minecraft.item.ItemStack;
@@ -18,27 +17,13 @@ public interface ICraftingTaskFactory {
/**
* Returns a crafting task for a given NBT tag and pattern.
*
* @param network the network
* @param stack the stack to create a task for
* @param pattern the pattern
* @param quantity the quantity
* @param automated whether this crafting task is created in an automated way
* @param tag the NBT tag, if this is null it isn't reading from disk but is used for making a task on demand
* @param network the network
* @param stack the stack to create a task for
* @param pattern the pattern
* @param quantity the quantity
* @param tag the NBT tag, if this is null it isn't reading from disk but is used for making a task on demand
* @return the crafting task
*/
@Nonnull
ICraftingTask create(INetwork network, @Nullable ItemStack stack, ICraftingPattern pattern, int quantity, boolean automated, @Nullable NBTTagCompound tag);
/**
* Returns a crafting task for a given NBT tag and pattern.
*
* @param network the network
* @param stack the stack to create a task for
* @param patternChain the pattern chain
* @param quantity the quantity
* @param automated whether this crafting task is created in an automated way
* @return the crafting task
*/
@Nonnull
ICraftingTask create(INetwork network, @Nullable ItemStack stack, ICraftingPatternChain patternChain, int quantity, boolean automated);
ICraftingTask create(INetwork network, ItemStack stack, int quantity, ICraftingPattern pattern, @Nullable NBTTagCompound tag);
}

View File

@@ -20,7 +20,7 @@ public interface ICraftingTaskRegistry {
* Returns the crafting task factory by factory id.
*
* @param id the factory id
* @return the factory
* @return the factory, or null if there is no factory
*/
@Nullable
ICraftingTaskFactory get(String id);

View File

@@ -1,100 +0,0 @@
package com.raoulvdberge.refinedstorage.api.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
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.
*/
public interface ICraftingStep {
/**
* @return the pattern
*/
ICraftingPattern getPattern();
/**
* @return the input stacks
*/
List<ItemStack> getInputs();
/**
* @return a list of steps the have to be done before this one can be started
*/
List<ICraftingStep> getPreliminarySteps();
/**
* 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 FluidStack} inputs against (eg. a bucket, machine insert)
* @return true if processing can start, false otherwise
*/
boolean canStartProcessing(IStackList<ItemStack> items, IStackList<FluidStack> fluids);
/**
* Check if the processing can start.
* Assuming you have all needed {@link ItemStack}s and {@link FluidStack}s
*
* @return true if processing can start, false otherwise
*/
boolean canStartProcessing();
/**
* When called, this step will be marked as started processing.
*/
void setStartedProcessing();
/**
* @return whether this step has started processing
*/
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 count), false otherwise
*/
boolean hasReceivedOutput(ItemStack stack);
/**
* @param stack the output to check
* @return amount of times this {@link ItemStack} has been received
*/
int getReceivedOutput(ItemStack stack);
/**
* The {@link ItemStack} given to it will be changed and contain the remainder.
* The return value will only be true if the stack size is zero.
*
* @param stack the stack that was inserted in the storage system
* @return true if this item belonged to the processable item and was fully used, false otherwise
*/
boolean onReceiveOutput(ItemStack stack);
/**
* Writes the crafting step to NBT.
*
* @param tag the tag
* @return the written tag
*/
NBTTagCompound writeToNBT(NBTTagCompound tag);
}

View File

@@ -1,28 +1,17 @@
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 com.raoulvdberge.refinedstorage.api.util.IStackList;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
/**
* Represents a crafting task.
*/
public interface ICraftingTask {
String NBT_QUANTITY = "Quantity";
String NBT_PATTERN_ID = "PatternID";
String NBT_PATTERN_STACK = "PatternStack";
String NBT_PATTERN_CONTAINER = "PatternContainer";
String NBT_REQUESTED = "Requested";
String NBT_AUTOMATED = "Automated";
/**
* Calculates what this task will do, but doesn't run the task yet.
*/
@@ -32,30 +21,23 @@ 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(Map<ICraftingPatternContainer, Integer> usedContainers);
boolean update();
/**
* Called when this task is cancelled.
*/
void onCancelled();
/**
* Reschedule the task. This does a recalculation and restart of the task.
*/
void reschedule();
/**
* @return the amount of items that have to be crafted
*/
int getQuantity();
/**
* @return the stack requested, or null if no specific stack is associated with this task
* @return the stack requested
*/
@Nullable
ItemStack getRequested();
/**
@@ -66,26 +48,6 @@ public interface ICraftingTask {
*/
NBTTagCompound writeToNBT(NBTTagCompound tag);
/**
* Helper method to write default necessary elements to NBT.
*
* @param tag the tag
* @return the written tag
*/
default NBTTagCompound writeDefaultsToNBT(NBTTagCompound tag) {
tag.setInteger(NBT_QUANTITY, getQuantity());
tag.setString(NBT_PATTERN_ID, getPattern().getId());
tag.setTag(NBT_PATTERN_STACK, getPattern().getStack().serializeNBT());
tag.setLong(NBT_PATTERN_CONTAINER, getPattern().getContainer().getPosition().toLong());
tag.setBoolean(NBT_AUTOMATED, isAutomated());
if (getRequested() != null) {
tag.setTag(NBT_REQUESTED, getRequested().serializeNBT());
}
return tag;
}
/**
* {@link ICraftingTask#calculate()} must be run before this!
*
@@ -100,13 +62,6 @@ public interface ICraftingTask {
*/
List<ICraftingPreviewElement> getPreviewStacks();
/**
* {@link ICraftingTask#calculate()} must be run before this!
*
* @return the steps for this task
*/
List<ICraftingStep> getSteps();
/**
* @return the crafting pattern corresponding to this task
*/
@@ -119,22 +74,4 @@ public interface ICraftingTask {
* @return true if no recursion was found, false otherwise
*/
boolean isValid();
/**
* @return true if the task is finished, false otherwise
*/
boolean isFinished();
/**
* @return the missing items
*/
IStackList<ItemStack> getMissing();
/**
* Returns whether the crafting task is created in an automated way.
* For example: through the Crafting Upgrade or the "Trigger task with redstone signal" option in the crafter.
*
* @return true if this crafting task is created in an automated way, false otherwise
*/
boolean isAutomated();
}

View File

@@ -1,15 +1,13 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.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.registry.ICraftingTaskFactory;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeProxy;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.container.ContainerCraftingMonitor;
import com.raoulvdberge.refinedstorage.network.MessageCraftingMonitorElements;
@@ -17,45 +15,27 @@ import com.raoulvdberge.refinedstorage.tile.TileController;
import net.minecraft.entity.player.EntityPlayerMP;
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.minecraftforge.common.util.Constants;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class CraftingManager implements ICraftingManager {
private static final String NBT_CRAFTING_TASKS = "CraftingTasks";
private static final String NBT_BLOCKED_CONTAINERS = "BlockedContainers";
private static final String NBT_BLOCKER_UUID = "BlockerUuid";
private static final String NBT_BLOCKEE_UUID = "BlockeeUuid";
private TileController network;
private List<ICraftingPatternContainer> containers = new ArrayList<>();
private Map<String, List<IItemHandlerModifiable>> containerInventories = new LinkedHashMap<>();
private CraftingPatternChainList patterns = new CraftingPatternChainList();
// A map of blockers to blockees.
private Map<UUID, UUID> blockingContainers = new HashMap<>();
// A set of blockees.
private Set<UUID> blockedContainers = new HashSet<>();
private List<ICraftingPattern> patterns = new ArrayList<>();
private List<ICraftingTask> craftingTasks = new ArrayList<>();
private List<ICraftingTask> craftingTasksToAdd = new ArrayList<>();
private List<ICraftingTask> craftingTasksToCancel = new ArrayList<>();
private List<NBTTagCompound> craftingTasksToRead = new ArrayList<>();
private List<ICraftingStep> runningSteps = new ArrayList<>();
private List<ICraftingTask> tasks = new ArrayList<>();
private List<ICraftingTask> tasksToAdd = new ArrayList<>();
private List<ICraftingTask> tasksToCancel = new ArrayList<>();
private boolean craftingMonitorUpdateRequested;
private int ticks;
private boolean updateRequested;
public CraftingManager(TileController network) {
this.network = network;
@@ -63,12 +43,7 @@ public class CraftingManager implements ICraftingManager {
@Override
public List<ICraftingTask> getTasks() {
return craftingTasks;
}
@Override
public List<ICraftingPatternContainer> getContainers() {
return containers;
return tasks;
}
@Override
@@ -76,189 +51,51 @@ public class CraftingManager implements ICraftingManager {
return containerInventories;
}
@Override
public void addContainerBlock(UUID blocker, UUID blockee) {
blockedContainers.add(blockee);
blockingContainers.put(blocker, blockee);
}
@Override
public void removeContainerBlock(UUID blocker) {
blockedContainers.remove(blockingContainers.get(blocker));
blockingContainers.remove(blocker);
}
@Override
public boolean isContainerBlocked(UUID blockee) {
return blockedContainers.contains(blockee);
}
@Override
public void setContainerBlocked(ICraftingPatternContainer container, boolean blocked) {
if (blocked) {
ICraftingPatternContainer proxy = container.getRootContainer();
if (proxy != null) {
addContainerBlock(container.getUuid(), proxy.getUuid());
}
} else {
removeContainerBlock(container.getUuid());
}
}
@Override
public void add(@Nonnull ICraftingTask task) {
craftingTasksToAdd.add(task);
tasksToAdd.add(task);
network.markDirty();
}
@Override
public void cancel(@Nonnull ICraftingTask task) {
craftingTasksToCancel.add(task);
tasksToCancel.add(task);
network.markDirty();
}
@Override
public ICraftingTask create(@Nullable ItemStack stack, ICraftingPattern pattern, int quantity, boolean automated) {
return API.instance().getCraftingTaskRegistry().get(pattern.getId()).create(network, stack, pattern, quantity, automated, null);
}
@Override
public ICraftingTask create(@Nullable ItemStack stack, ICraftingPatternChain patternChain, int quantity, boolean automated) {
return API.instance().getCraftingTaskRegistry().get(patternChain.getPrototype().getId()).create(network, stack, patternChain, quantity, automated);
}
@Override
public List<ICraftingPattern> getPatterns() {
return patterns.asList();
}
@Override
public List<ICraftingPattern> getPatterns(ItemStack pattern, int flags) {
return getPatternChains(pattern, flags).stream().flatMap(Collection::stream).collect(Collectors.toList());
}
private List<ICraftingPatternChain> getPatternChains(ItemStack pattern, int flags) {
List<ICraftingPatternChain> patternChains = new LinkedList<>();
for (CraftingPatternChainList.CraftingPatternChain chain : this.patterns) {
for (ItemStack output : chain.getPrototype().getOutputs()) {
if (API.instance().getComparer().isEqual(output, pattern, flags)) {
patternChains.add(chain);
}
}
}
return patternChains;
}
@Override
public boolean hasPattern(ItemStack stack, int flags) {
for (CraftingPatternChainList.CraftingPatternChain chain : this.patterns) {
for (ItemStack output : chain.getPrototype().getOutputs()) {
if (API.instance().getComparer().isEqual(output, stack, flags)) {
return true;
}
}
}
return false;
}
@Override
public ICraftingPatternChain getPatternChain(ItemStack pattern, int flags) {
return getPatternChain(pattern, flags, network.getItemStorageCache().getList().getOredicted());
}
@Override
public ICraftingPatternChain getPatternChain(ItemStack pattern, int flags, IStackList<ItemStack> itemList) {
List<ICraftingPatternChain> patternChains = getPatternChains(pattern, flags);
if (patternChains.isEmpty()) {
@Nullable
public ICraftingTask create(ItemStack stack, int quantity) {
ICraftingPattern pattern = getPattern(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT);
if (pattern == null) {
return null;
} else if (patternChains.size() == 1) {
return patternChains.get(0);
}
int highestScore = 0;
int highestPattern = 0;
for (int i = 0; i < patternChains.size(); ++i) {
int score = 0;
for (ItemStack input : patternChains.get(i).getPrototype().getInputs()) {
if (input != null) {
ItemStack stored = itemList.get(input, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | (patternChains.get(i).getPrototype().isOredict() ? IComparer.COMPARE_OREDICT : 0));
score += stored != null ? stored.getCount() : 0;
}
}
if (score > highestScore) {
highestScore = score;
highestPattern = i;
}
ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getId());
if (factory == null) {
return null;
}
return patternChains.get(highestPattern);
return factory.create(network, stack, quantity, pattern, null);
}
@Override
public void update() {
if (!craftingTasksToRead.isEmpty()) {
for (NBTTagCompound tag : craftingTasksToRead) {
ICraftingTask task = readCraftingTask(network, tag);
if (task != null) {
add(task);
}
}
craftingTasksToRead.clear();
}
if (network.canRun()) {
boolean craftingTasksChanged = !craftingTasksToAdd.isEmpty() || !craftingTasksToCancel.isEmpty();
tasksToCancel.forEach(ICraftingTask::onCancelled);
tasks.removeAll(tasksToCancel);
tasksToCancel.clear();
craftingTasksToCancel.forEach(ICraftingTask::onCancelled);
craftingTasks.removeAll(craftingTasksToCancel);
craftingTasksToCancel.clear();
tasksToAdd.stream().filter(ICraftingTask::isValid).forEach(tasks::add);
tasksToAdd.clear();
craftingTasksToAdd.stream().filter(ICraftingTask::isValid).forEach(craftingTasks::add);
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();
if (task.update(usedCrafters)) {
EventAutocraftingComplete.fire(network, task.getRequested(), task.getQuantity());
craftingTaskIterator.remove();
craftingTasksChanged = true;
} else if (!task.getMissing().isEmpty() && ticks % 100 == 0 && Math.random() > 0.5) {
task.getMissing().clear();
}
}
runningSteps = craftingTasks.stream()
.map(ICraftingTask::getSteps)
.flatMap(List::stream)
.filter(ICraftingStep::hasStartedProcessing)
.collect(Collectors.toList());
if (craftingTasksChanged) {
markCraftingMonitorForUpdate();
}
}
tasks.removeIf(ICraftingTask::update);
}
if (craftingMonitorUpdateRequested) {
craftingMonitorUpdateRequested = false;
if (updateRequested) {
updateRequested = false;
sendCraftingMonitorUpdate();
}
@@ -266,43 +103,17 @@ public class CraftingManager implements ICraftingManager {
@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));
}
}
if (tag.hasKey(NBT_BLOCKED_CONTAINERS)) {
NBTTagList containerList = tag.getTagList(NBT_BLOCKED_CONTAINERS, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < containerList.tagCount(); ++i) {
NBTTagCompound compound = containerList.getCompoundTagAt(i);
addContainerBlock(compound.getUniqueId(NBT_BLOCKER_UUID), compound.getUniqueId(NBT_BLOCKEE_UUID));
}
}
// TODO
}
@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);
NBTTagList blockingContainersList = new NBTTagList();
for (Entry<UUID, UUID> pair : blockingContainers.entrySet()) {
NBTTagCompound compound = new NBTTagCompound();
compound.setUniqueId(NBT_BLOCKER_UUID, pair.getKey());
compound.setUniqueId(NBT_BLOCKEE_UUID, pair.getValue());
blockingContainersList.appendTag(compound);
}
tag.setTag(NBT_BLOCKED_CONTAINERS, blockingContainersList);
// TODO
return tag;
}
@Override
@Nullable
public ICraftingTask schedule(ItemStack stack, int toSchedule, int compare) {
for (ICraftingTask task : getTasks()) {
for (ItemStack output : task.getPattern().getOutputs()) {
@@ -313,13 +124,10 @@ public class CraftingManager implements ICraftingManager {
}
if (toSchedule > 0) {
ICraftingPatternChain patternChain = getPatternChain(stack, compare);
if (patternChain != null) {
ICraftingTask task = create(stack, patternChain, toSchedule, true);
ICraftingTask task = create(stack, toSchedule);
if (task != null) {
task.calculate();
task.getMissing().clear();
add(task);
@@ -334,13 +142,12 @@ public class CraftingManager implements ICraftingManager {
@Override
public void track(ItemStack stack, int size) {
ItemStack inserted = ItemHandlerHelper.copyStackWithSize(stack, size);
// TODO
}
for (ICraftingStep step : runningSteps) {
if (step.onReceiveOutput(inserted)) {
return;
}
}
@Override
public List<ICraftingPattern> getPatterns() {
return patterns;
}
@Override
@@ -355,20 +162,30 @@ public class CraftingManager implements ICraftingManager {
patterns.addAll(container.getPatterns());
IItemHandlerModifiable handler = container.getPatternInventory();
if (handler != null) {
containerInventories.computeIfAbsent(container.getName(), k -> new ArrayList<>()).add(handler);
}
}
}
}
// Auto reschedules stuck tasks after a pattern rebuild
craftingTasks.forEach(t -> t.getMissing().clear());
@Nullable
@Override
public ICraftingPattern getPattern(ItemStack pattern, int flags) {
for (ICraftingPattern patternInList : patterns) {
for (ItemStack output : patternInList.getOutputs()) {
if (API.instance().getComparer().isEqual(output, pattern, flags)) {
return patternInList;
}
}
}
return null;
}
@Override
public void markCraftingMonitorForUpdate() {
craftingMonitorUpdateRequested = true;
this.updateRequested = true;
}
@Override
@@ -382,26 +199,4 @@ public class CraftingManager implements ICraftingManager {
public void sendCraftingMonitorUpdate(EntityPlayerMP player) {
RS.INSTANCE.network.sendTo(new MessageCraftingMonitorElements(((ContainerCraftingMonitor) player.openContainer).getCraftingMonitor()), player);
}
private static ICraftingTask readCraftingTask(INetwork network, NBTTagCompound tag) {
ItemStack stack = new ItemStack(tag.getCompoundTag(ICraftingTask.NBT_PATTERN_STACK));
if (!stack.isEmpty() && stack.getItem() instanceof ICraftingPatternProvider) {
TileEntity container = network.world().getTileEntity(BlockPos.fromLong(tag.getLong(ICraftingTask.NBT_PATTERN_CONTAINER)));
if (container instanceof INetworkNodeProxy) {
INetworkNodeProxy proxy = (INetworkNodeProxy) container;
if (proxy.getNode() instanceof ICraftingPatternContainer) {
ICraftingPattern pattern = ((ICraftingPatternProvider) stack.getItem()).create(network.world(), stack, (ICraftingPatternContainer) proxy.getNode());
ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(tag.getString(ICraftingTask.NBT_PATTERN_ID));
if (factory != null) {
return factory.create(network, tag.hasKey(ICraftingTask.NBT_REQUESTED) ? new ItemStack(tag.getCompoundTag(ICraftingTask.NBT_REQUESTED)) : null, pattern, tag.getInteger(ICraftingTask.NBT_QUANTITY), false, tag);
}
}
}
}
return null;
}
}

View File

@@ -2,130 +2,78 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry.CraftingTaskFactory;
import com.raoulvdberge.refinedstorage.apiimpl.util.Comparer;
import com.raoulvdberge.refinedstorage.item.ItemPattern;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.NonNullList;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.List;
public class CraftingPattern implements ICraftingPattern {
private ICraftingPatternContainer container;
private ItemStack stack;
private boolean processing;
private boolean oredict;
private boolean valid;
private IRecipe recipe;
private List<ItemStack> inputs = new ArrayList<>();
private List<List<ItemStack>> oreInputs = new ArrayList<>();
private List<ItemStack> outputs = new ArrayList<>();
private List<ItemStack> byproducts = new ArrayList<>();
private Integer hashCodeCached = null;
private List<NonNullList<ItemStack>> inputs = new ArrayList<>();
private NonNullList<ItemStack> outputs = NonNullList.create();
private NonNullList<ItemStack> byproducts = NonNullList.create();
public CraftingPattern(World world, ICraftingPatternContainer container, ItemStack stack) {
this.container = container;
this.stack = Comparer.stripTags(stack);
this.stack = stack;
this.processing = ItemPattern.isProcessing(stack);
this.oredict = ItemPattern.isOredict(stack);
InventoryCrafting inv = new InventoryCrafting(new Container() {
@Override
public boolean canInteractWith(EntityPlayer player) {
return false;
if (processing) {
this.valid = true;
for (int i = 0; i < 9; ++i) {
ItemStack input = ItemPattern.getSlot(stack, i);
inputs.add(input == null ? NonNullList.create() : NonNullList.from(ItemStack.EMPTY, input));
}
}, 3, 3);
for (int i = 0; i < 9; ++i) {
ItemStack slot = ItemPattern.getSlot(stack, i);
this.outputs = ItemPattern.getOutputs(stack);
} else {
InventoryCrafting inv = new InventoryCraftingDummy();
inputs.add(Comparer.stripTags(slot));
for (int i = 0; i < 9; ++i) {
ItemStack input = ItemPattern.getSlot(stack, i);
if (slot != null) {
inv.setInventorySlotContents(i, slot);
inputs.add(input == null ? NonNullList.create() : NonNullList.from(ItemStack.EMPTY, input));
if (input != null) {
inv.setInventorySlotContents(i, input);
}
}
}
if (!ItemPattern.isProcessing(stack)) {
for (IRecipe r : CraftingManager.REGISTRY) {
if (r.matches(inv, world)) {
recipe = r;
this.recipe = r;
this.byproducts = recipe.getRemainingItems(inv);
ItemStack output = recipe.getCraftingResult(inv);
if (!output.isEmpty()) {
this.valid = true;
outputs.add(output);
}
break;
}
}
if (recipe != null) {
ItemStack output = recipe.getCraftingResult(inv);
if (!output.isEmpty()) {
outputs.add(Comparer.stripTags(output.copy()));
if (isOredict()) {
List<List<ItemStack>> inputs = new LinkedList<>();
for (Ingredient ingredient : recipe.getIngredients()) {
inputs.add(Arrays.asList(ingredient.getMatchingStacks()));
}
for (List<ItemStack> input : inputs) {
if (input.isEmpty()) {
oreInputs.add(Collections.emptyList());
} else {
List<ItemStack> cleaned = new LinkedList<>();
for (ItemStack in : input) {
cleaned.add(Comparer.stripTags(in.copy()));
}
oreInputs.add(cleaned);
}
}
}
for (ItemStack remaining : recipe.getRemainingItems(inv)) {
if (!remaining.isEmpty()) {
ItemStack cleaned = Comparer.stripTags(remaining.copy());
byproducts.add(cleaned);
}
}
}
}
} else {
outputs = ItemPattern.getOutputs(stack);
}
if (oreInputs.isEmpty()) {
for (ItemStack input : inputs) {
if (input == null || input.isEmpty()) {
oreInputs.add(Collections.emptyList());
} else {
int[] ids = OreDictionary.getOreIDs(input);
if (ids.length == 0) {
oreInputs.add(Collections.singletonList(Comparer.stripTags(input)));
} else if (isOredict()) {
List<ItemStack> oredictInputs = Arrays.stream(ids)
.mapToObj(OreDictionary::getOreName)
.map(OreDictionary::getOres)
.flatMap(List::stream)
.map(ItemStack::copy)
.map(Comparer::stripTags)
.peek(s -> s.setCount(input.getCount()))
.collect(Collectors.toList());
// Add original stack as first, should prevent some issues
oredictInputs.add(0, Comparer.stripTags(input.copy()));
oreInputs.add(oredictInputs);
} else {
oreInputs.add(Collections.singletonList(Comparer.stripTags(input)));
}
}
}
}
}
@@ -141,95 +89,42 @@ public class CraftingPattern implements ICraftingPattern {
@Override
public boolean isValid() {
return !inputs.isEmpty() && inputs.stream().filter(Objects::nonNull).count() > 0 && !outputs.isEmpty();
return valid;
}
@Override
public boolean isProcessing() {
return ItemPattern.isProcessing(stack);
return processing;
}
@Override
public boolean isOredict() {
return ItemPattern.isOredict(stack);
return oredict;
}
@Override
public boolean isBlocking() {
return ItemPattern.isBlocking(stack);
}
@Override
public List<ItemStack> getInputs() {
public List<NonNullList<ItemStack>> getInputs() {
return inputs;
}
@Override
public List<List<ItemStack>> getOreInputs() {
return oreInputs;
}
@Override
@Nullable
public List<ItemStack> getOutputs(ItemStack[] took) {
List<ItemStack> outputs = new ArrayList<>();
InventoryCrafting inv = new InventoryCrafting(new Container() {
@Override
public boolean canInteractWith(EntityPlayer player) {
return false;
}
}, 3, 3);
for (int i = 0; i < 9; ++i) {
if (took[i] != null) {
inv.setInventorySlotContents(i, took[i]);
}
}
ItemStack cleaned = recipe.getCraftingResult(inv);
if (cleaned.isEmpty()) {
return null;
}
outputs.add(cleaned.copy());
public NonNullList<ItemStack> getOutputs() {
return outputs;
}
@Override
public List<ItemStack> getOutputs() {
return outputs;
public NonNullList<ItemStack> getOutputs(NonNullList<ItemStack> took) {
return StackUtils.emptyNonNullList();
}
@Override
public List<ItemStack> getByproducts(ItemStack[] took) {
List<ItemStack> byproducts = new ArrayList<>();
InventoryCrafting inv = new InventoryCrafting(new Container() {
@Override
public boolean canInteractWith(EntityPlayer player) {
return false;
}
}, 3, 3);
for (int i = 0; i < 9; ++i) {
if (took[i] != null) {
inv.setInventorySlotContents(i, took[i]);
}
}
for (ItemStack remaining : recipe.getRemainingItems(inv)) {
if (!remaining.isEmpty()) {
byproducts.add(remaining.copy());
}
}
public NonNullList<ItemStack> getByproducts() {
return byproducts;
}
@Override
public List<ItemStack> getByproducts() {
return byproducts;
public NonNullList<ItemStack> getByproducts(NonNullList<ItemStack> took) {
return StackUtils.emptyNonNullList();
}
@Override
@@ -237,100 +132,14 @@ public class CraftingPattern implements ICraftingPattern {
return CraftingTaskFactory.ID;
}
@Override
public int getQuantityPerRequest(ItemStack requested, int compare) {
int quantity = 0;
requested = Comparer.stripTags(requested.copy());
for (ItemStack output : outputs) {
if (API.instance().getComparer().isEqual(requested, output, compare)) {
quantity += output.getCount();
if (!ItemPattern.isProcessing(stack)) {
break;
private class InventoryCraftingDummy extends InventoryCrafting {
public InventoryCraftingDummy() {
super(new Container() {
@Override
public boolean canInteractWith(EntityPlayer player) {
return true;
}
}
}, 3, 3);
}
return quantity;
}
@Override
public ItemStack getActualOutput(ItemStack requested, int compare) {
requested = Comparer.stripTags(requested.copy());
for (ItemStack output : outputs) {
if (API.instance().getComparer().isEqual(requested, output, compare)) {
return output.copy();
}
}
return null;
}
@Override
public String toString() {
return "CraftingPattern{" +
"container=" + container +
", inputs=" + inputs +
", outputs=" + outputs +
", byproducts=" + byproducts +
'}';
}
@Override
public boolean equals(Object obj) {
return this == obj || (obj instanceof ICraftingPattern && this.alike((ICraftingPattern) obj));
}
@Override
public int hashCode() {
if (hashCodeCached == null) {
hashCodeCached = 0;
for (ItemStack outputItemStack : this.getOutputs()) {
int itemHashCode = 0;
itemHashCode = outputItemStack.getCount();
itemHashCode = itemHashCode * 31 + outputItemStack.getItem().hashCode();
itemHashCode = itemHashCode * 31 + outputItemStack.getItemDamage();
itemHashCode = itemHashCode * 31 + Objects.hashCode(outputItemStack.getTagCompound());
hashCodeCached = hashCodeCached * 31 + itemHashCode;
}
}
return hashCodeCached;
}
@Override
public boolean alike(ICraftingPattern other) {
if (other == this) {
return true;
}
if (other.getId().equals(this.getId())
&& other.isOredict() == this.isOredict()
&& other.isBlocking() == this.isBlocking()
&& other.isProcessing() == this.isProcessing()
&& other.getOreInputs().size() == this.getOreInputs().size()
&& other.getOutputs().size() == this.getOutputs().size()) {
boolean same = true;
for (int i = 0; i < other.getOreInputs().size(); i++) {
same &= other.getOreInputs().get(i).size() == this.getOreInputs().get(i).size();
}
int j = 0;
while (same && j < other.getOutputs().size()) {
same = ItemStack.areItemStacksEqual(other.getOutputs().get(j), this.getOutputs().get(j));
j++;
}
int i = 0;
while (same && i < other.getOreInputs().size()) {
List<ItemStack> otherList = other.getOreInputs().get(i);
List<ItemStack> thisList = this.getOreInputs().get(i);
j = 0;
while (same && j < otherList.size()) {
same = ItemStack.areItemStacksEqual(otherList.get(j), thisList.get(j));
j++;
}
i++;
}
return same;
}
return false;
}
}

View File

@@ -1,133 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternChain;
import java.util.*;
import java.util.stream.Collectors;
public class CraftingPatternChainList implements Iterable<CraftingPatternChainList.CraftingPatternChain> {
LinkedList<CraftingPatternChain> innerChain = new LinkedList<>();
Map<ICraftingPattern, CraftingPatternChain> innerChainMap = new HashMap<>();
public void add(ICraftingPattern pattern) {
CraftingPatternChain chain = innerChainMap.get(pattern);
if (chain == null) {
chain = new CraftingPatternChain(pattern);
innerChain.add(chain);
innerChainMap.put(pattern, chain);
} else {
if (!chain.add(pattern)) {
chain = new CraftingPatternChain(pattern);
innerChain.add(chain);
innerChainMap.put(pattern, chain);
}
}
}
public void addAll(Collection<ICraftingPattern> patterns) {
patterns.forEach(this::add);
}
public List<ICraftingPattern> asList() {
return innerChain.stream().flatMap(Collection::stream).collect(Collectors.toList());
}
@Override
public Iterator<CraftingPatternChain> iterator() {
return innerChain.iterator();
}
public void clear() {
innerChain.clear();
innerChainMap.clear();
}
public static class CraftingPatternChain implements ICraftingPatternChain {
private LinkedList<ICraftingPattern> innerList;
private ICraftingPattern prototype;
public CraftingPatternChain(ICraftingPattern prototype) {
this.prototype = prototype;
this.innerList = new LinkedList<>();
this.innerList.add(prototype);
}
public ICraftingPattern cycle() {
ICraftingPattern front = innerList.poll();
innerList.addLast(front);
return front;
}
public ICraftingPattern getPrototype() {
return prototype;
}
@Override
public int size() {
return innerList.size();
}
@Override
public boolean isEmpty() {
return innerList.isEmpty();
}
@Override
public boolean contains(Object o) {
return innerList.contains(o);
}
@Override
public Iterator<ICraftingPattern> iterator() {
return innerList.iterator();
}
@Override
public Object[] toArray() {
return innerList.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return innerList.toArray(a);
}
@Override
public boolean add(ICraftingPattern pattern) {
return isValidForChain(pattern) && innerList.add(pattern);
}
@Override
public boolean remove(Object o) {
return innerList.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return innerList.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends ICraftingPattern> c) {
c.removeIf(p -> !isValidForChain(p));
return innerList.addAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return innerList.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return innerList.retainAll(c);
}
@Override
public void clear() {
innerList.clear();
}
}
}

View File

@@ -1,84 +1,23 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternChain;
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.INetwork;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingStep;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fluids.FluidStack;
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 {
public static final String ID = "normal";
@Override
@Nonnull
public ICraftingTask create(INetwork network, @Nullable ItemStack stack, ICraftingPattern pattern, int quantity, boolean automated, @Nullable NBTTagCompound tag) {
if (tag != null) {
NBTTagList stepsList = tag.getTagList(CraftingTask.NBT_STEPS, Constants.NBT.TAG_COMPOUND);
List<ICraftingStep> steps = new ArrayList<>();
for (int i = 0; i < stepsList.tagCount(); ++i) {
NBTTagCompound stepTag = stepsList.getCompoundTagAt(i);
ICraftingStep step = CraftingStep.toCraftingStep(stepTag, network);
if (step != null) {
steps.add(step);
}
}
NBTTagList toInsertList = tag.getTagList(CraftingTask.NBT_TO_INSERT_ITEMS, Constants.NBT.TAG_COMPOUND);
Deque<ItemStack> toInsert = new ArrayDeque<>();
for (int i = 0; i < toInsertList.tagCount(); ++i) {
ItemStack insertStack = new ItemStack(toInsertList.getCompoundTagAt(i));
if (!insertStack.isEmpty()) {
toInsert.add(insertStack);
}
}
IStackList<FluidStack> toTakeFluids = StackUtils.readFluidStackList(tag.getTagList(CraftingTask.NBT_TO_TAKE_FLUIDS, Constants.NBT.TAG_COMPOUND));
NBTTagList toInsertFluidsList = tag.getTagList(CraftingTask.NBT_TO_INSERT_FLUIDS, Constants.NBT.TAG_COMPOUND);
Deque<FluidStack> toInsertFluids = new ArrayDeque<>();
for (int i = 0; i < toInsertFluidsList.tagCount(); ++i) {
FluidStack tookStack = FluidStack.loadFluidStackFromNBT(toInsertFluidsList.getCompoundTagAt(i));
if (tookStack != null) {
toInsertFluids.add(tookStack);
}
}
return new CraftingTask(network, stack, pattern, quantity, steps, toInsert, toTakeFluids, toInsertFluids, tag.hasKey(CraftingTask.NBT_AUTOMATED) && tag.getBoolean(CraftingTask.NBT_AUTOMATED));
}
return new CraftingTask(network, stack, pattern, quantity, automated);
}
@Nonnull
@Override
public ICraftingTask create(INetwork network, @Nullable ItemStack stack, ICraftingPatternChain patternChain, int quantity, boolean automated) {
return new CraftingTask(network, stack, patternChain, quantity, automated);
// TODO: handle tag?
public ICraftingTask create(INetwork network, ItemStack stack, int quantity, ICraftingPattern pattern, @Nullable NBTTagCompound tag) {
return new CraftingTask(network, stack, quantity, pattern);
}
}

View File

@@ -1,321 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
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.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeProxy;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.util.Comparer;
import com.raoulvdberge.refinedstorage.util.StackUtils;
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.minecraftforge.common.util.Constants;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public abstract class CraftingStep implements ICraftingStep {
public static final String NBT_CRAFTING_STEP_TYPE = "CraftingStepType";
private static final String NBT_SATISFIED = "Satisfied_%d";
private static final String NBT_PATTERN = "Pattern";
private static final String NBT_PATTERN_CONTAINER = "PatternContainer";
private static final String NBT_STARTED_PROCESSING = "StartedProcessing";
private static final String NBT_PRELIMINARY_STEPS = "PreliminarySteps";
protected INetwork network;
protected ICraftingPattern pattern;
protected Map<Integer, Integer> satisfied;
protected boolean startedProcessing;
protected List<ICraftingStep> preliminarySteps;
public CraftingStep(INetwork network, ICraftingPattern pattern, List<ICraftingStep> preliminarySteps) {
this.network = network;
this.pattern = pattern;
this.satisfied = new HashMap<>(getPattern().getOutputs().size());
this.preliminarySteps = new ArrayList<>(preliminarySteps);
}
public CraftingStep(INetwork network) {
this.network = network;
}
public boolean readFromNBT(NBTTagCompound tag) {
ItemStack patternStack = new ItemStack(tag.getCompoundTag(NBT_PATTERN));
if (!patternStack.isEmpty()) {
TileEntity container = network.world().getTileEntity(BlockPos.fromLong(tag.getLong(NBT_PATTERN_CONTAINER)));
if (container instanceof INetworkNodeProxy) {
INetworkNodeProxy proxy = (INetworkNodeProxy) container;
if (proxy.getNode() instanceof ICraftingPatternContainer) {
this.pattern = ((ICraftingPatternProvider) patternStack.getItem()).create(network.world(), patternStack, (ICraftingPatternContainer) proxy.getNode());
this.satisfied = new HashMap<>(pattern.getOutputs().size());
for (ItemStack stack : pattern.getOutputs()) {
int hashcode = API.instance().getItemStackHashCode(stack);
String id = String.format(NBT_SATISFIED, hashcode);
if (tag.hasKey(id)) {
this.satisfied.put(hashcode, tag.getInteger(id));
}
}
this.startedProcessing = tag.getBoolean(NBT_STARTED_PROCESSING);
NBTTagList preliminaryTagList = tag.getTagList(NBT_PRELIMINARY_STEPS, Constants.NBT.TAG_COMPOUND);
this.preliminarySteps = new LinkedList<>();
for (int i = 0; i < preliminaryTagList.tagCount(); i++) {
NBTTagCompound stepTag = preliminaryTagList.getCompoundTagAt(i);
ICraftingStep step = CraftingStep.toCraftingStep(stepTag, network);
if (step != null) {
this.preliminarySteps.add(step);
}
}
return true;
}
}
}
return false;
}
@Override
public ICraftingPattern getPattern() {
return pattern;
}
@Override
public List<ItemStack> getInputs() {
return pattern.getInputs().stream().filter(Objects::nonNull).filter(s -> !s.isEmpty()).collect(Collectors.toList());
}
@Override
public List<ICraftingStep> getPreliminarySteps() {
return preliminarySteps != null ? preliminarySteps : Collections.emptyList();
}
@Override
public boolean canStartProcessing() {
return getPreliminarySteps().size() == 0;
}
@Override
public void setStartedProcessing() {
if (getPattern().isBlocking()) {
network.getCraftingManager().setContainerBlocked(getPattern().getContainer(), true);
}
startedProcessing = true;
}
@Override
public boolean hasStartedProcessing() {
return startedProcessing;
}
@Override
public boolean hasReceivedOutputs() {
for (ItemStack stack : pattern.getOutputs()) {
Integer received = satisfied.get(API.instance().getItemStackHashCode(stack));
if (received == null || stack.getCount() > received) {
return false;
}
}
if (getPattern().isBlocking()) {
network.getCraftingManager().setContainerBlocked(getPattern().getContainer(), false);
}
return true;
}
@Override
public boolean hasReceivedOutput(ItemStack stack) {
return getReceivedOutput(stack) >= stack.getCount();
}
@Override
public int getReceivedOutput(ItemStack stack) {
Integer received = satisfied.get(API.instance().getItemStackHashCode(stack));
return received == null ? 0 : received;
}
@Override
public boolean onReceiveOutput(ItemStack stack) {
ItemStack compareStack = Comparer.stripTags(stack.copy());
for (ItemStack output : pattern.getOutputs()) {
int hash = API.instance().getItemStackHashCode(output);
Integer received = satisfied.get(hash);
if (received == null) {
received = 0;
}
if (API.instance().getComparer().isEqual(compareStack, output, CraftingTask.DEFAULT_COMPARE | (getPattern().isOredict() ? IComparer.COMPARE_OREDICT : 0))) {
if (received < output.getCount()) {
int toReceive = Math.min(output.getCount() - received, stack.getCount());
satisfied.put(hash, received + toReceive);
stack.shrink(toReceive);
network.getCraftingManager().markCraftingMonitorForUpdate();
if (stack.isEmpty()) {
return true;
}
}
}
}
return false;
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
for (Map.Entry<Integer, Integer> entry : satisfied.entrySet()) {
tag.setInteger(String.format(NBT_SATISFIED, entry.getKey()), entry.getValue());
}
tag.setTag(NBT_PATTERN, pattern.getStack().serializeNBT());
tag.setLong(NBT_PATTERN_CONTAINER, pattern.getContainer().getPosition().toLong());
tag.setBoolean(NBT_STARTED_PROCESSING, startedProcessing);
NBTTagList preliminaryTagList = new NBTTagList();
for (ICraftingStep step : preliminarySteps) {
preliminaryTagList.appendTag(step.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_PRELIMINARY_STEPS, preliminaryTagList);
return tag;
}
enum AvailableType {
ITEM, FLUID
}
@Nullable
protected AvailableType isItemAvailable(IStackList<ItemStack> items, IStackList<FluidStack> fluids, ItemStack stack, ItemStack actualStack, int compare) {
if (actualStack == null || actualStack.isEmpty() || !items.trackedRemove(actualStack, stack.getCount())) {
FluidStack fluidInItem;
if (API.instance().getComparer().isEqual(stack, StackUtils.WATER_BOTTLE)) {
FluidStack fluidStack = fluids.get(new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME), compare);
ItemStack emptyBottle = items.get(StackUtils.EMPTY_BOTTLE, compare);
if (emptyBottle != null && fluidStack != null && !emptyBottle.isEmpty() && items.trackedRemove(StackUtils.EMPTY_BOTTLE, 1)) {
return AvailableType.FLUID;
}
} else if ((fluidInItem = StackUtils.getFluid(stack, true).getValue()) != null && StackUtils.hasFluidBucket(fluidInItem)) {
FluidStack fluidStack = fluids.get(fluidInItem, compare);
ItemStack bucket = items.get(StackUtils.EMPTY_BUCKET, compare);
if (bucket != null && fluidStack != null && !bucket.isEmpty() && fluids.trackedRemove(fluidStack, fluidInItem.amount) && items.trackedRemove(bucket, 1)) {
return AvailableType.FLUID;
}
}
return null;
}
return AvailableType.ITEM;
}
protected boolean extractItems(List<ItemStack> extractedItems, int compare, Deque<ItemStack> toInsertItems) {
for (ItemStack input : getInputs()) {
// This will be a tool, like a hammer
if (input.isItemStackDamageable()) {
compare &= ~IComparer.COMPARE_DAMAGE;
} else {
compare |= IComparer.COMPARE_DAMAGE;
}
ItemStack extracted = network.extractItem(input, input.getCount(), compare, false);
if (extracted != null) {
extractedItems.add(extracted);
} else {
boolean abort = true;
FluidStack fluidInItem;
if (API.instance().getComparer().isEqual(input, StackUtils.WATER_BOTTLE)) {
FluidStack fluidStack = network.extractFluid(new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME), Fluid.BUCKET_VOLUME, compare, true); // Simulate is true because we won't actually get the fluid out of the storage for bottles!
ItemStack emptyBottleStack = network.extractItem(StackUtils.EMPTY_BOTTLE, 1, compare, false);
if (fluidStack != null && fluidStack.amount == Fluid.BUCKET_VOLUME && emptyBottleStack != null) {
abort = false;
extractedItems.add(input.copy());
}
} else if ((fluidInItem = StackUtils.getFluid(input, true).getValue()) != null) {
FluidStack fluidStack = network.extractFluid(fluidInItem, fluidInItem.amount, compare, false);
ItemStack bucketStack = network.extractItem(StackUtils.EMPTY_BUCKET, 1, compare, false);
if (fluidStack != null && fluidStack.amount == fluidInItem.amount && bucketStack != null) {
abort = false;
extractedItems.add(input.copy());
}
}
if (abort) {
// Abort task re-insert taken stacks and reset state
toInsertItems.addAll(extractedItems);
startedProcessing = false;
return false;
}
}
}
return true;
}
@Nullable
public static ICraftingStep toCraftingStep(NBTTagCompound tag, INetwork network) {
CraftingStep step = null;
switch (tag.getString(CraftingStep.NBT_CRAFTING_STEP_TYPE)) {
case CraftingStepCraft.ID:
step = new CraftingStepCraft(network);
break;
case CraftingStepProcess.ID:
step = new CraftingStepProcess(network);
break;
}
if (step != null && step.readFromNBT(tag)) {
return step;
}
return null;
}
}

View File

@@ -1,151 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.util.StackListItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fluids.FluidStack;
import java.util.*;
import java.util.stream.Collectors;
public class CraftingStepCraft extends CraftingStep {
public static final String ID = "craft";
private static final String NBT_TO_INSERT = "ToInsert";
private List<ItemStack> inputs;
public CraftingStepCraft(INetwork network, ICraftingPattern pattern, List<ItemStack> inputs, List<ICraftingStep> preliminarySteps) {
super(network, pattern, preliminarySteps);
this.inputs = new LinkedList<>();
for (ItemStack input : inputs) {
this.inputs.add(input == null ? null : input.copy());
}
}
public CraftingStepCraft(INetwork network) {
super(network);
}
@Override
public List<ItemStack> getInputs() {
return inputs == null ? super.getInputs() : inputs.stream().filter(Objects::nonNull).filter(s -> !s.isEmpty()).collect(Collectors.toList());
}
@Override
public boolean canStartProcessing(IStackList<ItemStack> items, IStackList<FluidStack> fluids) {
if (!super.canStartProcessing()) {
return false;
}
int compare = CraftingTask.DEFAULT_COMPARE;
for (ItemStack stack : getInputs()) {
// This will be a tool, like a hammer
if (stack.isItemStackDamageable()) {
compare &= ~IComparer.COMPARE_DAMAGE;
} else {
compare |= IComparer.COMPARE_DAMAGE;
}
ItemStack actualStack = items.get(stack, compare);
if (isItemAvailable(items, fluids, stack, actualStack, compare) == null) {
items.undo();
fluids.undo();
return false;
}
}
items.undo();
fluids.undo();
return true;
}
@Override
public void execute(Deque<ItemStack> toInsertItems, Deque<FluidStack> toInsertFluids) {
List<ItemStack> extracted = new LinkedList<>();
if (extractItems(extracted, CraftingTask.DEFAULT_COMPARE, toInsertItems)) {
IStackList<ItemStack> extractedStacks = API.instance().createItemStackList();
extracted.forEach(extractedStacks::add);
ItemStack[] took = StackListItem.toCraftingGrid(extractedStacks, inputs, CraftingTask.DEFAULT_COMPARE | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0));
List<ItemStack> outputs = pattern.isOredict() ? pattern.getOutputs(took) : pattern.getOutputs();
if (outputs == null) {
toInsertItems.addAll(extracted);
startedProcessing = false;
return;
}
for (ItemStack output : outputs) {
if (output != null && !output.isEmpty()) {
toInsertItems.add(output.copy());
}
}
for (ItemStack byproduct : (pattern.isOredict() ? pattern.getByproducts(took) : pattern.getByproducts())) {
toInsertItems.add(byproduct.copy());
}
} else {
// Couldn't extract items
startedProcessing = false;
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
tag.setString(NBT_CRAFTING_STEP_TYPE, ID);
super.writeToNBT(tag);
NBTTagList toInsertList = new NBTTagList();
for (ItemStack insert : inputs) {
toInsertList.appendTag(insert == null ? new NBTTagCompound() : insert.serializeNBT());
}
tag.setTag(NBT_TO_INSERT, toInsertList);
return tag;
}
@Override
public boolean readFromNBT(NBTTagCompound tag) {
if (super.readFromNBT(tag)) {
if (tag.hasKey(NBT_TO_INSERT)) {
NBTTagList toInsertList = tag.getTagList(NBT_TO_INSERT, Constants.NBT.TAG_COMPOUND);
inputs = new ArrayList<>(toInsertList.tagCount());
for (int i = 0; i < toInsertList.tagCount(); ++i) {
ItemStack stack = new ItemStack(toInsertList.getCompoundTagAt(i));
if (stack.isEmpty()) {
inputs.add(null);
} else {
inputs.add(stack);
}
}
}
return true;
}
return false;
}
}

View File

@@ -1,142 +0,0 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
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.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CraftingStepProcess extends CraftingStep {
public static final String ID = "process";
public CraftingStepProcess(INetwork network, ICraftingPattern pattern, List<ICraftingStep> preliminarySteps) {
super(network, pattern, preliminarySteps);
}
public CraftingStepProcess(INetwork network) {
super(network);
}
@Override
public boolean canStartProcessing(IStackList<ItemStack> items, IStackList<FluidStack> fluids) {
if (!super.canStartProcessing()) {
return false;
}
IItemHandler inventory = getPattern().getContainer().getConnectedInventory();
int compare = CraftingTask.DEFAULT_COMPARE | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0);
if (inventory != null) {
Deque<ItemStack> toInsert = new LinkedList<>();
for (ItemStack stack : getInputs()) {
// This will be a tool, like a hammer
if (stack.isItemStackDamageable()) {
compare &= ~IComparer.COMPARE_DAMAGE;
} else {
compare |= IComparer.COMPARE_DAMAGE;
}
ItemStack actualStack = items.get(stack, compare);
AvailableType type = isItemAvailable(items, fluids, stack, actualStack, compare);
if (type == AvailableType.ITEM) {
toInsert.add(ItemHandlerHelper.copyStackWithSize(actualStack, stack.getCount()));
} else if (type == AvailableType.FLUID) {
toInsert.add(ItemHandlerHelper.copyStackWithSize(stack, stack.getCount()));
} else {
items.undo();
fluids.undo();
return false;
}
}
items.undo();
fluids.undo();
return insertItems(inventory, toInsert, true);
}
return false;
}
@Override
public boolean canStartProcessing() {
if (!super.canStartProcessing()) {
return false;
}
IItemHandler inventory = getPattern().getContainer().getConnectedInventory();
return inventory != null && insertItems(inventory, new LinkedList<>(getInputs()), true);
}
@Override
public void execute(Deque<ItemStack> toInsertItems, Deque<FluidStack> toInsertFluids) {
LinkedList<ItemStack> extracted = new LinkedList<>();
int compare = CraftingTask.DEFAULT_COMPARE | (getPattern().isOredict() ? IComparer.COMPARE_OREDICT : 0);
if (extractItems(extracted, compare, toInsertItems)) {
IItemHandler inventory = getPattern().getContainer().getConnectedInventory();
if (insertItems(inventory, new ArrayDeque<>(extracted), true)) {
insertItems(inventory, extracted, false);
} else {
// Something went wrong here, redo!
toInsertItems.addAll(extracted);
startedProcessing = false;
}
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
tag.setString(NBT_CRAFTING_STEP_TYPE, ID);
return super.writeToNBT(tag);
}
private static boolean insertItems(IItemHandler inventory, Deque<ItemStack> stacks, boolean simulate) {
ItemStack current = stacks.poll();
List<Integer> availableSlots = IntStream.range(0, inventory.getSlots()).boxed().collect(Collectors.toList());
while (current != null && !availableSlots.isEmpty()) {
ItemStack remainder = null;
for (Integer slot : availableSlots) {
remainder = inventory.insertItem(slot, current, simulate);
if (remainder.isEmpty() || current.getCount() != remainder.getCount()) {
availableSlots.remove(slot);
break;
}
}
if (remainder == null || remainder.isEmpty()) {
current = stacks.poll();
} else if (current.getCount() == remainder.getCount()) {
break; // Can't be inserted
} else {
current = remainder;
}
}
return current == null && stacks.isEmpty();
}
}

View File

@@ -1,549 +1,41 @@
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternChain;
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.ICraftingStep;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementError;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementInfo;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementItemRender;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementText;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementError;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementFluidStack;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementItemStack;
import com.raoulvdberge.refinedstorage.apiimpl.util.StackListItem;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.oredict.OreDictionary;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.Collections;
import java.util.List;
public class CraftingTask implements ICraftingTask {
protected static final int DEFAULT_COMPARE = IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT | IComparer.COMPARE_STRIP_NBT;
public static final String NBT_STEPS = "Steps";
public static final String NBT_TO_TAKE_FLUIDS = "ToTakeFluids";
public static final String NBT_TO_INSERT_ITEMS = "ToInsertItems";
public static final String NBT_TO_INSERT_FLUIDS = "ToInsertFluids";
private INetwork network;
@Nullable
private ItemStack requested;
private ICraftingPattern pattern;
private ICraftingPatternChain chain;
private ItemStack stack;
private int quantity;
private boolean automated;
private ICraftingPattern pattern;
private List<ICraftingStep> mainSteps = new LinkedList<>();
private IStackList<ItemStack> toTake = API.instance().createItemStackList();
private IStackList<ItemStack> toCraft = API.instance().createItemStackList();
private IStackList<ItemStack> missing = API.instance().createItemStackList();
private Set<ICraftingPattern> usedPatterns = new HashSet<>();
private ICraftingPattern recursedPattern = null;
private Deque<ItemStack> toInsertItems = new ArrayDeque<>();
private Deque<FluidStack> toInsertFluids = new ArrayDeque<>();
private IStackList<FluidStack> toTakeFluids = API.instance().createFluidStackList();
public CraftingTask(INetwork network, @Nullable ItemStack requested, ICraftingPattern pattern, int quantity, boolean automated) {
public CraftingTask(INetwork network, ItemStack stack, int quantity, ICraftingPattern pattern) {
this.network = network;
this.requested = requested;
this.pattern = pattern;
this.stack = stack;
this.quantity = quantity;
this.automated = automated;
}
public CraftingTask(INetwork network, @Nullable ItemStack requested, ICraftingPatternChain chain, int quantity, boolean automated) {
this(network, requested, chain.getPrototype(), quantity, automated);
this.chain = chain;
}
public CraftingTask(INetwork network, @Nullable ItemStack requested, ICraftingPattern pattern, int quantity, List<ICraftingStep> mainSteps, Deque<ItemStack> toInsertItems, IStackList<FluidStack> toTakeFluids, Deque<FluidStack> toInsertFluids, boolean automated) {
this(network, requested, pattern, quantity, automated);
this.mainSteps = mainSteps;
this.toInsertItems = toInsertItems;
this.toTakeFluids = toTakeFluids;
this.toInsertFluids = toInsertFluids;
this.pattern = pattern;
}
@Override
public void calculate() {
// Copy here might be expensive but since it is only executed once it isn't a big impact
IStackList<ItemStack> networkList = network.getItemStorageCache().getList().copy().getOredicted();
IStackList<FluidStack> networkFluidList = network.getFluidStorageCache().getList().copy();
IStackList<ItemStack> toInsert = API.instance().createItemStackList();
ItemStack requested = this.requested != null ? this.requested : pattern.getOutputs().get(0);
toCraft.add(requested, quantity);
int quantity = this.quantity;
ICraftingPattern currentPattern;
while (quantity > 0 && recursedPattern == null) {
currentPattern = this.chain == null ? this.pattern : this.chain.cycle();
mainSteps.add(calculate(networkList, networkFluidList, currentPattern, toInsert));
quantity -= currentPattern.getQuantityPerRequest(requested);
}
usedPatterns.clear();
}
@Nullable
private ICraftingStep calculate(IStackList<ItemStack> networkItems, IStackList<FluidStack> networkFluids, ICraftingPattern pattern, IStackList<ItemStack> toInsert) {
if (!usedPatterns.add(pattern)) {
recursedPattern = pattern;
return null;
}
int compare = DEFAULT_COMPARE;
IStackList<ItemStack> actualInputs = API.instance().createItemStackList();
List<ItemStack> usedStacks = new LinkedList<>();
List<ICraftingStep> previousSteps = new LinkedList<>();
IStackList<ItemStack> byproductList = API.instance().createItemStackList();
pattern.getByproducts().forEach(byproductList::add);
for (List<ItemStack> inputs : pattern.getOreInputs()) {
if (inputs == null || inputs.isEmpty()) {
usedStacks.add(null);
continue;
}
int i = 0;
ItemStack input, extraStack, networkStack;
do {
input = inputs.get(i).copy();
// This will be a tool, like a hammer
if (input.isItemStackDamageable()) {
compare &= ~IComparer.COMPARE_DAMAGE;
} else {
compare |= IComparer.COMPARE_DAMAGE;
}
extraStack = toInsert.get(input, compare);
networkStack = networkItems.get(input, compare);
}
while (extraStack == null && networkStack == null && ++i < inputs.size() && !network.getCraftingManager().hasPattern(input, compare));
// Stack not found, just take first
if (i == inputs.size()) {
input = inputs.get(0).copy();
}
usedStacks.add(input.copy());
// This will be a tool, like a hammer
if (input.isItemStackDamageable()) {
compare &= ~IComparer.COMPARE_DAMAGE;
} else {
compare |= IComparer.COMPARE_DAMAGE;
}
// This handles recipes that use the output as input for the sub recipe
final int lambdaCompare = compare;
final ItemStack lambdaInput = input;
ICraftingPattern inputPattern = null;
int available = (extraStack == null ? 0 : extraStack.getCount()) + (networkStack == null ? 0 : networkStack.getCount());
if (available < input.getCount()) {
inputPattern = network.getCraftingManager().getPattern(input, compare, networkItems);
if (inputPattern != null) {
if (inputPattern.getInputs().stream().anyMatch(s -> API.instance().getComparer().isEqual(s, lambdaInput, lambdaCompare))) {
int craftQuantity = inputPattern.getQuantityPerRequest(input, compare);
// The needed amount is the actual needed amount of extraStacks + the needed input (twice so you can keep repeating it)
long needed = (networkStack == null ? 0 : -networkStack.getCount()) + input.getCount() + inputPattern.getInputs().stream().filter(s -> API.instance().getComparer().isEqual(s, lambdaInput, lambdaCompare)).count() * 2;
do {
previousSteps.add(calculate(networkItems, networkFluids, inputPattern, toInsert));
toCraft.add(input, craftQuantity);
extraStack = toInsert.get(input, compare);
} while (extraStack != null && extraStack.getCount() < needed);
}
}
}
while (input.getCount() > 0) {
if (extraStack != null && !extraStack.isEmpty()) {
int takeQuantity = Math.min(extraStack.getCount(), input.getCount());
ItemStack inputStack = ItemHandlerHelper.copyStackWithSize(extraStack, takeQuantity);
actualInputs.add(inputStack);
input.shrink(takeQuantity);
if (byproductList.get(inputStack, compare) == null) {
toCraft.add(inputStack);
}
toInsert.remove(inputStack);
if (input.getCount() > 0) {
i = 0;
do {
extraStack = toInsert.get(inputs.get(i), compare);
} while ((extraStack == null || extraStack.isEmpty()) && ++i < inputs.size());
}
} else if (networkStack != null && networkStack.getCount() > 0) {
int takeQuantity = Math.min(networkStack.getCount(), input.getCount());
ItemStack inputStack = ItemHandlerHelper.copyStackWithSize(networkStack, takeQuantity);
toTake.add(inputStack);
actualInputs.add(inputStack);
input.shrink(takeQuantity);
networkItems.remove(inputStack);
if (input.getCount() > 0) {
i = 0;
do {
networkStack = networkItems.get(inputs.get(i), compare);
} while ((extraStack == null || extraStack.getCount() == 0) && ++i < inputs.size());
}
} else {
int oreDictedCompare = compare | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0);
if (inputPattern == null) {
inputPattern = network.getCraftingManager().getPattern(input, oreDictedCompare, networkItems);
}
if (inputPattern != null) {
ItemStack actualCraft = inputPattern.getActualOutput(input, oreDictedCompare);
int craftQuantity = Math.min(inputPattern.getQuantityPerRequest(input, oreDictedCompare), input.getCount());
ItemStack inputCrafted = ItemHandlerHelper.copyStackWithSize(actualCraft, craftQuantity);
toCraft.add(inputCrafted);
actualInputs.add(inputCrafted);
ICraftingStep step = calculate(networkItems, networkFluids, inputPattern, toInsert);
input.shrink(craftQuantity);
if (step != null) {
previousSteps.add(step);
if (recursedPattern == null) {
// Calculate added all the crafted outputs toInsert
// So we remove the ones we use from toInsert
ItemStack inserted = toInsert.get(inputCrafted, compare);
toInsert.remove(inserted, craftQuantity);
}
}
} else {
// Fluid checks are with a stack size of one
ItemStack fluidCheck = ItemHandlerHelper.copyStackWithSize(input, 1);
while (!input.isEmpty() && doFluidCalculation(networkItems, networkFluids, fluidCheck, toInsert, previousSteps)) {
actualInputs.add(fluidCheck);
input.shrink(1);
}
// When it isn't a fluid or just doesn't have the needed fluids
if (input.getCount() > 0) {
ItemStack copy = input.copy();
if (copy.getItemDamage() == OreDictionary.WILDCARD_VALUE) {
copy.setItemDamage(0);
}
missing.add(copy);
input.setCount(0);
}
}
}
}
}
ItemStack[] took = null;
if (missing.isEmpty() && !pattern.isProcessing()) {
took = StackListItem.toCraftingGrid(actualInputs, usedStacks, compare | (pattern.isOredict() ? IComparer.COMPARE_OREDICT : 0));
}
List<ItemStack> outputs = (!pattern.isProcessing() && pattern.isOredict() && missing.isEmpty()) ? pattern.getOutputs(took) : pattern.getOutputs();
if (outputs == null) {
outputs = pattern.getOutputs();
}
for (ItemStack output : outputs) {
if (output != null && !output.isEmpty()) {
toInsert.add(output);
}
}
for (ItemStack byproduct : (!pattern.isProcessing() && pattern.isOredict() && missing.isEmpty()) ? pattern.getByproducts(took) : pattern.getByproducts()) {
toInsert.add(byproduct);
}
usedPatterns.remove(pattern);
return pattern.isProcessing() ? new CraftingStepProcess(network, pattern, previousSteps) : new CraftingStepCraft(network, pattern, usedStacks, previousSteps);
}
private boolean doFluidCalculation(IStackList<ItemStack> networkList, IStackList<FluidStack> networkFluidList, ItemStack input, IStackList<ItemStack> toInsert, List<ICraftingStep> previousSteps) {
FluidStack fluidInItem;
if (API.instance().getComparer().isEqual(input, StackUtils.WATER_BOTTLE)) {
FluidStack fluidInStorage = networkFluidList.get(new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME));
if (fluidInStorage == null || fluidInStorage.amount < Fluid.BUCKET_VOLUME) {
missing.add(input);
} else {
ItemStack emptyBottle = toInsert.get(StackUtils.EMPTY_BOTTLE);
boolean hasBottle = false;
if (emptyBottle != null && emptyBottle.getCount() > 0) {
hasBottle = toInsert.remove(StackUtils.EMPTY_BOTTLE, 1);
}
if (!hasBottle) {
emptyBottle = networkList.get(StackUtils.EMPTY_BOTTLE);
if (emptyBottle != null && emptyBottle.getCount() > 0) {
hasBottle = networkList.remove(StackUtils.EMPTY_BOTTLE);
}
}
ICraftingPattern emptyBottlePattern = network.getCraftingManager().getPattern(StackUtils.EMPTY_BOTTLE);
if (!hasBottle) {
if (emptyBottlePattern == null) {
missing.add(StackUtils.EMPTY_BOTTLE);
} else {
toCraft.add(StackUtils.EMPTY_BOTTLE);
previousSteps.add(calculate(networkList, networkFluidList, emptyBottlePattern, toInsert));
toInsert.remove(StackUtils.EMPTY_BOTTLE, 1);
}
}
if (hasBottle || emptyBottlePattern != null) {
toTake.add(StackUtils.EMPTY_BOTTLE);
networkList.remove(StackUtils.EMPTY_BOTTLE);
}
}
return true;
} else if ((fluidInItem = StackUtils.getFluid(input, true).getValue()) != null && StackUtils.hasFluidBucket(fluidInItem)) {
FluidStack fluidInStorage = networkFluidList.get(fluidInItem);
if (fluidInStorage == null || fluidInStorage.amount < fluidInItem.amount) {
missing.add(input);
} else {
ItemStack bucket = toInsert.get(StackUtils.EMPTY_BUCKET);
boolean hasBucket = false;
if (bucket != null && bucket.getCount() > 0) {
hasBucket = toInsert.remove(StackUtils.EMPTY_BUCKET, 1);
}
if (!hasBucket) {
bucket = networkList.get(StackUtils.EMPTY_BUCKET);
if (bucket != null && bucket.getCount() > 0) {
hasBucket = networkList.remove(StackUtils.EMPTY_BUCKET, 1);
}
}
ICraftingPattern bucketPattern = network.getCraftingManager().getPattern(StackUtils.EMPTY_BUCKET);
if (!hasBucket) {
if (bucketPattern == null) {
missing.add(StackUtils.EMPTY_BUCKET);
} else {
toCraft.add(StackUtils.EMPTY_BUCKET);
previousSteps.add(calculate(networkList, networkFluidList, bucketPattern, toInsert));
toInsert.remove(StackUtils.EMPTY_BUCKET, 1);
}
}
if (hasBucket || bucketPattern != null) {
toTakeFluids.add(fluidInItem);
networkFluidList.remove(fluidInItem);
}
}
return true;
}
@Override
public boolean update() {
return false;
}
@Override
public void onCancelled() {
for (ItemStack stack : toInsertItems) {
network.insertItemTracked(stack, stack.getCount());
}
for (ICraftingStep step : getSteps()) {
if (step.getPattern().isBlocking()) {
network.getCraftingManager().setContainerBlocked(step.getPattern().getContainer(), false);
}
}
network.getCraftingManager().markCraftingMonitorForUpdate();
}
@Override
public String toString() {
return "\nCraftingTask{quantity=" + quantity +
"\n, automated=" + automated +
"\n, toTake=" + toTake +
"\n, toTakeFluids=" + toTakeFluids +
"\n, toCraft=" + toCraft +
"\n, toInsertItems=" + toInsertItems +
"\n, toInsertFluids=" + toInsertFluids +
"\n, mainSteps=" + mainSteps +
'}';
}
@Override
public boolean update(Map<ICraftingPatternContainer, Integer> usedContainers) {
IStackList<ItemStack> networkItems = network.getItemStorageCache().getList().getOredicted();
IStackList<FluidStack> networkFluids = network.getFluidStorageCache().getList();
if (!missing.isEmpty()) {
for (ItemStack missing : this.missing.getStacks()) {
if (!networkItems.trackedRemove(missing)) {
networkItems.undo();
return false;
}
}
networkItems.undo();
reschedule();
return false;
}
// We need to copy the size cause we'll re-add unadded stacks to the queue
// Do inserting on the next tick, reliefs CPU time during insertion
// See TileController#runningSteps
int times = toInsertItems.size();
for (int i = 0; i < times; i++) {
ItemStack insert = toInsertItems.poll();
if (insert != null) {
ItemStack remainder = network.insertItemTracked(insert, insert.getCount());
if (remainder != null) {
toInsertItems.add(remainder);
}
}
}
// Collect all leaf steps
List<ICraftingStep> leafSteps = new LinkedList<>();
Queue<ICraftingStep> steps = new LinkedList<>();
steps.addAll(mainSteps);
while (steps.size() > 0) {
ICraftingStep step = steps.poll();
if (step.getPreliminarySteps().size() > 0) {
steps.addAll(step.getPreliminarySteps());
} else {
leafSteps.add(step);
}
}
for (ICraftingStep step : leafSteps) {
if (!step.hasStartedProcessing()) {
ICraftingPatternContainer container = step.getPattern().getContainer();
Integer timesUsed = usedContainers.get(container);
if (timesUsed == null) {
timesUsed = 0;
}
if (timesUsed++ <= container.getSpeedUpdateCount()) {
if (!step.getPattern().isProcessing() || !container.isBlocked()) {
if (step.canStartProcessing(networkItems, networkFluids)) {
step.setStartedProcessing();
step.execute(toInsertItems, toInsertFluids);
usedContainers.put(container, timesUsed);
network.getCraftingManager().markCraftingMonitorForUpdate();
}
}
}
}
}
if (getSteps().stream().filter(ICraftingStep::hasStartedProcessing).count() == 0) {
// When there is no started processes, restart the task.
reschedule();
}
// Remove finished tasks
steps.clear(); // Re use Queue from earlier
mainSteps.removeIf(ICraftingStep::hasReceivedOutputs);
steps.addAll(mainSteps);
while (steps.size() > 0) {
ICraftingStep step = steps.poll();
step.getPreliminarySteps().removeIf(ICraftingStep::hasReceivedOutputs);
steps.addAll(step.getPreliminarySteps());
}
return isFinished();
}
@Override
public void reschedule() {
List<ICraftingStep> mainSteps = this.mainSteps.stream().filter(s -> s.getPattern().alike(pattern)).collect(Collectors.toList());
missing.clear();
this.mainSteps.clear();
// if the list of main mainSteps is empty there is no point in rescheduling
if (!mainSteps.isEmpty()) {
quantity = 0;
int quantityPerRequest = pattern.getQuantityPerRequest(requested);
for (ICraftingStep step : mainSteps) {
quantity += quantityPerRequest - step.getReceivedOutput(requested);
}
if (quantity > 0) {
calculate();
}
network.getCraftingManager().markCraftingMonitorForUpdate();
}
}
@Override
@@ -551,142 +43,24 @@ public class CraftingTask implements ICraftingTask {
return quantity;
}
@Nullable
@Override
public ItemStack getRequested() {
return requested;
return stack;
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
writeDefaultsToNBT(tag);
NBTTagList stepsList = new NBTTagList();
for (ICraftingStep step : mainSteps) {
stepsList.appendTag(step.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_STEPS, stepsList);
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, StackUtils.serializeFluidStackList(toTakeFluids));
NBTTagList toInsertFluidsList = new NBTTagList();
for (FluidStack insert : toInsertFluids) {
toInsertFluidsList.appendTag(insert.writeToNBT(new NBTTagCompound()));
}
tag.setTag(NBT_TO_INSERT_FLUIDS, toInsertFluidsList);
return tag;
}
@Override
public List<ICraftingMonitorElement> getCraftingMonitorElements() {
ICraftingMonitorElementList elements = API.instance().createCraftingMonitorElementList();
return Collections.singletonList(new CraftingMonitorElementItemRender(network.getCraftingManager().getTasks().indexOf(this), stack, quantity, 0));
}
elements.directAdd(new CraftingMonitorElementItemRender(
network.getCraftingManager().getTasks().indexOf(this),
requested != null ? requested : pattern.getOutputs().get(0),
quantity,
0
));
if (!missing.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_missing", 16));
missing.getStacks().stream()
.map(stack -> new CraftingMonitorElementError(new CraftingMonitorElementItemRender(
-1,
stack,
stack.getCount(),
32
), ""))
.forEach(elements::add);
elements.commit();
}
if (!toInsertItems.isEmpty()) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 16));
toInsertItems.stream()
.map(stack -> new CraftingMonitorElementItemRender(
-1,
stack,
stack.getCount(),
32
))
.forEach(elements::add);
elements.commit();
}
if (!isFinished()) {
if (getSteps().stream().filter(s -> !s.getPattern().isProcessing()).count() > 0) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_crafting", 16));
IStackList<ItemStack> oreDictPrepped = network.getItemStorageCache().getList().getOredicted();
IStackList<FluidStack> networkFluids = network.getFluidStorageCache().getList();
for (ICraftingStep step : getSteps().stream().filter(s -> !s.getPattern().isProcessing()).collect(Collectors.toList())) {
for (int i = 0; i < step.getPattern().getOutputs().size(); ++i) {
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(
-1,
step.getPattern().getOutputs().get(i),
step.getPattern().getOutputs().get(i).getCount(),
32
);
if (!step.hasStartedProcessing() && !step.canStartProcessing(oreDictPrepped, networkFluids)) {
element = new CraftingMonitorElementInfo(element, "gui.refinedstorage:crafting_monitor.waiting_for_items");
}
elements.add(element);
}
}
elements.commit();
}
if (getSteps().stream().filter(s -> s.getPattern().isProcessing()).count() > 0) {
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_processing", 16));
for (ICraftingStep step : getSteps().stream().filter(s -> s.getPattern().isProcessing()).collect(Collectors.toList())) {
for (int i = 0; i < step.getPattern().getOutputs().size(); ++i) {
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(
-1,
step.getPattern().getOutputs().get(i),
step.getPattern().getOutputs().get(i).getCount(),
32
);
if (step.getPattern().getContainer().getConnectedTile() == null) {
element = new CraftingMonitorElementError(element, "gui.refinedstorage:crafting_monitor.machine_none");
} else if (!step.hasStartedProcessing() && !step.canStartProcessing()) {
element = new CraftingMonitorElementError(element, "gui.refinedstorage:crafting_monitor.machine_in_use");
} else if (!step.hasStartedProcessing() && step.getPattern().getContainer().isBlocked()) {
element = new CraftingMonitorElementError(element, "gui.refinedstorage:crafting_monitor.blocked");
}
elements.add(element);
}
}
elements.commit();
}
}
return elements.getElements();
@Override
public List<ICraftingPreviewElement> getPreviewStacks() {
return Collections.emptyList();
}
@Override
@@ -694,98 +68,8 @@ public class CraftingTask implements ICraftingTask {
return pattern;
}
public List<ICraftingStep> getSteps() {
List<ICraftingStep> allSteps = new LinkedList<>();
Queue<ICraftingStep> steps = new LinkedList<>();
steps.addAll(mainSteps);
while (steps.size() > 0) {
ICraftingStep step = steps.poll();
allSteps.add(step);
steps.addAll(step.getPreliminarySteps());
}
return allSteps;
}
@Override
public boolean isValid() {
return recursedPattern == null;
}
@Override
public IStackList<ItemStack> getMissing() {
return missing;
}
@Override
public List<ICraftingPreviewElement> getPreviewStacks() {
if (!isValid()) {
return Collections.singletonList(new CraftingPreviewElementError(recursedPattern.getStack()));
}
Map<Integer, CraftingPreviewElementItemStack> map = new LinkedHashMap<>();
for (ItemStack stack : toCraft.getStacks()) {
int hash = API.instance().getItemStackHashCode(stack);
CraftingPreviewElementItemStack previewStack = map.get(hash);
if (previewStack == null) {
previewStack = new CraftingPreviewElementItemStack(stack);
}
previewStack.addToCraft(stack.getCount());
map.put(hash, previewStack);
}
for (ItemStack stack : missing.getStacks()) {
int hash = API.instance().getItemStackHashCode(stack);
CraftingPreviewElementItemStack previewStack = map.get(hash);
if (previewStack == null) {
previewStack = new CraftingPreviewElementItemStack(stack);
}
previewStack.setMissing(true);
previewStack.addToCraft(stack.getCount());
map.put(hash, previewStack);
}
for (ItemStack stack : toTake.getStacks()) {
int hash = API.instance().getItemStackHashCode(stack);
CraftingPreviewElementItemStack previewStack = map.get(hash);
if (previewStack == null) {
previewStack = new CraftingPreviewElementItemStack(stack);
}
previewStack.addAvailable(stack.getCount());
map.put(hash, previewStack);
}
List<ICraftingPreviewElement> elements = new ArrayList<>(map.values());
toTakeFluids.getStacks().stream().map(CraftingPreviewElementFluidStack::new).forEach(elements::add);
return elements;
}
@Override
public boolean isAutomated() {
return automated;
}
@Override
public boolean isFinished() {
return mainSteps.stream().allMatch(ICraftingStep::hasReceivedOutputs);
return true;
}
}

View File

@@ -11,7 +11,6 @@ import com.raoulvdberge.refinedstorage.api.network.item.NetworkItemAction;
import com.raoulvdberge.refinedstorage.api.network.security.Permission;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.CraftingTask;
import com.raoulvdberge.refinedstorage.network.MessageGridCraftingPreviewResponse;
import com.raoulvdberge.refinedstorage.network.MessageGridCraftingStartResponse;
import com.raoulvdberge.refinedstorage.util.StackUtils;
@@ -171,13 +170,12 @@ public class ItemGridHandler implements IItemGridHandler {
return;
}
// TODO why?
IStackList<ItemStack> cache = API.instance().createItemStackList();
for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) {
for (ItemStack output : pattern.getOutputs()) {
if (output != null) {
cache.add(output);
}
cache.add(output);
}
}
@@ -185,11 +183,14 @@ public class ItemGridHandler implements IItemGridHandler {
if (stack != null) {
Thread calculationThread = new Thread(() -> {
ICraftingTask task = new CraftingTask(network, stack, network.getCraftingManager().getPatternChain(stack), quantity, false);
ICraftingTask task = network.getCraftingManager().create(stack, quantity);
if (task == null) {
return;
}
task.calculate();
if (noPreview && task.getMissing().isEmpty()) {
if (noPreview /*&& task.getMissing().isEmpty()*/) { // TODO
network.getCraftingManager().add(task);
RS.INSTANCE.network.sendTo(new MessageGridCraftingStartResponse(), player);
@@ -212,7 +213,7 @@ public class ItemGridHandler implements IItemGridHandler {
for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) {
for (ItemStack output : pattern.getOutputs()) {
if (output != null && API.instance().getItemStackHashCode(output) == hash) {
if (API.instance().getItemStackHashCode(output) == hash) {
stack = output;
break;
@@ -225,12 +226,13 @@ public class ItemGridHandler implements IItemGridHandler {
}
if (stack != null) {
ICraftingTask task = new CraftingTask(network, stack, network.getCraftingManager().getPatternChain(stack), quantity, false);
ICraftingTask task = network.getCraftingManager().create(stack, quantity);
if (task == null) {
return;
}
task.calculate();
task.getMissing().clear();
network.getCraftingManager().add(task);
}
}

View File

@@ -116,7 +116,6 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC
network.getCraftingManager().getTasks().stream()
.filter(task -> task.getPattern().getContainer().getPosition().equals(pos))
.forEach(task -> network.getCraftingManager().cancel(task));
network.getCraftingManager().setContainerBlocked(this, false);
}
network.getCraftingManager().rebuild();
@@ -268,13 +267,8 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC
visited = true;
ICraftingPatternContainer facingContainer = ((ICraftingPatternContainer)facing).getRootContainer();
visited = false;
return facingContainer;
}
@Override
public boolean isBlocked() {
ICraftingPatternContainer proxy = getRootContainer();
return proxy != null && network != null && network.getCraftingManager().isContainerBlocked(proxy.getUuid());
return facingContainer;
}
@Override
@@ -283,6 +277,7 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC
uuid = UUID.randomUUID();
markDirty();
}
return uuid;
}
}

View File

@@ -7,7 +7,6 @@ import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFilter;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerListenerNetworkNode;
import com.raoulvdberge.refinedstorage.tile.craftingmonitor.ICraftingMonitor;
import com.raoulvdberge.refinedstorage.tile.craftingmonitor.TileCraftingMonitor;
import com.raoulvdberge.refinedstorage.tile.data.TileDataManager;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.entity.player.EntityPlayer;
@@ -25,9 +24,6 @@ import java.util.List;
public class NetworkNodeCraftingMonitor extends NetworkNode implements ICraftingMonitor {
public static final String ID = "crafting_monitor";
private static final String NBT_VIEW_AUTOMATED = "ViewAutomated";
private boolean viewAutomated = true;
private List<IFilter> filters = new ArrayList<>();
private ItemHandlerListenerNetworkNode filterListener = new ItemHandlerListenerNetworkNode(this);
private ItemHandlerFilter filter = new ItemHandlerFilter(filters, new ArrayList<>(), slot -> {
@@ -102,8 +98,6 @@ public class NetworkNodeCraftingMonitor extends NetworkNode implements ICrafting
StackUtils.writeItems(filter, 0, tag);
tag.setBoolean(NBT_VIEW_AUTOMATED, viewAutomated);
return tag;
}
@@ -112,20 +106,6 @@ public class NetworkNodeCraftingMonitor extends NetworkNode implements ICrafting
super.read(tag);
StackUtils.readItems(filter, 0, tag);
if (tag.hasKey(NBT_VIEW_AUTOMATED)) {
viewAutomated = tag.getBoolean(NBT_VIEW_AUTOMATED);
}
}
@Override
public boolean canViewAutomated() {
return world.isRemote ? TileCraftingMonitor.VIEW_AUTOMATED.getValue() : viewAutomated;
}
@Override
public void onViewAutomatedChanged(boolean viewAutomated) {
TileDataManager.setParameter(TileCraftingMonitor.VIEW_AUTOMATED, viewAutomated);
}
@Override
@@ -133,10 +113,6 @@ public class NetworkNodeCraftingMonitor extends NetworkNode implements ICrafting
// NO OP
}
public void setViewAutomated(boolean viewAutomated) {
this.viewAutomated = viewAutomated;
}
public ItemHandlerFilter getFilter() {
return filter;
}

View File

@@ -63,7 +63,6 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware {
public static final String NBT_TAB_PAGE = "TabPage";
public static final String NBT_SIZE = "Size";
public static final String NBT_PROCESSING_PATTERN = "ProcessingPattern";
public static final String NBT_BLOCKING_PATTERN = "BlockingPattern";
private Container craftingContainer = new Container() {
@Override
@@ -130,7 +129,6 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware {
private boolean oredictPattern = false;
private boolean processingPattern = false;
private boolean blockingPattern = false;
public NetworkNodeGrid(World world, BlockPos pos) {
super(world, pos);
@@ -196,14 +194,6 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware {
this.processingPattern = processingPattern;
}
public boolean isBlockingPattern() {
return blockingPattern;
}
public void setBlockingPattern(boolean blockingPattern) {
this.blockingPattern = blockingPattern;
}
public GridType getType() {
if (type == null && world.getBlockState(pos).getBlock() == RSBlocks.GRID) {
type = (GridType) world.getBlockState(pos).getValue(BlockGrid.TYPE);
@@ -499,10 +489,6 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware {
ItemStack pattern = new ItemStack(RSItems.PATTERN);
if (processingPattern) {
ItemPattern.setBlocking(pattern, blockingPattern);
}
ItemPattern.setOredict(pattern, oredictPattern);
if (processingPattern) {
@@ -692,7 +678,6 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware {
tag.setBoolean(NBT_OREDICT_PATTERN, oredictPattern);
tag.setBoolean(NBT_PROCESSING_PATTERN, processingPattern);
tag.setBoolean(NBT_BLOCKING_PATTERN, blockingPattern);
return tag;
}
@@ -728,10 +713,6 @@ public class NetworkNodeGrid extends NetworkNode implements IGridNetworkAware {
if (tag.hasKey(NBT_PROCESSING_PATTERN)) {
processingPattern = tag.getBoolean(NBT_PROCESSING_PATTERN);
}
if (tag.hasKey(NBT_BLOCKING_PATTERN)) {
blockingPattern = tag.getBoolean(NBT_BLOCKING_PATTERN);
}
}
@Override

View File

@@ -6,7 +6,6 @@ import com.raoulvdberge.refinedstorage.api.render.IElementDrawer;
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
import com.raoulvdberge.refinedstorage.container.ContainerCraftingMonitor;
import com.raoulvdberge.refinedstorage.gui.control.Scrollbar;
import com.raoulvdberge.refinedstorage.gui.control.SideButtonCraftingMonitorViewAutomated;
import com.raoulvdberge.refinedstorage.gui.control.SideButtonRedstoneMode;
import com.raoulvdberge.refinedstorage.network.MessageCraftingMonitorCancel;
import com.raoulvdberge.refinedstorage.tile.craftingmonitor.ICraftingMonitor;
@@ -71,8 +70,6 @@ public class GuiCraftingMonitor extends GuiBase {
addSideButton(new SideButtonRedstoneMode(this, craftingMonitor.getRedstoneModeParameter()));
}
addSideButton(new SideButtonCraftingMonitorViewAutomated(this, craftingMonitor));
String cancel = t("gui.cancel");
String cancelAll = t("misc.refinedstorage:cancel_all");

View File

@@ -1,30 +0,0 @@
package com.raoulvdberge.refinedstorage.gui.control;
import com.raoulvdberge.refinedstorage.gui.GuiBase;
import com.raoulvdberge.refinedstorage.tile.craftingmonitor.ICraftingMonitor;
import net.minecraft.util.text.TextFormatting;
public class SideButtonCraftingMonitorViewAutomated extends SideButton {
private ICraftingMonitor craftingMonitor;
public SideButtonCraftingMonitorViewAutomated(GuiBase gui, ICraftingMonitor craftingMonitor) {
super(gui);
this.craftingMonitor = craftingMonitor;
}
@Override
public String getTooltip() {
return GuiBase.t("sidebutton.refinedstorage:crafting_monitor.view_automated") + "\n" + TextFormatting.GRAY + GuiBase.t("gui." + (craftingMonitor.canViewAutomated() ? "yes" : "no"));
}
@Override
protected void drawButtonIcon(int x, int y) {
gui.drawTexture(x, y, craftingMonitor.canViewAutomated() ? 0 : 16, 144, 16, 16);
}
@Override
public void actionPerformed() {
craftingMonitor.onViewAutomatedChanged(!craftingMonitor.canViewAutomated());
}
}

View File

@@ -55,7 +55,6 @@ public class GuiGrid extends GuiBase implements IResizableDisplay {
private TextFieldSearch searchField;
private GuiCheckBox oredictPattern;
private GuiCheckBox processingPattern;
private GuiCheckBox blockingPattern;
private GuiButton tabPageLeft;
private GuiButton tabPageRight;
@@ -129,10 +128,6 @@ public class GuiGrid extends GuiBase implements IResizableDisplay {
if (grid.getType() == GridType.PATTERN) {
processingPattern = addCheckBox(x + 7, y + getTabHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:processing"), TileGrid.PROCESSING_PATTERN.getValue());
oredictPattern = addCheckBox(processingPattern.x + processingPattern.width + 5, y + getTabHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:oredict"), TileGrid.OREDICT_PATTERN.getValue());
if (((NetworkNodeGrid) grid).isProcessingPattern()) {
blockingPattern = addCheckBox(oredictPattern.x + oredictPattern.width + 5, y + getTabHeight() + getTopHeight() + (getVisibleRows() * 18) + 60, t("misc.refinedstorage:blocking"), TileGrid.BLOCKING_PATTERN.getValue());
}
}
if (grid.getType() != GridType.FLUID && grid.getViewType() != -1) {
@@ -620,8 +615,6 @@ public class GuiGrid extends GuiBase implements IResizableDisplay {
if (button == oredictPattern) {
TileDataManager.setParameter(TileGrid.OREDICT_PATTERN, oredictPattern.isChecked());
} else if (button == blockingPattern) {
TileDataManager.setParameter(TileGrid.BLOCKING_PATTERN, blockingPattern.isChecked());
} else if (button == processingPattern) {
// Rebuild the inventory slots before the slot change packet arrives
TileGrid.PROCESSING_PATTERN.setValue(false, processingPattern.isChecked());
@@ -743,12 +736,6 @@ public class GuiGrid extends GuiBase implements IResizableDisplay {
}
}
public void updateBlockingPattern(boolean checked) {
if (blockingPattern != null) {
blockingPattern.setIsChecked(checked);
}
}
public void updateScrollbarAndTabs() {
if (scrollbar != null) {
scrollbar.setEnabled(getRows() > getVisibleRows());

View File

@@ -13,10 +13,8 @@ public class ConverterCraftingPattern implements Converter {
output.put("outputs", pattern.getOutputs());
output.put("inputs", pattern.getInputs());
output.put("oreInputs", pattern.getOreInputs());
output.put("byproducts", pattern.getByproducts());
output.put("processing", pattern.isProcessing());
output.put("blocking", pattern.isBlocking());
output.put("oredict", pattern.isOredict());
}
}

View File

@@ -12,7 +12,7 @@ public class ConverterCraftingTask implements Converter {
ICraftingTask task = (ICraftingTask) value;
output.put("stack", task.getRequested());
output.put("missing", task.getMissing().getStacks());
// TODO: output.put("missing", task.getMissing().getStacks());
output.put("pattern", task.getPattern());
output.put("quantity", task.getQuantity());
}

View File

@@ -22,9 +22,9 @@ import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import java.util.Map;
import java.util.List;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import static com.raoulvdberge.refinedstorage.api.util.IComparer.COMPARE_DAMAGE;
import static com.raoulvdberge.refinedstorage.api.util.IComparer.COMPARE_NBT;
@@ -68,7 +68,7 @@ public class EnvironmentNetwork extends AbstractManagedEnvironment {
}
ItemStack stack = args.checkItemStack(0);
return new Object[]{node.getNetwork().getCraftingManager().getPattern(stack)};
return new Object[]{node.getNetwork().getCraftingManager().getPattern(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT)};
}
@Callback(doc = "function():table -- Gets the patterns of this network.")
@@ -93,7 +93,7 @@ public class EnvironmentNetwork extends AbstractManagedEnvironment {
ItemStack stack = args.checkItemStack(0);
return new Object[]{node.getNetwork().getCraftingManager().hasPattern(stack)};
return new Object[]{node.getNetwork().getCraftingManager().getPattern(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT) != null};
}
@Callback(doc = "function(stack:table[, count: number]):table -- Gets a list of missing items for a crafting task.")
@@ -103,18 +103,17 @@ public class EnvironmentNetwork extends AbstractManagedEnvironment {
}
ItemStack stack = args.checkItemStack(0);
int count = args.optInteger(1, 1);
if (!node.getNetwork().getCraftingManager().hasPattern(stack)) {
throw new IllegalArgumentException("No pattern for this item exists");
ICraftingTask task = node.getNetwork().getCraftingManager().create(stack, count);
if (task == null) {
throw new IllegalArgumentException("Could not create crafting task");
}
int count = args.optInteger(1, 1);
ICraftingPattern pattern = node.getNetwork().getCraftingManager().getPattern(stack);
ICraftingTask task = node.getNetwork().getCraftingManager().create(stack, pattern, count, true);
task.calculate();
return new Object[]{task.getMissing().getStacks()};
//TODO return new Object[]{task.getMissing().getStacks()};
return new Object[]{};
}
@Callback(doc = "function(stack:table[, count: number]) -- Schedules a crafting task.")
@@ -124,15 +123,13 @@ public class EnvironmentNetwork extends AbstractManagedEnvironment {
}
ItemStack stack = args.checkItemStack(0);
int amount = args.optInteger(1, 1);
if (!node.getNetwork().getCraftingManager().hasPattern(stack)) {
throw new IllegalArgumentException("No pattern for this item stack exists");
ICraftingTask task = node.getNetwork().getCraftingManager().create(stack, amount);
if (task == null) {
throw new IllegalArgumentException("Could not create crafting task");
}
int amount = args.optInteger(1, 1);
ICraftingPattern pattern = node.getNetwork().getCraftingManager().getPattern(stack);
ICraftingTask task = node.getNetwork().getCraftingManager().create(stack, pattern, amount, true);
task.calculate();
node.getNetwork().getCraftingManager().add(task);

View File

@@ -6,6 +6,7 @@ import com.raoulvdberge.refinedstorage.RSItems;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IFilter;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFilterItems;
import com.raoulvdberge.refinedstorage.util.RenderUtils;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer;
@@ -73,7 +74,7 @@ public class ItemFilter extends ItemBase {
ItemHandlerFilterItems items = new ItemHandlerFilterItems(stack);
ItemPattern.combineItems(tooltip, false, items.getFilteredItems());
RenderUtils.addCombinedItemsToTooltip(tooltip, false, items.getFilteredItems());
}
public static int getCompare(ItemStack stack) {

View File

@@ -4,10 +4,8 @@ import com.raoulvdberge.refinedstorage.RSItems;
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.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingPattern;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import com.raoulvdberge.refinedstorage.util.RenderUtils;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
@@ -25,7 +23,10 @@ import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
private static Map<ItemStack, CraftingPattern> PATTERN_CACHE = new HashMap<>();
@@ -33,7 +34,6 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
private static final String NBT_SLOT = "Slot_%d";
private static final String NBT_OUTPUTS = "Outputs";
private static final String NBT_OREDICT = "Oredict";
private static final String NBT_BLOCKING = "Blocking";
public ItemPattern() {
super("pattern");
@@ -61,20 +61,16 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
if (GuiScreen.isShiftKeyDown() || isProcessing(stack)) {
tooltip.add(TextFormatting.YELLOW + I18n.format("misc.refinedstorage:pattern.inputs") + TextFormatting.RESET);
combineItems(tooltip, true, StackUtils.toNonNullList(pattern.getInputs()));
RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getInputs().stream().map(i -> i.size() > 0 ? i.get(0) : ItemStack.EMPTY).collect(Collectors.toList()));
tooltip.add(TextFormatting.YELLOW + I18n.format("misc.refinedstorage:pattern.outputs") + TextFormatting.RESET);
}
combineItems(tooltip, true, StackUtils.toNonNullList(pattern.getOutputs()));
RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getOutputs());
if (isOredict(stack)) {
tooltip.add(TextFormatting.BLUE + I18n.format("misc.refinedstorage:pattern.oredict") + TextFormatting.RESET);
}
if (isBlocking(stack)) {
tooltip.add(TextFormatting.BLUE + I18n.format("misc.refinedstorage:blocking") + TextFormatting.RESET);
}
} else {
tooltip.add(TextFormatting.RED + I18n.format("misc.refinedstorage:pattern.invalid") + TextFormatting.RESET);
}
@@ -117,12 +113,8 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
pattern.getTagCompound().setTag(NBT_OUTPUTS, outputs);
}
public static List<ItemStack> getOutputs(ItemStack pattern) {
if (!isProcessing(pattern)) {
return null;
}
IStackList<ItemStack> outputs = API.instance().createItemStackList();
public static NonNullList<ItemStack> getOutputs(ItemStack pattern) {
NonNullList<ItemStack> outputs = NonNullList.create();
NBTTagList outputsTag = pattern.getTagCompound().getTagList(NBT_OUTPUTS, Constants.NBT.TAG_COMPOUND);
@@ -134,7 +126,7 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
}
}
return new ArrayList<>(outputs.getStacks());
return outputs;
}
public static boolean isProcessing(ItemStack pattern) {
@@ -145,10 +137,6 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
return pattern.hasTagCompound() && pattern.getTagCompound().hasKey(NBT_OREDICT) && pattern.getTagCompound().getBoolean(NBT_OREDICT);
}
public static boolean isBlocking(ItemStack pattern) {
return pattern.hasTagCompound() && pattern.getTagCompound().hasKey(NBT_BLOCKING) && pattern.getTagCompound().getBoolean(NBT_BLOCKING);
}
public static void setOredict(ItemStack pattern, boolean oredict) {
if (!pattern.hasTagCompound()) {
pattern.setTagCompound(new NBTTagCompound());
@@ -157,40 +145,6 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
pattern.getTagCompound().setBoolean(NBT_OREDICT, oredict);
}
public static void setBlocking(ItemStack pattern, boolean blockingTask) {
if (!pattern.hasTagCompound()) {
pattern.setTagCompound(new NBTTagCompound());
}
pattern.getTagCompound().setBoolean(NBT_BLOCKING, blockingTask);
}
public static void combineItems(List<String> tooltip, boolean displayAmount, NonNullList<ItemStack> stacks) {
Set<Integer> combinedIndices = new HashSet<>();
for (int i = 0; i < stacks.size(); ++i) {
if (!stacks.get(i).isEmpty() && !combinedIndices.contains(i)) {
ItemStack stack = stacks.get(i);
String data = stack.getDisplayName();
int amount = stack.getCount();
for (int j = i + 1; j < stacks.size(); ++j) {
if (API.instance().getComparer().isEqual(stack, stacks.get(j))) {
amount += stacks.get(j).getCount();
combinedIndices.add(j);
}
}
data = (displayAmount ? (TextFormatting.WHITE + String.valueOf(amount) + " ") : "") + TextFormatting.GRAY + data;
tooltip.add(data);
}
}
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
if (!world.isRemote && player.isSneaking()) {
@@ -203,7 +157,6 @@ public class ItemPattern extends ItemBase implements ICraftingPatternProvider {
@Override
@Nonnull
public ICraftingPattern create(World world, ItemStack stack, ICraftingPatternContainer container) {
// We copy the pattern stack because if we remove it from the inventory, the crafting task will use a pattern with an invalid stack...
return new CraftingPattern(world, container, stack.copy());
return new CraftingPattern(world, container, stack);
}
}

View File

@@ -5,13 +5,10 @@ import com.raoulvdberge.refinedstorage.api.network.item.INetworkItemHandler;
import com.raoulvdberge.refinedstorage.apiimpl.network.item.NetworkItemWirelessCraftingMonitor;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nonnull;
public class ItemWirelessCraftingMonitor extends ItemNetworkItem {
private static final String NBT_VIEW_AUTOMATED = "ViewAutomated";
public ItemWirelessCraftingMonitor() {
super("wireless_crafting_monitor");
}
@@ -21,16 +18,4 @@ public class ItemWirelessCraftingMonitor extends ItemNetworkItem {
public INetworkItem provide(INetworkItemHandler handler, EntityPlayer player, ItemStack stack) {
return new NetworkItemWirelessCraftingMonitor(handler, player, stack);
}
public static void setViewAutomated(ItemStack stack, boolean viewAutomated) {
if (!stack.hasTagCompound()) {
stack.setTagCompound(new NBTTagCompound());
}
stack.getTagCompound().setBoolean(NBT_VIEW_AUTOMATED, viewAutomated);
}
public static boolean canViewAutomated(ItemStack stack) {
return (stack.hasTagCompound() && stack.getTagCompound().hasKey(NBT_VIEW_AUTOMATED)) ? stack.getTagCompound().getBoolean(NBT_VIEW_AUTOMATED) : true;
}
}

View File

@@ -51,10 +51,6 @@ public class MessageCraftingMonitorElements implements IMessage, IMessageHandler
for (ICraftingTask task : craftingMonitor.getTasks()) {
ItemStack stack = task.getRequested();
if (!craftingMonitor.canViewAutomated() && task.isAutomated()) {
continue;
}
if (stack == null || GridFilterFilter.accepts(craftingMonitor.getFilters(), stack, Item.REGISTRY.getNameForObject(stack.getItem()).getResourceDomain())) {
elements.addAll(task.getCraftingMonitorElements());
}

View File

@@ -17,7 +17,6 @@ import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
public class MessageGridItemUpdate implements IMessage, IMessageHandler<MessageGridItemUpdate, IMessage> {
@@ -33,7 +32,7 @@ public class MessageGridItemUpdate implements IMessage, IMessageHandler<MessageG
int size = network.getItemStorageCache().getList().getStacks().size();
for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) {
size += pattern.getOutputs().stream().filter(Objects::nonNull).count();
size += pattern.getOutputs().size();
}
buf.writeInt(size);
@@ -51,15 +50,13 @@ public class MessageGridItemUpdate implements IMessage, IMessageHandler<MessageG
for (ICraftingPattern pattern : network.getCraftingManager().getPatterns()) {
for (ItemStack output : pattern.getOutputs()) {
if (output != null) {
StackUtils.writeItemStack(buf, output, network, true);
StackUtils.writeItemStack(buf, output, network, true);
IStorageTracker.IStorageTrackerEntry entry = network.getItemStorageTracker().get(output);
buf.writeBoolean(entry != null);
if (entry != null) {
buf.writeLong(entry.getTime());
ByteBufUtils.writeUTF8String(buf, entry.getName());
}
IStorageTracker.IStorageTrackerEntry entry = network.getItemStorageTracker().get(output);
buf.writeBoolean(entry != null);
if (entry != null) {
buf.writeLong(entry.getTime());
ByteBufUtils.writeUTF8String(buf, entry.getName());
}
}
}

View File

@@ -1,44 +0,0 @@
package com.raoulvdberge.refinedstorage.network;
import com.raoulvdberge.refinedstorage.container.ContainerCraftingMonitor;
import com.raoulvdberge.refinedstorage.item.ItemWirelessCraftingMonitor;
import com.raoulvdberge.refinedstorage.tile.craftingmonitor.ICraftingMonitor;
import com.raoulvdberge.refinedstorage.tile.craftingmonitor.WirelessCraftingMonitor;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
public class MessageWirelessCraftingMonitorViewAutomated extends MessageHandlerPlayerToServer<MessageWirelessCraftingMonitorViewAutomated> implements IMessage {
private boolean viewAutomated;
public MessageWirelessCraftingMonitorViewAutomated() {
}
public MessageWirelessCraftingMonitorViewAutomated(boolean viewAutomated) {
this.viewAutomated = viewAutomated;
}
@Override
public void fromBytes(ByteBuf buf) {
viewAutomated = buf.readBoolean();
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeBoolean(viewAutomated);
}
@Override
public void handle(MessageWirelessCraftingMonitorViewAutomated message, EntityPlayerMP player) {
if (player.openContainer instanceof ContainerCraftingMonitor) {
ICraftingMonitor craftingMonitor = ((ContainerCraftingMonitor) player.openContainer).getCraftingMonitor();
if (craftingMonitor instanceof WirelessCraftingMonitor) {
ItemStack stack = ((WirelessCraftingMonitor) craftingMonitor).getStack();
ItemWirelessCraftingMonitor.setViewAutomated(stack, message.viewAutomated);
}
}
}
}

View File

@@ -137,7 +137,6 @@ public class ProxyCommon {
RS.INSTANCE.network.registerMessage(MessageReaderWriterChannelRemove.class, MessageReaderWriterChannelRemove.class, id++, Side.SERVER);
RS.INSTANCE.network.registerMessage(MessageSecurityManagerUpdate.class, MessageSecurityManagerUpdate.class, id++, Side.SERVER);
RS.INSTANCE.network.registerMessage(MessageWirelessFluidGridSettingsUpdate.class, MessageWirelessFluidGridSettingsUpdate.class, id++, Side.SERVER);
RS.INSTANCE.network.registerMessage(MessageWirelessCraftingMonitorViewAutomated.class, MessageWirelessCraftingMonitorViewAutomated.class, id++, Side.SERVER);
RS.INSTANCE.network.registerMessage(MessageCrafterManagerSlotSizes.class, MessageCrafterManagerSlotSizes.class, id++, Side.CLIENT);
RS.INSTANCE.network.registerMessage(MessageCrafterManagerRequestSlotData.class, MessageCrafterManagerRequestSlotData.class, id++, Side.SERVER);

View File

@@ -27,10 +27,6 @@ public interface ICraftingMonitor {
ItemHandlerBase getFilter();
boolean canViewAutomated();
void onViewAutomatedChanged(boolean viewAutomated);
boolean isActive();
void onClosed(EntityPlayer player);

View File

@@ -1,31 +1,13 @@
package com.raoulvdberge.refinedstorage.tile.craftingmonitor;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNodeCraftingMonitor;
import com.raoulvdberge.refinedstorage.tile.TileNode;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
public class TileCraftingMonitor extends TileNode<NetworkNodeCraftingMonitor> {
public static final TileDataParameter<Boolean, TileCraftingMonitor> VIEW_AUTOMATED = new TileDataParameter<>(DataSerializers.BOOLEAN, true, t -> t.getNode().canViewAutomated(), (t, v) -> {
t.getNode().setViewAutomated(v);
t.getNode().markDirty();
INetwork network = t.getNode().getNetwork();
if (network != null) {
network.getCraftingManager().sendCraftingMonitorUpdate();
}
});
public TileCraftingMonitor() {
dataManager.addWatchedParameter(VIEW_AUTOMATED);
}
@Override
@Nonnull
public NetworkNodeCraftingMonitor createNode(World world, BlockPos pos) {

View File

@@ -1,13 +1,11 @@
package com.raoulvdberge.refinedstorage.tile.craftingmonitor;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.util.IFilter;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBase;
import com.raoulvdberge.refinedstorage.inventory.ItemHandlerFilter;
import com.raoulvdberge.refinedstorage.item.ItemWirelessCraftingMonitor;
import com.raoulvdberge.refinedstorage.network.MessageWirelessCraftingMonitorViewAutomated;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import com.raoulvdberge.refinedstorage.util.StackUtils;
import net.minecraft.entity.player.EntityPlayer;
@@ -29,8 +27,6 @@ public class WirelessCraftingMonitor implements ICraftingMonitor {
private int networkDimension;
private BlockPos network;
private boolean viewAutomated;
private List<IFilter> filters = new ArrayList<>();
private ItemHandlerFilter filter = new ItemHandlerFilter(filters, new ArrayList<>(), null) {
@Override
@@ -55,7 +51,6 @@ public class WirelessCraftingMonitor implements ICraftingMonitor {
this.stack = stack;
this.networkDimension = networkDimension;
this.network = new BlockPos(ItemWirelessCraftingMonitor.getX(stack), ItemWirelessCraftingMonitor.getY(stack), ItemWirelessCraftingMonitor.getZ(stack));
this.viewAutomated = ItemWirelessCraftingMonitor.canViewAutomated(stack);
if (stack.hasTagCompound()) {
StackUtils.readItems(filter, 0, stack.getTagCompound());
@@ -107,18 +102,6 @@ public class WirelessCraftingMonitor implements ICraftingMonitor {
return filter;
}
@Override
public boolean canViewAutomated() {
return viewAutomated;
}
@Override
public void onViewAutomatedChanged(boolean viewAutomated) {
RS.INSTANCE.network.sendToServer(new MessageWirelessCraftingMonitorViewAutomated(viewAutomated));
this.viewAutomated = viewAutomated;
}
private INetwork getNetwork() {
World world = DimensionManager.getWorld(networkDimension);

View File

@@ -80,10 +80,6 @@ public class TileGrid extends TileNode<NetworkNodeGrid> {
((ContainerGrid) player.openContainer).sendAllSlots();
});
}, (initial, p) -> GuiBase.executeLater(GuiGrid.class, GuiBase::initGui));
public static final TileDataParameter<Boolean, TileGrid> BLOCKING_PATTERN = new TileDataParameter<>(DataSerializers.BOOLEAN, false, t -> t.getNode().isBlockingPattern(), (t, v) -> {
t.getNode().setBlockingPattern(v);
t.getNode().markDirty();
}, (initial, p) -> GuiBase.executeLater(GuiGrid.class, grid -> grid.updateBlockingPattern(p)));
public static void trySortGrid(boolean initial) {
if (!initial) {
@@ -101,7 +97,6 @@ public class TileGrid extends TileNode<NetworkNodeGrid> {
dataManager.addWatchedParameter(TAB_PAGE);
dataManager.addWatchedParameter(OREDICT_PATTERN);
dataManager.addWatchedParameter(PROCESSING_PATTERN);
dataManager.addWatchedParameter(BLOCKING_PATTERN);
}
@Override

View File

@@ -1,6 +1,7 @@
package com.raoulvdberge.refinedstorage.util;
import com.google.common.collect.ImmutableMap;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
@@ -11,11 +12,13 @@ import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
@@ -23,6 +26,9 @@ import net.minecraftforge.fluids.FluidStack;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public final class RenderUtils {
public static final Matrix4f EMPTY_MATRIX_TRANSFORM = getTransform(0, 0, 0, 0, 0, 0, 1.0f).getMatrix();
@@ -294,4 +300,30 @@ public final class RenderUtils {
}
}
}
public static void addCombinedItemsToTooltip(List<String> tooltip, boolean displayAmount, List<ItemStack> stacks) {
Set<Integer> combinedIndices = new HashSet<>();
for (int i = 0; i < stacks.size(); ++i) {
if (!stacks.get(i).isEmpty() && !combinedIndices.contains(i)) {
ItemStack stack = stacks.get(i);
String data = stack.getDisplayName();
int amount = stack.getCount();
for (int j = i + 1; j < stacks.size(); ++j) {
if (API.instance().getComparer().isEqual(stack, stacks.get(j))) {
amount += stacks.get(j).getCount();
combinedIndices.add(j);
}
}
data = (displayAmount ? (TextFormatting.WHITE + String.valueOf(amount) + " ") : "") + TextFormatting.GRAY + data;
tooltip.add(data);
}
}
}
}

View File

@@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.util;
import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.storage.IStorageDisk;
import com.raoulvdberge.refinedstorage.api.storage.IStorageDiskProvider;
import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import io.netty.buffer.ByteBuf;
@@ -110,7 +111,7 @@ public final class StackUtils {
buf.writeInt(API.instance().getItemStackHashCode(stack));
if (network != null) {
buf.writeBoolean(network.getCraftingManager().hasPattern(stack));
buf.writeBoolean(network.getCraftingManager().getPattern(stack, IComparer.COMPARE_DAMAGE | IComparer.COMPARE_NBT) != null);
buf.writeBoolean(displayCraftText);
} else {
buf.writeBoolean(false);
@@ -160,18 +161,6 @@ public final class StackUtils {
}
}
public static NonNullList<ItemStack> toNonNullList(List<ItemStack> list) {
NonNullList<ItemStack> other = NonNullList.create();
for (ItemStack item : list) {
if (item != null) {
other.add(item);
}
}
return other;
}
@SuppressWarnings("unchecked")
public static <T> NonNullList<T> emptyNonNullList() {
return (NonNullList<T>) EMPTY_NON_NULL_LIST;

View File

@@ -110,7 +110,6 @@ misc.refinedstorage:set=Set
misc.refinedstorage:cancel_all=Cancel All
misc.refinedstorage:priority=Priority
misc.refinedstorage:oredict=Oredict
misc.refinedstorage:blocking=Blocking
misc.refinedstorage:processing=Processing
misc.refinedstorage:reader_writer.redstone=Redstone strength: %d
@@ -164,8 +163,6 @@ sidebutton.refinedstorage:grid.size.1=Small
sidebutton.refinedstorage:grid.size.2=Medium
sidebutton.refinedstorage:grid.size.3=Large
sidebutton.refinedstorage:crafting_monitor.view_automated=View automated tasks
sidebutton.refinedstorage:mode=Mode
sidebutton.refinedstorage:mode.whitelist=Whitelist
sidebutton.refinedstorage:mode.blacklist=Blacklist

View File

@@ -109,7 +109,6 @@ misc.refinedstorage:set=Poner
misc.refinedstorage:cancel_all=Cancelar todo
misc.refinedstorage:priority=Prioridad
misc.refinedstorage:oredict=Diccionario de minerales
misc.refinedstorage:blocking=Bloqueo
misc.refinedstorage:processing=Procesándose
misc.refinedstorage:reader_writer.redstone=Fuerza de señal: %d
@@ -163,8 +162,6 @@ sidebutton.refinedstorage:grid.size.1=Pequeño
sidebutton.refinedstorage:grid.size.2=Mediano
sidebutton.refinedstorage:grid.size.3=largo
sidebutton.refinedstorage:crafting_monitor.view_automated=Ver tareas automatizadas
sidebutton.refinedstorage:mode=Modo
sidebutton.refinedstorage:mode.whitelist=Permitido
sidebutton.refinedstorage:mode.blacklist=No permitido

View File

@@ -104,7 +104,6 @@ misc.refinedstorage:set=Fixer
misc.refinedstorage:cancel_all=Tout annuler
misc.refinedstorage:priority=Priorité
misc.refinedstorage:oredict=Oredict
misc.refinedstorage:blocking=Blocker
misc.refinedstorage:processing=En Traitement
misc.refinedstorage:reader_writer.redstone=Redstone strength: %d
@@ -140,8 +139,6 @@ sidebutton.refinedstorage:grid.size.1=Petit
sidebutton.refinedstorage:grid.size.2=Moyen
sidebutton.refinedstorage:grid.size.3=Grand
sidebutton.refinedstorage:crafting_monitor.view_automated=Vue des tâches automatisées
sidebutton.refinedstorage:mode=Mode
sidebutton.refinedstorage:mode.whitelist=Liste blanche
sidebutton.refinedstorage:mode.blacklist=Liste noire

View File

@@ -103,7 +103,6 @@ misc.refinedstorage:set=설정
misc.refinedstorage:cancel_all=모두 취소
misc.refinedstorage:priority=우선 순위
misc.refinedstorage:oredict=Ore Dictionary
misc.refinedstorage:blocking=Blocking
misc.refinedstorage:reader_writer.redstone=레드스톤 강도: %d
@@ -138,8 +137,6 @@ sidebutton.refinedstorage:grid.size.1=작음
sidebutton.refinedstorage:grid.size.2=중간
sidebutton.refinedstorage:grid.size.3=큼
sidebutton.refinedstorage:crafting_monitor.view_automated=자동으로 시작된 작업 보기
sidebutton.refinedstorage:mode=모드
sidebutton.refinedstorage:mode.whitelist=화이트리스트
sidebutton.refinedstorage:mode.blacklist=블랙리스트

View File

@@ -104,7 +104,6 @@ misc.refinedstorage:set=Definir
misc.refinedstorage:cancel_all=Cancelar tudo
misc.refinedstorage:priority=Prioridade
misc.refinedstorage:oredict=Oredict
misc.refinedstorage:blocking=Bloqueio
misc.refinedstorage:processing=Processamento
misc.refinedstorage:reader_writer.redstone=Força de redstone: %d
@@ -141,8 +140,6 @@ sidebutton.refinedstorage:grid.size.1=Pequeno
sidebutton.refinedstorage:grid.size.2=Médio
sidebutton.refinedstorage:grid.size.3=Grande
sidebutton.refinedstorage:crafting_monitor.view_automated=Ver tarefas automatizadas
sidebutton.refinedstorage:mode=Modo
sidebutton.refinedstorage:mode.whitelist=Lista branca
sidebutton.refinedstorage:mode.blacklist=Lista negra

View File

@@ -110,7 +110,6 @@ misc.refinedstorage:set=Установить
misc.refinedstorage:cancel_all=Отменить все
misc.refinedstorage:priority=Приоритет
misc.refinedstorage:oredict=Словарь руды
misc.refinedstorage:blocking=Блокировка
misc.refinedstorage:processing=Обработка
misc.refinedstorage:reader_writer.redstone=Сила красного камня: %d
@@ -164,8 +163,6 @@ sidebutton.refinedstorage:grid.size.1=Маленький
sidebutton.refinedstorage:grid.size.2=Средний
sidebutton.refinedstorage:grid.size.3=Большой
sidebutton.refinedstorage:crafting_monitor.view_automated=Просмотр автоматизированных задач
sidebutton.refinedstorage:mode=Режим
sidebutton.refinedstorage:mode.whitelist=Белый список
sidebutton.refinedstorage:mode.blacklist=Черный список

View File

@@ -105,7 +105,6 @@ misc.refinedstorage:set=设置
misc.refinedstorage:cancel_all=取消所有
misc.refinedstorage:priority=优先级
misc.refinedstorage:oredict=矿物辞典
misc.refinedstorage:blocking=阻塞中
misc.refinedstorage:processing=进行中
misc.refinedstorage:reader_writer.redstone=红石强度:%d
@@ -142,8 +141,6 @@ sidebutton.refinedstorage:grid.size.1=小
sidebutton.refinedstorage:grid.size.2=中
sidebutton.refinedstorage:grid.size.3=大
sidebutton.refinedstorage:crafting_monitor.view_automated=查看自动化进程
sidebutton.refinedstorage:mode=模式
sidebutton.refinedstorage:mode.whitelist=白名单
sidebutton.refinedstorage:mode.blacklist=黑名单

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB