networking stuff

This commit is contained in:
Ell 2024-09-15 15:17:16 +02:00
parent 2e05cd7b70
commit bc710789c8
22 changed files with 244 additions and 391 deletions

View file

@ -47,7 +47,6 @@ import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalGui; import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalGui;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.client.renderer.entity.EntityRenderers; import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -153,8 +152,8 @@ public final class Registry {
} }
BuiltInRegistries.BLOCK.entrySet().stream() BuiltInRegistries.BLOCK.entrySet().stream()
.filter(b -> b.getKey().location().getNamespace().equals(PrettyPipes.ID)) .filter(b -> b.getKey().location().getNamespace().equals(PrettyPipes.ID))
.forEach(b -> h.register(b.getKey().location(), new BlockItem(b.getValue(), new Item.Properties()))); .forEach(b -> h.register(b.getKey().location(), new BlockItem(b.getValue(), new Item.Properties())));
}); });
event.register(Registries.BLOCK_ENTITY_TYPE, h -> { event.register(Registries.BLOCK_ENTITY_TYPE, h -> {
@ -165,7 +164,7 @@ public final class Registry {
}); });
event.register(Registries.ENTITY_TYPE, h -> event.register(Registries.ENTITY_TYPE, h ->
h.register(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "pipe_frame"), Registry.pipeFrameEntity = EntityType.Builder.<PipeFrameEntity>of(PipeFrameEntity::new, MobCategory.MISC).build("pipe_frame"))); h.register(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "pipe_frame"), Registry.pipeFrameEntity = EntityType.Builder.<PipeFrameEntity>of(PipeFrameEntity::new, MobCategory.MISC).build("pipe_frame")));
event.register(Registries.MENU, h -> { event.register(Registries.MENU, h -> {
h.register(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "pipe"), Registry.pipeContainer = IMenuTypeExtension.create((windowId, inv, data) -> new MainPipeContainer(Registry.pipeContainer, windowId, inv.player, data.readBlockPos()))); h.register(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "pipe"), Registry.pipeContainer = IMenuTypeExtension.create((windowId, inv, data) -> new MainPipeContainer(Registry.pipeContainer, windowId, inv.player, data.readBlockPos())));
@ -184,12 +183,12 @@ public final class Registry {
event.register(BuiltInRegistries.CREATIVE_MODE_TAB.key(), h -> { event.register(BuiltInRegistries.CREATIVE_MODE_TAB.key(), h -> {
h.register(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "tab"), CreativeModeTab.builder() h.register(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "tab"), CreativeModeTab.builder()
.title(Component.translatable("item_group." + PrettyPipes.ID + ".tab")) .title(Component.translatable("item_group." + PrettyPipes.ID + ".tab"))
.icon(() -> new ItemStack(Registry.wrenchItem)) .icon(() -> new ItemStack(Registry.wrenchItem))
.displayItems((params, output) -> BuiltInRegistries.ITEM.entrySet().stream() .displayItems((params, output) -> BuiltInRegistries.ITEM.entrySet().stream()
.filter(b -> b.getKey().location().getNamespace().equals(PrettyPipes.ID)) .filter(b -> b.getKey().location().getNamespace().equals(PrettyPipes.ID))
.sorted(Comparator.comparing(b -> b.getValue().getClass().getSimpleName())) .sorted(Comparator.comparing(b -> b.getValue().getClass().getSimpleName()))
.forEach(b -> output.accept(b.getValue()))).build() .forEach(b -> output.accept(b.getValue()))).build()
); );
}); });
@ -211,12 +210,12 @@ public final class Registry {
@SubscribeEvent @SubscribeEvent
public static void registerPayloads(final RegisterPayloadHandlersEvent event) { public static void registerPayloads(final RegisterPayloadHandlersEvent event) {
var registrar = event.registrar(PrettyPipes.ID); var registrar = event.registrar(PrettyPipes.ID);
registrar.play(PacketItemEnterPipe.ID, PacketItemEnterPipe::new, PacketItemEnterPipe::onMessage); registrar.playBidirectional(PacketItemEnterPipe.TYPE, PacketItemEnterPipe.CODEC, PacketItemEnterPipe::onMessage);
registrar.play(PacketButton.ID, PacketButton::new, PacketButton::onMessage); registrar.playBidirectional(PacketButton.TYPE, PacketButton.CODEC, PacketButton::onMessage);
registrar.play(PacketCraftingModuleTransfer.ID, PacketCraftingModuleTransfer::new, PacketCraftingModuleTransfer::onMessage); registrar.playBidirectional(PacketCraftingModuleTransfer.TYPE, PacketCraftingModuleTransfer.CODEC, PacketCraftingModuleTransfer::onMessage);
registrar.play(PacketGhostSlot.ID, PacketGhostSlot::new, PacketGhostSlot::onMessage); registrar.playBidirectional(PacketGhostSlot.TYPE, PacketGhostSlot.CODEC, PacketGhostSlot::onMessage);
registrar.play(PacketNetworkItems.ID, PacketNetworkItems::new, PacketNetworkItems::onMessage); registrar.playBidirectional(PacketNetworkItems.TYPE, PacketNetworkItems.CODEC, PacketNetworkItems::onMessage);
registrar.play(PacketRequest.ID, PacketRequest::new, PacketRequest::onMessage); registrar.playBidirectional(PacketRequest.TYPE, PacketRequest.CODEC, PacketRequest::onMessage);
} }
private static <T extends AbstractPipeContainer<?>> MenuType<T> registerPipeContainer(RegisterEvent.RegisterHelper<MenuType<?>> helper, String name) { private static <T extends AbstractPipeContainer<?>> MenuType<T> registerPipeContainer(RegisterEvent.RegisterHelper<MenuType<?>> helper, String name) {

View file

@ -46,7 +46,7 @@ public class CraftingTerminalTransferHandler implements IRecipeTransferHandler<C
List<PacketGhostSlot.Entry> stacks = new ArrayList<>(); List<PacketGhostSlot.Entry> stacks = new ArrayList<>();
var ingredients = slots.getSlotViews(RecipeIngredientRole.INPUT); var ingredients = slots.getSlotViews(RecipeIngredientRole.INPUT);
for (var entry : ingredients) for (var entry : ingredients)
stacks.add(new PacketGhostSlot.Entry(player.level(), entry.getIngredients(VanillaTypes.ITEM_STACK).collect(Collectors.toList()))); stacks.add(PacketGhostSlot.Entry.fromStacks(player.level(), entry.getIngredients(VanillaTypes.ITEM_STACK).collect(Collectors.toList())));
PacketDistributor.sendToServer(new PacketGhostSlot(container.getTile().getBlockPos(), stacks)); PacketDistributor.sendToServer(new PacketGhostSlot(container.getTile().getBlockPos(), stacks));
return null; return null;
} }

View file

@ -13,6 +13,8 @@ import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.gui.widget.ExtendedButton; import net.neoforged.neoforge.client.gui.widget.ExtendedButton;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import java.util.List;
public class DirectionSelector { public class DirectionSelector {
private static final Direction[] ALL = ArrayUtils.addAll(Direction.values(), (Direction) null); private static final Direction[] ALL = ArrayUtils.addAll(Direction.values(), (Direction) null);
@ -33,7 +35,7 @@ public class DirectionSelector {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public AbstractWidget getButton(int x, int y) { public AbstractWidget getButton(int x, int y) {
return new ExtendedButton(x, y, 100, 20, Component.translatable("info." + PrettyPipes.ID + ".populate"), button -> return new ExtendedButton(x, y, 100, 20, Component.translatable("info." + PrettyPipes.ID + ".populate"), button ->
PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.DIRECTION_SELECTOR)) { PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.DIRECTION_SELECTOR, List.of())) {
@Override @Override
public Component getMessage() { public Component getMessage() {
var pipe = DirectionSelector.this.pipe; var pipe = DirectionSelector.this.pipe;
@ -92,9 +94,9 @@ public class DirectionSelector {
if (this.pipe.getItemHandler(dir) == null) if (this.pipe.getItemHandler(dir) == null)
return false; return false;
return this.pipe.streamModules() return this.pipe.streamModules()
.filter(p -> p.getLeft() != this.stack) .filter(p -> p.getLeft() != this.stack)
.map(p -> p.getRight().getDirectionSelector(p.getLeft(), this.pipe)) .map(p -> p.getRight().getDirectionSelector(p.getLeft(), this.pipe))
.noneMatch(p -> p != null && p.direction == dir); .noneMatch(p -> p != null && p.direction == dir);
} }
public interface IDirectionContainer { public interface IDirectionContainer {
@ -102,4 +104,5 @@ public class DirectionSelector {
DirectionSelector getSelector(); DirectionSelector getSelector();
} }
} }

View file

@ -54,12 +54,12 @@ public class ItemFilter extends ItemStackHandler {
if (this.canModifyWhitelist) { if (this.canModifyWhitelist) {
var whitelistText = (Supplier<String>) () -> "info." + PrettyPipes.ID + "." + (this.isWhitelist ? "whitelist" : "blacklist"); var whitelistText = (Supplier<String>) () -> "info." + PrettyPipes.ID + "." + (this.isWhitelist ? "whitelist" : "blacklist");
buttons.add(Button.builder(Component.translatable(whitelistText.get()), button -> { buttons.add(Button.builder(Component.translatable(whitelistText.get()), button -> {
PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.FILTER_CHANGE, 0); PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.FILTER_CHANGE, List.of(0));
button.setMessage(Component.translatable(whitelistText.get())); button.setMessage(Component.translatable(whitelistText.get()));
}).bounds(x - 20, y, 20, 20).tooltip(Tooltip.create(Component.translatable(whitelistText.get() + ".description").withStyle(ChatFormatting.GRAY))).build()); }).bounds(x - 20, y, 20, 20).tooltip(Tooltip.create(Component.translatable(whitelistText.get() + ".description").withStyle(ChatFormatting.GRAY))).build());
} }
if (this.canPopulateFromInventories) { if (this.canPopulateFromInventories) {
buttons.add(Button.builder(Component.translatable("info." + PrettyPipes.ID + ".populate"), button -> PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.FILTER_CHANGE, 1)).bounds(x - 42, y, 20, 20).tooltip(Tooltip.create(Component.translatable("info." + PrettyPipes.ID + ".populate.description").withStyle(ChatFormatting.GRAY))).build()); buttons.add(Button.builder(Component.translatable("info." + PrettyPipes.ID + ".populate"), button -> PacketButton.sendAndExecute(this.pipe.getBlockPos(), PacketButton.ButtonResult.FILTER_CHANGE, List.of(1))).bounds(x - 42, y, 20, 20).tooltip(Tooltip.create(Component.translatable("info." + PrettyPipes.ID + ".populate.description").withStyle(ChatFormatting.GRAY))).build());
} }
return buttons; return buttons;
} }
@ -152,9 +152,9 @@ public class ItemFilter extends ItemStackHandler {
public static ItemEquality[] getEqualityTypes(PipeBlockEntity pipe) { public static ItemEquality[] getEqualityTypes(PipeBlockEntity pipe) {
return pipe.streamModules() return pipe.streamModules()
.filter(m -> m.getRight() instanceof FilterModifierModuleItem) .filter(m -> m.getRight() instanceof FilterModifierModuleItem)
.map(m -> ((FilterModifierModuleItem) m.getRight()).getEqualityType(m.getLeft())) .map(m -> ((FilterModifierModuleItem) m.getRight()).getEqualityType(m.getLeft()))
.toArray(ItemEquality[]::new); .toArray(ItemEquality[]::new);
} }
public interface IFilteredContainer { public interface IFilteredContainer {

View file

@ -102,11 +102,11 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
@Override @Override
public String toString() { public String toString() {
return "PipeNetwork{" + return "PipeNetwork{" +
"\ngraph=" + this.graph + "\ngraph=" + this.graph +
",\nnodeToConnectedNodes=" + this.nodeToConnectedNodes + ",\nnodeToConnectedNodes=" + this.nodeToConnectedNodes +
",\ntileCache=" + this.tileCache.keySet() + ",\ntileCache=" + this.tileCache.keySet() +
",\npipeItems=" + this.pipeItems + ",\npipeItems=" + this.pipeItems +
",\nnetworkLocks=" + this.networkLocks + '}'; ",\nnetworkLocks=" + this.networkLocks + '}';
} }
@Override @Override
@ -119,8 +119,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
for (var edge : this.graph.edgeSet()) for (var edge : this.graph.edgeSet())
edges.add(edge.serializeNBT(provider)); edges.add(edge.serializeNBT(provider));
nbt.put("edges", edges); nbt.put("edges", edges);
nbt.put("items", Utility.serializeAll(this.pipeItems.values())); nbt.put("items", Utility.serializeAll(provider, this.pipeItems.values()));
nbt.put("locks", Utility.serializeAll(this.networkLocks.values())); nbt.put("locks", Utility.serializeAll(provider, this.networkLocks.values()));
return nbt; return nbt;
} }
@ -201,7 +201,7 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
var item = itemSupplier.apply(startPipe.getItemSpeed(stack)); var item = itemSupplier.apply(startPipe.getItemSpeed(stack));
item.setDestination(startInventory, destInventory, path); item.setDestination(startInventory, destInventory, path);
startPipe.addNewItem(item); startPipe.addNewItem(item);
PacketDistributor.sendToPlayersTrackingChunk((ServerLevel) this.level, new ChunkPos(startPipePos), new PacketItemEnterPipe(startPipePos, item)); PacketDistributor.sendToPlayersTrackingChunk((ServerLevel) this.level, new ChunkPos(startPipePos), new PacketItemEnterPipe(startPipePos, item.serializeNBT(this.level.registryAccess())));
return true; return true;
} }
@ -289,8 +289,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
var stack = request.getRight(); var stack = request.getRight();
// 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(dest) && ItemEquality.compareItems(s.getRight(), stack, equalityTypes)) .filter(s -> s.getLeft().equals(dest) && ItemEquality.compareItems(s.getRight(), stack, equalityTypes))
.findFirst(); .findFirst();
if (existing.isPresent()) { if (existing.isPresent()) {
existing.get().getRight().grow(stack.getCount()); existing.get().getRight().grow(stack.getCount());
} else { } else {
@ -304,8 +304,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
public int getCurrentlyCraftingAmount(BlockPos destNode, ItemStack stack, ItemEquality... equalityTypes) { public int getCurrentlyCraftingAmount(BlockPos destNode, ItemStack stack, ItemEquality... equalityTypes) {
return this.getCurrentlyCrafting(destNode).stream() return this.getCurrentlyCrafting(destNode).stream()
.filter(p -> p.getLeft().equals(destNode) && ItemEquality.compareItems(p.getRight(), stack, equalityTypes)) .filter(p -> p.getLeft().equals(destNode) && ItemEquality.compareItems(p.getRight(), stack, equalityTypes))
.mapToInt(p -> p.getRight().getCount()).sum(); .mapToInt(p -> p.getRight().getCount()).sum();
} }
public List<Pair<BlockPos, ItemStack>> getAllCraftables(BlockPos node) { public List<Pair<BlockPos, ItemStack>> getAllCraftables(BlockPos node) {
@ -377,8 +377,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
public int getLockedAmount(BlockPos pos, ItemStack stack, NetworkLock ignoredLock, ItemEquality... equalityTypes) { public int getLockedAmount(BlockPos pos, ItemStack stack, NetworkLock ignoredLock, ItemEquality... equalityTypes) {
return this.getNetworkLocks(pos).stream() return this.getNetworkLocks(pos).stream()
.filter(l -> !l.equals(ignoredLock) && ItemEquality.compareItems(l.stack, stack, equalityTypes)) .filter(l -> !l.equals(ignoredLock) && ItemEquality.compareItems(l.stack, stack, equalityTypes))
.mapToInt(l -> l.stack.getCount()).sum(); .mapToInt(l -> l.stack.getCount()).sum();
} }
private void refreshNode(BlockPos pos, BlockState state) { private void refreshNode(BlockPos pos, BlockState state) {
@ -483,9 +483,9 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
// sort destinations first by their priority (eg trash pipes should be last) // sort destinations first by their priority (eg trash pipes should be last)
// and then by their distance from the specified node // and then by their distance from the specified node
ret = Streams.stream(new BreadthFirstIterator<>(this.graph, node)) ret = Streams.stream(new BreadthFirstIterator<>(this.graph, node))
.filter(p -> this.getPipe(p) != null) .filter(p -> this.getPipe(p) != null)
.sorted(Comparator.<BlockPos>comparingInt(p -> this.getPipe(p).getPriority()).reversed().thenComparing(paths::getWeight)) .sorted(Comparator.<BlockPos>comparingInt(p -> this.getPipe(p).getPriority()).reversed().thenComparing(paths::getWeight))
.collect(Collectors.toList()); .collect(Collectors.toList());
this.nodeToConnectedNodes.put(node, ret); this.nodeToConnectedNodes.put(node, ret);
this.endProfile(); this.endProfile();
} }
@ -515,8 +515,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
public int getItemsOnTheWay(BlockPos goalInv, ItemStack type, ItemEquality... equalityTypes) { public int getItemsOnTheWay(BlockPos goalInv, ItemStack type, ItemEquality... equalityTypes) {
return this.getPipeItemsOnTheWay(goalInv) return this.getPipeItemsOnTheWay(goalInv)
.filter(i -> type == null || ItemEquality.compareItems(i.getContent(), type, equalityTypes)) .filter(i -> type == null || ItemEquality.compareItems(i.getContent(), type, equalityTypes))
.mapToInt(i -> i.getItemsOnTheWay(goalInv)).sum(); .mapToInt(i -> i.getItemsOnTheWay(goalInv)).sum();
} }
public void startProfile(String name) { public void startProfile(String name) {

View file

@ -13,8 +13,10 @@ import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.MenuProvider; import net.minecraft.world.MenuProvider;
@ -22,64 +24,50 @@ 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.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.network.handling.PlayPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
import org.apache.logging.log4j.util.TriConsumer; import org.apache.logging.log4j.util.TriConsumer;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import static de.ellpeck.prettypipes.misc.DirectionSelector.IDirectionContainer; import static de.ellpeck.prettypipes.misc.DirectionSelector.IDirectionContainer;
public class PacketButton implements CustomPacketPayload { public record PacketButton(BlockPos pos, int result, List<Integer> data) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(PrettyPipes.ID, "button"); public static final Type<PacketButton> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "button"));
public static final StreamCodec<RegistryFriendlyByteBuf, PacketButton> CODEC = StreamCodec.composite(
BlockPos.STREAM_CODEC, PacketButton::pos,
ByteBufCodecs.INT, PacketButton::result,
ByteBufCodecs.collection(ArrayList::new, ByteBufCodecs.INT), PacketButton::data,
PacketButton::new);
private final BlockPos pos; public PacketButton(BlockPos pos, ButtonResult result, List<Integer> data) {
private final ButtonResult result; this(pos, result.ordinal(), data);
private final int[] data;
public PacketButton(BlockPos pos, ButtonResult result, int... data) {
this.pos = pos;
this.result = result;
this.data = data;
}
public PacketButton(FriendlyByteBuf buf) {
this.pos = buf.readBlockPos();
this.result = ButtonResult.values()[buf.readByte()];
this.data = buf.readVarIntArray();
} }
@Override @Override
public void write(FriendlyByteBuf buf) { public Type<? extends CustomPacketPayload> type() {
buf.writeBlockPos(this.pos); return PacketButton.TYPE;
buf.writeByte(this.result.ordinal());
buf.writeVarIntArray(this.data);
} }
@Override public static void onMessage(PacketButton message, IPayloadContext ctx) {
public ResourceLocation id() { var player = ctx.player();
return PacketButton.ID; ButtonResult.values()[message.result].action.accept(message.pos, message.data, player);
} }
public static void onMessage(PacketButton message, PlayPayloadContext ctx) { public static void sendAndExecute(BlockPos pos, ButtonResult result, List<Integer> data) {
ctx.workHandler().execute(() -> { PacketDistributor.sendToServer(new PacketButton(pos, result, data));
var player = ctx.player().orElseThrow();
message.result.action.accept(message.pos, message.data, player);
});
}
public static void sendAndExecute(BlockPos pos, ButtonResult result, int... data) {
PacketDistributor.SERVER.noArg().send(new PacketButton(pos, result, data));
result.action.accept(pos, data, Minecraft.getInstance().player); result.action.accept(pos, data, Minecraft.getInstance().player);
} }
public enum ButtonResult { public enum ButtonResult {
PIPE_TAB((pos, data, player) -> { PIPE_TAB((pos, data, player) -> {
var tile = Utility.getBlockEntity(PipeBlockEntity.class, player.level(), pos); var tile = Utility.getBlockEntity(PipeBlockEntity.class, player.level(), pos);
if (data[0] < 0) { if (data.getFirst() < 0) {
player.openMenu(tile, pos); player.openMenu(tile, pos);
} else { } else {
var stack = tile.modules.getStackInSlot(data[0]); var stack = tile.modules.getStackInSlot(data.getFirst());
player.openMenu(new MenuProvider() { player.openMenu(new MenuProvider() {
@Override @Override
public Component getDisplayName() { public Component getDisplayName() {
@ -89,18 +77,18 @@ public class PacketButton implements CustomPacketPayload {
@Nullable @Nullable
@Override @Override
public AbstractContainerMenu createMenu(int windowId, Inventory inv, Player player) { public AbstractContainerMenu createMenu(int windowId, Inventory inv, Player player) {
return ((IModule) stack.getItem()).getContainer(stack, tile, windowId, inv, player, data[0]); return ((IModule) stack.getItem()).getContainer(stack, tile, windowId, inv, player, data.getFirst());
} }
}, buf -> { }, buf -> {
buf.writeBlockPos(pos); buf.writeBlockPos(pos);
buf.writeInt(data[0]); buf.writeInt(data.getFirst());
}); });
} }
}), }),
FILTER_CHANGE((pos, data, player) -> { FILTER_CHANGE((pos, data, player) -> {
if (player.containerMenu instanceof IFilteredContainer filtered) if (player.containerMenu instanceof IFilteredContainer filtered)
filtered.getFilter().onButtonPacket(filtered, data[0]); filtered.getFilter().onButtonPacket(filtered, data.getFirst());
}), }),
STACK_SIZE_MODULE_BUTTON((pos, data, player) -> { STACK_SIZE_MODULE_BUTTON((pos, data, player) -> {
var container = (AbstractPipeContainer<?>) player.containerMenu; var container = (AbstractPipeContainer<?>) player.containerMenu;
@ -108,11 +96,11 @@ public class PacketButton implements CustomPacketPayload {
}), }),
STACK_SIZE_AMOUNT((pos, data, player) -> { STACK_SIZE_AMOUNT((pos, data, player) -> {
var container = (AbstractPipeContainer<?>) player.containerMenu; var container = (AbstractPipeContainer<?>) player.containerMenu;
StackSizeModuleItem.setMaxStackSize(container.moduleStack, data[0]); StackSizeModuleItem.setMaxStackSize(container.moduleStack, data.getFirst());
}), }),
CRAFT_TERMINAL_REQUEST((pos, data, player) -> { CRAFT_TERMINAL_REQUEST((pos, data, player) -> {
var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, player.level(), pos); var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, player.level(), pos);
tile.requestCraftingItems(player, data[0], data[1] > 0); tile.requestCraftingItems(player, data.getFirst(), data.get(1) > 0);
}), }),
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);
@ -120,16 +108,16 @@ public class PacketButton implements CustomPacketPayload {
}), }),
TAG_FILTER((pos, data, player) -> { TAG_FILTER((pos, data, player) -> {
var container = (FilterModifierModuleContainer) player.containerMenu; var container = (FilterModifierModuleContainer) player.containerMenu;
FilterModifierModuleItem.setFilterTag(container.moduleStack, container.getTags().get(data[0])); FilterModifierModuleItem.setFilterTag(container.moduleStack, container.getTags().get(data.getFirst()));
}), }),
DIRECTION_SELECTOR((pos, data, player) -> { DIRECTION_SELECTOR((pos, data, player) -> {
if (player.containerMenu instanceof IDirectionContainer filtered) if (player.containerMenu instanceof IDirectionContainer filtered)
filtered.getSelector().onButtonPacket(); filtered.getSelector().onButtonPacket();
}); });
public final TriConsumer<BlockPos, int[], Player> action; public final TriConsumer<BlockPos, List<Integer>, Player> action;
ButtonResult(TriConsumer<BlockPos, int[], Player> action) { ButtonResult(TriConsumer<BlockPos, List<Integer>, Player> action) {
this.action = action; this.action = action;
} }
} }

View file

@ -2,63 +2,40 @@ package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer; import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleContainer;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
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 net.neoforged.neoforge.network.handling.PlayPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PacketCraftingModuleTransfer implements CustomPacketPayload { public record PacketCraftingModuleTransfer(List<ItemStack> inputs, List<ItemStack> outputs) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(PrettyPipes.ID, "crafting_module_transfer"); public static final Type<PacketCraftingModuleTransfer> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "crafting_module_transfer"));
public static final StreamCodec<RegistryFriendlyByteBuf, PacketCraftingModuleTransfer> CODEC = StreamCodec.composite(
private final List<ItemStack> inputs; ByteBufCodecs.collection(ArrayList::new, ItemStack.STREAM_CODEC), PacketCraftingModuleTransfer::inputs,
private final List<ItemStack> outputs; ByteBufCodecs.collection(ArrayList::new, ItemStack.STREAM_CODEC), PacketCraftingModuleTransfer::outputs,
PacketCraftingModuleTransfer::new);
public PacketCraftingModuleTransfer(List<ItemStack> inputs, List<ItemStack> outputs) {
this.inputs = inputs;
this.outputs = outputs;
}
public PacketCraftingModuleTransfer(FriendlyByteBuf buf) {
this.inputs = new ArrayList<>();
for (var i = buf.readInt(); i > 0; i--)
this.inputs.add(buf.readItem());
this.outputs = new ArrayList<>();
for (var i = buf.readInt(); i > 0; i--)
this.outputs.add(buf.readItem());
}
@Override @Override
public void write(FriendlyByteBuf buf) { public Type<? extends CustomPacketPayload> type() {
buf.writeInt(this.inputs.size()); return PacketCraftingModuleTransfer.TYPE;
for (var stack : this.inputs)
buf.writeItem(stack);
buf.writeInt(this.outputs.size());
for (var stack : this.outputs)
buf.writeItem(stack);
} }
@Override public static void onMessage(PacketCraftingModuleTransfer message, IPayloadContext ctx) {
public ResourceLocation id() { var player = ctx.player();
return PacketCraftingModuleTransfer.ID; if (player.containerMenu instanceof CraftingModuleContainer container) {
} PacketCraftingModuleTransfer.copy(container.input, message.inputs);
PacketCraftingModuleTransfer.copy(container.output, message.outputs);
public static void onMessage(PacketCraftingModuleTransfer message, PlayPayloadContext ctx) { container.modified = true;
ctx.workHandler().execute(() -> { container.broadcastChanges();
var player = ctx.player().orElseThrow(); }
if (player.containerMenu instanceof CraftingModuleContainer container) {
PacketCraftingModuleTransfer.copy(container.input, message.inputs);
PacketCraftingModuleTransfer.copy(container.output, message.outputs);
container.modified = true;
container.broadcastChanges();
}
});
} }
private static void copy(ItemStackHandler container, List<ItemStack> contents) { private static void copy(ItemStackHandler container, List<ItemStack> contents) {

View file

@ -7,7 +7,9 @@ import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
@ -15,78 +17,45 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.neoforged.neoforge.network.handling.PlayPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class PacketGhostSlot implements CustomPacketPayload { public record PacketGhostSlot(BlockPos pos, List<Entry> stacks) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(PrettyPipes.ID, "ghost_slot"); public static final Type<PacketGhostSlot> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "ghost_slot"));
public static final StreamCodec<RegistryFriendlyByteBuf, PacketGhostSlot> CODEC = StreamCodec.composite(
private final BlockPos pos; BlockPos.STREAM_CODEC, PacketGhostSlot::pos,
private final List<Entry> stacks; ByteBufCodecs.collection(ArrayList::new, Entry.CODEC), PacketGhostSlot::stacks,
PacketGhostSlot::new);
public PacketGhostSlot(BlockPos pos, List<Entry> stacks) {
this.pos = pos;
this.stacks = stacks;
}
public PacketGhostSlot(FriendlyByteBuf buf) {
this.pos = buf.readBlockPos();
this.stacks = new ArrayList<>();
for (var i = buf.readInt(); i > 0; i--)
this.stacks.add(new Entry(buf));
}
@Override @Override
public void write(FriendlyByteBuf buf) { public Type<? extends CustomPacketPayload> type() {
buf.writeBlockPos(this.pos); return PacketGhostSlot.TYPE;
buf.writeInt(this.stacks.size());
for (var entry : this.stacks)
entry.write(buf);
} }
@Override public static void onMessage(PacketGhostSlot message, IPayloadContext ctx) {
public ResourceLocation id() { var player = ctx.player();
return PacketGhostSlot.ID; var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, player.level(), message.pos);
if (tile != null)
tile.setGhostItems(message.stacks);
} }
public static void onMessage(PacketGhostSlot message, PlayPayloadContext ctx) { public record Entry(List<ItemStack> stacks, TagKey<Item> tag) {
ctx.workHandler().execute(() -> {
var player = ctx.player().orElseThrow();
var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, player.level(), message.pos);
if (tile != null)
tile.setGhostItems(message.stacks);
});
}
public static class Entry { public static final StreamCodec<RegistryFriendlyByteBuf, Entry> CODEC = StreamCodec.composite(
ByteBufCodecs.collection(ArrayList::new, ItemStack.STREAM_CODEC), Entry::stacks,
ByteBufCodecs.fromCodec(TagKey.codec(Registries.ITEM)), Entry::tag,
Entry::new);
private final List<ItemStack> stacks; public static Entry fromStacks(Level level, List<ItemStack> stacks) {
private final TagKey<Item> tag;
public Entry(Level level, List<ItemStack> stacks) {
var tag = Entry.getTagForStacks(level, stacks); var tag = Entry.getTagForStacks(level, stacks);
if (tag != null) { if (tag != null) {
this.stacks = null; return new Entry(null, tag);
this.tag = tag;
} else { } else {
this.stacks = stacks; return new Entry(stacks, null);
this.tag = null;
}
}
public Entry(FriendlyByteBuf buf) {
if (buf.readBoolean()) {
this.tag = null;
this.stacks = new ArrayList<>();
for (var i = buf.readInt(); i > 0; i--)
this.stacks.add(buf.readItem());
} else {
this.stacks = null;
this.tag = TagKey.create(Registries.ITEM, new ResourceLocation(buf.readUtf()));
} }
} }
@ -94,20 +63,8 @@ public class PacketGhostSlot implements CustomPacketPayload {
if (this.stacks != null) if (this.stacks != null)
return this.stacks; return this.stacks;
return Streams.stream(level.registryAccess().registry(Registries.ITEM).orElseThrow().getTagOrEmpty(this.tag).iterator()) return Streams.stream(level.registryAccess().registry(Registries.ITEM).orElseThrow().getTagOrEmpty(this.tag).iterator())
.filter(h -> h.value() != null & h.value() != Items.AIR) .filter(h -> h.value() != null & h.value() != Items.AIR)
.map(h -> new ItemStack(h.value())).collect(Collectors.toList()); .map(h -> new ItemStack(h.value())).collect(Collectors.toList());
}
public void write(FriendlyByteBuf buf) {
if (this.stacks != null) {
buf.writeBoolean(true);
buf.writeInt(this.stacks.size());
for (var stack : this.stacks)
buf.writeItem(stack);
} else {
buf.writeBoolean(false);
buf.writeUtf(this.tag.location().toString());
}
} }
private static TagKey<Item> getTagForStacks(Level level, List<ItemStack> stacks) { private static TagKey<Item> getTagForStacks(Level level, List<ItemStack> stacks) {

View file

@ -7,49 +7,34 @@ import de.ellpeck.prettypipes.pipe.PipeBlockEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.network.handling.PlayPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
public class PacketItemEnterPipe implements CustomPacketPayload { public record PacketItemEnterPipe(BlockPos tilePos, CompoundTag item) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(PrettyPipes.ID, "item_enter_pipe"); public static final Type<PacketItemEnterPipe> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "item_enter_pipe"));
public static final StreamCodec<RegistryFriendlyByteBuf, PacketItemEnterPipe> CODEC = StreamCodec.composite(
private final BlockPos tilePos; BlockPos.STREAM_CODEC, PacketItemEnterPipe::tilePos,
private final CompoundTag item; ByteBufCodecs.COMPOUND_TAG, PacketItemEnterPipe::item,
PacketItemEnterPipe::new);
public PacketItemEnterPipe(BlockPos tilePos, IPipeItem item) {
this.tilePos = tilePos;
this.item = item.serializeNBT();
}
public PacketItemEnterPipe(FriendlyByteBuf buf) {
this.tilePos = buf.readBlockPos();
this.item = buf.readNbt();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBlockPos(this.tilePos);
buf.writeNbt(this.item);
}
@Override @Override
public ResourceLocation id() { public Type<? extends CustomPacketPayload> type() {
return PacketItemEnterPipe.ID; return PacketItemEnterPipe.TYPE;
} }
public static void onMessage(PacketItemEnterPipe message, PlayPayloadContext ctx) { public static void onMessage(PacketItemEnterPipe message, IPayloadContext ctx) {
ctx.workHandler().execute(() -> { var mc = Minecraft.getInstance();
var mc = Minecraft.getInstance(); if (mc.level == null)
if (mc.level == null) return;
return; var item = IPipeItem.load(message.item);
var item = IPipeItem.load(message.item); var pipe = Utility.getBlockEntity(PipeBlockEntity.class, mc.level, message.tilePos);
var pipe = Utility.getBlockEntity(PipeBlockEntity.class, mc.level, message.tilePos); if (pipe != null)
if (pipe != null) pipe.getItems().add(item);
pipe.getItems().add(item);
});
} }
} }

View file

@ -3,76 +3,35 @@ package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui; import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.network.handling.PlayPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PacketNetworkItems implements CustomPacketPayload { public record PacketNetworkItems(List<ItemStack> items, List<ItemStack> craftables, List<ItemStack> currentlyCrafting) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(PrettyPipes.ID, "network_items"); public static final Type<PacketNetworkItems> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "network_items"));
public static final StreamCodec<RegistryFriendlyByteBuf, PacketNetworkItems> CODEC = StreamCodec.composite(
private final List<ItemStack> items; ByteBufCodecs.collection(ArrayList::new, ItemStack.STREAM_CODEC), PacketNetworkItems::items,
private final List<ItemStack> craftables; ByteBufCodecs.collection(ArrayList::new, ItemStack.STREAM_CODEC), PacketNetworkItems::craftables,
private final List<ItemStack> currentlyCrafting; ByteBufCodecs.collection(ArrayList::new, ItemStack.STREAM_CODEC), PacketNetworkItems::currentlyCrafting,
PacketNetworkItems::new);
public PacketNetworkItems(List<ItemStack> items, List<ItemStack> craftables, List<ItemStack> currentlyCrafting) {
this.items = items;
this.craftables = craftables;
this.currentlyCrafting = currentlyCrafting;
}
public PacketNetworkItems(FriendlyByteBuf buf) {
this.items = new ArrayList<>();
for (var i = buf.readVarInt(); i > 0; i--) {
var stack = buf.readItem();
stack.setCount(buf.readVarInt());
this.items.add(stack);
}
this.craftables = new ArrayList<>();
for (var i = buf.readVarInt(); i > 0; i--)
this.craftables.add(buf.readItem());
this.currentlyCrafting = new ArrayList<>();
for (var i = buf.readVarInt(); i > 0; i--)
this.currentlyCrafting.add(buf.readItem());
}
@Override @Override
public void write(FriendlyByteBuf buf) { public Type<? extends CustomPacketPayload> type() {
buf.writeVarInt(this.items.size()); return PacketNetworkItems.TYPE;
for (var stack : this.items) {
var copy = stack.copy();
copy.setCount(1);
buf.writeItem(copy);
buf.writeVarInt(stack.getCount());
}
buf.writeVarInt(this.craftables.size());
for (var stack : this.craftables)
buf.writeItem(stack);
buf.writeVarInt(this.currentlyCrafting.size());
for (var stack : this.currentlyCrafting)
buf.writeItem(stack);
} }
@Override public static void onMessage(PacketNetworkItems message, IPayloadContext ctx) {
public ResourceLocation id() { var mc = Minecraft.getInstance();
return PacketNetworkItems.ID; if (mc.screen instanceof ItemTerminalGui terminal)
} terminal.updateItemList(message.items, message.craftables, message.currentlyCrafting);
@SuppressWarnings("Convert2Lambda")
public static void onMessage(PacketNetworkItems message, PlayPayloadContext ctx) {
ctx.workHandler().execute(new Runnable() {
@Override
public void run() {
var mc = Minecraft.getInstance();
if (mc.screen instanceof ItemTerminalGui terminal)
terminal.updateItemList(message.items, message.craftables, message.currentlyCrafting);
}
});
} }
} }

View file

@ -4,59 +4,39 @@ import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
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.network.FriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.network.handling.PlayPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
public class PacketRequest implements CustomPacketPayload { public record PacketRequest(BlockPos pos, ItemStack stack, int nbtHash, int amount) implements CustomPacketPayload {
public static final ResourceLocation ID = new ResourceLocation(PrettyPipes.ID, "request"); public static final Type<PacketRequest> TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "request"));
public static final StreamCodec<RegistryFriendlyByteBuf, PacketRequest> CODEC = StreamCodec.composite(
private final BlockPos pos; BlockPos.STREAM_CODEC, PacketRequest::pos,
private final ItemStack stack; ItemStack.STREAM_CODEC, PacketRequest::stack,
private final int nbtHash; ByteBufCodecs.INT, PacketRequest::nbtHash,
private final int amount; ByteBufCodecs.INT, PacketRequest::amount,
PacketRequest::new);
public PacketRequest(BlockPos pos, ItemStack stack, int amount) { public PacketRequest(BlockPos pos, ItemStack stack, int amount) {
this.pos = pos; this(pos, stack, stack.hasTag() ? stack.getTag().hashCode() : 0, amount);
this.stack = stack;
this.nbtHash = stack.hasTag() ? stack.getTag().hashCode() : 0;
this.amount = amount;
}
public PacketRequest(FriendlyByteBuf buf) {
this.pos = buf.readBlockPos();
this.stack = buf.readItem();
this.nbtHash = buf.readVarInt();
this.amount = buf.readVarInt();
} }
@Override @Override
public void write(FriendlyByteBuf buf) { public Type<? extends CustomPacketPayload> type() {
buf.writeBlockPos(this.pos); return PacketRequest.TYPE;
buf.writeItem(this.stack);
buf.writeVarInt(this.nbtHash);
buf.writeVarInt(this.amount);
} }
@Override public static void onMessage(PacketRequest message, IPayloadContext ctx) {
public ResourceLocation id() { var player = ctx.player();
return PacketRequest.ID; var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level(), message.pos);
} message.stack.setCount(message.amount);
tile.requestItem(player, message.stack, message.nbtHash);
@SuppressWarnings("Convert2Lambda")
public static void onMessage(PacketRequest message, PlayPayloadContext ctx) {
ctx.workHandler().execute(new Runnable() {
@Override
public void run() {
var player = ctx.player().orElseThrow();
var tile = Utility.getBlockEntity(ItemTerminalBlockEntity.class, player.level(), message.pos);
message.stack.setCount(message.amount);
tile.requestItem(player, message.stack, message.nbtHash);
}
});
} }
} }

View file

@ -5,6 +5,7 @@ import de.ellpeck.prettypipes.network.NetworkEdge;
import de.ellpeck.prettypipes.network.PipeItem; import de.ellpeck.prettypipes.network.PipeItem;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -12,18 +13,18 @@ import net.minecraft.world.level.Level;
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.common.util.INBTSerializable; import net.neoforged.neoforge.common.util.INBTSerializable;
import org.apache.commons.lang3.function.TriFunction;
import org.jgrapht.GraphPath; import org.jgrapht.GraphPath;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.function.BiFunction;
public interface IPipeItem extends INBTSerializable<CompoundTag> { public interface IPipeItem extends INBTSerializable<CompoundTag> {
Map<ResourceLocation, BiFunction<ResourceLocation, CompoundTag, IPipeItem>> TYPES = new HashMap<>( Map<ResourceLocation, TriFunction<HolderLookup.Provider, ResourceLocation, CompoundTag, IPipeItem>> TYPES = new HashMap<>(
Collections.singletonMap(PipeItem.TYPE, PipeItem::new)); Collections.singletonMap(PipeItem.TYPE, PipeItem::new));
ItemStack getContent(); ItemStack getContent();
@ -44,9 +45,10 @@ public interface IPipeItem extends INBTSerializable<CompoundTag> {
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
void render(PipeBlockEntity tile, PoseStack matrixStack, Random random, float partialTicks, int light, int overlay, MultiBufferSource source); void render(PipeBlockEntity tile, PoseStack matrixStack, Random random, float partialTicks, int light, int overlay, MultiBufferSource source);
static IPipeItem load(CompoundTag nbt) { static IPipeItem load(HolderLookup.Provider provider, CompoundTag nbt) {
var type = new ResourceLocation(nbt.getString("type")); var type = ResourceLocation.parse(nbt.getString("type"));
var func = IPipeItem.TYPES.get(type); var func = IPipeItem.TYPES.get(type);
return func != null ? func.apply(type, nbt) : null; return func != null ? func.apply(provider, type, nbt) : null;
} }
} }

View file

@ -10,7 +10,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.tags.FluidTags; import net.minecraft.tags.FluidTags;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
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;
@ -54,13 +54,13 @@ public class PipeBlock extends BaseEntityBlock implements SimpleWaterloggedBlock
private static final Map<Pair<BlockState, BlockState>, VoxelShape> COLL_SHAPE_CACHE = new HashMap<>(); private static final Map<Pair<BlockState, BlockState>, VoxelShape> COLL_SHAPE_CACHE = new HashMap<>();
private static final VoxelShape CENTER_SHAPE = Block.box(5, 5, 5, 11, 11, 11); private static final VoxelShape CENTER_SHAPE = Block.box(5, 5, 5, 11, 11, 11);
public static final Map<Direction, VoxelShape> DIR_SHAPES = ImmutableMap.<Direction, VoxelShape>builder() public static final Map<Direction, VoxelShape> DIR_SHAPES = ImmutableMap.<Direction, VoxelShape>builder()
.put(Direction.UP, Block.box(5, 10, 5, 11, 16, 11)) .put(Direction.UP, Block.box(5, 10, 5, 11, 16, 11))
.put(Direction.DOWN, Block.box(5, 0, 5, 11, 6, 11)) .put(Direction.DOWN, Block.box(5, 0, 5, 11, 6, 11))
.put(Direction.NORTH, Block.box(5, 5, 0, 11, 11, 6)) .put(Direction.NORTH, Block.box(5, 5, 0, 11, 11, 6))
.put(Direction.SOUTH, Block.box(5, 5, 10, 11, 11, 16)) .put(Direction.SOUTH, Block.box(5, 5, 10, 11, 11, 16))
.put(Direction.EAST, Block.box(10, 5, 5, 16, 11, 11)) .put(Direction.EAST, Block.box(10, 5, 5, 16, 11, 11))
.put(Direction.WEST, Block.box(0, 5, 5, 6, 11, 11)) .put(Direction.WEST, Block.box(0, 5, 5, 6, 11, 11))
.build(); .build();
static { static {
for (var dir : Direction.values()) for (var dir : Direction.values())
@ -77,12 +77,12 @@ public class PipeBlock extends BaseEntityBlock implements SimpleWaterloggedBlock
} }
@Override @Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) { public ItemInteractionResult useItemOn(ItemStack pStack, BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) {
var tile = Utility.getBlockEntity(PipeBlockEntity.class, worldIn, pos); var tile = Utility.getBlockEntity(PipeBlockEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return InteractionResult.PASS; return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
if (!tile.canHaveModules()) if (!tile.canHaveModules())
return InteractionResult.PASS; return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
var stack = player.getItemInHand(handIn); var stack = player.getItemInHand(handIn);
if (stack.getItem() instanceof IModule) { if (stack.getItem() instanceof IModule) {
var copy = stack.copy(); var copy = stack.copy();
@ -90,14 +90,14 @@ public class PipeBlock extends BaseEntityBlock implements SimpleWaterloggedBlock
var remain = ItemHandlerHelper.insertItem(tile.modules, copy, false); var remain = ItemHandlerHelper.insertItem(tile.modules, copy, false);
if (remain.isEmpty()) { if (remain.isEmpty()) {
stack.shrink(1); stack.shrink(1);
return InteractionResult.SUCCESS; return ItemInteractionResult.SUCCESS;
} }
} else if (handIn == InteractionHand.MAIN_HAND && stack.isEmpty()) { } else if (handIn == InteractionHand.MAIN_HAND && stack.isEmpty()) {
if (!worldIn.isClientSide) if (!worldIn.isClientSide)
player.openMenu(tile, pos); player.openMenu(tile, pos);
return InteractionResult.SUCCESS; return ItemInteractionResult.SUCCESS;
} }
return InteractionResult.PASS; return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
} }
@Override @Override

View file

@ -97,7 +97,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
super.saveAdditional(compound, provider); super.saveAdditional(compound, provider);
compound.put("modules", this.modules.serializeNBT(provider)); compound.put("modules", this.modules.serializeNBT(provider));
compound.putInt("module_drop_check", this.moduleDropCheck); compound.putInt("module_drop_check", this.moduleDropCheck);
compound.put("requests", Utility.serializeAll(this.craftIngredientRequests)); compound.put("requests", Utility.serializeAll(provider, this.craftIngredientRequests));
if (this.cover != null) if (this.cover != null)
compound.put("cover", NbtUtils.writeBlockState(this.cover)); compound.put("cover", NbtUtils.writeBlockState(this.cover));
var results = new ListTag(); var results = new ListTag();
@ -122,8 +122,8 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
for (var i = 0; i < results.size(); i++) { for (var i = 0; i < results.size(); i++) {
var nbt = results.getCompound(i); var nbt = results.getCompound(i);
this.craftResultRequests.add(Pair.of( this.craftResultRequests.add(Pair.of(
BlockPos.of(nbt.getLong("dest_pipe")), BlockPos.of(nbt.getLong("dest_pipe")),
ItemStack.parseOptional(provider, nbt.getCompound("item")))); ItemStack.parseOptional(provider, nbt.getCompound("item"))));
} }
super.loadAdditional(compound, provider); super.loadAdditional(compound, provider);
} }
@ -132,7 +132,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
public CompoundTag getUpdateTag(HolderLookup.Provider provider) { public CompoundTag getUpdateTag(HolderLookup.Provider provider) {
// sync pipe items on load // sync pipe items on load
var nbt = this.saveWithoutMetadata(provider); var nbt = this.saveWithoutMetadata(provider);
nbt.put("items", Utility.serializeAll(this.getItems())); nbt.put("items", Utility.serializeAll(provider, this.getItems()));
return nbt; return nbt;
} }
@ -280,8 +280,8 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
public List<ItemStack> getAllCraftables() { public List<ItemStack> getAllCraftables() {
return this.streamModules() return this.streamModules()
.flatMap(m -> m.getRight().getAllCraftables(m.getLeft(), this).stream()) .flatMap(m -> m.getRight().getAllCraftables(m.getLeft(), this).stream())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) { public int getCraftableAmount(Consumer<ItemStack> unavailableConsumer, ItemStack stack, Stack<ItemStack> dependencyChain) {
@ -374,8 +374,8 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
public int getNextNode(List<BlockPos> nodes, int index) { public int getNextNode(List<BlockPos> nodes, int index) {
return this.streamModules() return this.streamModules()
.map(m -> m.getRight().getCustomNextNode(m.getLeft(), this, nodes, index)) .map(m -> m.getRight().getCustomNextNode(m.getLeft(), this, nodes, index))
.filter(m -> m != null && m >= 0).findFirst().orElse(index); .filter(m -> m != null && m >= 0).findFirst().orElse(index);
} }
public List<ItemFilter> getFilters(Direction direction) { public List<ItemFilter> getFilters(Direction direction) {

View file

@ -144,7 +144,7 @@ public abstract class AbstractPipeGui<T extends AbstractPipeContainer<?>> extend
return false; return false;
if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 28 || mouseY >= this.y + 32) if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 28 || mouseY >= this.y + 32)
return false; return false;
PacketDistributor.sendToServer(new PacketButton(AbstractPipeGui.this.menu.tile.getBlockPos(), PacketButton.ButtonResult.PIPE_TAB, this.index)); PacketDistributor.sendToServer(new PacketButton(AbstractPipeGui.this.menu.tile.getBlockPos(), PacketButton.ButtonResult.PIPE_TAB, List.of(this.index)));
AbstractPipeGui.this.getMinecraft().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1)); AbstractPipeGui.this.getMinecraft().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1));
return true; return true;
} }

View file

@ -134,7 +134,7 @@ public class FilterModifierModuleGui extends AbstractPipeGui<FilterModifierModul
return false; return false;
if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 140 || mouseY >= this.y + 12) if (mouseX < this.x || mouseY < this.y || mouseX >= this.x + 140 || mouseY >= this.y + 12)
return false; return false;
PacketButton.sendAndExecute(FilterModifierModuleGui.this.menu.tile.getBlockPos(), PacketButton.ButtonResult.TAG_FILTER, FilterModifierModuleGui.this.tags.indexOf(this.tag)); PacketButton.sendAndExecute(FilterModifierModuleGui.this.menu.tile.getBlockPos(), PacketButton.ButtonResult.TAG_FILTER, List.of(FilterModifierModuleGui.this.tags.indexOf(this.tag)));
FilterModifierModuleGui.this.getMinecraft().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1)); FilterModifierModuleGui.this.getMinecraft().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1));
return true; return true;
} }

View file

@ -11,6 +11,7 @@ import net.minecraft.client.resources.language.I18n;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
public class StackSizeModuleGui extends AbstractPipeGui<StackSizeModuleContainer> { public class StackSizeModuleGui extends AbstractPipeGui<StackSizeModuleContainer> {
@ -40,11 +41,11 @@ public class StackSizeModuleGui extends AbstractPipeGui<StackSizeModuleContainer
if (s.isEmpty()) if (s.isEmpty())
return; return;
var amount = Integer.parseInt(s); var amount = Integer.parseInt(s);
PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), ButtonResult.STACK_SIZE_AMOUNT, amount); PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), ButtonResult.STACK_SIZE_AMOUNT, List.of(amount));
}); });
Supplier<Component> buttonText = () -> Component.translatable("info." + PrettyPipes.ID + ".limit_to_max_" + (StackSizeModuleItem.getLimitToMaxStackSize(this.menu.moduleStack) ? "on" : "off")); Supplier<Component> buttonText = () -> Component.translatable("info." + PrettyPipes.ID + ".limit_to_max_" + (StackSizeModuleItem.getLimitToMaxStackSize(this.menu.moduleStack) ? "on" : "off"));
this.addRenderableWidget(Button.builder(buttonText.get(), b -> { this.addRenderableWidget(Button.builder(buttonText.get(), b -> {
PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), ButtonResult.STACK_SIZE_MODULE_BUTTON); PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), ButtonResult.STACK_SIZE_MODULE_BUTTON, List.of());
b.setMessage(buttonText.get()); b.setMessage(buttonText.get());
}).bounds(this.leftPos + 7, this.topPos + 17 + 32 + 10 + 22, 120, 20).build()); }).bounds(this.leftPos + 7, this.topPos + 17 + 32 + 10 + 22, 120, 20).build());
} }
@ -55,4 +56,5 @@ public class StackSizeModuleGui extends AbstractPipeGui<StackSizeModuleContainer
graphics.drawString(this.font, I18n.get("info." + PrettyPipes.ID + ".max_stack_size") + ":", 7, 17 + 32, 4210752, false); graphics.drawString(this.font, I18n.get("info." + PrettyPipes.ID + ".max_stack_size") + ":", 7, 17 + 32, 4210752, false);
} }
} }

View file

@ -6,12 +6,11 @@ import de.ellpeck.prettypipes.Utility;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock; import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.RenderShape;
@ -22,7 +21,6 @@ import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class PressurizerBlock extends BaseEntityBlock { public class PressurizerBlock extends BaseEntityBlock {
@ -39,7 +37,7 @@ public class PressurizerBlock extends BaseEntityBlock {
} }
@Override @Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult result) { public InteractionResult useWithoutItem(BlockState state, Level worldIn, BlockPos pos, Player player, BlockHitResult result) {
var tile = Utility.getBlockEntity(PressurizerBlockEntity.class, worldIn, pos); var tile = Utility.getBlockEntity(PressurizerBlockEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return InteractionResult.PASS; return InteractionResult.PASS;
@ -60,8 +58,8 @@ public class PressurizerBlock extends BaseEntityBlock {
} }
@Override @Override
public void appendHoverText(ItemStack stack, @Nullable BlockGetter worldIn, List<Component> tooltip, TooltipFlag flagIn) { public void appendHoverText(ItemStack pStack, Item.TooltipContext pContext, List<Component> pTooltipComponents, TooltipFlag pTooltipFlag) {
Utility.addTooltip(BuiltInRegistries.BLOCK.getKey(this).getPath(), tooltip); Utility.addTooltip(BuiltInRegistries.BLOCK.getKey(this).getPath(), pTooltipComponents);
} }
@org.jetbrains.annotations.Nullable @org.jetbrains.annotations.Nullable

View file

@ -13,6 +13,7 @@ import de.ellpeck.prettypipes.terminal.containers.CraftingTerminalContainer;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
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.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.Style; import net.minecraft.network.chat.Style;
@ -78,8 +79,8 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
var network = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT)); var network = this.networkItems.get(new EquatableItemStack(stack, ItemEquality.NBT));
if (network != null) { if (network != null) {
amount = network.getLocations().stream() amount = network.getLocations().stream()
.mapToInt(l -> l.getItemAmount(this.level, stack, ItemEquality.NBT)) .mapToInt(l -> l.getItemAmount(this.level, stack, ItemEquality.NBT))
.sum(); .sum();
} }
// check craftables // check craftables
if (amount <= 0 && highestAmount <= 0) { if (amount <= 0 && highestAmount <= 0) {
@ -99,7 +100,7 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
if (!this.level.isClientSide) { if (!this.level.isClientSide) {
List<PacketGhostSlot.Entry> clients = new ArrayList<>(); List<PacketGhostSlot.Entry> clients = new ArrayList<>();
for (var i = 0; i < this.ghostItems.getSlots(); i++) for (var i = 0; i < this.ghostItems.getSlots(); i++)
clients.add(new PacketGhostSlot.Entry(this.level, Collections.singletonList(this.ghostItems.getStackInSlot(i)))); clients.add(PacketGhostSlot.Entry.fromStacks(this.level, List.of(this.ghostItems.getStackInSlot(i))));
PacketDistributor.sendToPlayersTrackingChunk((ServerLevel) this.level, new ChunkPos(this.getBlockPos()), new PacketGhostSlot(this.getBlockPos(), clients)); PacketDistributor.sendToPlayersTrackingChunk((ServerLevel) this.level, new ChunkPos(this.getBlockPos()), new PacketGhostSlot(this.getBlockPos(), clients));
} }
} }
@ -139,15 +140,15 @@ public class CraftingTerminalBlockEntity extends ItemTerminalBlockEntity {
} }
@Override @Override
public void saveAdditional(CompoundTag compound) { public void saveAdditional(CompoundTag compound, HolderLookup.Provider provider) {
super.saveAdditional(compound); super.saveAdditional(compound, provider);
compound.put("craft_items", this.craftItems.serializeNBT()); compound.put("craft_items", this.craftItems.serializeNBT(provider));
} }
@Override @Override
public void load(CompoundTag compound) { public void loadAdditional(CompoundTag compound, HolderLookup.Provider provider) {
this.craftItems.deserializeNBT(compound.getCompound("craft_items")); this.craftItems.deserializeNBT(provider, compound.getCompound("craft_items"));
super.load(compound); super.loadAdditional(compound, provider);
} }
@Override @Override

View file

@ -109,8 +109,8 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
public String getInvalidTerminalReason() { public String getInvalidTerminalReason() {
var network = PipeNetwork.get(this.level); var network = PipeNetwork.get(this.level);
var pipes = Arrays.stream(Direction.values()) var pipes = Arrays.stream(Direction.values())
.map(d -> network.getPipe(this.worldPosition.relative(d))) .map(d -> network.getPipe(this.worldPosition.relative(d)))
.filter(Objects::nonNull).count(); .filter(Objects::nonNull).count();
if (pipes <= 0) if (pipes <= 0)
return "info." + PrettyPipes.ID + ".no_pipe_connected"; return "info." + PrettyPipes.ID + ".no_pipe_connected";
if (pipes > 1) if (pipes > 1)
@ -154,10 +154,10 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
if (nbtHash != 0) { if (nbtHash != 0) {
var filter = stack; var filter = stack;
stack = this.networkItems.values().stream() stack = this.networkItems.values().stream()
.map(NetworkItem::asStack) .map(NetworkItem::asStack)
// don't compare with nbt equality here or the whole hashing thing is pointless // don't compare with nbt equality here or the whole hashing thing is pointless
.filter(s -> ItemEquality.compareItems(s, filter) && s.hasTag() && s.getTag().hashCode() == nbtHash) .filter(s -> ItemEquality.compareItems(s, filter) && s.hasTag() && s.getTag().hashCode() == nbtHash)
.findFirst().orElse(filter); .findFirst().orElse(filter);
stack.setCount(filter.getCount()); stack.setCount(filter.getCount());
} }
var requested = this.requestItemImpl(stack, ItemTerminalBlockEntity.onItemUnavailable(player, false)); var requested = this.requestItemImpl(stack, ItemTerminalBlockEntity.onItemUnavailable(player, false));
@ -232,7 +232,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
public void saveAdditional(CompoundTag compound, HolderLookup.Provider pRegistries) { public void saveAdditional(CompoundTag compound, HolderLookup.Provider pRegistries) {
super.saveAdditional(compound, pRegistries); super.saveAdditional(compound, pRegistries);
compound.put("items", this.items.serializeNBT(pRegistries)); compound.put("items", this.items.serializeNBT(pRegistries));
compound.put("requests", Utility.serializeAll(this.existingRequests)); compound.put("requests", Utility.serializeAll(pRegistries, this.existingRequests));
} }
@Override @Override

View file

@ -11,6 +11,8 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import java.util.Arrays;
public class CraftingTerminalGui extends ItemTerminalGui { public class CraftingTerminalGui extends ItemTerminalGui {
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "textures/gui/crafting_terminal.png"); private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(PrettyPipes.ID, "textures/gui/crafting_terminal.png");
@ -28,7 +30,7 @@ public class CraftingTerminalGui extends ItemTerminalGui {
var amount = ItemTerminalGui.requestModifier(); var amount = ItemTerminalGui.requestModifier();
// also allow holding backspace instead of alt for people whose alt key is inaccessible (linux?) // also allow holding backspace instead of alt for people whose alt key is inaccessible (linux?)
var force = Screen.hasAltDown() || InputConstants.isKeyDown(this.minecraft.getWindow().getWindow(), 259) ? 1 : 0; var force = Screen.hasAltDown() || InputConstants.isKeyDown(this.minecraft.getWindow().getWindow(), 259) ? 1 : 0;
PacketDistributor.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, amount, force)); PacketDistributor.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CRAFT_TERMINAL_REQUEST, Arrays.asList(amount, force)));
}).bounds(this.leftPos + 8, this.topPos + 100, 50, 20).build()); }).bounds(this.leftPos + 8, this.topPos + 100, 50, 20).build());
this.tick(); this.tick();
} }

View file

@ -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)); PacketDistributor.sendToServer(new PacketButton(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.CANCEL_CRAFTING, List.of()));
return true; return true;
} }
} }