Merge pull request #3004 from Darkere/insert_to_crafter

Allow addons to override crafter insertion
This commit is contained in:
Darkere
2021-10-17 16:44:17 +02:00
committed by GitHub
4 changed files with 128 additions and 86 deletions

View File

@@ -1,16 +1,22 @@
package com.refinedmods.refinedstorage.api.autocrafting;
import com.refinedmods.refinedstorage.api.util.Action;
import com.refinedmods.refinedstorage.api.util.StackListEntry;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import org.apache.logging.log4j.LogManager;
import javax.annotation.Nullable;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* Represents a network node that contains crafting patterns.
@@ -124,4 +130,114 @@ public interface ICraftingPatternContainer {
*/
default void onUsedForProcessing() {
}
/**
* @return whether the container is successfully connected to the inventory it wants to insert to
*/
default boolean hasConnectedInventory() {
return getConnectedInventory() != null;
}
/**
* @return whether the container is successfully connected to the fluid inventory it wants to insert to
*/
default boolean hasConnectedFluidInventory() {
return getConnectedFluidInventory() != null;
}
/**
* Called by Autocrafting when it uses this crafter in a processing recipe that has items as input
*
* @param toInsert Collection of Itemstack stacklist entries to insert into the inventory
* @param action action to perform
* @return whether insertion was successful
*/
default boolean insertItemsIntoInventory(Collection<StackListEntry<ItemStack>> toInsert, Action action) {
IItemHandler dest = getConnectedInventory();
if (toInsert.isEmpty()) {
return true;
}
if (dest == null) {
return false;
}
Deque<StackListEntry<ItemStack>> stacks = new ArrayDeque<>(toInsert);
StackListEntry<ItemStack> currentEntry = stacks.poll();
ItemStack current = currentEntry != null ? currentEntry.getStack() : null;
List<Integer> availableSlots = IntStream.range(0, dest.getSlots()).boxed().collect(Collectors.toList());
while (current != null && !availableSlots.isEmpty()) {
ItemStack remainder = ItemStack.EMPTY;
for (int i = 0; i < availableSlots.size(); ++i) {
int slot = availableSlots.get(i);
// .copy() is mandatory!
remainder = dest.insertItem(slot, current.copy(), action == Action.SIMULATE);
// If we inserted *something*
if (remainder.isEmpty() || current.getCount() != remainder.getCount()) {
availableSlots.remove(i);
break;
}
}
if (remainder.isEmpty()) { // If we inserted successfully, get a next stack.
currentEntry = stacks.poll();
current = currentEntry != null ? currentEntry.getStack() : null;
} else if (current.getCount() == remainder.getCount()) { // If we didn't insert anything over ALL these slots, stop here.
break;
} else { // If we didn't insert all, continue with other slots and use our remainder.
current = remainder;
}
}
boolean success = current == null && stacks.isEmpty();
if (!success && action == Action.PERFORM) {
LogManager.getLogger().warn("Inventory unexpectedly didn't accept {}, the remainder has been voided!", current != null ? current.getTranslationKey() : null);
}
return success;
}
/**
* Called by Autocrafting when it uses this crafter in a processing recipe that has fluids as input
*
* @param toInsert Collection of Fluidstack stacklist entries to insert into the inventory
* @param action action to perform
* @return whether insertion was successful
*/
default boolean insertFluidsIntoInventory(Collection<StackListEntry<FluidStack>> toInsert, Action action) {
IFluidHandler dest = getConnectedFluidInventory();
if (toInsert.isEmpty()) {
return true;
}
if (dest == null) {
return false;
}
for (StackListEntry<FluidStack> entry : toInsert) {
int filled = dest.fill(entry.getStack(), action == Action.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE);
if (filled != entry.getStack().getAmount()) {
if (action == Action.PERFORM) {
LogManager.getLogger().warn("Inventory unexpectedly didn't accept all of {}, the remainder has been voided!", entry.getStack().getTranslationKey());
}
return false;
}
}
return true;
}
}

View File

@@ -9,18 +9,11 @@ import com.refinedmods.refinedstorage.api.util.StackListEntry;
import com.refinedmods.refinedstorage.apiimpl.API;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.ArrayList;
import java.util.List;
public final class IoUtil {
private static final Logger LOGGER = LogManager.getLogger(IoUtil.class);
private static final int DEFAULT_EXTRACT_FLAGS = IComparer.COMPARE_NBT;
private IoUtil() {
@@ -66,75 +59,6 @@ public final class IoUtil {
return extracted;
}
public static boolean insertIntoInventory(@Nullable IItemHandler dest, Collection<StackListEntry<ItemStack>> toInsert, Action action) {
if (dest == null) {
return false;
}
if (toInsert.isEmpty()) {
return true;
}
Deque<StackListEntry<ItemStack>> stacks = new ArrayDeque<>(toInsert);
StackListEntry<ItemStack> currentEntry = stacks.poll();
ItemStack current = currentEntry != null ? currentEntry.getStack() : null;
List<Integer> availableSlots = IntStream.range(0, dest.getSlots()).boxed().collect(Collectors.toList());
while (current != null && !availableSlots.isEmpty()) {
ItemStack remainder = ItemStack.EMPTY;
for (int i = 0; i < availableSlots.size(); ++i) {
int slot = availableSlots.get(i);
// .copy() is mandatory!
remainder = dest.insertItem(slot, current.copy(), action == Action.SIMULATE);
// If we inserted *something*
if (remainder.isEmpty() || current.getCount() != remainder.getCount()) {
availableSlots.remove(i);
break;
}
}
if (remainder.isEmpty()) { // If we inserted successfully, get a next stack.
currentEntry = stacks.poll();
current = currentEntry != null ? currentEntry.getStack() : null;
} else if (current.getCount() == remainder.getCount()) { // If we didn't insert anything over ALL these slots, stop here.
break;
} else { // If we didn't insert all, continue with other slots and use our remainder.
current = remainder;
}
}
boolean success = current == null && stacks.isEmpty();
if (!success && action == Action.PERFORM) {
LOGGER.warn("Inventory unexpectedly didn't accept {}, the remainder has been voided!", current != null ? current.getTranslationKey() : null);
}
return success;
}
public static boolean insertIntoInventory(IFluidHandler dest, Collection<StackListEntry<FluidStack>> toInsert, Action action) {
for (StackListEntry<FluidStack> entry : toInsert) {
int filled = dest.fill(entry.getStack(), action == Action.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE);
if (filled != entry.getStack().getAmount()) {
if (action == Action.PERFORM) {
LOGGER.warn("Inventory unexpectedly didn't accept all of {}, the remainder has been voided!", entry.getStack().getTranslationKey());
}
return false;
}
}
return true;
}
public static void extractItemsFromNetwork(IStackList<ItemStack> toExtractInitial, INetwork network, IStorageDisk<ItemStack> internalStorage) {
if (toExtractInitial.isEmpty()) {
return;

View File

@@ -104,8 +104,8 @@ public class ProcessingNode extends Node {
allLocked = false;
}
if ((!singleItemSetToRequire.isEmpty() && container.getConnectedInventory() == null) ||
(!singleFluidSetToRequire.isEmpty() && container.getConnectedFluidInventory() == null)) {
if ((!singleItemSetToRequire.isEmpty() && !container.hasConnectedInventory()) ||
(!singleFluidSetToRequire.isEmpty() && !container.hasConnectedFluidInventory())) {
if (allMissingMachine) {
this.state = ProcessingState.MACHINE_NONE;
}
@@ -128,9 +128,9 @@ public class ProcessingNode extends Node {
boolean canInsertFullAmount = false;
if (hasAllRequirements) {
canInsertFullAmount = IoUtil.insertIntoInventory(container.getConnectedInventory(), extractedItems.getStacks(), Action.SIMULATE);
canInsertFullAmount = container.insertItemsIntoInventory(extractedItems.getStacks(), Action.SIMULATE);
if (canInsertFullAmount) {
canInsertFullAmount = IoUtil.insertIntoInventory(container.getConnectedFluidInventory(), extractedFluids.getStacks(), Action.SIMULATE);
canInsertFullAmount = container.insertFluidsIntoInventory(extractedFluids.getStacks(), Action.SIMULATE);
}
} else {
break;
@@ -151,8 +151,8 @@ public class ProcessingNode extends Node {
extractedItems = IoUtil.extractFromInternalItemStorage(requirements.getSingleItemRequirementSet(false), internalStorage, Action.PERFORM);
extractedFluids = IoUtil.extractFromInternalFluidStorage(requirements.getSingleFluidRequirementSet(false), internalFluidStorage, Action.PERFORM);
IoUtil.insertIntoInventory(container.getConnectedInventory(), extractedItems.getStacks(), Action.PERFORM);
IoUtil.insertIntoInventory(container.getConnectedFluidInventory(), extractedFluids.getStacks(), Action.PERFORM);
container.insertItemsIntoInventory(extractedItems.getStacks(), Action.PERFORM);
container.insertFluidsIntoInventory(extractedFluids.getStacks(), Action.PERFORM);
next();

View File

@@ -38,6 +38,7 @@ import java.util.Optional;
import java.util.UUID;
public class CrafterNetworkNode extends NetworkNode implements ICraftingPatternContainer {
public enum CrafterMode {
IGNORE,
SIGNAL_UNLOCKS_AUTOCRAFTING,
@@ -467,4 +468,5 @@ public class CrafterNetworkNode extends NetworkNode implements ICraftingPatternC
markDirty();
}
}
}