mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-12-05 00:38:35 +01:00
pass active crafts when started
This commit is contained in:
parent
805393ba6e
commit
0eb8740fde
7 changed files with 151 additions and 129 deletions
|
@ -2,6 +2,7 @@ package de.ellpeck.prettypipes.items;
|
||||||
|
|
||||||
import de.ellpeck.prettypipes.misc.DirectionSelector;
|
import de.ellpeck.prettypipes.misc.DirectionSelector;
|
||||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||||
|
import de.ellpeck.prettypipes.network.ActiveCraft;
|
||||||
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
|
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
|
||||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -10,7 +11,9 @@ import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
import net.neoforged.neoforge.items.IItemHandler;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -41,7 +44,7 @@ public interface IModule {
|
||||||
|
|
||||||
int getCraftableAmount(ItemStack module, PipeBlockEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain);
|
int getCraftableAmount(ItemStack module, PipeBlockEntity tile, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain);
|
||||||
|
|
||||||
ItemStack craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain);
|
Pair<ItemStack, Collection<ActiveCraft>> craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain);
|
||||||
|
|
||||||
Integer getCustomNextNode(ItemStack module, PipeBlockEntity tile, List<BlockPos> nodes, int index);
|
Integer getCustomNextNode(ItemStack module, PipeBlockEntity tile, List<BlockPos> nodes, int index);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package de.ellpeck.prettypipes.items;
|
||||||
import de.ellpeck.prettypipes.Utility;
|
import de.ellpeck.prettypipes.Utility;
|
||||||
import de.ellpeck.prettypipes.misc.DirectionSelector;
|
import de.ellpeck.prettypipes.misc.DirectionSelector;
|
||||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||||
|
import de.ellpeck.prettypipes.network.ActiveCraft;
|
||||||
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
|
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
|
||||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -16,7 +17,9 @@ import net.minecraft.world.item.TooltipFlag;
|
||||||
import net.neoforged.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
import net.neoforged.api.distmarker.OnlyIn;
|
import net.neoforged.api.distmarker.OnlyIn;
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
import net.neoforged.neoforge.items.IItemHandler;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
@ -89,8 +92,8 @@ public abstract class ModuleItem extends Item implements IModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
|
public Pair<ItemStack, Collection<ActiveCraft>> craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
|
||||||
return stack;
|
return Pair.of(stack, List.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package de.ellpeck.prettypipes.network;
|
||||||
|
|
||||||
|
import de.ellpeck.prettypipes.Utility;
|
||||||
|
import de.ellpeck.prettypipes.misc.ItemEquality;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.HolderLookup;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.neoforged.neoforge.common.util.INBTSerializable;
|
||||||
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ActiveCraft implements INBTSerializable<CompoundTag> {
|
||||||
|
|
||||||
|
public List<ItemStack> travelingIngredients = new ArrayList<>();
|
||||||
|
public List<NetworkLock> ingredientsToRequest;
|
||||||
|
public BlockPos resultDestPipe;
|
||||||
|
public ItemStack resultStackRemain;
|
||||||
|
public boolean inProgress;
|
||||||
|
// we only remove canceled requests from the queue once their items are fully delivered to the crafting location, so that unfinished recipes don't get stuck in crafters etc.
|
||||||
|
public boolean canceled;
|
||||||
|
|
||||||
|
public ActiveCraft(List<NetworkLock> ingredientsToRequest, BlockPos resultDestPipe, ItemStack resultStackRemain) {
|
||||||
|
this.ingredientsToRequest = ingredientsToRequest;
|
||||||
|
this.resultDestPipe = resultDestPipe;
|
||||||
|
this.resultStackRemain = resultStackRemain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveCraft(HolderLookup.Provider provider, CompoundTag tag) {
|
||||||
|
this.deserializeNBT(provider, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @UnknownNullability CompoundTag serializeNBT(HolderLookup.Provider provider) {
|
||||||
|
var ret = new CompoundTag();
|
||||||
|
ret.put("ingredients_to_request", Utility.serializeAll(this.ingredientsToRequest, n -> n.serializeNBT(provider)));
|
||||||
|
ret.put("traveling_ingredients", Utility.serializeAll(this.travelingIngredients, s -> (CompoundTag) s.save(provider, new CompoundTag())));
|
||||||
|
ret.putLong("result_dest_pipe", this.resultDestPipe.asLong());
|
||||||
|
ret.put("result_stack_remain", this.resultStackRemain.saveOptional(provider));
|
||||||
|
ret.putBoolean("in_progress", this.inProgress);
|
||||||
|
ret.putBoolean("canceled", this.canceled);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserializeNBT(HolderLookup.Provider provider, CompoundTag nbt) {
|
||||||
|
this.ingredientsToRequest = Utility.deserializeAll(nbt.getList("ingredients_to_request", Tag.TAG_COMPOUND), t -> new NetworkLock(provider, t));
|
||||||
|
this.travelingIngredients = Utility.deserializeAll(nbt.getList("traveling_ingredients", Tag.TAG_COMPOUND), t -> ItemStack.parse(provider, t).orElseThrow());
|
||||||
|
this.resultDestPipe = BlockPos.of(nbt.getLong("result_dest_pipe"));
|
||||||
|
this.resultStackRemain = ItemStack.parseOptional(provider, nbt.getCompound("result_stack_remain"));
|
||||||
|
this.inProgress = nbt.getBoolean("in_progress");
|
||||||
|
this.canceled = nbt.getBoolean("canceled");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack getTravelingIngredient(ItemStack stack, ItemEquality... equalityTypes) {
|
||||||
|
for (var traveling : this.travelingIngredients) {
|
||||||
|
if (ItemEquality.compareItems(stack, traveling, equalityTypes))
|
||||||
|
return traveling;
|
||||||
|
}
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean markCanceledOrResolve(PipeNetwork network) {
|
||||||
|
if (this.inProgress) {
|
||||||
|
this.canceled = true;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
for (var lock : this.ingredientsToRequest)
|
||||||
|
network.resolveNetworkLock(lock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import net.minecraft.world.level.saveddata.SavedData;
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
import net.neoforged.neoforge.items.IItemHandler;
|
||||||
import net.neoforged.neoforge.network.PacketDistributor;
|
import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.apache.commons.lang3.tuple.Triple;
|
||||||
import org.jgrapht.ListenableGraph;
|
import org.jgrapht.ListenableGraph;
|
||||||
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
||||||
import org.jgrapht.event.GraphEdgeChangeEvent;
|
import org.jgrapht.event.GraphEdgeChangeEvent;
|
||||||
|
@ -213,21 +214,58 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
return remain;
|
return remain;
|
||||||
}
|
}
|
||||||
// check craftable items
|
// check craftable items
|
||||||
return this.requestCraftedItem(destPipe, null, remain, new Stack<>(), equalityTypes);
|
return this.requestCraftedItem(destPipe, null, remain, new Stack<>(), equalityTypes).getLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack requestCraftedItem(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
|
public Triple<List<NetworkLock>, ItemStack, Collection<ActiveCraft>> requestLocksAndCrafts(BlockPos destPipe, Collection<NetworkLocation> locations, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
|
||||||
|
List<NetworkLock> requests = new ArrayList<>();
|
||||||
|
var remain = stack.copy();
|
||||||
|
// check for existing items
|
||||||
|
for (var location : locations) {
|
||||||
|
var amount = location.getItemAmount(this.level, stack, equalityTypes);
|
||||||
|
if (amount <= 0)
|
||||||
|
continue;
|
||||||
|
amount -= this.getLockedAmount(location.getPos(), stack, null, equalityTypes);
|
||||||
|
if (amount > 0) {
|
||||||
|
if (remain.getCount() < amount)
|
||||||
|
amount = remain.getCount();
|
||||||
|
remain.shrink(amount);
|
||||||
|
while (amount > 0) {
|
||||||
|
var copy = stack.copy();
|
||||||
|
copy.setCount(Math.min(stack.getMaxStackSize(), amount));
|
||||||
|
var lock = new NetworkLock(location, copy);
|
||||||
|
this.createNetworkLock(lock);
|
||||||
|
requests.add(lock);
|
||||||
|
amount -= copy.getCount();
|
||||||
|
}
|
||||||
|
if (remain.isEmpty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!remain.isEmpty()) {
|
||||||
|
// check for craftable items
|
||||||
|
var started = this.requestCraftedItem(destPipe, unavailableConsumer, remain, dependencyChain, equalityTypes);
|
||||||
|
return Triple.of(requests, started.getLeft(), started.getRight());
|
||||||
|
} else {
|
||||||
|
return Triple.of(requests, remain, List.of());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<ItemStack, Collection<ActiveCraft>> requestCraftedItem(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
|
||||||
|
var crafts = new ArrayList<ActiveCraft>();
|
||||||
for (var craftable : this.getAllCraftables(destPipe)) {
|
for (var craftable : this.getAllCraftables(destPipe)) {
|
||||||
if (!ItemEquality.compareItems(stack, craftable.getRight(), equalityTypes))
|
if (!ItemEquality.compareItems(stack, craftable.getRight(), equalityTypes))
|
||||||
continue;
|
continue;
|
||||||
var pipe = this.getPipe(craftable.getLeft());
|
var pipe = this.getPipe(craftable.getLeft());
|
||||||
if (pipe == null)
|
if (pipe == null)
|
||||||
continue;
|
continue;
|
||||||
stack = pipe.craft(destPipe, unavailableConsumer, stack, dependencyChain);
|
var started = pipe.craft(destPipe, unavailableConsumer, stack, dependencyChain);
|
||||||
|
stack = started.getLeft();
|
||||||
|
crafts.addAll(started.getRight());
|
||||||
if (stack.isEmpty())
|
if (stack.isEmpty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return stack;
|
return Pair.of(stack, crafts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, NetworkLock ignoredLock, ItemStack stack, ItemEquality... equalityTypes) {
|
public ItemStack requestExistingItem(NetworkLocation location, BlockPos destPipe, BlockPos destInventory, NetworkLock ignoredLock, ItemStack stack, ItemEquality... equalityTypes) {
|
||||||
|
|
|
@ -5,10 +5,9 @@ import de.ellpeck.prettypipes.Registry;
|
||||||
import de.ellpeck.prettypipes.Utility;
|
import de.ellpeck.prettypipes.Utility;
|
||||||
import de.ellpeck.prettypipes.items.IModule;
|
import de.ellpeck.prettypipes.items.IModule;
|
||||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||||
import de.ellpeck.prettypipes.network.NetworkLock;
|
import de.ellpeck.prettypipes.network.ActiveCraft;
|
||||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||||
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
|
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
|
||||||
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleItem;
|
|
||||||
import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity;
|
import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
|
@ -42,7 +41,6 @@ import net.neoforged.neoforge.items.IItemHandler;
|
||||||
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.commons.lang3.tuple.Triple;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -72,7 +70,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
PipeBlockEntity.this.setChanged();
|
PipeBlockEntity.this.setChanged();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public final List<Pair<Integer, CraftingModuleItem.ActiveCraft>> activeCrafts = new ArrayList<>();
|
public final List<Pair<Integer, ActiveCraft>> activeCrafts = new ArrayList<>();
|
||||||
public PressurizerBlockEntity pressurizer;
|
public PressurizerBlockEntity pressurizer;
|
||||||
public BlockState cover;
|
public BlockState cover;
|
||||||
public int moduleDropCheck;
|
public int moduleDropCheck;
|
||||||
|
@ -120,7 +118,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
var crafts = compound.getList("active_crafts", Tag.TAG_COMPOUND);
|
var crafts = compound.getList("active_crafts", Tag.TAG_COMPOUND);
|
||||||
for (var i = 0; i < crafts.size(); i++) {
|
for (var i = 0; i < crafts.size(); i++) {
|
||||||
var tag = crafts.getCompound(i);
|
var tag = crafts.getCompound(i);
|
||||||
this.activeCrafts.add(Pair.of(tag.getInt("module_slot"), new CraftingModuleItem.ActiveCraft(provider, tag.getCompound("data"))));
|
this.activeCrafts.add(Pair.of(tag.getInt("module_slot"), new ActiveCraft(provider, tag.getCompound("data"))));
|
||||||
}
|
}
|
||||||
super.loadAdditional(compound, provider);
|
super.loadAdditional(compound, provider);
|
||||||
}
|
}
|
||||||
|
@ -296,15 +294,18 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
|
public Pair<ItemStack, Collection<ActiveCraft>> craft(BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
|
||||||
|
var crafts = new ArrayList<ActiveCraft>();
|
||||||
var modules = this.streamModules().iterator();
|
var modules = this.streamModules().iterator();
|
||||||
while (modules.hasNext()) {
|
while (modules.hasNext()) {
|
||||||
var module = modules.next();
|
var module = modules.next();
|
||||||
stack = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack, dependencyChain);
|
var started = module.getRight().craft(module.getLeft(), this, destPipe, unavailableConsumer, stack, dependencyChain);
|
||||||
|
stack = started.getLeft();
|
||||||
|
crafts.addAll(started.getRight());
|
||||||
if (stack.isEmpty())
|
if (stack.isEmpty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return stack;
|
return Pair.of(stack, crafts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IItemHandler getItemHandler(Direction dir) {
|
public IItemHandler getItemHandler(Direction dir) {
|
||||||
|
|
|
@ -7,9 +7,9 @@ import de.ellpeck.prettypipes.Utility;
|
||||||
import de.ellpeck.prettypipes.items.IModule;
|
import de.ellpeck.prettypipes.items.IModule;
|
||||||
import de.ellpeck.prettypipes.items.ModuleItem;
|
import de.ellpeck.prettypipes.items.ModuleItem;
|
||||||
import de.ellpeck.prettypipes.items.ModuleTier;
|
import de.ellpeck.prettypipes.items.ModuleTier;
|
||||||
import de.ellpeck.prettypipes.misc.EquatableItemStack;
|
|
||||||
import de.ellpeck.prettypipes.misc.ItemEquality;
|
import de.ellpeck.prettypipes.misc.ItemEquality;
|
||||||
import de.ellpeck.prettypipes.misc.ItemFilter;
|
import de.ellpeck.prettypipes.misc.ItemFilter;
|
||||||
|
import de.ellpeck.prettypipes.network.ActiveCraft;
|
||||||
import de.ellpeck.prettypipes.network.NetworkLock;
|
import de.ellpeck.prettypipes.network.NetworkLock;
|
||||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||||
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
|
import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
|
||||||
|
@ -18,21 +18,15 @@ import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
|
||||||
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity;
|
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.core.HolderLookup;
|
|
||||||
import net.minecraft.core.component.DataComponentType;
|
import net.minecraft.core.component.DataComponentType;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.nbt.Tag;
|
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.neoforged.neoforge.common.util.INBTSerializable;
|
|
||||||
import net.neoforged.neoforge.items.IItemHandler;
|
import net.neoforged.neoforge.items.IItemHandler;
|
||||||
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.apache.commons.lang3.tuple.Triple;
|
|
||||||
import org.jetbrains.annotations.UnknownNullability;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -174,11 +168,11 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
|
public Pair<ItemStack, Collection<ActiveCraft>> craft(ItemStack module, PipeBlockEntity tile, BlockPos destPipe, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
|
||||||
// check if we can craft the required amount of items
|
// check if we can craft the required amount of items
|
||||||
var craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack, dependencyChain);
|
var craftableAmount = this.getCraftableAmount(module, tile, unavailableConsumer, stack, dependencyChain);
|
||||||
if (craftableAmount <= 0)
|
if (craftableAmount <= 0)
|
||||||
return stack;
|
return Pair.of(stack, List.of());
|
||||||
var slot = tile.getModuleSlot(module);
|
var slot = tile.getModuleSlot(module);
|
||||||
|
|
||||||
var network = PipeNetwork.get(tile.getLevel());
|
var network = PipeNetwork.get(tile.getLevel());
|
||||||
|
@ -192,6 +186,7 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
var toCraft = Math.min(craftableCrafts, requiredCrafts);
|
var toCraft = Math.min(craftableCrafts, requiredCrafts);
|
||||||
|
|
||||||
var locks = new ArrayList<NetworkLock>();
|
var locks = new ArrayList<NetworkLock>();
|
||||||
|
var crafts = new ArrayList<ActiveCraft>();
|
||||||
var contents = module.get(Contents.TYPE);
|
var contents = module.get(Contents.TYPE);
|
||||||
// if we're ensuring item order, all items for a single recipe should be sent in order first before starting on the next one!
|
// if we're ensuring item order, all items for a single recipe should be sent in order first before starting on the next one!
|
||||||
for (var c = contents.ensureItemOrder ? toCraft : 1; c > 0; c--) {
|
for (var c = contents.ensureItemOrder ? toCraft : 1; c > 0; c--) {
|
||||||
|
@ -202,8 +197,9 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
var copy = in.copy();
|
var copy = in.copy();
|
||||||
if (!contents.ensureItemOrder)
|
if (!contents.ensureItemOrder)
|
||||||
copy.setCount(in.getCount() * toCraft);
|
copy.setCount(in.getCount() * toCraft);
|
||||||
var ret = ItemTerminalBlockEntity.requestItemLater(tile.getLevel(), tile.getBlockPos(), items, unavailableConsumer, copy, CraftingModuleItem.addDependency(dependencyChain, module), equalityTypes);
|
var ret = network.requestLocksAndCrafts(tile.getBlockPos(), items, unavailableConsumer, copy, CraftingModuleItem.addDependency(dependencyChain, module), equalityTypes);
|
||||||
locks.addAll(ret.getLeft());
|
locks.addAll(ret.getLeft());
|
||||||
|
crafts.addAll(ret.getRight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,10 +208,11 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
var result = stack.copy();
|
var result = stack.copy();
|
||||||
result.shrink(remain.getCount());
|
result.shrink(remain.getCount());
|
||||||
|
|
||||||
var activeCraft = new ActiveCraft(locks, new ArrayList<>(), destPipe, result);
|
var activeCraft = new ActiveCraft(locks, destPipe, result);
|
||||||
tile.activeCrafts.add(Pair.of(slot, activeCraft));
|
tile.activeCrafts.add(Pair.of(slot, activeCraft));
|
||||||
|
crafts.add(activeCraft);
|
||||||
|
|
||||||
return remain;
|
return Pair.of(remain, crafts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -277,68 +274,4 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ActiveCraft implements INBTSerializable<CompoundTag> {
|
|
||||||
|
|
||||||
public List<NetworkLock> ingredientsToRequest;
|
|
||||||
public List<ItemStack> travelingIngredients;
|
|
||||||
public BlockPos resultDestPipe;
|
|
||||||
public ItemStack resultStackRemain;
|
|
||||||
public boolean inProgress;
|
|
||||||
// we only remove canceled requests from the queue once their items are fully delivered to the crafting location, so that unfinished recipes don't get stuck in crafters etc.
|
|
||||||
public boolean canceled;
|
|
||||||
|
|
||||||
public ActiveCraft(List<NetworkLock> ingredientsToRequest, List<ItemStack> travelingIngredients, BlockPos resultDestPipe, ItemStack resultStackRemain) {
|
|
||||||
this.ingredientsToRequest = ingredientsToRequest;
|
|
||||||
this.travelingIngredients = travelingIngredients;
|
|
||||||
this.resultDestPipe = resultDestPipe;
|
|
||||||
this.resultStackRemain = resultStackRemain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActiveCraft(HolderLookup.Provider provider, CompoundTag tag) {
|
|
||||||
this.deserializeNBT(provider, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @UnknownNullability CompoundTag serializeNBT(HolderLookup.Provider provider) {
|
|
||||||
var ret = new CompoundTag();
|
|
||||||
ret.put("ingredients_to_request", Utility.serializeAll(this.ingredientsToRequest, n -> n.serializeNBT(provider)));
|
|
||||||
ret.put("traveling_ingredients", Utility.serializeAll(this.travelingIngredients, s -> (CompoundTag) s.save(provider, new CompoundTag())));
|
|
||||||
ret.putLong("result_dest_pipe", this.resultDestPipe.asLong());
|
|
||||||
ret.put("result_stack_remain", this.resultStackRemain.saveOptional(provider));
|
|
||||||
ret.putBoolean("in_progress", this.inProgress);
|
|
||||||
ret.putBoolean("canceled", this.canceled);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deserializeNBT(HolderLookup.Provider provider, CompoundTag nbt) {
|
|
||||||
this.ingredientsToRequest = Utility.deserializeAll(nbt.getList("ingredients_to_request", Tag.TAG_COMPOUND), t -> new NetworkLock(provider, t));
|
|
||||||
this.travelingIngredients = Utility.deserializeAll(nbt.getList("traveling_ingredients", Tag.TAG_COMPOUND), t -> ItemStack.parse(provider, t).orElseThrow());
|
|
||||||
this.resultDestPipe = BlockPos.of(nbt.getLong("result_dest_pipe"));
|
|
||||||
this.resultStackRemain = ItemStack.parseOptional(provider, nbt.getCompound("result_stack_remain"));
|
|
||||||
this.inProgress = nbt.getBoolean("in_progress");
|
|
||||||
this.canceled = nbt.getBoolean("canceled");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemStack getTravelingIngredient(ItemStack stack, ItemEquality... equalityTypes) {
|
|
||||||
for (var traveling : this.travelingIngredients) {
|
|
||||||
if (ItemEquality.compareItems(stack, traveling, equalityTypes))
|
|
||||||
return traveling;
|
|
||||||
}
|
|
||||||
return ItemStack.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean markCanceledOrResolve(PipeNetwork network) {
|
|
||||||
if (this.inProgress) {
|
|
||||||
this.canceled = true;
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
for (var lock : this.ingredientsToRequest)
|
|
||||||
network.resolveNetworkLock(lock);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,7 @@ import de.ellpeck.prettypipes.Registry;
|
||||||
import de.ellpeck.prettypipes.Utility;
|
import de.ellpeck.prettypipes.Utility;
|
||||||
import de.ellpeck.prettypipes.misc.EquatableItemStack;
|
import de.ellpeck.prettypipes.misc.EquatableItemStack;
|
||||||
import de.ellpeck.prettypipes.misc.ItemEquality;
|
import de.ellpeck.prettypipes.misc.ItemEquality;
|
||||||
import de.ellpeck.prettypipes.network.NetworkItem;
|
import de.ellpeck.prettypipes.network.*;
|
||||||
import de.ellpeck.prettypipes.network.NetworkLocation;
|
|
||||||
import de.ellpeck.prettypipes.network.NetworkLock;
|
|
||||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
|
||||||
import de.ellpeck.prettypipes.packets.PacketNetworkItems;
|
import de.ellpeck.prettypipes.packets.PacketNetworkItems;
|
||||||
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
||||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||||
|
@ -35,6 +32,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
import net.neoforged.neoforge.items.ItemHandlerHelper;
|
||||||
import net.neoforged.neoforge.items.ItemStackHandler;
|
import net.neoforged.neoforge.items.ItemStackHandler;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.apache.commons.lang3.tuple.Triple;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -172,9 +170,10 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
|
||||||
public int requestItemImpl(ItemStack stack, Consumer<ItemStack> unavailableConsumer) {
|
public int requestItemImpl(ItemStack stack, Consumer<ItemStack> unavailableConsumer) {
|
||||||
var item = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT));
|
var item = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT));
|
||||||
Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations();
|
Collection<NetworkLocation> locations = item == null ? Collections.emptyList() : item.getLocations();
|
||||||
var ret = ItemTerminalBlockEntity.requestItemLater(this.level, this.getConnectedPipe().getBlockPos(), locations, unavailableConsumer, stack, new Stack<>(), ItemEquality.NBT);
|
var network = PipeNetwork.get(this.level);
|
||||||
|
var ret = network.requestLocksAndCrafts(this.getConnectedPipe().getBlockPos(), locations, unavailableConsumer, stack, new Stack<>(), ItemEquality.NBT);
|
||||||
this.existingRequests.addAll(ret.getLeft());
|
this.existingRequests.addAll(ret.getLeft());
|
||||||
return stack.getCount() - ret.getRight().getCount();
|
return stack.getCount() - ret.getMiddle().getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player[] getLookingPlayers() {
|
public Player[] getLookingPlayers() {
|
||||||
|
@ -269,38 +268,6 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Pair<List<NetworkLock>, ItemStack> requestItemLater(Level world, BlockPos destPipe, Collection<NetworkLocation> locations, Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain, ItemEquality... equalityTypes) {
|
|
||||||
List<NetworkLock> requests = new ArrayList<>();
|
|
||||||
var remain = stack.copy();
|
|
||||||
var network = PipeNetwork.get(world);
|
|
||||||
// check for existing items
|
|
||||||
for (var location : locations) {
|
|
||||||
var amount = location.getItemAmount(world, stack, equalityTypes);
|
|
||||||
if (amount <= 0)
|
|
||||||
continue;
|
|
||||||
amount -= network.getLockedAmount(location.getPos(), stack, null, equalityTypes);
|
|
||||||
if (amount > 0) {
|
|
||||||
if (remain.getCount() < amount)
|
|
||||||
amount = remain.getCount();
|
|
||||||
remain.shrink(amount);
|
|
||||||
while (amount > 0) {
|
|
||||||
var copy = stack.copy();
|
|
||||||
copy.setCount(Math.min(stack.getMaxStackSize(), amount));
|
|
||||||
var lock = new NetworkLock(location, copy);
|
|
||||||
network.createNetworkLock(lock);
|
|
||||||
requests.add(lock);
|
|
||||||
amount -= copy.getCount();
|
|
||||||
}
|
|
||||||
if (remain.isEmpty())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check for craftable items
|
|
||||||
if (!remain.isEmpty())
|
|
||||||
remain = network.requestCraftedItem(destPipe, unavailableConsumer, remain, dependencyChain, equalityTypes);
|
|
||||||
return Pair.of(requests, remain);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Consumer<ItemStack> onItemUnavailable(Player player, boolean ignore) {
|
public static Consumer<ItemStack> onItemUnavailable(Player player, boolean ignore) {
|
||||||
return s -> {
|
return s -> {
|
||||||
if (ignore)
|
if (ignore)
|
||||||
|
|
Loading…
Reference in a new issue