part 2: actual crafting implementation

This commit is contained in:
Ell 2020-10-14 23:39:11 +02:00
parent 8029cc21a0
commit 57c3b13b64
9 changed files with 251 additions and 94 deletions

View file

@ -1,10 +1,12 @@
package de.ellpeck.prettypipes.items;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.IItemHandler;
import java.util.List;
@ -32,4 +34,6 @@ public interface IModule {
boolean canPipeWork(ItemStack module, PipeTileEntity tile);
List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile);
ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes);
}

View file

@ -2,6 +2,7 @@ package de.ellpeck.prettypipes.items;
import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import net.minecraft.client.util.ITooltipFlag;
@ -9,6 +10,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.*;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
@ -79,4 +81,9 @@ public abstract class ModuleItem extends Item implements IModule {
public List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile) {
return Collections.emptyList();
}
@Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
return stack;
}
}

View file

@ -108,7 +108,7 @@ public class ItemFilter extends ItemStackHandler {
}
private boolean isFiltered(ItemStack stack) {
ItemEqualityType[] types = this.getEqualityTypes();
ItemEqualityType[] types = getEqualityTypes(this.pipe);
// also check if any filter increase modules have the item we need
for (ItemStackHandler handler : this.getAllFilters()) {
for (int i = 0; i < handler.getSlots(); i++) {
@ -132,14 +132,6 @@ public class ItemFilter extends ItemStackHandler {
return filters;
}
public ItemEqualityType[] getEqualityTypes() {
return this.pipe.streamModules()
.map(Pair::getRight)
.filter(m -> m instanceof FilterModifierModuleItem)
.map(m -> ((FilterModifierModuleItem) m).type)
.toArray(ItemEqualityType[]::new);
}
public void save() {
if (this.modified) {
this.stack.getOrCreateTag().put("filter", this.serializeNBT());
@ -167,6 +159,14 @@ public class ItemFilter extends ItemStackHandler {
this.modified = true;
}
public static ItemEqualityType[] getEqualityTypes(PipeTileEntity pipe) {
return pipe.streamModules()
.map(Pair::getRight)
.filter(m -> m instanceof FilterModifierModuleItem)
.map(m -> ((FilterModifierModuleItem) m).type)
.toArray(ItemEqualityType[]::new);
}
public interface IFilteredContainer {
ItemFilter getFilter();
}

View file

@ -190,14 +190,14 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
return stack;
ItemStack remain = stack.copy();
for (NetworkLocation location : locations) {
remain = this.requestItem(location, destPipe, destInventory, remain, equalityTypes);
remain = this.requestExistingItem(location, destPipe, destInventory, remain, equalityTypes);
if (remain.isEmpty())
break;
}
return remain;
}
public ItemStack requestItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
if (location.getPos().equals(destInventory))
return stack;
ItemStack remain = stack.copy();

View file

@ -4,6 +4,9 @@ import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeItem;
import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
@ -57,6 +60,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
return 1;
}
};
public final Queue<NetworkLock> craftIngredientRequests = new ArrayDeque<>();
public PressurizerTileEntity pressurizer;
public int moduleDropCheck;
protected List<PipeItem> items;
@ -75,6 +79,7 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
public CompoundNBT write(CompoundNBT compound) {
compound.put("modules", this.modules.serializeNBT());
compound.putInt("module_drop_check", this.moduleDropCheck);
compound.put("requests", Utility.serializeAll(this.craftIngredientRequests));
return super.write(compound);
}
@ -82,6 +87,8 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
public void read(BlockState state, CompoundNBT compound) {
this.modules.deserializeNBT(compound.getCompound("modules"));
this.moduleDropCheck = compound.getInt("module_drop_check");
this.craftIngredientRequests.clear();
this.craftIngredientRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
super.read(state, compound);
}
@ -133,6 +140,26 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
PipeNetwork.get(this.world).clearDestinationCache(this.pos);
}
profiler.endSection();
// request crafting ingredients
if (this.world.getGameTime() % 4 == 0 && !this.craftIngredientRequests.isEmpty()) {
PipeNetwork network = PipeNetwork.get(this.world);
NetworkLock request = this.craftIngredientRequests.remove();
Pair<BlockPos, ItemStack> dest = this.getAvailableDestination(request.stack, true, true);
if (dest != null) {
network.requestExistingItem(request.location, this.getPos(), dest.getLeft(), dest.getRight(), ItemEqualityType.NBT);
network.resolveNetworkLock(request);
// if we couldn't fit all items into the destination, create another request for the rest
ItemStack remain = request.stack.copy();
remain.shrink(dest.getRight().getCount());
if (!remain.isEmpty()) {
NetworkLock remainRequest = new NetworkLock(request.location, remain);
this.craftIngredientRequests.add(remainRequest);
network.createNetworkLock(remainRequest);
}
}
}
}
profiler.startSection("ticking_items");
@ -238,6 +265,17 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
.collect(Collectors.toList());
}
public ItemStack craft(BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
Iterator<Pair<ItemStack, IModule>> modules = this.streamModules().iterator();
while (modules.hasNext()) {
Pair<ItemStack, IModule> module = modules.next();
stack = module.getRight().craft(module.getLeft(), this, destPipe, destInventory, stack, equalityTypes);
if (stack.isEmpty())
break;
}
return stack;
}
public IItemHandler getItemHandler(Direction dir, PipeItem item) {
if (!this.isConnected(dir))
return null;
@ -301,6 +339,9 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
public void remove() {
super.remove();
this.getItems().clear();
PipeNetwork network = PipeNetwork.get(this.world);
for (NetworkLock lock : this.craftIngredientRequests)
network.resolveNetworkLock(lock);
}
@Override

View file

@ -4,13 +4,23 @@ import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.misc.ItemEqualityType;
import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
import de.ellpeck.prettypipes.terminal.CraftingTerminalTileEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.items.ItemStackHandler;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.List;
@ -43,14 +53,60 @@ public class CraftingModuleItem extends ModuleItem {
@Override
public List<ItemStack> getCraftables(ItemStack module, PipeTileEntity tile) {
PipeNetwork network = PipeNetwork.get(tile.getWorld());
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
List<Pair<BlockPos, ItemStack>> craftables = network.getOrderedCraftables(tile.getPos());
ItemEqualityType[] equalityTypes = ItemFilter.getEqualityTypes(tile);
ItemStackHandler output = this.getOutput(module);
List<ItemStack> items = new ArrayList<>();
ItemStackHandler input = this.getInput(module);
List<ItemStack> ret = new ArrayList<>();
for (int i = 0; i < output.getSlots(); i++) {
ItemStack stack = output.getStackInSlot(i);
if (!stack.isEmpty())
items.add(stack);
if (!stack.isEmpty()) {
int availableCrafts = CraftingTerminalTileEntity.getAvailableCrafts(tile.getWorld(), input.getSlots(), input::getStackInSlot, k -> false, s -> items, craftables, null, equalityTypes);
if (availableCrafts > 0) {
ItemStack copy = stack.copy();
copy.setCount(stack.getCount() * availableCrafts);
ret.add(copy);
}
}
}
return ret;
}
@Override
public ItemStack craft(ItemStack module, PipeTileEntity tile, BlockPos destPipe, BlockPos destInventory, ItemStack stack, ItemEqualityType... equalityTypes) {
// check if we can craft the required amount of items
List<ItemStack> craftables = this.getCraftables(module, tile);
int craftableAmount = craftables.stream()
.filter(c -> ItemEqualityType.compareItems(c, stack, equalityTypes))
.mapToInt(ItemStack::getCount).sum();
if (craftableAmount > 0) {
PipeNetwork network = PipeNetwork.get(tile.getWorld());
List<NetworkLocation> items = network.getOrderedNetworkItems(tile.getPos());
List<Pair<BlockPos, ItemStack>> allCraftables = network.getOrderedCraftables(tile.getPos());
int resultAmount = this.getResultAmountPerCraft(module, stack, equalityTypes);
int requiredCrafts = MathHelper.ceil(stack.getCount() / (float) resultAmount);
ItemStackHandler input = this.getInput(module);
for (int i = 0; i < input.getSlots(); i++) {
ItemStack in = input.getStackInSlot(i).copy();
if (in.isEmpty())
continue;
in.setCount(in.getCount() * requiredCrafts);
List<NetworkLock> requests = ItemTerminalTileEntity.requestItemLater(tile.getWorld(), destPipe, destInventory, in, items, allCraftables, equalityTypes);
tile.craftIngredientRequests.addAll(requests);
}
ItemStack remain = stack.copy();
remain.shrink(craftableAmount);
return remain;
} else {
return stack;
}
return items;
}
public ItemStackHandler getInput(ItemStack module) {
@ -74,4 +130,15 @@ public class CraftingModuleItem extends ModuleItem {
if (output != null)
tag.put("output", output.serializeNBT());
}
private int getResultAmountPerCraft(ItemStack module, ItemStack stack, ItemEqualityType... equalityTypes) {
ItemStackHandler output = this.getOutput(module);
int resultAmount = 0;
for (int i = 0; i < output.getSlots(); i++) {
ItemStack out = output.getStackInSlot(i);
if (ItemEqualityType.compareItems(stack, out, equalityTypes))
resultAmount += out.getCount();
}
return resultAmount;
}
}

View file

@ -54,7 +54,7 @@ public class RetrievalModuleItem extends ModuleItem {
Pair<BlockPos, ItemStack> dest = tile.getAvailableDestination(copy, true, this.preventOversending);
if (dest == null)
continue;
if (network.requestItem(tile.getPos(), dest.getLeft(), dest.getRight(), filter.getEqualityTypes()).isEmpty())
if (network.requestItem(tile.getPos(), dest.getLeft(), dest.getRight(), ItemFilter.getEqualityTypes(tile)).isEmpty())
break;
}
}

View file

@ -20,10 +20,13 @@ import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.Pair;
@ -31,6 +34,9 @@ import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
@ -97,45 +103,11 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_crafting");
this.updateItems();
// the highest amount we can craft with the items we have
int lowestAvailable = Integer.MAX_VALUE;
// this is the amount of items required for each ingredient when crafting ONE
Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>();
for (int i = 0; i < this.craftItems.getSlots(); i++) {
ItemStack requested = this.getRequestedCraftItem(i);
if (requested.isEmpty())
continue;
MutableInt amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested), s -> new MutableInt());
amount.add(1);
int fit = requested.getMaxStackSize() - (this.isGhostItem(i) ? 0 : requested.getCount());
if (lowestAvailable > fit)
lowestAvailable = fit;
}
for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
EquatableItemStack stack = entry.getKey();
NetworkItem item = this.networkItems.get(stack);
// total amount of available items of this type
int available = 0;
if (item != null) {
for (NetworkLocation location : item.getLocations()) {
int amount = location.getItemAmount(this.world, stack.stack, ItemEqualityType.NBT);
if (amount <= 0)
continue;
amount -= network.getLockedAmount(location.getPos(), stack.stack, ItemEqualityType.NBT);
available += amount;
}
// divide the total by the amount required to get the amount that
// we have available for each crafting slot that contains this item
available /= entry.getValue().intValue();
if (available < lowestAvailable)
lowestAvailable = available;
} else {
lowestAvailable = 0;
}
if (available <= 0)
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.stack.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), UUID.randomUUID());
}
// get the amount of crafts that we can do
int lowestAvailable = getAvailableCrafts(this.world, this.craftItems.getSlots(), this::getRequestedCraftItem, this::isGhostItem, s -> {
NetworkItem item = this.networkItems.get(s);
return item != null ? item.getLocations() : Collections.emptyList();
}, this.craftables, s -> player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", s.getDisplayName()).setStyle(Style.EMPTY.setFormatting(TextFormatting.RED)), UUID.randomUUID()), ItemEqualityType.NBT);
if (lowestAvailable > 0) {
// if we're limiting the amount, pretend we only have that amount available
if (maxAmount < lowestAvailable)
@ -175,4 +147,54 @@ public class CraftingTerminalTileEntity extends ItemTerminalTileEntity {
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new CraftingTerminalContainer(Registry.craftingTerminalContainer, window, player, this.pos);
}
public static int getAvailableCrafts(World world, int slots, Function<Integer, ItemStack> inputFunction, Predicate<Integer> isGhost, Function<EquatableItemStack, Collection<NetworkLocation>> locationsFunction, List<Pair<BlockPos, ItemStack>> craftables, Consumer<ItemStack> unavailableConsumer, ItemEqualityType... equalityTypes) {
PipeNetwork network = PipeNetwork.get(world);
// the highest amount we can craft with the items we have
int lowestAvailable = Integer.MAX_VALUE;
// this is the amount of items required for each ingredient when crafting ONE
Map<EquatableItemStack, MutableInt> requiredItems = new HashMap<>();
for (int i = 0; i < slots; i++) {
ItemStack requested = inputFunction.apply(i);
if (requested.isEmpty())
continue;
MutableInt amount = requiredItems.computeIfAbsent(new EquatableItemStack(requested), s -> new MutableInt());
amount.add(1);
int fit = requested.getMaxStackSize() - (isGhost.test(i) ? 0 : requested.getCount());
if (lowestAvailable > fit)
lowestAvailable = fit;
}
for (Map.Entry<EquatableItemStack, MutableInt> entry : requiredItems.entrySet()) {
EquatableItemStack stack = entry.getKey();
// total amount of available items of this type
int available = 0;
for (NetworkLocation location : locationsFunction.apply(stack)) {
int amount = location.getItemAmount(world, stack.stack, equalityTypes);
if (amount <= 0)
continue;
amount -= network.getLockedAmount(location.getPos(), stack.stack, equalityTypes);
available += amount;
}
// divide the total by the amount required to get the amount that
// we have available for each crafting slot that contains this item
available /= entry.getValue().intValue();
// check how many craftable items we have and add those on
if (!craftables.isEmpty()) {
int craftable = craftables.stream().map(Pair::getRight)
.filter(c -> ItemEqualityType.compareItems(c, stack.stack))
.mapToInt(ItemStack::getCount).sum();
available += craftable / entry.getValue().intValue();
}
// clamp to lowest available
if (available < lowestAvailable)
lowestAvailable = available;
if (available <= 0 && unavailableConsumer != null)
unavailableConsumer.accept(stack.stack);
}
return lowestAvailable;
}
}

View file

@ -28,6 +28,7 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.Constants.NBT;
@ -40,6 +41,7 @@ import org.apache.commons.lang3.tuple.Triple;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ItemTerminalTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity {
@ -52,7 +54,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
};
public Map<EquatableItemStack, NetworkItem> networkItems;
public List<Pair<BlockPos, ItemStack>> craftables;
private final Queue<NetworkLock> pendingRequests = new ArrayDeque<>();
private final Queue<NetworkLock> existingRequests = new ArrayDeque<>();
protected ItemTerminalTileEntity(TileEntityType<?> tileEntityTypeIn) {
super(tileEntityTypeIn);
@ -85,10 +87,10 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
break;
}
if (!this.pendingRequests.isEmpty()) {
NetworkLock request = this.pendingRequests.remove();
if (!this.existingRequests.isEmpty()) {
NetworkLock request = this.existingRequests.remove();
network.resolveNetworkLock(request);
network.requestItem(request.location, pipe.getPos(), this.pos, request.stack, ItemEqualityType.NBT);
network.requestExistingItem(request.location, pipe.getPos(), this.pos, request.stack, ItemEqualityType.NBT);
update = true;
}
}
@ -104,7 +106,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
public void remove() {
super.remove();
PipeNetwork network = PipeNetwork.get(this.world);
for (NetworkLock lock : this.pendingRequests)
for (NetworkLock lock : this.existingRequests)
network.resolveNetworkLock(lock);
}
@ -151,37 +153,12 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
network.endProfile();
}
protected int requestItemImpl(ItemStack stack) {
PipeNetwork network = PipeNetwork.get(this.world);
EquatableItemStack equatable = new EquatableItemStack(stack);
NetworkItem item = this.networkItems.get(equatable);
if (item != null) {
int remain = stack.getCount();
for (NetworkLocation location : item.getLocations()) {
int amount = location.getItemAmount(this.world, stack, ItemEqualityType.NBT);
if (amount <= 0)
continue;
amount -= network.getLockedAmount(location.getPos(), stack, ItemEqualityType.NBT);
if (amount > 0) {
if (remain < amount)
amount = remain;
remain -= amount;
while (amount > 0) {
ItemStack copy = stack.copy();
copy.setCount(Math.min(stack.getMaxStackSize(), amount));
NetworkLock lock = new NetworkLock(location, copy);
this.pendingRequests.add(lock);
network.createNetworkLock(lock);
amount -= copy.getCount();
}
if (remain <= 0)
break;
}
}
return stack.getCount() - remain;
}
return 0;
public int requestItemImpl(ItemStack stack){
ItemStack remain = stack.copy();
NetworkItem item = this.networkItems.get(new EquatableItemStack(remain));
Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations();
this.existingRequests.addAll(requestItemLater(this.world, this.getConnectedPipe().getPos(), this.pos, remain, locations, this.craftables, ItemEqualityType.NBT));
return stack.getCount() - remain.getCount();
}
protected PlayerEntity[] getLookingPlayers() {
@ -210,15 +187,15 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("items", this.items.serializeNBT());
compound.put("requests", Utility.serializeAll(this.pendingRequests));
compound.put("requests", Utility.serializeAll(this.existingRequests));
return super.write(compound);
}
@Override
public void read(BlockState state, CompoundNBT compound) {
this.items.deserializeNBT(compound.getCompound("items"));
this.pendingRequests.clear();
this.pendingRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
this.existingRequests.clear();
this.existingRequests.addAll(Utility.deserializeAll(compound.getList("requests", NBT.TAG_COMPOUND), NetworkLock::new));
super.read(state, compound);
}
@ -232,4 +209,43 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos);
}
public static List<NetworkLock> requestItemLater(World world, BlockPos destPipe, BlockPos destInventory, ItemStack stack, Collection<NetworkLocation> locations, List<Pair<BlockPos, ItemStack>> craftables, ItemEqualityType... equalityTypes) {
List<NetworkLock> requests = new ArrayList<>();
PipeNetwork network = PipeNetwork.get(world);
// check for existing items
for (NetworkLocation location : locations) {
int amount = location.getItemAmount(world, stack, ItemEqualityType.NBT);
if (amount <= 0)
continue;
amount -= network.getLockedAmount(location.getPos(), stack, ItemEqualityType.NBT);
if (amount > 0) {
if (stack.getCount() < amount)
amount = stack.getCount();
stack.shrink(amount);
while (amount > 0) {
ItemStack copy = stack.copy();
copy.setCount(Math.min(stack.getMaxStackSize(), amount));
NetworkLock lock = new NetworkLock(location, copy);
network.createNetworkLock(lock);
requests.add(lock);
amount -= copy.getCount();
}
if (stack.isEmpty())
break;
}
}
// check for craftable items
for (Pair<BlockPos, ItemStack> craftable : craftables) {
if (!ItemEqualityType.compareItems(stack, craftable.getRight(), equalityTypes))
continue;
PipeTileEntity pipe = network.getPipe(craftable.getLeft());
if (pipe == null)
continue;
stack = pipe.craft(destPipe, destInventory, stack, equalityTypes);
if (stack.isEmpty())
break;
}
return requests;
}
}