Added error handling in crafting tasks: recursive pattern check and max time.
This commit is contained in:
@@ -7,6 +7,8 @@
|
|||||||
- Removed Storage Drawers integration (you can still attach an External Storage to drawers, though) (raoulvdberge)
|
- Removed Storage Drawers integration (you can still attach an External Storage to drawers, though) (raoulvdberge)
|
||||||
- Removed blocking mode in autocrafting (raoulvdberge)
|
- Removed blocking mode in autocrafting (raoulvdberge)
|
||||||
- Removed the Wrench (raoulvdberge)
|
- Removed the Wrench (raoulvdberge)
|
||||||
|
- Rewrote autocrafting (raoulvdberge)
|
||||||
|
- Autocrafting tasks that take longer than 5 seconds to calculate are automatically stopped to avoid server strain (raoulvdberge)
|
||||||
- Added new storage disk system where the storage disk data (items, fluids) are stored off the disk itself, in another file (refinedstorage_disks.dat). The disk itself only stores its ID (raoulvdberge)
|
- Added new storage disk system where the storage disk data (items, fluids) are stored off the disk itself, in another file (refinedstorage_disks.dat). The disk itself only stores its ID (raoulvdberge)
|
||||||
- Changed fluid storage progression to be 64k - 256k - 1024k - 4096k (raoulvdberge)
|
- Changed fluid storage progression to be 64k - 256k - 1024k - 4096k (raoulvdberge)
|
||||||
- You can no longer put a Filter in filter slots to gain additional filter slots (raoulvdberge)
|
- You can no longer put a Filter in filter slots to gain additional filter slots (raoulvdberge)
|
||||||
|
@@ -0,0 +1,15 @@
|
|||||||
|
package com.raoulvdberge.refinedstorage.api.autocrafting.task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The error type.
|
||||||
|
*/
|
||||||
|
public enum CraftingTaskErrorType {
|
||||||
|
/**
|
||||||
|
* When the crafting task would cause too much server strain or is too complex.
|
||||||
|
*/
|
||||||
|
TOO_COMPLEX,
|
||||||
|
/**
|
||||||
|
* When one of the used patterns during the calculation reuses itself again and would cause an infinite loop.
|
||||||
|
*/
|
||||||
|
RECURSIVE
|
||||||
|
}
|
@@ -7,6 +7,7 @@ import com.raoulvdberge.refinedstorage.api.util.IStackList;
|
|||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,8 +16,11 @@ import java.util.List;
|
|||||||
public interface ICraftingTask {
|
public interface ICraftingTask {
|
||||||
/**
|
/**
|
||||||
* Calculates what this task will do, but doesn't run the task yet.
|
* Calculates what this task will do, but doesn't run the task yet.
|
||||||
|
*
|
||||||
|
* @return the error, or null if there was no error
|
||||||
*/
|
*/
|
||||||
void calculate();
|
@Nullable
|
||||||
|
ICraftingTaskError calculate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates this task.
|
* Updates this task.
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
package com.raoulvdberge.refinedstorage.api.autocrafting.task;
|
||||||
|
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returned from {@link ICraftingTask#calculate()} when an error occurs during the calculation.
|
||||||
|
*/
|
||||||
|
public interface ICraftingTaskError {
|
||||||
|
/**
|
||||||
|
* @return the type
|
||||||
|
*/
|
||||||
|
CraftingTaskErrorType getType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this error type is a {@link CraftingTaskErrorType#RECURSIVE}, the recursed pattern will be returned here.
|
||||||
|
*
|
||||||
|
* @return the recursed pattern, or null if this error is not {@link CraftingTaskErrorType#RECURSIVE}
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
ICraftingPattern getRecursedPattern();
|
||||||
|
}
|
@@ -6,6 +6,7 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContaine
|
|||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskFactory;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.registry.ICraftingTaskFactory;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
||||||
import com.raoulvdberge.refinedstorage.api.util.IComparer;
|
import com.raoulvdberge.refinedstorage.api.util.IComparer;
|
||||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||||
@@ -138,14 +139,15 @@ public class CraftingManager implements ICraftingManager {
|
|||||||
ICraftingTask task = create(stack, toSchedule);
|
ICraftingTask task = create(stack, toSchedule);
|
||||||
|
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
task.calculate();
|
ICraftingTaskError error = task.calculate();
|
||||||
|
|
||||||
|
if (error == null) {
|
||||||
this.add(task);
|
this.add(task);
|
||||||
this.onTaskChanged();
|
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview;
|
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview;
|
||||||
|
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||||
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
|
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
@@ -11,9 +12,11 @@ import net.minecraftforge.fml.common.network.ByteBufUtils;
|
|||||||
public class CraftingPreviewElementError implements ICraftingPreviewElement<ItemStack> {
|
public class CraftingPreviewElementError implements ICraftingPreviewElement<ItemStack> {
|
||||||
public static final String ID = "error";
|
public static final String ID = "error";
|
||||||
|
|
||||||
|
private CraftingTaskErrorType type;
|
||||||
private ItemStack stack;
|
private ItemStack stack;
|
||||||
|
|
||||||
public CraftingPreviewElementError(ItemStack stack) {
|
public CraftingPreviewElementError(CraftingTaskErrorType type, ItemStack stack) {
|
||||||
|
this.type = type;
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,17 +42,25 @@ public class CraftingPreviewElementError implements ICraftingPreviewElement<Item
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMissing() {
|
public boolean hasMissing() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToByteBuf(ByteBuf buf) {
|
public void writeToByteBuf(ByteBuf buf) {
|
||||||
|
buf.writeInt(type.ordinal());
|
||||||
buf.writeInt(Item.getIdFromItem(stack.getItem()));
|
buf.writeInt(Item.getIdFromItem(stack.getItem()));
|
||||||
buf.writeInt(stack.getMetadata());
|
buf.writeInt(stack.getMetadata());
|
||||||
ByteBufUtils.writeTag(buf, stack.getTagCompound());
|
ByteBufUtils.writeTag(buf, stack.getTagCompound());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CraftingTaskErrorType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
public static CraftingPreviewElementError fromByteBuf(ByteBuf buf) {
|
public static CraftingPreviewElementError fromByteBuf(ByteBuf buf) {
|
||||||
|
int errorIdx = buf.readInt();
|
||||||
|
CraftingTaskErrorType error = errorIdx >= 0 && errorIdx < CraftingTaskErrorType.values().length ? CraftingTaskErrorType.values()[errorIdx] : CraftingTaskErrorType.TOO_COMPLEX;
|
||||||
|
|
||||||
Item item = Item.getItemById(buf.readInt());
|
Item item = Item.getItemById(buf.readInt());
|
||||||
int meta = buf.readInt();
|
int meta = buf.readInt();
|
||||||
NBTTagCompound tag = ByteBufUtils.readTag(buf);
|
NBTTagCompound tag = ByteBufUtils.readTag(buf);
|
||||||
@@ -57,7 +68,7 @@ public class CraftingPreviewElementError implements ICraftingPreviewElement<Item
|
|||||||
ItemStack stack = new ItemStack(item, 1, meta);
|
ItemStack stack = new ItemStack(item, 1, meta);
|
||||||
stack.setTagCompound(tag);
|
stack.setTagCompound(tag);
|
||||||
|
|
||||||
return new CraftingPreviewElementError(stack);
|
return new CraftingPreviewElementError(error, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -4,7 +4,9 @@ import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
|||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||||
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
||||||
import com.raoulvdberge.refinedstorage.api.util.IComparer;
|
import com.raoulvdberge.refinedstorage.api.util.IComparer;
|
||||||
import com.raoulvdberge.refinedstorage.api.util.IStackList;
|
import com.raoulvdberge.refinedstorage.api.util.IStackList;
|
||||||
@@ -24,17 +26,23 @@ import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task.step.CraftingSt
|
|||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.util.NonNullList;
|
import net.minecraft.util.NonNullList;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class CraftingTask implements ICraftingTask {
|
public class CraftingTask implements ICraftingTask {
|
||||||
|
private static final long CALCULATION_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
private INetwork network;
|
private INetwork network;
|
||||||
private ItemStack requested;
|
private ItemStack requested;
|
||||||
private int quantity;
|
private int quantity;
|
||||||
private ICraftingPattern pattern;
|
private ICraftingPattern pattern;
|
||||||
private List<CraftingStep> steps = new LinkedList<>();
|
private List<CraftingStep> steps = new LinkedList<>();
|
||||||
private CraftingInserter inserter;
|
private CraftingInserter inserter;
|
||||||
|
private Set<ICraftingPattern> patternsUsed = new HashSet<>();
|
||||||
private int ticks = 0;
|
private int ticks = 0;
|
||||||
|
private long calculationStarted;
|
||||||
|
|
||||||
private IStackList<ItemStack> toTake = API.instance().createItemStackList();
|
private IStackList<ItemStack> toTake = API.instance().createItemStackList();
|
||||||
private IStackList<ItemStack> missing = API.instance().createItemStackList();
|
private IStackList<ItemStack> missing = API.instance().createItemStackList();
|
||||||
@@ -49,7 +57,10 @@ public class CraftingTask implements ICraftingTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void calculate() {
|
@Nullable
|
||||||
|
public ICraftingTaskError calculate() {
|
||||||
|
this.calculationStarted = System.currentTimeMillis();
|
||||||
|
|
||||||
int qty = this.quantity;
|
int qty = this.quantity;
|
||||||
int qtyPerCraft = getQuantityPerCraft(pattern, requested);
|
int qtyPerCraft = getQuantityPerCraft(pattern, requested);
|
||||||
int crafted = 0;
|
int crafted = 0;
|
||||||
@@ -58,7 +69,13 @@ public class CraftingTask implements ICraftingTask {
|
|||||||
IStackList<ItemStack> storage = network.getItemStorageCache().getList().copy();
|
IStackList<ItemStack> storage = network.getItemStorageCache().getList().copy();
|
||||||
|
|
||||||
while (qty > 0) {
|
while (qty > 0) {
|
||||||
this.steps.add(calculateInternal(storage, results, pattern));
|
Pair<CraftingStep, ICraftingTaskError> result = calculateInternal(storage, results, pattern);
|
||||||
|
|
||||||
|
if (result.getRight() != null) {
|
||||||
|
return result.getRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.steps.add(result.getLeft());
|
||||||
|
|
||||||
qty -= qtyPerCraft;
|
qty -= qtyPerCraft;
|
||||||
|
|
||||||
@@ -66,9 +83,19 @@ public class CraftingTask implements ICraftingTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.toCraft.add(requested, crafted);
|
this.toCraft.add(requested, crafted);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pair<CraftingStep, ICraftingTaskError> calculateInternal(IStackList<ItemStack> mutatedStorage, IStackList<ItemStack> results, ICraftingPattern pattern) {
|
||||||
|
if (System.currentTimeMillis() - calculationStarted > CALCULATION_TIMEOUT_MS) {
|
||||||
|
return Pair.of(null, new CraftingTaskError(CraftingTaskErrorType.TOO_COMPLEX));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!patternsUsed.add(pattern)) {
|
||||||
|
return Pair.of(null, new CraftingTaskError(CraftingTaskErrorType.RECURSIVE, pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CraftingStep calculateInternal(IStackList<ItemStack> mutatedStorage, IStackList<ItemStack> results, ICraftingPattern pattern) {
|
|
||||||
IStackList<ItemStack> itemsToExtract = API.instance().createItemStackList();
|
IStackList<ItemStack> itemsToExtract = API.instance().createItemStackList();
|
||||||
|
|
||||||
NonNullList<ItemStack> took = NonNullList.create();
|
NonNullList<ItemStack> took = NonNullList.create();
|
||||||
@@ -140,7 +167,13 @@ public class CraftingTask implements ICraftingTask {
|
|||||||
|
|
||||||
if (subPattern != null) {
|
if (subPattern != null) {
|
||||||
while ((fromSelf == null ? 0 : fromSelf.getCount()) < remaining) {
|
while ((fromSelf == null ? 0 : fromSelf.getCount()) < remaining) {
|
||||||
this.steps.add(calculateInternal(mutatedStorage, results, subPattern));
|
Pair<CraftingStep, ICraftingTaskError> result = calculateInternal(mutatedStorage, results, subPattern);
|
||||||
|
|
||||||
|
if (result.getRight() != null) {
|
||||||
|
return Pair.of(null, result.getRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.steps.add(result.getLeft());
|
||||||
|
|
||||||
fromSelf = results.get(possibleInput);
|
fromSelf = results.get(possibleInput);
|
||||||
if (fromSelf == null) {
|
if (fromSelf == null) {
|
||||||
@@ -161,12 +194,14 @@ public class CraftingTask implements ICraftingTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
patternsUsed.remove(pattern);
|
||||||
|
|
||||||
if (pattern.isProcessing()) {
|
if (pattern.isProcessing()) {
|
||||||
for (ItemStack output : pattern.getOutputs()) {
|
for (ItemStack output : pattern.getOutputs()) {
|
||||||
results.add(output);
|
results.add(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CraftingStepProcess(pattern, network, new ArrayList<>(itemsToExtract.getStacks()));
|
return Pair.of(new CraftingStepProcess(pattern, network, new ArrayList<>(itemsToExtract.getStacks())), null);
|
||||||
} else {
|
} else {
|
||||||
results.add(pattern.getOutput(took));
|
results.add(pattern.getOutput(took));
|
||||||
|
|
||||||
@@ -174,7 +209,7 @@ public class CraftingTask implements ICraftingTask {
|
|||||||
results.add(byproduct);
|
results.add(byproduct);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CraftingStepCraft(pattern, inserter, network, new ArrayList<>(itemsToExtract.getStacks()), took);
|
return Pair.of(new CraftingStepCraft(pattern, inserter, network, new ArrayList<>(itemsToExtract.getStacks()), took), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||||
|
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class CraftingTaskError implements ICraftingTaskError {
|
||||||
|
private CraftingTaskErrorType type;
|
||||||
|
private ICraftingPattern recursedPattern;
|
||||||
|
|
||||||
|
public CraftingTaskError(CraftingTaskErrorType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CraftingTaskError(CraftingTaskErrorType type, ICraftingPattern recursedPattern) {
|
||||||
|
this.type = type;
|
||||||
|
this.recursedPattern = recursedPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CraftingTaskErrorType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public ICraftingPattern getRecursedPattern() {
|
||||||
|
return recursedPattern;
|
||||||
|
}
|
||||||
|
}
|
@@ -4,6 +4,7 @@ import com.raoulvdberge.refinedstorage.RS;
|
|||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingManager;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingManager;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||||
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
||||||
import com.raoulvdberge.refinedstorage.api.network.grid.handler.IItemGridHandler;
|
import com.raoulvdberge.refinedstorage.api.network.grid.handler.IItemGridHandler;
|
||||||
import com.raoulvdberge.refinedstorage.api.network.item.INetworkItem;
|
import com.raoulvdberge.refinedstorage.api.network.item.INetworkItem;
|
||||||
@@ -11,6 +12,7 @@ import com.raoulvdberge.refinedstorage.api.network.item.NetworkItemAction;
|
|||||||
import com.raoulvdberge.refinedstorage.api.network.security.Permission;
|
import com.raoulvdberge.refinedstorage.api.network.security.Permission;
|
||||||
import com.raoulvdberge.refinedstorage.api.util.IStackList;
|
import com.raoulvdberge.refinedstorage.api.util.IStackList;
|
||||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||||
|
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementError;
|
||||||
import com.raoulvdberge.refinedstorage.network.MessageGridCraftingPreviewResponse;
|
import com.raoulvdberge.refinedstorage.network.MessageGridCraftingPreviewResponse;
|
||||||
import com.raoulvdberge.refinedstorage.network.MessageGridCraftingStartResponse;
|
import com.raoulvdberge.refinedstorage.network.MessageGridCraftingStartResponse;
|
||||||
import com.raoulvdberge.refinedstorage.util.StackUtils;
|
import com.raoulvdberge.refinedstorage.util.StackUtils;
|
||||||
@@ -21,6 +23,8 @@ import net.minecraftforge.items.CapabilityItemHandler;
|
|||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public class ItemGridHandler implements IItemGridHandler {
|
public class ItemGridHandler implements IItemGridHandler {
|
||||||
private INetwork network;
|
private INetwork network;
|
||||||
|
|
||||||
@@ -187,9 +191,11 @@ public class ItemGridHandler implements IItemGridHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
task.calculate();
|
ICraftingTaskError error = task.calculate();
|
||||||
|
|
||||||
if (noPreview && task.getMissing().isEmpty()) {
|
if (error != null) {
|
||||||
|
RS.INSTANCE.network.sendTo(new MessageGridCraftingPreviewResponse(Collections.singletonList(new CraftingPreviewElementError(error.getType(), error.getRecursedPattern() == null ? ItemStack.EMPTY : error.getRecursedPattern().getStack())), hash, quantity), player);
|
||||||
|
} else if (noPreview && task.getMissing().isEmpty()) {
|
||||||
network.getCraftingManager().add(task);
|
network.getCraftingManager().add(task);
|
||||||
|
|
||||||
RS.INSTANCE.network.sendTo(new MessageGridCraftingStartResponse(), player);
|
RS.INSTANCE.network.sendTo(new MessageGridCraftingStartResponse(), player);
|
||||||
@@ -230,11 +236,12 @@ public class ItemGridHandler implements IItemGridHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
task.calculate();
|
ICraftingTaskError error = task.calculate();
|
||||||
|
if (error == null) {
|
||||||
network.getCraftingManager().add(task);
|
network.getCraftingManager().add(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCraftingCancelRequested(EntityPlayerMP player, int id) {
|
public void onCraftingCancelRequested(EntityPlayerMP player, int id) {
|
||||||
|
@@ -3,6 +3,7 @@ package com.raoulvdberge.refinedstorage.gui;
|
|||||||
import com.raoulvdberge.refinedstorage.RS;
|
import com.raoulvdberge.refinedstorage.RS;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.CraftingTaskErrorType;
|
||||||
import com.raoulvdberge.refinedstorage.api.render.IElementDrawer;
|
import com.raoulvdberge.refinedstorage.api.render.IElementDrawer;
|
||||||
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
|
import com.raoulvdberge.refinedstorage.api.render.IElementDrawers;
|
||||||
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementError;
|
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementError;
|
||||||
@@ -25,6 +26,7 @@ import net.minecraftforge.fluids.FluidStack;
|
|||||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -77,7 +79,7 @@ public class GuiCraftingPreview extends GuiBase {
|
|||||||
public void init(int x, int y) {
|
public void init(int x, int y) {
|
||||||
cancelButton = addButton(x + 16, y + 144, 50, 20, t("gui.cancel"));
|
cancelButton = addButton(x + 16, y + 144, 50, 20, t("gui.cancel"));
|
||||||
startButton = addButton(x + 85, y + 144, 50, 20, t("misc.refinedstorage:start"));
|
startButton = addButton(x + 85, y + 144, 50, 20, t("misc.refinedstorage:start"));
|
||||||
startButton.enabled = stacks.stream().noneMatch(ICraftingPreviewElement::hasMissing);
|
startButton.enabled = stacks.stream().noneMatch(ICraftingPreviewElement::hasMissing) && getErrorType() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,13 +89,18 @@ public class GuiCraftingPreview extends GuiBase {
|
|||||||
scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS);
|
scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startButton != null && !startButton.enabled && isCtrlKeyDown() && isShiftKeyDown()) {
|
if (startButton != null && !startButton.enabled && isCtrlKeyDown() && isShiftKeyDown() && getErrorType() == null) {
|
||||||
startButton.enabled = true;
|
startButton.enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasErrored() {
|
@Nullable
|
||||||
return stacks.size() == 1 && stacks.get(0) instanceof CraftingPreviewElementError;
|
private CraftingTaskErrorType getErrorType() {
|
||||||
|
if (stacks.size() == 1 && stacks.get(0) instanceof CraftingPreviewElementError) {
|
||||||
|
return ((CraftingPreviewElementError) stacks.get(0)).getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -102,7 +109,7 @@ public class GuiCraftingPreview extends GuiBase {
|
|||||||
|
|
||||||
drawTexture(x, y, 0, 0, screenWidth, screenHeight);
|
drawTexture(x, y, 0, 0, screenWidth, screenHeight);
|
||||||
|
|
||||||
if (hasErrored()) {
|
if (getErrorType() != null) {
|
||||||
drawRect(x + 7, y + 20, x + 142, y + 139, 0xFFDBDBDB);
|
drawRect(x + 7, y + 20, x + 142, y + 139, 0xFFDBDBDB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,28 +123,31 @@ public class GuiCraftingPreview extends GuiBase {
|
|||||||
|
|
||||||
float scale = fontRenderer.getUnicodeFlag() ? 1F : 0.5F;
|
float scale = fontRenderer.getUnicodeFlag() ? 1F : 0.5F;
|
||||||
|
|
||||||
if (hasErrored()) {
|
if (getErrorType() != null) {
|
||||||
GlStateManager.pushMatrix();
|
GlStateManager.pushMatrix();
|
||||||
GlStateManager.scale(scale, scale, 1);
|
GlStateManager.scale(scale, scale, 1);
|
||||||
|
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 10, scale), t("gui.refinedstorage:crafting_preview.error.0"));
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 11, scale), t("gui.refinedstorage:crafting_preview.error"));
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 20, scale), t("gui.refinedstorage:crafting_preview.error.1"));
|
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 30, scale), t("gui.refinedstorage:crafting_preview.error.2"));
|
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 40, scale), t("gui.refinedstorage:crafting_preview.error.3"));
|
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 50, scale), t("gui.refinedstorage:crafting_preview.error.4"));
|
|
||||||
|
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 60, scale), t("gui.refinedstorage:crafting_preview.error.5"));
|
switch (getErrorType()) {
|
||||||
|
case RECURSIVE: {
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), t("gui.refinedstorage:crafting_preview.error.recursive.0"));
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), t("gui.refinedstorage:crafting_preview.error.recursive.1"));
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 41, scale), t("gui.refinedstorage:crafting_preview.error.recursive.2"));
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 51, scale), t("gui.refinedstorage:crafting_preview.error.recursive.3"));
|
||||||
|
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 61, scale), t("gui.refinedstorage:crafting_preview.error.recursive.4"));
|
||||||
|
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
ICraftingPattern pattern = ItemPattern.getPatternFromCache(parent.mc.world, (ItemStack) stacks.get(0).getElement());
|
ICraftingPattern pattern = ItemPattern.getPatternFromCache(parent.mc.world, (ItemStack) stacks.get(0).getElement());
|
||||||
|
|
||||||
int yy = 80;
|
int yy = 83;
|
||||||
for (ItemStack output : pattern.getOutputs()) {
|
for (ItemStack output : pattern.getOutputs()) {
|
||||||
if (output != null) {
|
if (output != null) {
|
||||||
GlStateManager.pushMatrix();
|
GlStateManager.pushMatrix();
|
||||||
GlStateManager.scale(scale, scale, 1);
|
GlStateManager.scale(scale, scale, 1);
|
||||||
drawString(RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy + 7, scale), output.getDisplayName());
|
drawString(RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy + 6, scale), output.getDisplayName());
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
RenderHelper.enableGUIStandardItemLighting();
|
RenderHelper.enableGUIStandardItemLighting();
|
||||||
@@ -148,6 +158,18 @@ public class GuiCraftingPreview extends GuiBase {
|
|||||||
yy += 17;
|
yy += 17;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TOO_COMPLEX: {
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), t("gui.refinedstorage:crafting_preview.error.too_complex.0"));
|
||||||
|
drawString(RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), t("gui.refinedstorage:crafting_preview.error.too_complex.1"));
|
||||||
|
|
||||||
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int slot = scrollbar != null ? (scrollbar.getOffset() * 2) : 0;
|
int slot = scrollbar != null ? (scrollbar.getOffset() * 2) : 0;
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.integration.oc;
|
|||||||
|
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||||
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTask;
|
||||||
|
import com.raoulvdberge.refinedstorage.api.autocrafting.task.ICraftingTaskError;
|
||||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
||||||
import com.raoulvdberge.refinedstorage.api.util.IComparer;
|
import com.raoulvdberge.refinedstorage.api.util.IComparer;
|
||||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||||
@@ -129,9 +130,11 @@ public class EnvironmentNetwork extends AbstractManagedEnvironment {
|
|||||||
throw new IllegalArgumentException("Could not create crafting task");
|
throw new IllegalArgumentException("Could not create crafting task");
|
||||||
}
|
}
|
||||||
|
|
||||||
task.calculate();
|
ICraftingTaskError error = task.calculate();
|
||||||
|
|
||||||
|
if (error == null) {
|
||||||
node.getNetwork().getCraftingManager().add(task);
|
node.getNetwork().getCraftingManager().add(task);
|
||||||
|
}
|
||||||
|
|
||||||
return new Object[]{};
|
return new Object[]{};
|
||||||
}
|
}
|
||||||
|
@@ -55,12 +55,14 @@ gui.refinedstorage:crafting_preview=Crafting Preview
|
|||||||
gui.refinedstorage:crafting_preview.to_craft=To craft: %d
|
gui.refinedstorage:crafting_preview.to_craft=To craft: %d
|
||||||
gui.refinedstorage:crafting_preview.available=Available: %d
|
gui.refinedstorage:crafting_preview.available=Available: %d
|
||||||
gui.refinedstorage:crafting_preview.missing=Missing: %d
|
gui.refinedstorage:crafting_preview.missing=Missing: %d
|
||||||
gui.refinedstorage:crafting_preview.error.0=Cannot craft
|
gui.refinedstorage:crafting_preview.error=Request failed
|
||||||
gui.refinedstorage:crafting_preview.error.1=One of the crafting ingredients ended up needing
|
gui.refinedstorage:crafting_preview.error.recursive.0=One of the crafting ingredients ended up needing
|
||||||
gui.refinedstorage:crafting_preview.error.2=itself.
|
gui.refinedstorage:crafting_preview.error.recursive.1=itself.
|
||||||
gui.refinedstorage:crafting_preview.error.3=You need to remove the pattern or make sure
|
gui.refinedstorage:crafting_preview.error.recursive.2=You need to remove the pattern or make sure
|
||||||
gui.refinedstorage:crafting_preview.error.4=the pattern is not used during crafting.
|
gui.refinedstorage:crafting_preview.error.recursive.3=the pattern is not used during crafting.
|
||||||
gui.refinedstorage:crafting_preview.error.5=Offending pattern:
|
gui.refinedstorage:crafting_preview.error.recursive.4=Offending pattern:
|
||||||
|
gui.refinedstorage:crafting_preview.error.too_complex.0=The crafting task calculation was too complex
|
||||||
|
gui.refinedstorage:crafting_preview.error.too_complex.1=and was stopped to avoid server strain.
|
||||||
gui.refinedstorage:crafting_preview.force_start=Press CTRL + SHIFT to ignore
|
gui.refinedstorage:crafting_preview.force_start=Press CTRL + SHIFT to ignore
|
||||||
gui.refinedstorage:reader=Reader
|
gui.refinedstorage:reader=Reader
|
||||||
gui.refinedstorage:writer=Writer
|
gui.refinedstorage:writer=Writer
|
||||||
|
@@ -52,12 +52,12 @@ gui.refinedstorage:crafting_preview=Avance de Fabricación
|
|||||||
gui.refinedstorage:crafting_preview.to_craft=Para fabricar: %d
|
gui.refinedstorage:crafting_preview.to_craft=Para fabricar: %d
|
||||||
gui.refinedstorage:crafting_preview.available=Disponible: %d
|
gui.refinedstorage:crafting_preview.available=Disponible: %d
|
||||||
gui.refinedstorage:crafting_preview.missing=Falta: %d
|
gui.refinedstorage:crafting_preview.missing=Falta: %d
|
||||||
gui.refinedstorage:crafting_preview.error.0=No puede fabricar
|
gui.refinedstorage:crafting_preview.error=No puede fabricar
|
||||||
gui.refinedstorage:crafting_preview.error.1=Uno de los objetos de creación termino faltando
|
gui.refinedstorage:crafting_preview.error.recursive.0=Uno de los objetos de creación termino faltando
|
||||||
gui.refinedstorage:crafting_preview.error.2=sí mismo.
|
gui.refinedstorage:crafting_preview.error.recursive.1=sí mismo.
|
||||||
gui.refinedstorage:crafting_preview.error.3=Necesita remover el patrón o revisarlo
|
gui.refinedstorage:crafting_preview.error.recursive.2=Necesita remover el patrón o revisarlo
|
||||||
gui.refinedstorage:crafting_preview.error.4=el patrón no se usa para la fabricación.
|
gui.refinedstorage:crafting_preview.error.recursive.3=el patrón no se usa para la fabricación.
|
||||||
gui.refinedstorage:crafting_preview.error.5=Patrón ofensivo:
|
gui.refinedstorage:crafting_preview.error.recursive.4=Patrón ofensivo:
|
||||||
gui.refinedstorage:crafting_preview.force_start=Presiona CTRL + SHIFT para forzar el inicio
|
gui.refinedstorage:crafting_preview.force_start=Presiona CTRL + SHIFT para forzar el inicio
|
||||||
gui.refinedstorage:reader=Lector
|
gui.refinedstorage:reader=Lector
|
||||||
gui.refinedstorage:writer=Escritor
|
gui.refinedstorage:writer=Escritor
|
||||||
|
@@ -52,12 +52,12 @@ gui.refinedstorage:crafting_preview=Предварительный просмо
|
|||||||
gui.refinedstorage:crafting_preview.to_craft=Создать: %d
|
gui.refinedstorage:crafting_preview.to_craft=Создать: %d
|
||||||
gui.refinedstorage:crafting_preview.available=Доступно: %d
|
gui.refinedstorage:crafting_preview.available=Доступно: %d
|
||||||
gui.refinedstorage:crafting_preview.missing=Отсутствует: %d
|
gui.refinedstorage:crafting_preview.missing=Отсутствует: %d
|
||||||
gui.refinedstorage:crafting_preview.error.0=Не удается создать
|
gui.refinedstorage:crafting_preview.error=Не удается создать
|
||||||
gui.refinedstorage:crafting_preview.error.1=Один из ингредиентов для крафта оказался нуждающимся
|
gui.refinedstorage:crafting_preview.error.recursive.0=Один из ингредиентов для крафта оказался нуждающимся
|
||||||
gui.refinedstorage:crafting_preview.error.2=в себе.
|
gui.refinedstorage:crafting_preview.error.recursive.1=в себе.
|
||||||
gui.refinedstorage:crafting_preview.error.3=Вам нужно удалить шаблон или убедиться, что
|
gui.refinedstorage:crafting_preview.error.recursive.2=Вам нужно удалить шаблон или убедиться, что
|
||||||
gui.refinedstorage:crafting_preview.error.4=шаблон не используется во время обработки.
|
gui.refinedstorage:crafting_preview.error.recursive.3=шаблон не используется во время обработки.
|
||||||
gui.refinedstorage:crafting_preview.error.5=Нарушение шаблона:
|
gui.refinedstorage:crafting_preview.error.recursive.4=Нарушение шаблона:
|
||||||
gui.refinedstorage:crafting_preview.force_start=Нажмите CTRL + SHIFT, чтобы все равно начать
|
gui.refinedstorage:crafting_preview.force_start=Нажмите CTRL + SHIFT, чтобы все равно начать
|
||||||
gui.refinedstorage:reader=Устройство чтения
|
gui.refinedstorage:reader=Устройство чтения
|
||||||
gui.refinedstorage:writer=Устройство записи
|
gui.refinedstorage:writer=Устройство записи
|
||||||
|
Reference in New Issue
Block a user