mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-12-05 00:38:35 +01:00
Compare commits
6 commits
805393ba6e
...
cee38be5cd
Author | SHA1 | Date | |
---|---|---|---|
cee38be5cd | |||
9fc0c12bf9 | |||
887bfed229 | |||
1b0c36d5e5 | |||
0942be0725 | |||
0eb8740fde |
13 changed files with 283 additions and 225 deletions
|
@ -34,8 +34,9 @@ mod_name=PrettyPipes
|
||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=MIT
|
mod_license=MIT
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=1.18.1
|
mod_version=1.19.0
|
||||||
mod_release_state=STABLE
|
# STABLE, BETA, ALPHA
|
||||||
|
mod_release_state=BETA
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -19,31 +19,37 @@ public final class Events {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onServerStarting(ServerStartingEvent event) {
|
public static void onServerStarting(ServerStartingEvent event) {
|
||||||
event.getServer().getCommands().getDispatcher().register(Commands.literal(PrettyPipes.ID).requires(s -> s.hasPermission(2))
|
event.getServer().getCommands().getDispatcher().register(Commands.literal(PrettyPipes.ID).requires(s -> s.hasPermission(2))
|
||||||
.then(Commands.literal("dump").executes(c -> {
|
.then(Commands.literal("dump").executes(c -> {
|
||||||
var source = c.getSource();
|
var source = c.getSource();
|
||||||
var file = Paths.get('_' + PrettyPipes.ID + "dump.txt");
|
var file = Paths.get('_' + PrettyPipes.ID + "dump.txt");
|
||||||
var dump = PipeNetwork.get(source.getLevel()).toString();
|
var dump = PipeNetwork.get(source.getLevel()).toString();
|
||||||
try {
|
try {
|
||||||
Files.writeString(file, dump, StandardCharsets.UTF_8);
|
Files.writeString(file, dump, StandardCharsets.UTF_8);
|
||||||
source.sendSuccess(() -> Component.literal("Wrote network dump to file " + file.toAbsolutePath()), true);
|
source.sendSuccess(() -> Component.literal("Wrote network dump to file " + file.toAbsolutePath()), true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
source.sendFailure(Component.literal("Failed to write network dump to file " + file.toAbsolutePath()));
|
source.sendFailure(Component.literal("Failed to write network dump to file " + file.toAbsolutePath()));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}))
|
}))
|
||||||
.then(Commands.literal("uncache").executes(c -> {
|
.then(Commands.literal("uncache").executes(c -> {
|
||||||
var source = c.getSource();
|
var source = c.getSource();
|
||||||
PipeNetwork.get(source.getLevel()).clearCaches();
|
PipeNetwork.get(source.getLevel()).clearCaches();
|
||||||
source.sendSuccess(() -> Component.literal("Cleared all pipe caches in the world"), true);
|
source.sendSuccess(() -> Component.literal("Cleared all pipe caches in the world"), true);
|
||||||
return 0;
|
return 0;
|
||||||
}))
|
}))
|
||||||
.then(Commands.literal("unlock").executes(c -> {
|
.then(Commands.literal("unlock").executes(c -> {
|
||||||
var source = c.getSource();
|
var source = c.getSource();
|
||||||
PipeNetwork.get(source.getLevel()).unlock();
|
PipeNetwork.get(source.getLevel()).unlock();
|
||||||
source.sendSuccess(() -> Component.literal("Resolved all network locks in the world"), true);
|
source.sendSuccess(() -> Component.literal("Resolved all network locks in the world"), true);
|
||||||
return 0;
|
return 0;
|
||||||
})));
|
}))
|
||||||
|
.then(Commands.literal("uncraft").executes(c -> {
|
||||||
|
var source = c.getSource();
|
||||||
|
PipeNetwork.get(source.getLevel()).cancelCrafts();
|
||||||
|
source.sendSuccess(() -> Component.literal("Canceled all active crafts in the world"), true);
|
||||||
|
return 0;
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
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 BlockPos pipe;
|
||||||
|
public int moduleSlot;
|
||||||
|
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(BlockPos pipe, int moduleSlot, List<NetworkLock> ingredientsToRequest, BlockPos resultDestPipe, ItemStack resultStackRemain) {
|
||||||
|
this.pipe = pipe;
|
||||||
|
this.moduleSlot = moduleSlot;
|
||||||
|
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.putLong("pipe", this.pipe.asLong());
|
||||||
|
ret.putInt("module_slot", this.moduleSlot);
|
||||||
|
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.pipe = BlockPos.of(nbt.getLong("pipe"));
|
||||||
|
this.moduleSlot = nbt.getInt("module_slot");
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ActiveCraft{" +
|
||||||
|
"pipe=" + this.pipe +
|
||||||
|
", moduleSlot=" + this.moduleSlot +
|
||||||
|
", travelingIngredients=" + this.travelingIngredients +
|
||||||
|
", ingredientsToRequest=" + this.ingredientsToRequest +
|
||||||
|
", resultDestPipe=" + this.resultDestPipe +
|
||||||
|
", resultStackRemain=" + this.resultStackRemain +
|
||||||
|
", inProgress=" + this.inProgress +
|
||||||
|
", canceled=" + this.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, boolean force) {
|
||||||
|
if (force || !this.inProgress) {
|
||||||
|
for (var lock : this.ingredientsToRequest)
|
||||||
|
network.resolveNetworkLock(lock);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this.canceled = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
@ -54,6 +55,7 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
private final Map<BlockPos, PipeBlockEntity> tileCache = new HashMap<>();
|
private final Map<BlockPos, PipeBlockEntity> tileCache = new HashMap<>();
|
||||||
private final ListMultimap<BlockPos, IPipeItem> pipeItems = ArrayListMultimap.create();
|
private final ListMultimap<BlockPos, IPipeItem> pipeItems = ArrayListMultimap.create();
|
||||||
private final ListMultimap<BlockPos, NetworkLock> networkLocks = ArrayListMultimap.create();
|
private final ListMultimap<BlockPos, NetworkLock> networkLocks = ArrayListMultimap.create();
|
||||||
|
private final ListMultimap<BlockPos, ActiveCraft> activeCrafts = ArrayListMultimap.create();
|
||||||
private Level level;
|
private Level level;
|
||||||
|
|
||||||
public PipeNetwork() {
|
public PipeNetwork() {
|
||||||
|
@ -73,6 +75,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
this.pipeItems.put(item.getCurrentPipe(), item);
|
this.pipeItems.put(item.getCurrentPipe(), item);
|
||||||
for (var lock : Utility.deserializeAll(nbt.getList("locks", Tag.TAG_COMPOUND), t -> new NetworkLock(provider, t)))
|
for (var lock : Utility.deserializeAll(nbt.getList("locks", Tag.TAG_COMPOUND), t -> new NetworkLock(provider, t)))
|
||||||
this.createNetworkLock(lock);
|
this.createNetworkLock(lock);
|
||||||
|
for (var craft : Utility.deserializeAll(nbt.getList("crafts", Tag.TAG_COMPOUND), t -> new ActiveCraft(provider, t)))
|
||||||
|
this.activeCrafts.put(craft.pipe, craft);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,12 +104,12 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PipeNetwork{" +
|
return "graph:\n\tnodes: " + this.graph.edgeSet() + "\n\tedges: " + this.graph.edgeSet() +
|
||||||
"\ngraph=" + this.graph +
|
"\nnodeToConnectedNodes:\n" + PipeNetwork.toNewlineDelimitedString(this.nodeToConnectedNodes.entrySet()) +
|
||||||
",\nnodeToConnectedNodes=" + this.nodeToConnectedNodes +
|
"\ntileCache:\n" + PipeNetwork.toNewlineDelimitedString(this.tileCache.keySet()) +
|
||||||
",\ntileCache=" + this.tileCache.keySet() +
|
"\npipeItems:\n" + PipeNetwork.toNewlineDelimitedString(this.pipeItems.entries()) +
|
||||||
",\npipeItems=" + this.pipeItems +
|
"\nnetworkLocks:\n" + PipeNetwork.toNewlineDelimitedString(this.networkLocks.entries()) +
|
||||||
",\nnetworkLocks=" + this.networkLocks + '}';
|
"\nactiveCrafts:\n" + PipeNetwork.toNewlineDelimitedString(this.activeCrafts.entries());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,6 +124,7 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
nbt.put("edges", edges);
|
nbt.put("edges", edges);
|
||||||
nbt.put("items", Utility.serializeAll(this.pipeItems.values(), i -> i.serializeNBT(provider)));
|
nbt.put("items", Utility.serializeAll(this.pipeItems.values(), i -> i.serializeNBT(provider)));
|
||||||
nbt.put("locks", Utility.serializeAll(this.networkLocks.values(), l -> l.serializeNBT(provider)));
|
nbt.put("locks", Utility.serializeAll(this.networkLocks.values(), l -> l.serializeNBT(provider)));
|
||||||
|
nbt.put("crafts", Utility.serializeAll(this.activeCrafts.values(), c -> c.serializeNBT(provider)));
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,21 +218,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>> requestLocksAndStartCrafting(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) {
|
||||||
|
@ -283,18 +325,17 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
var craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator();
|
var craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator();
|
||||||
while (craftingPipes.hasNext()) {
|
while (craftingPipes.hasNext()) {
|
||||||
var pipe = craftingPipes.next();
|
var pipe = craftingPipes.next();
|
||||||
for (var craft : pipe.activeCrafts) {
|
for (var craft : pipe.getActiveCrafts()) {
|
||||||
var data = craft.getRight();
|
if (!includeCanceled && craft.canceled)
|
||||||
if (!includeCanceled && data.canceled)
|
|
||||||
continue;
|
continue;
|
||||||
// add up all the items that should go to the same location
|
// add up all the items that should go to the same location
|
||||||
var existing = items.stream()
|
var existing = items.stream()
|
||||||
.filter(s -> s.getLeft().equals(data.resultDestPipe) && ItemEquality.compareItems(s.getRight(), data.resultStackRemain, equalityTypes))
|
.filter(s -> s.getLeft().equals(craft.resultDestPipe) && ItemEquality.compareItems(s.getRight(), craft.resultStackRemain, equalityTypes))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (existing.isPresent()) {
|
if (existing.isPresent()) {
|
||||||
existing.get().getRight().grow(data.resultStackRemain.getCount());
|
existing.get().getRight().grow(craft.resultStackRemain.getCount());
|
||||||
} else {
|
} else {
|
||||||
items.add(Pair.of(data.resultDestPipe, data.resultStackRemain.copy()));
|
items.add(Pair.of(craft.resultDestPipe, craft.resultStackRemain.copy()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,6 +459,10 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
this.networkLocks.clear();
|
this.networkLocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void cancelCrafts() {
|
||||||
|
this.activeCrafts.entries().removeIf(c -> c.getValue().markCanceledOrResolve(this, true));
|
||||||
|
}
|
||||||
|
|
||||||
private List<NetworkEdge> createAllEdges(BlockPos pos, BlockState state, boolean ignoreCurrBlocked) {
|
private List<NetworkEdge> createAllEdges(BlockPos pos, BlockState state, boolean ignoreCurrBlocked) {
|
||||||
this.startProfile("create_all_edges");
|
this.startProfile("create_all_edges");
|
||||||
List<NetworkEdge> edges = new ArrayList<>();
|
List<NetworkEdge> edges = new ArrayList<>();
|
||||||
|
@ -496,7 +541,7 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
this.startProfile("clear_node_cache");
|
this.startProfile("clear_node_cache");
|
||||||
// remove caches for the nodes
|
// remove caches for the nodes
|
||||||
for (var node : nodes)
|
for (var node : nodes)
|
||||||
this.nodeToConnectedNodes.keySet().remove(node);
|
this.nodeToConnectedNodes.remove(node);
|
||||||
// remove caches that contain the nodes as a destination
|
// remove caches that contain the nodes as a destination
|
||||||
this.nodeToConnectedNodes.values().removeIf(cached -> nodes.stream().anyMatch(cached::contains));
|
this.nodeToConnectedNodes.values().removeIf(cached -> nodes.stream().anyMatch(cached::contains));
|
||||||
this.endProfile();
|
this.endProfile();
|
||||||
|
@ -506,6 +551,10 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
return this.pipeItems.get(pos);
|
return this.pipeItems.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ActiveCraft> getActiveCrafts(BlockPos pos) {
|
||||||
|
return this.activeCrafts.get(pos);
|
||||||
|
}
|
||||||
|
|
||||||
public Stream<IPipeItem> getPipeItemsOnTheWay(BlockPos goalInv) {
|
public Stream<IPipeItem> getPipeItemsOnTheWay(BlockPos goalInv) {
|
||||||
this.startProfile("get_pipe_items_on_the_way");
|
this.startProfile("get_pipe_items_on_the_way");
|
||||||
var ret = this.pipeItems.values().stream().filter(i -> i.getDestInventory().equals(goalInv));
|
var ret = this.pipeItems.values().stream().filter(i -> i.getDestInventory().equals(goalInv));
|
||||||
|
@ -544,4 +593,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String toNewlineDelimitedString(Collection<?> collection) {
|
||||||
|
return collection.stream().map(c -> "\t" + c.toString()).collect(Collectors.joining("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ public record PacketButton(BlockPos pos, int result, List<Integer> data) impleme
|
||||||
}),
|
}),
|
||||||
CANCEL_CRAFTING((pos, data, player) -> {
|
CANCEL_CRAFTING((pos, data, player) -> {
|
||||||
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level(), pos);
|
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level(), pos);
|
||||||
tile.cancelCrafting();
|
tile.cancelCrafting(data.getFirst() == 1);
|
||||||
}),
|
}),
|
||||||
TAG_FILTER((pos, data, player) -> {
|
TAG_FILTER((pos, data, player) -> {
|
||||||
var container = (FilterModifierModuleContainer) player.containerMenu;
|
var container = (FilterModifierModuleContainer) player.containerMenu;
|
||||||
|
|
|
@ -270,8 +270,8 @@ public class PipeBlock extends BaseEntityBlock implements SimpleWaterloggedBlock
|
||||||
network.onPipeChanged(pos, state);
|
network.onPipeChanged(pos, state);
|
||||||
if (worldIn.getBlockEntity(pos) instanceof PipeBlockEntity pipe) {
|
if (worldIn.getBlockEntity(pos) instanceof PipeBlockEntity pipe) {
|
||||||
pipe.getItems().clear();
|
pipe.getItems().clear();
|
||||||
for (var craft : pipe.activeCrafts) {
|
for (var craft : pipe.getActiveCrafts()) {
|
||||||
for (var lock : craft.getRight().ingredientsToRequest)
|
for (var lock : craft.ingredientsToRequest)
|
||||||
network.resolveNetworkLock(lock);
|
network.resolveNetworkLock(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,11 +70,11 @@ 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 PressurizerBlockEntity pressurizer;
|
public PressurizerBlockEntity pressurizer;
|
||||||
public BlockState cover;
|
public BlockState cover;
|
||||||
public int moduleDropCheck;
|
public int moduleDropCheck;
|
||||||
protected List<IPipeItem> items;
|
private List<IPipeItem> itemCache;
|
||||||
|
private List<ActiveCraft> activeCraftCache;
|
||||||
private int lastItemAmount;
|
private int lastItemAmount;
|
||||||
private int priority;
|
private int priority;
|
||||||
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
|
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
|
||||||
|
@ -101,14 +99,6 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
compound.putInt("module_drop_check", this.moduleDropCheck);
|
compound.putInt("module_drop_check", this.moduleDropCheck);
|
||||||
if (this.cover != null)
|
if (this.cover != null)
|
||||||
compound.put("cover", NbtUtils.writeBlockState(this.cover));
|
compound.put("cover", NbtUtils.writeBlockState(this.cover));
|
||||||
var crafts = new ListTag();
|
|
||||||
for (var craft : this.activeCrafts) {
|
|
||||||
var tag = new CompoundTag();
|
|
||||||
tag.putInt("module_slot", craft.getLeft());
|
|
||||||
tag.put("data", craft.getRight().serializeNBT(provider));
|
|
||||||
crafts.add(tag);
|
|
||||||
}
|
|
||||||
compound.put("active_crafts", crafts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,12 +106,6 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
this.modules.deserializeNBT(provider, compound.getCompound("modules"));
|
this.modules.deserializeNBT(provider, compound.getCompound("modules"));
|
||||||
this.moduleDropCheck = compound.getInt("module_drop_check");
|
this.moduleDropCheck = compound.getInt("module_drop_check");
|
||||||
this.cover = compound.contains("cover") ? NbtUtils.readBlockState(this.level != null ? this.level.holderLookup(Registries.BLOCK) : BuiltInRegistries.BLOCK.asLookup(), compound.getCompound("cover")) : null;
|
this.cover = compound.contains("cover") ? NbtUtils.readBlockState(this.level != null ? this.level.holderLookup(Registries.BLOCK) : BuiltInRegistries.BLOCK.asLookup(), compound.getCompound("cover")) : null;
|
||||||
this.activeCrafts.clear();
|
|
||||||
var crafts = compound.getList("active_crafts", Tag.TAG_COMPOUND);
|
|
||||||
for (var i = 0; i < crafts.size(); i++) {
|
|
||||||
var tag = crafts.getCompound(i);
|
|
||||||
this.activeCrafts.add(Pair.of(tag.getInt("module_slot"), new CraftingModuleItem.ActiveCraft(provider, tag.getCompound("data"))));
|
|
||||||
}
|
|
||||||
super.loadAdditional(compound, provider);
|
super.loadAdditional(compound, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,9 +131,15 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IPipeItem> getItems() {
|
public List<IPipeItem> getItems() {
|
||||||
if (this.items == null)
|
if (this.itemCache == null)
|
||||||
this.items = PipeNetwork.get(this.level).getItemsInPipe(this.worldPosition);
|
this.itemCache = PipeNetwork.get(this.level).getItemsInPipe(this.worldPosition);
|
||||||
return this.items;
|
return this.itemCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActiveCraft> getActiveCrafts() {
|
||||||
|
if (this.activeCraftCache == null)
|
||||||
|
this.activeCraftCache = PipeNetwork.get(this.level).getActiveCrafts(this.worldPosition);
|
||||||
|
return this.activeCraftCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNewItem(IPipeItem item) {
|
public void addNewItem(IPipeItem item) {
|
||||||
|
@ -296,15 +286,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,32 +7,25 @@ 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;
|
||||||
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
import de.ellpeck.prettypipes.pipe.containers.AbstractPipeContainer;
|
||||||
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
|
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
|
||||||
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;
|
||||||
|
@ -77,15 +70,14 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
return;
|
return;
|
||||||
var slot = tile.getModuleSlot(module);
|
var slot = tile.getModuleSlot(module);
|
||||||
var network = PipeNetwork.get(tile.getLevel());
|
var network = PipeNetwork.get(tile.getLevel());
|
||||||
if (!tile.activeCrafts.isEmpty()) {
|
var crafts = tile.getActiveCrafts();
|
||||||
var activeCraft = tile.activeCrafts.getFirst();
|
if (!crafts.isEmpty()) {
|
||||||
if (activeCraft.getLeft() == slot) {
|
var craft = crafts.getFirst();
|
||||||
var craftData = activeCraft.getRight();
|
if (craft.moduleSlot == slot) {
|
||||||
|
|
||||||
// process crafting ingredient requests
|
// process crafting ingredient requests
|
||||||
if (!craftData.ingredientsToRequest.isEmpty()) {
|
if (!craft.ingredientsToRequest.isEmpty()) {
|
||||||
network.startProfile("crafting_ingredients");
|
network.startProfile("crafting_ingredients");
|
||||||
var lock = craftData.ingredientsToRequest.getFirst();
|
var lock = craft.ingredientsToRequest.getFirst();
|
||||||
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||||
var dest = tile.getAvailableDestination(Direction.values(), lock.stack, true, true);
|
var dest = tile.getAvailableDestination(Direction.values(), lock.stack, true, true);
|
||||||
if (dest != null) {
|
if (dest != null) {
|
||||||
|
@ -94,12 +86,12 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
if (!ensureItemOrder || network.getPipeItemsOnTheWay(dest.getLeft()).findAny().isEmpty()) {
|
if (!ensureItemOrder || network.getPipeItemsOnTheWay(dest.getLeft()).findAny().isEmpty()) {
|
||||||
var requestRemain = network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes);
|
var requestRemain = network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes);
|
||||||
network.resolveNetworkLock(lock);
|
network.resolveNetworkLock(lock);
|
||||||
craftData.ingredientsToRequest.remove(lock);
|
craft.ingredientsToRequest.remove(lock);
|
||||||
craftData.inProgress = true;
|
craft.inProgress = true;
|
||||||
|
|
||||||
var traveling = lock.stack.copy();
|
var traveling = lock.stack.copy();
|
||||||
traveling.shrink(requestRemain.getCount());
|
traveling.shrink(requestRemain.getCount());
|
||||||
craftData.travelingIngredients.add(traveling);
|
craft.travelingIngredients.add(traveling);
|
||||||
|
|
||||||
// if we couldn't fit all items into the destination, create another request for the rest
|
// if we couldn't fit all items into the destination, create another request for the rest
|
||||||
var remain = lock.stack.copy();
|
var remain = lock.stack.copy();
|
||||||
|
@ -107,8 +99,8 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
if (!remain.isEmpty()) {
|
if (!remain.isEmpty()) {
|
||||||
var remainRequest = new NetworkLock(lock.location, remain);
|
var remainRequest = new NetworkLock(lock.location, remain);
|
||||||
// if we're ensuring item order, we need to insert the remaining request at the start so that it gets processed first
|
// if we're ensuring item order, we need to insert the remaining request at the start so that it gets processed first
|
||||||
var index = ensureItemOrder ? 0 : craftData.ingredientsToRequest.size();
|
var index = ensureItemOrder ? 0 : craft.ingredientsToRequest.size();
|
||||||
craftData.ingredientsToRequest.add(index, remainRequest);
|
craft.ingredientsToRequest.add(index, remainRequest);
|
||||||
network.createNetworkLock(remainRequest);
|
network.createNetworkLock(remainRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,19 +109,19 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull requested crafting results from the network once they are stored
|
// pull requested crafting results from the network once they are stored
|
||||||
if (!craftData.resultStackRemain.isEmpty()) {
|
if (!craft.resultStackRemain.isEmpty()) {
|
||||||
network.startProfile("crafting_results");
|
network.startProfile("crafting_results");
|
||||||
var items = network.getOrderedNetworkItems(tile.getBlockPos());
|
var items = network.getOrderedNetworkItems(tile.getBlockPos());
|
||||||
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||||
var destPipe = network.getPipe(craftData.resultDestPipe);
|
var destPipe = network.getPipe(craft.resultDestPipe);
|
||||||
if (destPipe != null) {
|
if (destPipe != null) {
|
||||||
var dest = destPipe.getAvailableDestinationOrConnectable(craftData.resultStackRemain, true, true);
|
var dest = destPipe.getAvailableDestinationOrConnectable(craft.resultStackRemain, true, true);
|
||||||
if (dest != null) {
|
if (dest != null) {
|
||||||
for (var item : items) {
|
for (var item : items) {
|
||||||
var requestRemain = network.requestExistingItem(item, craftData.resultDestPipe, dest.getLeft(), null, dest.getRight(), equalityTypes);
|
var requestRemain = network.requestExistingItem(item, craft.resultDestPipe, dest.getLeft(), null, dest.getRight(), equalityTypes);
|
||||||
craftData.resultStackRemain.shrink(dest.getRight().getCount() - requestRemain.getCount());
|
craft.resultStackRemain.shrink(dest.getRight().getCount() - requestRemain.getCount());
|
||||||
if (craftData.resultStackRemain.isEmpty()) {
|
if (craft.resultStackRemain.isEmpty()) {
|
||||||
tile.activeCrafts.remove(activeCraft);
|
crafts.remove(craft);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,11 +166,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 +184,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,32 +195,37 @@ 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.requestLocksAndStartCrafting(tile.getBlockPos(), items, unavailableConsumer, copy, CraftingModuleItem.addDependency(dependencyChain, module), equalityTypes);
|
||||||
locks.addAll(ret.getLeft());
|
locks.addAll(ret.getLeft());
|
||||||
|
crafts.addAll(ret.getRight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// set crafting dependencies as in progress immediately so that, when canceling, they don't leave behind half-crafted inbetween dependencies
|
||||||
|
// TODO to be more optimal, we should really do this when setting the main craft as in progress, but that would require storing references to all of the dependencies
|
||||||
|
crafts.forEach(c -> c.inProgress = true);
|
||||||
|
|
||||||
var remain = stack.copy();
|
var remain = stack.copy();
|
||||||
remain.shrink(resultAmount * toCraft);
|
remain.shrink(resultAmount * toCraft);
|
||||||
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(tile.getBlockPos(), slot, locks, destPipe, result);
|
||||||
tile.activeCrafts.add(Pair.of(slot, activeCraft));
|
tile.getActiveCrafts().add(activeCraft);
|
||||||
|
crafts.add(activeCraft);
|
||||||
|
|
||||||
return remain;
|
return Pair.of(remain, crafts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack store(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction) {
|
public ItemStack store(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction) {
|
||||||
var slot = tile.getModuleSlot(module);
|
var slot = tile.getModuleSlot(module);
|
||||||
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||||
var matchingCraft = tile.activeCrafts.stream()
|
var crafts = tile.getActiveCrafts();
|
||||||
.filter(c -> c.getLeft() == slot && !c.getRight().getTravelingIngredient(stack, equalityTypes).isEmpty())
|
var craft = crafts.stream()
|
||||||
|
.filter(c -> c.moduleSlot == slot && !c.getTravelingIngredient(stack, equalityTypes).isEmpty())
|
||||||
.findAny().orElse(null);
|
.findAny().orElse(null);
|
||||||
if (matchingCraft != null) {
|
if (craft != null) {
|
||||||
var data = matchingCraft.getRight();
|
craft.travelingIngredients.remove(craft.getTravelingIngredient(stack, equalityTypes));
|
||||||
data.travelingIngredients.remove(data.getTravelingIngredient(stack, equalityTypes));
|
|
||||||
|
|
||||||
if (module.get(Contents.TYPE).insertSingles) {
|
if (module.get(Contents.TYPE).insertSingles) {
|
||||||
var handler = tile.getItemHandler(direction);
|
var handler = tile.getItemHandler(direction);
|
||||||
|
@ -242,8 +240,8 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we canceled the request and all input items are delivered (ie the machine actually got what it expected), remove it from the queue
|
// if we canceled the request and all input items are delivered (ie the machine actually got what it expected), remove it from the queue
|
||||||
if (data.canceled && data.travelingIngredients.size() <= 0 && data.ingredientsToRequest.size() <= 0)
|
if (craft.canceled && craft.travelingIngredients.size() <= 0 && craft.ingredientsToRequest.size() <= 0)
|
||||||
tile.activeCrafts.remove(matchingCraft);
|
crafts.remove(craft);
|
||||||
}
|
}
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
@ -260,6 +258,7 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stack<ItemStack> addDependency(Stack<ItemStack> deps, ItemStack module) {
|
private static Stack<ItemStack> addDependency(Stack<ItemStack> deps, ItemStack module) {
|
||||||
|
// noinspection unchecked
|
||||||
deps = (Stack<ItemStack>) deps.clone();
|
deps = (Stack<ItemStack>) deps.clone();
|
||||||
deps.push(module);
|
deps.push(module);
|
||||||
return deps;
|
return deps;
|
||||||
|
@ -277,68 +276,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;
|
||||||
|
@ -136,7 +133,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
|
||||||
if (playersToSync.length > 0) {
|
if (playersToSync.length > 0) {
|
||||||
var clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList());
|
var clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList());
|
||||||
var clientCraftables = PipeNetwork.get(this.level).getAllCraftables(pipe.getBlockPos()).stream().map(Pair::getRight).collect(Collectors.toList());
|
var clientCraftables = PipeNetwork.get(this.level).getAllCraftables(pipe.getBlockPos()).stream().map(Pair::getRight).collect(Collectors.toList());
|
||||||
var currentlyCrafting = this.getCurrentlyCrafting(false).stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList());
|
var currentlyCrafting = this.getCurrentlyCrafting(true).stream().sorted(Comparator.comparingInt(ItemStack::getCount).reversed()).collect(Collectors.toList());
|
||||||
for (var player : playersToSync) {
|
for (var player : playersToSync) {
|
||||||
if (!(player.containerMenu instanceof ItemTerminalContainer container))
|
if (!(player.containerMenu instanceof ItemTerminalContainer container))
|
||||||
continue;
|
continue;
|
||||||
|
@ -172,9 +169,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.requestLocksAndStartCrafting(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() {
|
||||||
|
@ -209,7 +207,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
|
||||||
return crafting.stream().map(Pair::getRight).collect(Collectors.toList());
|
return crafting.stream().map(Pair::getRight).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelCrafting() {
|
public void cancelCrafting(boolean force) {
|
||||||
var network = PipeNetwork.get(this.level);
|
var network = PipeNetwork.get(this.level);
|
||||||
var pipe = this.getConnectedPipe();
|
var pipe = this.getConnectedPipe();
|
||||||
if (pipe == null)
|
if (pipe == null)
|
||||||
|
@ -217,7 +215,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
|
||||||
for (var craftable : network.getAllCraftables(pipe.getBlockPos())) {
|
for (var craftable : network.getAllCraftables(pipe.getBlockPos())) {
|
||||||
var otherPipe = network.getPipe(craftable.getLeft());
|
var otherPipe = network.getPipe(craftable.getLeft());
|
||||||
if (otherPipe != null)
|
if (otherPipe != null)
|
||||||
otherPipe.activeCrafts.removeIf(c -> c.getRight().markCanceledOrResolve(network));
|
otherPipe.getActiveCrafts().removeIf(c -> c.markCanceledOrResolve(network, force));
|
||||||
}
|
}
|
||||||
var lookingPlayers = this.getLookingPlayers();
|
var lookingPlayers = this.getLookingPlayers();
|
||||||
if (lookingPlayers.length > 0)
|
if (lookingPlayers.length > 0)
|
||||||
|
@ -269,38 +267,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)
|
||||||
|
|
|
@ -161,7 +161,7 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
|
||||||
// and vanilla buttons are activated when the click starts, so we'll always invoke jei accidentally by default
|
// and vanilla buttons are activated when the click starts, so we'll always invoke jei accidentally by default
|
||||||
if (button == 0 && this.cancelCraftingButton.visible && this.cancelCraftingButton.isHovered()) {
|
if (button == 0 && this.cancelCraftingButton.visible && this.cancelCraftingButton.isHovered()) {
|
||||||
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
|
if (this.currentlyCrafting != null && !this.currentlyCrafting.isEmpty()) {
|
||||||
PacketDistributor.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CANCEL_CRAFTING, List.of()));
|
PacketDistributor.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CANCEL_CRAFTING, List.of(hasShiftDown() ? 1 : 0)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
|
||||||
} else if (search.startsWith("#")) {
|
} else if (search.startsWith("#")) {
|
||||||
// search item description
|
// search item description
|
||||||
var hoverText = s.getLeft().getTooltipLines(Item.TooltipContext.of(this.minecraft.level), this.minecraft.player,
|
var hoverText = s.getLeft().getTooltipLines(Item.TooltipContext.of(this.minecraft.level), this.minecraft.player,
|
||||||
this.minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL);
|
this.minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL);
|
||||||
toCompare = hoverText.stream().map(Component::getString).collect(Collectors.joining("\n"));
|
toCompare = hoverText.stream().map(Component::getString).collect(Collectors.joining("\n"));
|
||||||
search = search.substring(1);
|
search = search.substring(1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -364,8 +364,8 @@ public class ItemTerminalGui extends AbstractContainerScreen<ItemTerminalContain
|
||||||
|
|
||||||
public Stream<ItemTerminalWidget> streamWidgets() {
|
public Stream<ItemTerminalWidget> streamWidgets() {
|
||||||
return this.renderables.stream()
|
return this.renderables.stream()
|
||||||
.filter(w -> w instanceof ItemTerminalWidget)
|
.filter(w -> w instanceof ItemTerminalWidget)
|
||||||
.map(w -> (ItemTerminalWidget) w);
|
.map(w -> (ItemTerminalWidget) w);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int requestModifier() {
|
public static int requestModifier() {
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
"info.prettypipes.energy": "%s / %s FE",
|
"info.prettypipes.energy": "%s / %s FE",
|
||||||
"info.prettypipes.crafting": "Awaiting",
|
"info.prettypipes.crafting": "Awaiting",
|
||||||
"info.prettypipes.cancel_all": "Cancel",
|
"info.prettypipes.cancel_all": "Cancel",
|
||||||
"info.prettypipes.cancel_all.desc": "Stops waiting for current crafting outputs\nOngoing crafting operations are still completed",
|
"info.prettypipes.cancel_all.desc": "Stops waiting for current crafting outputs\nOngoing crafting operations are still completed\nHold Shift to include ongoing crafting operations,\nwhich may cause partial recipes to stay behind",
|
||||||
"info.prettypipes.no_pipe_connected": "The terminal needs to be connected to a pipe network",
|
"info.prettypipes.no_pipe_connected": "The terminal needs to be connected to a pipe network",
|
||||||
"info.prettypipes.too_many_pipes_connected": "The terminal can only be connected to a single pipe at a time",
|
"info.prettypipes.too_many_pipes_connected": "The terminal can only be connected to a single pipe at a time",
|
||||||
"dir.prettypipes.up": "Up",
|
"dir.prettypipes.up": "Up",
|
||||||
|
|
Loading…
Reference in a new issue