From b351c8cee1b410fc4644ab8734ec3dec206a0c4a Mon Sep 17 00:00:00 2001 From: Basique Evangelist Date: Tue, 28 Mar 2023 21:23:55 +0300 Subject: [PATCH] epic packet dump rewrite (also makes bundle packets work) --- .../client/config/GadgetConfigScreen.java | 2 +- .../config/RemappingListOptionContainer.java | 4 +- .../gadget/client/dump/DumpStatsScreen.java | 12 ++-- .../gadget/client/dump/ErrorPacket.java | 40 ----------- .../gadget/client/dump/OpenDumpScreen.java | 16 ++--- .../gadget/client/dump/PacketDumpReader.java | 17 +---- .../gadget/client/dump/PacketDumper.java | 26 ++----- .../client/dump/ProcessedDumpedPacket.java | 26 +++++-- .../dump/handler/DrawPacketHandler.java | 6 +- .../client/dump/handler/OwoSupport.java | 4 +- .../client/dump/handler/PacketHandlers.java | 9 ++- .../gadget/client/field/FieldDataIsland.java | 10 +-- .../gadget/client/field/FieldDataScreen.java | 14 ++-- .../client/gui/BasedVerticalFlowLayout.java | 6 +- .../wispforest/gadget/client/gui/GuiUtil.java | 5 +- .../gadget/client/gui/NotificationToast.java | 4 +- .../gadget/client/gui/SubObjectContainer.java | 5 +- .../gadget/client/nbt/NbtDataIsland.java | 18 +++-- .../gadget/client/nbt/StackNbtDataScreen.java | 14 ++-- .../client/resource/ViewClassesScreen.java | 27 ++++--- .../gadget/dump/FakeGadgetPacket.java | 30 ++++++++ .../gadget/dump/GadgetBundlePacket.java | 67 +++++++++++++++++ .../gadget/dump/GadgetReadErrorPacket.java | 26 +++++++ .../gadget/dump/GadgetWriteErrorPacket.java | 34 +++++++++ .../wispforest/gadget/dump/PacketDumping.java | 71 +++++++++++++++++++ .../wispforest/gadget/util/NetworkUtil.java | 29 ++++++++ .../wispforest/gadget/util/SupplierUtil.java | 37 ++++++++++ .../resources/assets/gadget/lang/en_us.json | 7 ++ 28 files changed, 409 insertions(+), 157 deletions(-) delete mode 100644 src/main/java/io/wispforest/gadget/client/dump/ErrorPacket.java create mode 100644 src/main/java/io/wispforest/gadget/dump/FakeGadgetPacket.java create mode 100644 src/main/java/io/wispforest/gadget/dump/GadgetBundlePacket.java create mode 100644 src/main/java/io/wispforest/gadget/dump/GadgetReadErrorPacket.java create mode 100644 src/main/java/io/wispforest/gadget/dump/GadgetWriteErrorPacket.java create mode 100644 src/main/java/io/wispforest/gadget/dump/PacketDumping.java create mode 100644 src/main/java/io/wispforest/gadget/util/SupplierUtil.java diff --git a/src/main/java/io/wispforest/gadget/client/config/GadgetConfigScreen.java b/src/main/java/io/wispforest/gadget/client/config/GadgetConfigScreen.java index 9afc106..731961e 100644 --- a/src/main/java/io/wispforest/gadget/client/config/GadgetConfigScreen.java +++ b/src/main/java/io/wispforest/gadget/client/config/GadgetConfigScreen.java @@ -51,7 +51,7 @@ public GadgetConfigScreen(@Nullable Screen parent) { FieldPathStep::remapFieldId, id -> MappingsManager.displayMappings().unmapFieldId(id) ); - return new OptionComponentFactory.Result(layout, layout); + return new OptionComponentFactory.Result<>(layout, layout); }); } } diff --git a/src/main/java/io/wispforest/gadget/client/config/RemappingListOptionContainer.java b/src/main/java/io/wispforest/gadget/client/config/RemappingListOptionContainer.java index 3c29175..a6f3374 100644 --- a/src/main/java/io/wispforest/gadget/client/config/RemappingListOptionContainer.java +++ b/src/main/java/io/wispforest/gadget/client/config/RemappingListOptionContainer.java @@ -5,7 +5,7 @@ import io.wispforest.owo.config.Option; import io.wispforest.owo.config.annotation.Expanded; import io.wispforest.owo.config.ui.component.ConfigTextBox; -import io.wispforest.owo.config.ui.component.OptionComponent; +import io.wispforest.owo.config.ui.component.OptionValueProvider; import io.wispforest.owo.config.ui.component.SearchAnchorComponent; import io.wispforest.owo.ops.TextOps; import io.wispforest.owo.ui.component.ButtonComponent; @@ -29,7 +29,7 @@ import net.minecraft.util.Formatting; @SuppressWarnings("UnstableApiUsage") -public class RemappingListOptionContainer extends CollapsibleContainer implements OptionComponent { +public class RemappingListOptionContainer extends CollapsibleContainer implements Component, OptionValueProvider { protected final Option> backingOption; protected final List backingList; diff --git a/src/main/java/io/wispforest/gadget/client/dump/DumpStatsScreen.java b/src/main/java/io/wispforest/gadget/client/dump/DumpStatsScreen.java index ad12896..933ddbc 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/DumpStatsScreen.java +++ b/src/main/java/io/wispforest/gadget/client/dump/DumpStatsScreen.java @@ -5,8 +5,8 @@ import io.wispforest.owo.ui.base.BaseOwoScreen; import io.wispforest.owo.ui.component.Components; import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; -import io.wispforest.owo.ui.container.VerticalFlowLayout; import io.wispforest.owo.ui.core.*; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.MutableText; @@ -16,7 +16,7 @@ import java.util.*; -public class DumpStatsScreen extends BaseOwoScreen { +public class DumpStatsScreen extends BaseOwoScreen { private final Map packetTypes = new HashMap<>(); private final Screen parent; private final List packets; @@ -34,19 +34,19 @@ public DumpStatsScreen(Screen parent, List packets) { } @Override - protected @NotNull OwoUIAdapter createAdapter() { + protected @NotNull OwoUIAdapter createAdapter() { return OwoUIAdapter.create(this, Containers::verticalFlow); } @Override - protected void build(VerticalFlowLayout rootComponent) { + protected void build(FlowLayout rootComponent) { rootComponent .horizontalAlignment(HorizontalAlignment.CENTER) .verticalAlignment(VerticalAlignment.CENTER) .surface(Surface.VANILLA_TRANSLUCENT); - VerticalFlowLayout main = new BasedVerticalFlowLayout(Sizing.fill(100), Sizing.content()); - ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(90), main) + FlowLayout main = new BasedVerticalFlowLayout(Sizing.fill(100), Sizing.content()); + ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(90), main) .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0FFFFFF))); packetTypes diff --git a/src/main/java/io/wispforest/gadget/client/dump/ErrorPacket.java b/src/main/java/io/wispforest/gadget/client/dump/ErrorPacket.java deleted file mode 100644 index 05957c5..0000000 --- a/src/main/java/io/wispforest/gadget/client/dump/ErrorPacket.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.wispforest.gadget.client.dump; - -import net.minecraft.network.packet.Packet; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.listener.PacketListener; - -public class ErrorPacket implements Packet { - private final byte[] data; - private final int packetId; - private final Exception exception; - - public ErrorPacket(PacketByteBuf buf, int packetId, Exception exception) { - this.data = new byte[buf.readableBytes()]; - this.packetId = packetId; - this.exception = exception; - buf.readBytes(this.data); - } - - @Override - public void write(PacketByteBuf buf) { - buf.writeBytes(data); - } - - public byte[] getData() { - return data; - } - - public int getPacketId() { - return packetId; - } - - public Exception getException() { - return exception; - } - - @Override - public void apply(PacketListener listener) { - throw new UnsupportedOperationException("bruh"); - } -} diff --git a/src/main/java/io/wispforest/gadget/client/dump/OpenDumpScreen.java b/src/main/java/io/wispforest/gadget/client/dump/OpenDumpScreen.java index 1c17034..77f54ad 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/OpenDumpScreen.java +++ b/src/main/java/io/wispforest/gadget/client/dump/OpenDumpScreen.java @@ -25,11 +25,11 @@ import java.util.List; import java.util.concurrent.CompletableFuture; -public class OpenDumpScreen extends BaseOwoScreen { +public class OpenDumpScreen extends BaseOwoScreen { private final Screen parent; private ProgressToast toast; private final List packets; - private VerticalFlowLayout main; + private FlowLayout main; private FlowLayout infoButton; private BasedSliderComponent timeSlider; private final long startTime; @@ -82,19 +82,19 @@ public static void openWithProgress(Screen parent, Path path) { } @Override - protected @NotNull OwoUIAdapter createAdapter() { + protected @NotNull OwoUIAdapter createAdapter() { return OwoUIAdapter.create(this, Containers::verticalFlow); } @Override - protected void build(VerticalFlowLayout rootComponent) { + protected void build(FlowLayout rootComponent) { rootComponent .horizontalAlignment(HorizontalAlignment.CENTER) .verticalAlignment(VerticalAlignment.CENTER) .surface(Surface.VANILLA_TRANSLUCENT); this.main = new BasedVerticalFlowLayout(Sizing.fill(100), Sizing.content()); - ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(90), this.main) + ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(90), this.main) .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0FFFFFF))); var searchBox = Components.textBox(Sizing.fill(95)); @@ -140,9 +140,9 @@ protected void build(VerticalFlowLayout rootComponent) { rebuild("", startTime); - VerticalFlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content()); + FlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content()); - infoButton = new VerticalFlowLayout(Sizing.fixed(16), Sizing.fixed(16)) { + infoButton = new FlowLayout(Sizing.fixed(16), Sizing.fixed(16), FlowLayout.Algorithm.VERTICAL) { private int totalComponents = -1; private int frameNumber = 11; @@ -191,7 +191,7 @@ public void drawTooltip(MatrixStack matrices, int mouseX, int mouseY, float part infoButton.mouseLeave().subscribe( () -> infoButton.surface(Surface.BLANK)); - VerticalFlowLayout statsButton = Containers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16)); + FlowLayout statsButton = Containers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16)); statsButton .child(Components.label(Text.translatable("text.gadget.stats")) diff --git a/src/main/java/io/wispforest/gadget/client/dump/PacketDumpReader.java b/src/main/java/io/wispforest/gadget/client/dump/PacketDumpReader.java index d63547d..42d7d30 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/PacketDumpReader.java +++ b/src/main/java/io/wispforest/gadget/client/dump/PacketDumpReader.java @@ -1,5 +1,6 @@ package io.wispforest.gadget.client.dump; +import io.wispforest.gadget.dump.PacketDumping; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import io.wispforest.gadget.util.NetworkUtil; @@ -54,9 +55,8 @@ public static List readV0(InputStream is) throws IOException { case 0b0110 -> NetworkState.LOGIN; default -> throw new IllegalStateException(); }; - int packetId = buf.readVarInt(); int size = buf.readableBytes(); - Packet packet = readPacket(packetId, state, outbound, buf); + Packet packet = PacketDumping.readPacket(buf, state, outbound ? NetworkSide.SERVERBOUND : NetworkSide.CLIENTBOUND); Identifier channelId = NetworkUtil.getChannelOrNull(packet); if (packet instanceof LoginQueryRequestS2CPacket req) { @@ -118,9 +118,8 @@ private static List readV1(DataInputStream is) throws IOException default -> throw new IllegalStateException(); }; long sentAt = buf.readLong(); - int packetId = buf.readVarInt(); int size = buf.readableBytes(); - Packet packet = readPacket(packetId, state, outbound, buf); + Packet packet = PacketDumping.readPacket(buf, state, outbound ? NetworkSide.SERVERBOUND : NetworkSide.CLIENTBOUND); Identifier channelId = NetworkUtil.getChannelOrNull(packet); if (packet instanceof LoginQueryRequestS2CPacket req) { @@ -137,14 +136,4 @@ private static List readV1(DataInputStream is) throws IOException } } - private static Packet readPacket(int packetId, NetworkState state, boolean outbound, PacketByteBuf buf) { - int startOfData = buf.readerIndex(); - - try { - return state.getPacketHandler(outbound ? NetworkSide.SERVERBOUND : NetworkSide.CLIENTBOUND, packetId, buf); - } catch (Exception e) { - buf.readerIndex(startOfData); - return new ErrorPacket(buf, packetId, e); - } - } } diff --git a/src/main/java/io/wispforest/gadget/client/dump/PacketDumper.java b/src/main/java/io/wispforest/gadget/client/dump/PacketDumper.java index c456a0c..86ffe5d 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/PacketDumper.java +++ b/src/main/java/io/wispforest/gadget/client/dump/PacketDumper.java @@ -2,6 +2,8 @@ import io.wispforest.gadget.Gadget; import io.wispforest.gadget.client.gui.NotificationToast; +import io.wispforest.gadget.dump.PacketDumping; +import io.wispforest.gadget.util.NetworkUtil; import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; @@ -100,27 +102,13 @@ public static void dump(boolean outbound, Packet packet) { case LOGIN -> flags |= 0b0110; } - buf.writeInt(0); - buf.writeShort(flags); + try (var lengthWriter = NetworkUtil.writeByteLength(buf)) { + buf.writeShort(flags); - buf.writeLong(System.currentTimeMillis()); + buf.writeLong(System.currentTimeMillis()); - int packetId = state.getPacketId(outbound ? NetworkSide.SERVERBOUND : NetworkSide.CLIENTBOUND, packet); - - // TODO: fix bundle packets. - if (packetId == -1) - throw new UnsupportedOperationException("Invalid packet: " + packet); - - buf.writeVarInt(packetId); - - packet.write(buf); - - int totalLength = buf.readableBytes(); - int prevWriterIdx = buf.writerIndex(); - - buf.writerIndex(0); - buf.writeInt(totalLength - 4); - buf.writerIndex(prevWriterIdx); + PacketDumping.writePacket(buf, packet, state, outbound ? NetworkSide.SERVERBOUND : NetworkSide.CLIENTBOUND); + } ByteBuffer nioBuf = buf.nioBuffer(); diff --git a/src/main/java/io/wispforest/gadget/client/dump/ProcessedDumpedPacket.java b/src/main/java/io/wispforest/gadget/client/dump/ProcessedDumpedPacket.java index b051a09..978b07f 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/ProcessedDumpedPacket.java +++ b/src/main/java/io/wispforest/gadget/client/dump/ProcessedDumpedPacket.java @@ -5,6 +5,8 @@ import io.wispforest.gadget.client.gui.BasedLabelComponent; import io.wispforest.gadget.client.gui.GuiUtil; import io.wispforest.gadget.client.gui.LayoutCacheWrapper; +import io.wispforest.gadget.dump.GadgetReadErrorPacket; +import io.wispforest.gadget.dump.GadgetWriteErrorPacket; import io.wispforest.gadget.util.ReflectionUtil; import io.wispforest.owo.ui.container.*; import io.wispforest.owo.ui.core.*; @@ -29,7 +31,7 @@ public DumpedPacket packet() { public Component component() { if (component == null || component.get() == null) { - VerticalFlowLayout view = Containers.verticalFlow(Sizing.content(), Sizing.content()); + FlowLayout view = Containers.verticalFlow(Sizing.content(), Sizing.content()); view .padding(Insets.of(5)) @@ -40,8 +42,10 @@ public Component component() { MutableText typeText = Text.literal(""); - if (packet.packet() instanceof ErrorPacket errorPacket) { - typeText.append(Text.translatable("text.gadget.packet_read_error", errorPacket.getPacketId())); + if (packet.packet() instanceof GadgetReadErrorPacket errorPacket) { + typeText.append(Text.translatable("text.gadget.packet_read_error", errorPacket.packetId())); + } else if (packet.packet() instanceof GadgetWriteErrorPacket errorPacket) { + typeText.append(Text.translatable("text.gadget.packet_write_error", errorPacket.packetId())); } else { typeText.append(ReflectionUtil.nameWithoutPackage(packet.packet().getClass())); @@ -55,7 +59,10 @@ public Component component() { DrawPacketHandler.EVENT.invoker().onDrawPacket(packet, view); - if (!packet.drawErrors().isEmpty() || !packet.searchTextErrors().isEmpty() || packet.packet() instanceof ErrorPacket) { + if (!packet.drawErrors().isEmpty() + || !packet.searchTextErrors().isEmpty() + || packet.packet() instanceof GadgetReadErrorPacket + || packet.packet() instanceof GadgetWriteErrorPacket) { CollapsibleContainer errors = Containers.collapsible( Sizing.content(), Sizing.content(), @@ -70,8 +77,13 @@ public Component component() { ((FlowLayout) errors.children().get(0)) .padding(Insets.of(2, 2, 2, 0)); - if (packet.packet() instanceof ErrorPacket error) { - errors.child(GuiUtil.showException(error.getException()) + if (packet.packet() instanceof GadgetReadErrorPacket error) { + errors.child(GuiUtil.showException(error.exception()) + .margins(Insets.bottom(2))); + } + + if (packet.packet() instanceof GadgetWriteErrorPacket error) { + errors.child(GuiUtil.showExceptionText(error.exceptionText()) .margins(Insets.bottom(2))); } @@ -88,7 +100,7 @@ public Component component() { view.child(1, errors); } - HorizontalFlowLayout fullRow = Containers.horizontalFlow(Sizing.fill(100), Sizing.content()); + FlowLayout fullRow = Containers.horizontalFlow(Sizing.fill(100), Sizing.content()); fullRow .child(view) diff --git a/src/main/java/io/wispforest/gadget/client/dump/handler/DrawPacketHandler.java b/src/main/java/io/wispforest/gadget/client/dump/handler/DrawPacketHandler.java index 22d0f16..31fc2d9 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/handler/DrawPacketHandler.java +++ b/src/main/java/io/wispforest/gadget/client/dump/handler/DrawPacketHandler.java @@ -2,7 +2,7 @@ import io.wispforest.gadget.client.dump.DumpedPacket; import io.wispforest.gadget.util.NetworkUtil; -import io.wispforest.owo.ui.container.VerticalFlowLayout; +import io.wispforest.owo.ui.container.FlowLayout; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; @@ -11,7 +11,7 @@ public interface DrawPacketHandler { packet.drawErrors().clear(); for (var callback : callbacks) { - try (var reset = NetworkUtil.resetIndexes(packet.packet())) { + try (var ignored = NetworkUtil.resetIndexes(packet.packet())) { boolean result = callback.onDrawPacket(packet, view); if (result) return true; @@ -23,5 +23,5 @@ public interface DrawPacketHandler { return false; }); - boolean onDrawPacket(DumpedPacket packet, VerticalFlowLayout view); + boolean onDrawPacket(DumpedPacket packet, FlowLayout view); } \ No newline at end of file diff --git a/src/main/java/io/wispforest/gadget/client/dump/handler/OwoSupport.java b/src/main/java/io/wispforest/gadget/client/dump/handler/OwoSupport.java index abcbdab..c0559b7 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/handler/OwoSupport.java +++ b/src/main/java/io/wispforest/gadget/client/dump/handler/OwoSupport.java @@ -9,7 +9,7 @@ import io.wispforest.owo.particles.systems.ParticleSystem; import io.wispforest.owo.particles.systems.ParticleSystemController; import io.wispforest.owo.ui.component.Components; -import io.wispforest.owo.ui.container.VerticalFlowLayout; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.Insets; import io.wispforest.owo.util.VectorSerializer; import io.wispforest.gadget.util.NetworkUtil; @@ -156,7 +156,7 @@ public static void init() { // TODO: OwO handshake and config sync. } - private static void drawHandshakeMap(Map data, Text prefix, VerticalFlowLayout view) { + private static void drawHandshakeMap(Map data, Text prefix, FlowLayout view) { for (var entry : data.entrySet()) { view.child(Components.label( Text.literal("") diff --git a/src/main/java/io/wispforest/gadget/client/dump/handler/PacketHandlers.java b/src/main/java/io/wispforest/gadget/client/dump/handler/PacketHandlers.java index 5a5b371..491fc62 100644 --- a/src/main/java/io/wispforest/gadget/client/dump/handler/PacketHandlers.java +++ b/src/main/java/io/wispforest/gadget/client/dump/handler/PacketHandlers.java @@ -1,8 +1,9 @@ package io.wispforest.gadget.client.dump.handler; import io.wispforest.gadget.Gadget; -import io.wispforest.gadget.client.dump.ErrorPacket; +import io.wispforest.gadget.dump.GadgetReadErrorPacket; import io.wispforest.gadget.client.gui.GuiUtil; +import io.wispforest.gadget.dump.GadgetWriteErrorPacket; import io.wispforest.gadget.util.NetworkUtil; import io.wispforest.gadget.client.field.FieldDataIsland; import io.wispforest.gadget.util.ReflectionUtil; @@ -33,11 +34,13 @@ public static void init() { DrawPacketHandler.EVENT.addPhaseOrdering(Event.DEFAULT_PHASE, LAST_PHASE); DrawPacketHandler.EVENT.register(LAST_PHASE, (packet, view) -> { - if (packet.packet() instanceof ErrorPacket errorPacket) { - view.child(GuiUtil.hexDump(errorPacket.getData(), true)); + if (packet.packet() instanceof GadgetReadErrorPacket errorPacket) { + view.child(GuiUtil.hexDump(errorPacket.data(), true)); return true; } + if (packet.packet() instanceof GadgetWriteErrorPacket) return true; + if (packet.channelId() != null) { var buf = NetworkUtil.unwrapCustom(packet.packet()); byte[] bytes = new byte[buf.readableBytes()]; diff --git a/src/main/java/io/wispforest/gadget/client/field/FieldDataIsland.java b/src/main/java/io/wispforest/gadget/client/field/FieldDataIsland.java index 8a8f94c..a8443d2 100644 --- a/src/main/java/io/wispforest/gadget/client/field/FieldDataIsland.java +++ b/src/main/java/io/wispforest/gadget/client/field/FieldDataIsland.java @@ -14,7 +14,7 @@ import io.wispforest.gadget.util.WeakObservableDispatcher; import io.wispforest.owo.ui.component.Components; import io.wispforest.owo.ui.container.Containers; -import io.wispforest.owo.ui.container.VerticalFlowLayout; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.Insets; import io.wispforest.owo.ui.core.Sizing; import io.wispforest.gadget.network.FieldData; @@ -41,7 +41,7 @@ public class FieldDataIsland { } protected final Map fields = new TreeMap<>(); - private final VerticalFlowLayout mainContainer; + private final FlowLayout mainContainer; private Consumer pathRequester = path -> {}; private boolean shortenNames = false; private ComponentAdditionRound currentRound = null; @@ -103,11 +103,11 @@ public void shortenNames() { this.shortenNames = true; } - public VerticalFlowLayout mainContainer() { + public FlowLayout mainContainer() { return mainContainer; } - private void makeComponent(VerticalFlowLayout container, ObjectPath path, ClientFieldData data, ComponentAdditionRound round) { + private void makeComponent(FlowLayout container, ObjectPath path, ClientFieldData data, ComponentAdditionRound round) { var rowContainer = Containers.verticalFlow(Sizing.content(), Sizing.content()); var row = Containers.horizontalFlow(Sizing.content(), Sizing.content()); @@ -251,7 +251,7 @@ public void addFieldData(ObjectPath path, FieldData data) { currentRound = new ComponentAdditionRound(); ClientFieldData old = fields.get(path); - VerticalFlowLayout container; + FlowLayout container; if (path.steps().length == 1) { container = mainContainer; diff --git a/src/main/java/io/wispforest/gadget/client/field/FieldDataScreen.java b/src/main/java/io/wispforest/gadget/client/field/FieldDataScreen.java index 43db60c..283e19b 100644 --- a/src/main/java/io/wispforest/gadget/client/field/FieldDataScreen.java +++ b/src/main/java/io/wispforest/gadget/client/field/FieldDataScreen.java @@ -8,8 +8,8 @@ import io.wispforest.owo.ui.base.BaseOwoScreen; import io.wispforest.owo.ui.component.Components; import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; -import io.wispforest.owo.ui.container.VerticalFlowLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.ui.util.UISounds; import io.wispforest.gadget.path.ObjectPath; @@ -20,7 +20,7 @@ import java.util.Map; -public class FieldDataScreen extends BaseOwoScreen { +public class FieldDataScreen extends BaseOwoScreen { private final InspectionTarget target; private final boolean isClient; public FieldDataIsland island; @@ -56,21 +56,21 @@ public boolean isClient() { } @Override - protected @NotNull OwoUIAdapter createAdapter() { + protected @NotNull OwoUIAdapter createAdapter() { return OwoUIAdapter.create(this, Containers::verticalFlow); } @Override - protected void build(VerticalFlowLayout verticalFlowLayout) { + protected void build(FlowLayout verticalFlowLayout) { verticalFlowLayout .horizontalAlignment(HorizontalAlignment.CENTER) .verticalAlignment(VerticalAlignment.CENTER) .surface(Surface.VANILLA_TRANSLUCENT); - VerticalFlowLayout main = Containers.verticalFlow(Sizing.fill(100), Sizing.content()); + FlowLayout main = Containers.verticalFlow(Sizing.fill(100), Sizing.content()); - ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(100), main) + ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(100), main) .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0FFFFFF))); verticalFlowLayout.child(scroll.child(main)); @@ -80,7 +80,7 @@ protected void build(VerticalFlowLayout verticalFlowLayout) { main.child(island.mainContainer()); - VerticalFlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content()); + FlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content()); var switchButton = Containers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16)) .child(Components.label(Text.translatable("text.gadget." + (isClient() ? "client" : "server") + "_current")) diff --git a/src/main/java/io/wispforest/gadget/client/gui/BasedVerticalFlowLayout.java b/src/main/java/io/wispforest/gadget/client/gui/BasedVerticalFlowLayout.java index 318f1db..0ad780e 100644 --- a/src/main/java/io/wispforest/gadget/client/gui/BasedVerticalFlowLayout.java +++ b/src/main/java/io/wispforest/gadget/client/gui/BasedVerticalFlowLayout.java @@ -1,10 +1,10 @@ package io.wispforest.gadget.client.gui; -import io.wispforest.owo.ui.container.VerticalFlowLayout; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.Sizing; -public class BasedVerticalFlowLayout extends VerticalFlowLayout { +public class BasedVerticalFlowLayout extends FlowLayout { public BasedVerticalFlowLayout(Sizing horizontalSizing, Sizing verticalSizing) { - super(horizontalSizing, verticalSizing); + super(horizontalSizing, verticalSizing, Algorithm.VERTICAL); } } diff --git a/src/main/java/io/wispforest/gadget/client/gui/GuiUtil.java b/src/main/java/io/wispforest/gadget/client/gui/GuiUtil.java index 82a923c..a287ebb 100644 --- a/src/main/java/io/wispforest/gadget/client/gui/GuiUtil.java +++ b/src/main/java/io/wispforest/gadget/client/gui/GuiUtil.java @@ -69,6 +69,7 @@ public static ParentComponent root(Component component) { if (root == null) throw new IllegalStateException(); + //noinspection DataFlowIssue while (root.hasParent()) root = root.parent(); @@ -102,8 +103,10 @@ public static void textFieldVerifier(TextFieldWidget textField, Predicate adapter; + private final OwoUIAdapter adapter; private final MinecraftClient client = MinecraftClient.getInstance(); public NotificationToast(Text headText, Text messageText) { diff --git a/src/main/java/io/wispforest/gadget/client/gui/SubObjectContainer.java b/src/main/java/io/wispforest/gadget/client/gui/SubObjectContainer.java index 8a8997b..8f7b72a 100644 --- a/src/main/java/io/wispforest/gadget/client/gui/SubObjectContainer.java +++ b/src/main/java/io/wispforest/gadget/client/gui/SubObjectContainer.java @@ -2,7 +2,6 @@ import io.wispforest.owo.ui.component.LabelComponent; import io.wispforest.owo.ui.container.FlowLayout; -import io.wispforest.owo.ui.container.VerticalFlowLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.ui.util.Drawer; import io.wispforest.owo.ui.util.UISounds; @@ -16,7 +15,7 @@ import java.util.function.Consumer; // Copied from owo-ui's CollapsibleContainer -public class SubObjectContainer extends VerticalFlowLayout { +public class SubObjectContainer extends FlowLayout { public static final Surface SURFACE = (matrices, component) -> Drawer.fill(matrices, component.x() + 5, @@ -34,7 +33,7 @@ public class SubObjectContainer extends VerticalFlowLayout { protected final SpinnyBoiComponent spinnyBoi; public SubObjectContainer(Consumer loader, Consumer unloader) { - super(Sizing.content(), Sizing.content()); + super(Sizing.content(), Sizing.content(), Algorithm.VERTICAL); this.loader = loader; this.unloader = unloader; this.surface(SURFACE); diff --git a/src/main/java/io/wispforest/gadget/client/nbt/NbtDataIsland.java b/src/main/java/io/wispforest/gadget/client/nbt/NbtDataIsland.java index b4fa05d..f515100 100644 --- a/src/main/java/io/wispforest/gadget/client/nbt/NbtDataIsland.java +++ b/src/main/java/io/wispforest/gadget/client/nbt/NbtDataIsland.java @@ -6,8 +6,7 @@ import io.wispforest.owo.ui.component.Components; import io.wispforest.owo.ui.component.LabelComponent; import io.wispforest.owo.ui.container.Containers; -import io.wispforest.owo.ui.container.HorizontalFlowLayout; -import io.wispforest.owo.ui.container.VerticalFlowLayout; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.*; import net.minecraft.nbt.*; import net.minecraft.text.MutableText; @@ -19,14 +18,14 @@ import java.util.function.Consumer; import java.util.function.Predicate; -public class NbtDataIsland extends VerticalFlowLayout { +public class NbtDataIsland extends FlowLayout { private final Map elements = new HashMap<>(); final NbtCompound data; final Consumer reloader; public NbtDataIsland(NbtCompound data, Consumer reloader) { - super(Sizing.content(), Sizing.content()); + super(Sizing.content(), Sizing.content(), Algorithm.VERTICAL); this.data = data; this.reloader = reloader; @@ -37,9 +36,8 @@ public NbtDataIsland(NbtCompound data, Consumer reloader) { } void makeComponent(NbtPath path, NbtElement element) { - VerticalFlowLayout full = Containers.verticalFlow(Sizing.content(), Sizing.content()); - HorizontalFlowLayout row = Containers.horizontalFlow(Sizing.content(), Sizing.content()); - + FlowLayout full = Containers.verticalFlow(Sizing.content(), Sizing.content()); + FlowLayout row = Containers.horizontalFlow(Sizing.content(), Sizing.content()); full.child(row); var parentContainer = subContainerOf(path.parent()); @@ -186,7 +184,7 @@ else if (number instanceof NbtDouble) } } - VerticalFlowLayout target = subContainerOf(path.parent()); + FlowLayout target = subContainerOf(path.parent()); if (reloader != null) { var crossLabel = Components.label(Text.literal("❌")); @@ -262,7 +260,7 @@ public void reloadPath(NbtPath path) { } } - private VerticalFlowLayout subContainerOf(NbtPath path) { + private FlowLayout subContainerOf(NbtPath path) { if (path.steps().length == 0) return this; else @@ -270,7 +268,7 @@ private VerticalFlowLayout subContainerOf(NbtPath path) { } private static class WidgetData { - private VerticalFlowLayout fullContainer; + private FlowLayout fullContainer; private SubObjectContainer subContainer; } diff --git a/src/main/java/io/wispforest/gadget/client/nbt/StackNbtDataScreen.java b/src/main/java/io/wispforest/gadget/client/nbt/StackNbtDataScreen.java index 2e74d4a..dc522be 100644 --- a/src/main/java/io/wispforest/gadget/client/nbt/StackNbtDataScreen.java +++ b/src/main/java/io/wispforest/gadget/client/nbt/StackNbtDataScreen.java @@ -6,8 +6,8 @@ import io.wispforest.owo.ui.base.BaseOwoScreen; import io.wispforest.owo.ui.component.Components; import io.wispforest.owo.ui.container.Containers; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; -import io.wispforest.owo.ui.container.VerticalFlowLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.ui.util.UISounds; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; @@ -20,7 +20,7 @@ import java.util.function.Consumer; -public class StackNbtDataScreen extends BaseOwoScreen { +public class StackNbtDataScreen extends BaseOwoScreen { private final NbtDataIsland island; private final HandledScreen parent; @@ -50,21 +50,21 @@ public StackNbtDataScreen(HandledScreen parent, Slot slot) { } @Override - protected @NotNull OwoUIAdapter createAdapter() { + protected @NotNull OwoUIAdapter createAdapter() { return OwoUIAdapter.create(this, Containers::verticalFlow); } @Override - protected void build(VerticalFlowLayout rootComponent) { + protected void build(FlowLayout rootComponent) { rootComponent .horizontalAlignment(HorizontalAlignment.CENTER) .verticalAlignment(VerticalAlignment.CENTER) .surface(Surface.VANILLA_TRANSLUCENT); - VerticalFlowLayout main = Containers.verticalFlow(Sizing.fill(100), Sizing.content()); + FlowLayout main = Containers.verticalFlow(Sizing.fill(100), Sizing.content()); - ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(100), main) + ScrollContainer scroll = Containers.verticalScroll(Sizing.fill(95), Sizing.fill(100), main) .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0FFFFFF))); rootComponent.child(scroll.child(main)); @@ -74,7 +74,7 @@ protected void build(VerticalFlowLayout rootComponent) { main.child(island); - VerticalFlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content()); + FlowLayout sidebar = Containers.verticalFlow(Sizing.content(), Sizing.content()); var addButton = Containers.verticalFlow(Sizing.fixed(16), Sizing.fixed(16)) .child(Components.label(Text.literal("+")) diff --git a/src/main/java/io/wispforest/gadget/client/resource/ViewClassesScreen.java b/src/main/java/io/wispforest/gadget/client/resource/ViewClassesScreen.java index 42e42c3..8165114 100644 --- a/src/main/java/io/wispforest/gadget/client/resource/ViewClassesScreen.java +++ b/src/main/java/io/wispforest/gadget/client/resource/ViewClassesScreen.java @@ -13,9 +13,8 @@ import io.wispforest.owo.ui.base.BaseOwoScreen; import io.wispforest.owo.ui.component.Components; import io.wispforest.owo.ui.container.Containers; -import io.wispforest.owo.ui.container.HorizontalFlowLayout; +import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.container.ScrollContainer; -import io.wispforest.owo.ui.container.VerticalFlowLayout; import io.wispforest.owo.ui.core.*; import io.wispforest.owo.ui.util.UISounds; import net.minecraft.client.MinecraftClient; @@ -32,12 +31,12 @@ import java.util.*; import java.util.concurrent.ForkJoinPool; -public class ViewClassesScreen extends BaseOwoScreen { +public class ViewClassesScreen extends BaseOwoScreen { private final Screen parent; private final boolean showAll; private ProgressToast toast; - private ScrollContainer contentsScroll; - private final VerticalFlowLayout contents = Containers.verticalFlow(Sizing.content(), Sizing.content()); + private ScrollContainer contentsScroll; + private final FlowLayout contents = Containers.verticalFlow(Sizing.content(), Sizing.content()); private final QuiltflowerHandler decompiler; private String currentFileName = null; private String currentFileContents = null; @@ -80,18 +79,18 @@ public static void openWithProgress(Screen parent) { } @Override - protected @NotNull OwoUIAdapter createAdapter() { + protected @NotNull OwoUIAdapter createAdapter() { return OwoUIAdapter.create(this, Containers::horizontalFlow); } @Override - protected void build(HorizontalFlowLayout rootComponent) { + protected void build(FlowLayout rootComponent) { rootComponent .surface(Surface.VANILLA_TRANSLUCENT) .padding(Insets.of(5)); - VerticalFlowLayout tree = Containers.verticalFlow(Sizing.content(), Sizing.content()); - ScrollContainer treeScroll = Containers.verticalScroll(Sizing.fill(25), Sizing.fill(100), tree) + FlowLayout tree = Containers.verticalFlow(Sizing.content(), Sizing.content()); + ScrollContainer treeScroll = Containers.verticalScroll(Sizing.fill(25), Sizing.fill(100), tree) .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0FFFFFF))); contentsScroll = Containers.verticalScroll(Sizing.fill(72), Sizing.fill(100), contents) .scrollbar(ScrollContainer.Scrollbar.flat(Color.ofArgb(0xA0FFFFFF))); @@ -160,7 +159,7 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { return super.keyPressed(keyCode, scanCode, modifiers); } - private HorizontalFlowLayout makeRecipeRow(String name, String fullPath) { + private FlowLayout makeRecipeRow(String name, String fullPath) { var row = Containers.horizontalFlow(Sizing.content(), Sizing.content()); var fileLabel = Components.label(Text.literal(name)); @@ -265,9 +264,9 @@ public void close() { private static class TreeEntry { private final String name; private final List children = new ArrayList<>(); - private final VerticalFlowLayout container; + private final FlowLayout container; - private TreeEntry(String name, VerticalFlowLayout container) { + private TreeEntry(String name, FlowLayout container) { this.name = name; this.container = container; } @@ -280,8 +279,8 @@ public TreeEntry directory(String name) { SubObjectContainer sub = new SubObjectContainer(unused -> { }, unused -> { }); - VerticalFlowLayout entryContainer = Containers.verticalFlow(Sizing.content(), Sizing.content()); - HorizontalFlowLayout row = Containers.horizontalFlow(Sizing.content(), Sizing.content()); + FlowLayout entryContainer = Containers.verticalFlow(Sizing.content(), Sizing.content()); + FlowLayout row = Containers.horizontalFlow(Sizing.content(), Sizing.content()); container .child(entryContainer diff --git a/src/main/java/io/wispforest/gadget/dump/FakeGadgetPacket.java b/src/main/java/io/wispforest/gadget/dump/FakeGadgetPacket.java new file mode 100644 index 0000000..479aba9 --- /dev/null +++ b/src/main/java/io/wispforest/gadget/dump/FakeGadgetPacket.java @@ -0,0 +1,30 @@ +package io.wispforest.gadget.dump; + +import net.minecraft.network.NetworkSide; +import net.minecraft.network.NetworkState; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.Packet; + +/** + * Marks a fake packet that is not meant to actually be in the network. + */ +public interface FakeGadgetPacket extends Packet { + int id(); + + void writeToDump(PacketByteBuf buf, NetworkState state, NetworkSide side); + + default Packet unwrap() { + return this; + } + + @Override + default void write(PacketByteBuf buf) { + throw new IllegalStateException(); + } + + @Override + default void apply(PacketListener listener) { + throw new IllegalStateException(); + } +} diff --git a/src/main/java/io/wispforest/gadget/dump/GadgetBundlePacket.java b/src/main/java/io/wispforest/gadget/dump/GadgetBundlePacket.java new file mode 100644 index 0000000..c87bcfa --- /dev/null +++ b/src/main/java/io/wispforest/gadget/dump/GadgetBundlePacket.java @@ -0,0 +1,67 @@ +package io.wispforest.gadget.dump; + +import com.google.common.collect.Lists; +import io.wispforest.gadget.util.NetworkUtil; +import net.minecraft.network.NetworkSide; +import net.minecraft.network.NetworkState; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.BundlePacket; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.BundleS2CPacket; + +import java.util.ArrayList; +import java.util.List; + +public record GadgetBundlePacket(NetworkState state, NetworkSide side, List> packets) implements FakeGadgetPacket { + public static final int ID = -2; + + public static GadgetBundlePacket wrap(BundlePacket bundle) { + List> packets = Lists.newArrayList(bundle.getPackets()); + + if (bundle instanceof BundleS2CPacket) { + return new GadgetBundlePacket(NetworkState.PLAY, NetworkSide.CLIENTBOUND, packets); + } else { + throw new IllegalStateException("Unknown bundle packet type " + bundle); + } + } + + public static GadgetBundlePacket read(PacketByteBuf buf, NetworkState state, NetworkSide side) { + int size = buf.readVarInt(); + List> packets = new ArrayList<>(size); + + for (int i = 0; i < size; i++) { + PacketByteBuf subBuf = NetworkUtil.readOfLengthIntoTmp(buf); + packets.add(PacketDumping.readPacket(subBuf, state, side)); + } + + return new GadgetBundlePacket(state, side, packets); + } + + @Override + public int id() { + return ID; + } + + @Override + public void writeToDump(PacketByteBuf buf, NetworkState state, NetworkSide side) { + buf.writeVarInt(packets.size()); + + for (var subPacket : packets) { + try (var ignored = NetworkUtil.writeByteLength(buf)) { + PacketDumping.writePacket(buf, subPacket, state, side); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Packet unwrap() { + if (state == NetworkState.PLAY && side == NetworkSide.CLIENTBOUND) { + // java i promise this cast is fine + return new BundleS2CPacket((Iterable>)(Object) packets); + } else { + throw new IllegalStateException("No such BundlePacket type for " + state + " and " + side); + } + } +} diff --git a/src/main/java/io/wispforest/gadget/dump/GadgetReadErrorPacket.java b/src/main/java/io/wispforest/gadget/dump/GadgetReadErrorPacket.java new file mode 100644 index 0000000..2c2498b --- /dev/null +++ b/src/main/java/io/wispforest/gadget/dump/GadgetReadErrorPacket.java @@ -0,0 +1,26 @@ +package io.wispforest.gadget.dump; + +import net.minecraft.network.NetworkSide; +import net.minecraft.network.NetworkState; +import net.minecraft.network.PacketByteBuf; + +public record GadgetReadErrorPacket(byte[] data, int packetId, Exception exception) implements FakeGadgetPacket { + public static final int ID = -3; + + public static GadgetReadErrorPacket from(PacketByteBuf buf, int packetId, Exception exception) { + byte[] data = new byte[buf.readableBytes()]; + buf.readBytes(data); + + return new GadgetReadErrorPacket(data, packetId, exception); + } + + @Override + public int id() { + return ID; + } + + @Override + public void writeToDump(PacketByteBuf buf, NetworkState state, NetworkSide side) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/io/wispforest/gadget/dump/GadgetWriteErrorPacket.java b/src/main/java/io/wispforest/gadget/dump/GadgetWriteErrorPacket.java new file mode 100644 index 0000000..4dc6ef8 --- /dev/null +++ b/src/main/java/io/wispforest/gadget/dump/GadgetWriteErrorPacket.java @@ -0,0 +1,34 @@ +package io.wispforest.gadget.dump; + +import net.minecraft.network.NetworkSide; +import net.minecraft.network.NetworkState; +import net.minecraft.network.PacketByteBuf; + +import java.io.CharArrayWriter; +import java.io.PrintWriter; + +public record GadgetWriteErrorPacket(int packetId, String exceptionText) implements FakeGadgetPacket { + public static final int ID = -1; + + public static GadgetWriteErrorPacket fromThrowable(int packetId, Throwable t) { + CharArrayWriter writer = new CharArrayWriter(); + t.printStackTrace(new PrintWriter(writer)); + String fullExceptionText = writer.toString(); + return new GadgetWriteErrorPacket(packetId, fullExceptionText); + } + + public static GadgetWriteErrorPacket read(PacketByteBuf buf) { + return new GadgetWriteErrorPacket(buf.readVarInt(), buf.readString()); + } + + @Override + public int id() { + return ID; + } + + @Override + public void writeToDump(PacketByteBuf buf, NetworkState state, NetworkSide side) { + buf.writeVarInt(packetId); + buf.writeString(exceptionText); + } +} diff --git a/src/main/java/io/wispforest/gadget/dump/PacketDumping.java b/src/main/java/io/wispforest/gadget/dump/PacketDumping.java new file mode 100644 index 0000000..a35b673 --- /dev/null +++ b/src/main/java/io/wispforest/gadget/dump/PacketDumping.java @@ -0,0 +1,71 @@ +package io.wispforest.gadget.dump; + +import io.wispforest.gadget.Gadget; +import net.minecraft.network.NetworkSide; +import net.minecraft.network.NetworkState; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.BundlePacket; +import net.minecraft.network.packet.Packet; + +public final class PacketDumping { + private PacketDumping() { + + } + + public static void writePacket(PacketByteBuf buf, Packet packet, NetworkState state, NetworkSide side) { + int startWriteIdx = buf.writerIndex(); + int packetId = 0; + + try { + if (packet instanceof BundlePacket bundle) { + packet = GadgetBundlePacket.wrap(bundle); + } + + if (packet instanceof FakeGadgetPacket fakePacket) { + packetId = fakePacket.id(); + buf.writeVarInt(packetId); + fakePacket.writeToDump(buf, state, side); + return; + } + + packetId = state.getPacketId(side, packet); + + if (packetId == -1) + throw new UnsupportedOperationException(packet.getClass().getName() + " is an invalid packet in " + side + " " + state); + + buf.writeVarInt(packetId); + + packet.write(buf); + } catch (Exception e) { + buf.writerIndex(startWriteIdx); + + Gadget.LOGGER.error("Error while writing packet {}", packet, e); + + GadgetWriteErrorPacket writeError = GadgetWriteErrorPacket.fromThrowable(packetId, e); + buf.writeVarInt(writeError.id()); + writeError.writeToDump(buf, state, side); + } + } + + public static Packet readPacket(PacketByteBuf buf, NetworkState state, NetworkSide side) { + int startOfData = buf.readerIndex(); + int packetId = buf.readVarInt(); + + try { + switch (packetId) { + case GadgetWriteErrorPacket.ID -> { + return GadgetWriteErrorPacket.read(buf); + } + case GadgetBundlePacket.ID -> { + return GadgetBundlePacket.read(buf, state, side).unwrap(); + } + default -> { } + } + + return state.getPacketHandler(side, packetId, buf); + } catch (Exception e) { + buf.readerIndex(startOfData); + return GadgetReadErrorPacket.from(buf, packetId, e); + } + } +} diff --git a/src/main/java/io/wispforest/gadget/util/NetworkUtil.java b/src/main/java/io/wispforest/gadget/util/NetworkUtil.java index 1dd0e59..aaa5dd5 100644 --- a/src/main/java/io/wispforest/gadget/util/NetworkUtil.java +++ b/src/main/java/io/wispforest/gadget/util/NetworkUtil.java @@ -1,5 +1,6 @@ package io.wispforest.gadget.util; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; import net.minecraft.network.packet.Packet; import net.minecraft.network.PacketByteBuf; import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket; @@ -8,7 +9,11 @@ import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; import net.minecraft.util.Identifier; +import java.util.function.Supplier; + public final class NetworkUtil { + private static final ThreadLocal> TMP_BUF_SOURCE = ThreadLocal.withInitial(() -> SupplierUtil.weakLazy(PacketByteBufs::create)); + private NetworkUtil() { } @@ -50,6 +55,30 @@ public static InfallibleClosable resetIndexes(Packet packet) { }; } + public static InfallibleClosable writeByteLength(PacketByteBuf buf) { + int idIdx = buf.writerIndex(); + buf.writeInt(0); + int startIdx = buf.writerIndex(); + + return () -> { + int endIdx = buf.writerIndex(); + buf.writerIndex(idIdx); + buf.writeInt(endIdx - startIdx); + buf.writerIndex(endIdx); + }; + } + + public static PacketByteBuf readOfLengthIntoTmp(PacketByteBuf buf) { + PacketByteBuf tmpBuf = TMP_BUF_SOURCE.get().get(); + int length = buf.readInt(); + + tmpBuf.readerIndex(0); + tmpBuf.writerIndex(0); + tmpBuf.writeBytes(buf, length); + + return tmpBuf; + } + public interface InfallibleClosable extends AutoCloseable { @Override void close(); diff --git a/src/main/java/io/wispforest/gadget/util/SupplierUtil.java b/src/main/java/io/wispforest/gadget/util/SupplierUtil.java new file mode 100644 index 0000000..19d3ebb --- /dev/null +++ b/src/main/java/io/wispforest/gadget/util/SupplierUtil.java @@ -0,0 +1,37 @@ +package io.wispforest.gadget.util; + +import java.lang.ref.WeakReference; +import java.util.function.Supplier; + +public final class SupplierUtil { + private SupplierUtil() { + + } + + public static Supplier weakLazy(Supplier wrapped) { + if (wrapped instanceof WeakLazy lazy) + return lazy; + + return new WeakLazy<>(wrapped); + } + + private static class WeakLazy implements Supplier { + private WeakReference holder = null; + private final Supplier wrapped; + + public WeakLazy(Supplier wrapped) { + this.wrapped = wrapped; + } + + @Override + public T get() { + T value = holder == null ? null : holder.get(); + if (value == null) { + value = wrapped.get(); + holder = new WeakReference<>(value); + } + + return value; + } + } +} diff --git a/src/main/resources/assets/gadget/lang/en_us.json b/src/main/resources/assets/gadget/lang/en_us.json index dc1e064..d4c614b 100644 --- a/src/main/resources/assets/gadget/lang/en_us.json +++ b/src/main/resources/assets/gadget/lang/en_us.json @@ -263,6 +263,13 @@ {"index": 0} ] ], + "text.gadget.packet_write_error": [ + {"text": "Packet Write Error!", "color": "red"}, + [ + {"text": " Type #", "color": "gray"}, + {"index": 0} + ] + ], "text.gadget.packet_errors": { "text": "Packet errors", "color": "red"