Add better framework for extracting and inserting items for crafting.
This commit is contained in:
@@ -100,6 +100,7 @@ public interface ICraftingManager {
|
||||
/**
|
||||
* Makes the network send a crafting monitor update to all players as soon as it can.
|
||||
*/
|
||||
// TODO: rework system to be subscribed-based, per task
|
||||
void markCraftingMonitorForUpdate();
|
||||
|
||||
/**
|
||||
@@ -107,6 +108,7 @@ public interface ICraftingManager {
|
||||
* <p>
|
||||
* WARNING: In most cases, you should just use {@link ICraftingManager#markCraftingMonitorForUpdate()}, if not, you can get high bandwidth usage.
|
||||
*/
|
||||
// TODO: rework system to be subscribed-based, per task
|
||||
void sendCraftingMonitorUpdate();
|
||||
|
||||
/**
|
||||
@@ -114,5 +116,6 @@ public interface ICraftingManager {
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
// TODO: rework system to be subscribed-based, per task
|
||||
void sendCraftingMonitorUpdate(EntityPlayerMP player);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface ICraftingPatternContainer {
|
||||
/**
|
||||
* @return the amount of speed upgrades in the container
|
||||
*/
|
||||
int getSpeedUpdateCount();
|
||||
int getSpeedUpgradeCount();
|
||||
|
||||
/**
|
||||
* @return the inventory that this container is connected to
|
||||
|
||||
@@ -19,7 +19,7 @@ public interface ICraftingTask {
|
||||
void calculate();
|
||||
|
||||
/**
|
||||
* Updates this task. Gets called every few ticks, depending on the speed of the pattern container.
|
||||
* Updates this task.
|
||||
* {@link ICraftingTask#calculate()} must be run before this!
|
||||
*
|
||||
* @return true if this crafting task is finished and can be deleted from the list, false otherwise
|
||||
|
||||
@@ -84,6 +84,8 @@ public class CraftingManager implements ICraftingManager {
|
||||
@Override
|
||||
public void update() {
|
||||
if (network.canRun()) {
|
||||
boolean changed = !tasksToCancel.isEmpty() || !tasksToAdd.isEmpty();
|
||||
|
||||
tasksToCancel.forEach(ICraftingTask::onCancelled);
|
||||
tasks.removeAll(tasksToCancel);
|
||||
tasksToCancel.clear();
|
||||
@@ -91,7 +93,11 @@ public class CraftingManager implements ICraftingManager {
|
||||
tasksToAdd.stream().filter(ICraftingTask::isValid).forEach(tasks::add);
|
||||
tasksToAdd.clear();
|
||||
|
||||
tasks.removeIf(ICraftingTask::update);
|
||||
changed = tasks.removeIf(ICraftingTask::update);
|
||||
|
||||
if (changed) {
|
||||
markCraftingMonitorForUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if (updateRequested) {
|
||||
|
||||
@@ -167,7 +167,16 @@ public class CraftingPattern implements ICraftingPattern {
|
||||
inv.setInventorySlotContents(i, took.get(i));
|
||||
}
|
||||
|
||||
return recipe.getRemainingItems(inv);
|
||||
NonNullList<ItemStack> remainingItems = recipe.getRemainingItems(inv);
|
||||
NonNullList<ItemStack> sanitized = NonNullList.create();
|
||||
|
||||
for (ItemStack item : remainingItems) {
|
||||
if (!item.isEmpty()) {
|
||||
sanitized.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||
|
||||
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingExtractor {
|
||||
private INetwork network;
|
||||
private List<ItemStack> items;
|
||||
private List<CraftingExtractorItemStatus> status = new ArrayList<>();
|
||||
|
||||
public CraftingExtractor(INetwork network, List<ItemStack> items) {
|
||||
this.network = network;
|
||||
this.items = items;
|
||||
|
||||
for (int i = 0; i < items.size(); ++i) {
|
||||
status.add(CraftingExtractorItemStatus.MISSING);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ItemStack> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public List<CraftingExtractorItemStatus> getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void updateStatus() {
|
||||
for (int i = 0; i < items.size(); ++i) {
|
||||
if (status.get(i) != CraftingExtractorItemStatus.EXTRACTED) {
|
||||
ItemStack stack = items.get(i);
|
||||
|
||||
ItemStack inNetwork = network.extractItem(stack, stack.getCount(), true);
|
||||
|
||||
if (inNetwork == null || inNetwork.getCount() < stack.getCount()) {
|
||||
status.set(i, CraftingExtractorItemStatus.MISSING);
|
||||
} else {
|
||||
status.set(i, CraftingExtractorItemStatus.AVAILABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAllAvailable() {
|
||||
return status.stream().allMatch(s -> s == CraftingExtractorItemStatus.AVAILABLE || s == CraftingExtractorItemStatus.EXTRACTED);
|
||||
}
|
||||
|
||||
public boolean isAllExtracted() {
|
||||
return status.stream().allMatch(s -> s == CraftingExtractorItemStatus.EXTRACTED);
|
||||
}
|
||||
|
||||
public void extractOne() {
|
||||
for (int i = 0; i < items.size(); ++i) {
|
||||
if (status.get(i) == CraftingExtractorItemStatus.AVAILABLE) {
|
||||
ItemStack extracted = network.extractItem(items.get(i), items.get(i).getCount(), false);
|
||||
if (extracted == null) {
|
||||
throw new IllegalStateException("Did not extract anything");
|
||||
}
|
||||
|
||||
status.set(i, CraftingExtractorItemStatus.EXTRACTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||
|
||||
public enum CraftingExtractorItemStatus {
|
||||
AVAILABLE,
|
||||
MISSING,
|
||||
EXTRACTED
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||
|
||||
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
|
||||
public class CraftingInserter {
|
||||
private INetwork network;
|
||||
private Deque<CraftingInserterItem> items = new ArrayDeque<>();
|
||||
|
||||
public CraftingInserter(INetwork network) {
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
public void insert(ItemStack stack) {
|
||||
items.push(new CraftingInserterItem(stack, CraftingInserterItemStatus.WAITING));
|
||||
|
||||
network.getCraftingManager().sendCraftingMonitorUpdate();
|
||||
}
|
||||
|
||||
public void insertSingle() {
|
||||
CraftingInserterItem item = items.peek();
|
||||
|
||||
if (item != null) {
|
||||
if (network.insertItem(item.getStack(), item.getStack().getCount(), true) == null) {
|
||||
ItemStack inserted = network.insertItem(item.getStack(), item.getStack().getCount(), false);
|
||||
if (inserted != null) {
|
||||
throw new IllegalStateException("Could not insert item");
|
||||
}
|
||||
|
||||
items.pop();
|
||||
} else {
|
||||
item.setStatus(CraftingInserterItemStatus.FULL);
|
||||
}
|
||||
|
||||
network.getCraftingManager().sendCraftingMonitorUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<CraftingInserterItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class CraftingInserterItem {
|
||||
private ItemStack stack;
|
||||
private CraftingInserterItemStatus status;
|
||||
|
||||
public CraftingInserterItem(ItemStack stack, CraftingInserterItemStatus status) {
|
||||
this.stack = stack;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public ItemStack getStack() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public CraftingInserterItemStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(CraftingInserterItemStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||
|
||||
public enum CraftingInserterItemStatus {
|
||||
WAITING,
|
||||
FULL
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public abstract class CraftingStep {
|
||||
|
||||
public abstract boolean canExecute();
|
||||
|
||||
public abstract void execute();
|
||||
public abstract boolean execute();
|
||||
|
||||
public ICraftingPattern getPattern() {
|
||||
return pattern;
|
||||
|
||||
@@ -2,57 +2,50 @@ package com.raoulvdberge.refinedstorage.apiimpl.autocrafting.task;
|
||||
|
||||
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPattern;
|
||||
import com.raoulvdberge.refinedstorage.api.network.INetwork;
|
||||
import com.raoulvdberge.refinedstorage.api.util.IStackList;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
public class CraftingStepCraft extends CraftingStep {
|
||||
private INetwork network;
|
||||
import java.util.List;
|
||||
|
||||
public class CraftingStepCraft extends CraftingStep {
|
||||
private CraftingInserter inserter;
|
||||
private CraftingExtractor extractor;
|
||||
|
||||
private IStackList<ItemStack> toExtract;
|
||||
private NonNullList<ItemStack> took;
|
||||
|
||||
public CraftingStepCraft(ICraftingPattern pattern, INetwork network, IStackList<ItemStack> toExtract, NonNullList<ItemStack> took) {
|
||||
public CraftingStepCraft(ICraftingPattern pattern, CraftingInserter inserter, INetwork network, List<ItemStack> toExtract, NonNullList<ItemStack> took) {
|
||||
super(pattern);
|
||||
|
||||
this.network = network;
|
||||
this.toExtract = toExtract;
|
||||
this.inserter = inserter;
|
||||
this.extractor = new CraftingExtractor(network, toExtract);
|
||||
this.took = took;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
for (ItemStack toExtractItem : toExtract.getStacks()) {
|
||||
ItemStack extracted = network.extractItem(toExtractItem, toExtractItem.getCount(), false);
|
||||
public boolean execute() {
|
||||
extractor.extractOne();
|
||||
|
||||
if (extracted == null) {
|
||||
throw new IllegalStateException("Did not extract anything");
|
||||
}
|
||||
}
|
||||
boolean allExtracted = extractor.isAllExtracted();
|
||||
|
||||
ItemStack output = pattern.getOutput(took);
|
||||
|
||||
network.insertItem(output, output.getCount(), false);
|
||||
if (allExtracted) {
|
||||
inserter.insert(pattern.getOutput(took));
|
||||
|
||||
for (ItemStack byproduct : pattern.getByproducts(took)) {
|
||||
network.insertItem(byproduct, byproduct.getCount(), false);
|
||||
inserter.insert(byproduct);
|
||||
}
|
||||
}
|
||||
|
||||
return allExtracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute() {
|
||||
for (ItemStack toExtractItem : toExtract.getStacks()) {
|
||||
ItemStack inNetwork = network.extractItem(toExtractItem, toExtractItem.getCount(), true);
|
||||
extractor.updateStatus();
|
||||
|
||||
if (inNetwork == null || inNetwork.getCount() < toExtractItem.getCount()) {
|
||||
return false;
|
||||
}
|
||||
return extractor.isAllAvailable();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IStackList<ItemStack> getToExtract() {
|
||||
return toExtract;
|
||||
public CraftingExtractor getExtractor() {
|
||||
return extractor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ public class CraftingTask implements ICraftingTask {
|
||||
private int quantity;
|
||||
private ICraftingPattern pattern;
|
||||
private List<CraftingStep> steps = new LinkedList<>();
|
||||
private CraftingInserter inserter;
|
||||
private int ticks = 0;
|
||||
|
||||
private IStackList<ItemStack> toTake = API.instance().createItemStackList();
|
||||
private IStackList<ItemStack> missing = API.instance().createItemStackList();
|
||||
@@ -33,6 +35,7 @@ public class CraftingTask implements ICraftingTask {
|
||||
|
||||
public CraftingTask(INetwork network, ItemStack requested, int quantity, ICraftingPattern pattern) {
|
||||
this.network = network;
|
||||
this.inserter = new CraftingInserter(network);
|
||||
this.requested = requested;
|
||||
this.quantity = quantity;
|
||||
this.pattern = pattern;
|
||||
@@ -128,7 +131,7 @@ public class CraftingTask implements ICraftingTask {
|
||||
}
|
||||
}
|
||||
|
||||
return new CraftingStepCraft(pattern, network, itemsToExtract, took);
|
||||
return new CraftingStepCraft(pattern, inserter, network, new ArrayList<>(itemsToExtract.getStacks()), took);
|
||||
}
|
||||
|
||||
private int getQuantityPerCraft(ICraftingPattern pattern, ItemStack requested) {
|
||||
@@ -155,8 +158,7 @@ public class CraftingTask implements ICraftingTask {
|
||||
if (!step.isCompleted()) {
|
||||
allCompleted = false;
|
||||
|
||||
if (step.canExecute()) {
|
||||
step.execute();
|
||||
if (step.canExecute() && step.execute() && ticks % getTickInterval(step.getPattern().getContainer().getSpeedUpgradeCount()) == 0) { // TODO: speed upgrades handling
|
||||
step.setCompleted();
|
||||
|
||||
network.getCraftingManager().sendCraftingMonitorUpdate();
|
||||
@@ -164,7 +166,11 @@ public class CraftingTask implements ICraftingTask {
|
||||
}
|
||||
}
|
||||
|
||||
return allCompleted;
|
||||
inserter.insertSingle();
|
||||
|
||||
ticks++;
|
||||
|
||||
return allCompleted && inserter.getItems().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,21 +217,46 @@ public class CraftingTask implements ICraftingTask {
|
||||
elements.commit();
|
||||
}
|
||||
|
||||
if (!inserter.getItems().isEmpty()) {
|
||||
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_inserting", 16));
|
||||
|
||||
for (CraftingInserterItem item : inserter.getItems()) {
|
||||
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(
|
||||
-1,
|
||||
item.getStack(),
|
||||
item.getStack().getCount(),
|
||||
32
|
||||
);
|
||||
|
||||
if (item.getStatus() == CraftingInserterItemStatus.FULL) {
|
||||
element = new CraftingMonitorElementError(element, "gui.refinedstorage:crafting_monitor.network_full");
|
||||
}
|
||||
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
elements.commit();
|
||||
}
|
||||
|
||||
if (steps.stream().anyMatch(s -> s instanceof CraftingStepCraft && !s.isCompleted())) {
|
||||
elements.directAdd(new CraftingMonitorElementText("gui.refinedstorage:crafting_monitor.items_crafting", 16));
|
||||
|
||||
for (CraftingStep step : steps) {
|
||||
if (step instanceof CraftingStepCraft && !step.isCompleted()) {
|
||||
for (ItemStack stack : ((CraftingStepCraft) step).getToExtract().getStacks()) {
|
||||
CraftingExtractor extractor = ((CraftingStepCraft) step).getExtractor();
|
||||
|
||||
for (int i = 0; i < extractor.getItems().size(); ++i) {
|
||||
ItemStack item = extractor.getItems().get(i);
|
||||
CraftingExtractorItemStatus status = extractor.getStatus().get(i);
|
||||
|
||||
ICraftingMonitorElement element = new CraftingMonitorElementItemRender(
|
||||
-1,
|
||||
stack,
|
||||
stack.getCount(),
|
||||
item,
|
||||
item.getCount(),
|
||||
32
|
||||
);
|
||||
|
||||
// TODO: cache this
|
||||
if (!step.canExecute()) {
|
||||
if (status == CraftingExtractorItemStatus.MISSING) {
|
||||
element = new CraftingMonitorElementInfo(element, "gui.refinedstorage:crafting_monitor.waiting_for_items");
|
||||
}
|
||||
|
||||
@@ -304,4 +335,20 @@ public class CraftingTask implements ICraftingTask {
|
||||
public IStackList<ItemStack> getMissing() {
|
||||
return missing;
|
||||
}
|
||||
|
||||
private int getTickInterval(int speedUpgrades) {
|
||||
switch (speedUpgrades) {
|
||||
case 1:
|
||||
return 8;
|
||||
case 2:
|
||||
return 6;
|
||||
case 3:
|
||||
return 4;
|
||||
case 4:
|
||||
return 2;
|
||||
case 0:
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ public class NetworkNodeCrafter extends NetworkNode implements ICraftingPatternC
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpeedUpdateCount() {
|
||||
public int getSpeedUpgradeCount() {
|
||||
return upgrades.getUpgradeCount(ItemUpgrade.TYPE_SPEED);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ gui.refinedstorage:crafting_monitor.items_missing=Items missing
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=Machine is in use
|
||||
gui.refinedstorage:crafting_monitor.machine_none=No machine found
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=Waiting for items
|
||||
gui.refinedstorage:crafting_monitor.blocked=Blocked, waiting on other task
|
||||
gui.refinedstorage:crafting_monitor.network_full=Network is full
|
||||
gui.refinedstorage:wireless_transmitter=Wireless Transmitter
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d block(s)
|
||||
gui.refinedstorage:crafter=Crafter
|
||||
|
||||
@@ -33,7 +33,6 @@ gui.refinedstorage:crafting_monitor.items_missing=Faltan objetos
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=Maquina en uso
|
||||
gui.refinedstorage:crafting_monitor.machine_none=Maquina no Hallada
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=Esperando Objetos
|
||||
gui.refinedstorage:crafting_monitor.blocked=Bloqueado, esperando otra tarea
|
||||
gui.refinedstorage:wireless_transmitter=Emisor inalámbrico
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d bloque(s)
|
||||
gui.refinedstorage:crafter=Fabricador
|
||||
|
||||
@@ -32,7 +32,6 @@ gui.refinedstorage:crafting_monitor.items_missing=Items manquants
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=Machine en cours d'utilisation
|
||||
gui.refinedstorage:crafting_monitor.machine_none=Pas de machine disponible
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=En attente d'items
|
||||
gui.refinedstorage:crafting_monitor.blocked=Bloqué, en attente d'autres taches
|
||||
gui.refinedstorage:wireless_transmitter=Emetteur sans-fil
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d bloc(s)
|
||||
gui.refinedstorage:crafter=Crafteur
|
||||
|
||||
@@ -31,7 +31,6 @@ gui.refinedstorage:crafting_monitor.items_missing=부족한 아이템
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=기계가 이미 사용 중임
|
||||
gui.refinedstorage:crafting_monitor.machine_none=기계를 찾을 수 없음
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=아이템을 기다리는 중
|
||||
gui.refinedstorage:crafting_monitor.blocked=막힘 - 다른 작업에서 대기 중
|
||||
gui.refinedstorage:wireless_transmitter=무선 송신기
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d블럭
|
||||
gui.refinedstorage:crafter=조합기
|
||||
|
||||
@@ -32,7 +32,6 @@ gui.refinedstorage:crafting_monitor.items_missing=Ausência de itens
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=A máquina está em uso
|
||||
gui.refinedstorage:crafting_monitor.machine_none=Nenhuma máquina encontrada
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=Esperando itens
|
||||
gui.refinedstorage:crafting_monitor.blocked=Bloqueado, aguardando outra tarefa
|
||||
gui.refinedstorage:wireless_transmitter=Transmissor Wireless
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d Blocos
|
||||
gui.refinedstorage:crafter=Fabricador
|
||||
|
||||
@@ -33,7 +33,6 @@ gui.refinedstorage:crafting_monitor.items_missing=Отсутствуют пре
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=Машина используется
|
||||
gui.refinedstorage:crafting_monitor.machine_none=Машина не найдена
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=Ожидание предметов
|
||||
gui.refinedstorage:crafting_monitor.blocked=Заблокировано, ожидание другой задачи
|
||||
gui.refinedstorage:wireless_transmitter=Передатчик
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d блоков
|
||||
gui.refinedstorage:crafter=Крафтер
|
||||
|
||||
@@ -33,7 +33,6 @@ gui.refinedstorage:crafting_monitor.items_missing=物品丢失中
|
||||
gui.refinedstorage:crafting_monitor.machine_in_use=该机器正在处理其他工作,请稍等
|
||||
gui.refinedstorage:crafting_monitor.machine_none=找不到机器
|
||||
gui.refinedstorage:crafting_monitor.waiting_for_items=正在等待物品
|
||||
gui.refinedstorage:crafting_monitor.blocked=被阻塞,正在等待其他任务
|
||||
gui.refinedstorage:wireless_transmitter=无线访问点
|
||||
gui.refinedstorage:wireless_transmitter.distance=%d 方块
|
||||
gui.refinedstorage:crafter=装配室
|
||||
|
||||
Reference in New Issue
Block a user