From c79f6e0cd7f8818e25219a9f2c9da1014f5b7b89 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Wed, 25 Mar 2026 12:59:22 +0100 Subject: [PATCH 01/19] Implement new packets, add new API for logging, implement config via Cloth Config + Mod Menu - New packets: implement PlayerInfoUpdate, PlayerInfoRemove, SetCursorItem, CommandSuggestionsRequest/Response - Logging API: add PacketInfoList and PacketInfoValue to allow handles to log list-like values and pure values without a key-value pairing. - Config: implement Cloth Config and Mod Menu to control the packet delay setting which is now enabled. The config file is stored in config/packetninja.json. - Updated formatting: update the formatting of many packets which use list-like values (ContainerSetContent, RemoveEntities, SetPassengers, SetPlayerTeam) - Misc: added AGENTS.md for GitHub Copilot users --- AGENTS.md | 44 +++++++++ build.gradle | 13 ++- gradle.properties | 4 +- gradlew | 0 .../bitsquidd/ninja/PacketInterceptorMod.java | 8 +- .../command/PacketInterceptionCommand.java | 2 +- .../xyz/bitsquidd/ninja/config/Config.java | 49 ++++++++++ .../bitsquidd/ninja/config/ConfigMenu.java | 11 +++ .../bitsquidd/ninja/config/ConfigScreen.java | 39 ++++++++ .../ninja/format/PacketInfoBundle.java | 24 ++--- .../ninja/format/PacketInfoList.java | 46 ++++++++++ .../ninja/format/PacketInfoListElement.java | 12 +++ .../bitsquidd/ninja/format/PacketInfoRow.java | 14 +++ .../ninja/format/PacketInfoSegment.java | 21 ++++- .../ninja/format/PacketInfoValue.java | 38 ++++++++ .../bitsquidd/ninja/format/PacketLogger.java | 31 ++++--- .../ninja/handler/PacketHandler.java | 1 + .../CommandSuggestionsResponseHandler.java | 61 +++++++++++++ .../ContainerSetContentHandler.java | 32 +++++-- .../clientbound/PlayerInfoRemoveHandler.java | 38 ++++++++ .../clientbound/PlayerInfoUpdateHandler.java | 89 +++++++++++++++++++ .../clientbound/RemoveEntitiesHandler.java | 34 +++++-- .../clientbound/SetCursorItemHandler.java | 50 +++++++++++ .../clientbound/SetPassengersHandler.java | 30 +++++-- .../clientbound/SetPlayerTeamHandler.java | 43 +++++---- .../CommandSuggestionsRequestHandler.java | 39 ++++++++ src/main/resources/fabric.mod.json | 8 +- 27 files changed, 707 insertions(+), 74 deletions(-) create mode 100644 AGENTS.md mode change 100644 => 100755 gradlew create mode 100644 src/client/java/xyz/bitsquidd/ninja/config/Config.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/config/ConfigMenu.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..37e4858 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,44 @@ +# AGENTS Guide: PacketNinja + +## What this repo is +- Fabric client-side mod (`minecraft` 1.21.11, Java 21) for packet interception/logging. +- Primary runtime logic is in `src/client/java`; `src/main/java` only contains a minimal common initializer. + +## Core architecture (read these first) +- Entrypoints are declared in `src/main/resources/fabric.mod.json`: + - client init: `xyz.bitsquidd.ninja.PacketInterceptorMod` + - Mod Menu config hook: `xyz.bitsquidd.ninja.config.ConfigMenu` +- Packet tap is injected via Mixin in `src/client/java/xyz/bitsquidd/ninja/mixin/MixinConnection.java`: + - intercepts outgoing `Connection#doSendPacket` + - intercepts incoming `Connection#channelRead0` + - unwraps `BundlePacket` and forwards each sub-packet. +- Runtime flow: Mixin -> `PacketInterceptorMod.logPacket(...)` -> `PacketFilter.shouldInterceptPacket(...)` -> `PacketLogger.addPacket(...)` -> chat output. + +## Handler system (project-specific) +- Packet formatters are `PacketHandler` implementations under `src/client/java/xyz/bitsquidd/ninja/handler/impl/**`. +- Registration is reflection-based (`PacketRegistry` + `org.reflections.Reflections`) scanning package `xyz.bitsquidd.ninja.handler.impl`. +- New handlers must have: + - concrete class (not abstract), public no-arg constructor + - `super(PacketClass, "FriendlyName", "Description", PacketType.CLIENTBOUND|SERVERBOUND)` + - `getPacketInfoInternal(...)` returning `PacketInfoBundle` + `PacketInfoSegment` list. +- `/packets filter` suggestions and toggle lookup come from handler `friendlyName` (`PacketRegistry.findHandler`). + +## Formatting and UI conventions +- Chat output uses Adventure components (`PacketLogger`, `PacketInfoBundle`) with custom glyph icons from `src/client/resources/assets/minecraft/font/default.json` and `.../textures/text/font/icons.png`. +- Use `FormatHelper` for repeated formatting patterns (positions, rotations, capped lists, item stacks). +- Packet categories/colors are centralized in `PacketType`; command response styles in `ResponseType`. + +## Config and commands +- Config file is JSON at Fabric config dir: `packetninja.json` (`Config.java`), loaded on client init. +- Mod Menu screen (`ConfigScreen`) currently exposes `packetDelayMs` with 50ms snapping. +- Commands are client-only in `PacketInterceptionCommand`: + - `/packets start`, `/packets stop`, `/packets filter [packetName]`. + +## Build/dev workflow (verified from repo files) +- Build uses Gradle + Fabric Loom (`build.gradle`), Java release target is 21. +- Wrapper script may not be executable in some environments; use `bash ./gradlew ` if needed. +- In this environment, Gradle tasks could not be listed because `JAVA_HOME`/`java` was missing. +- No test sources were found (`**/*Test*.java`). + +## Known implementation watch-outs +- `PacketInterceptorMod.MOD_ID` is `packet-interceptor` while mod id in `fabric.mod.json` is `packet-ninja`. diff --git a/build.gradle b/build.gradle index 4ae6006..a88356c 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,12 @@ base { repositories { mavenCentral() + + maven { + name "Terraformers" + url "https://maven.terraformersmc.com/releases" + } + maven { url "https://maven.shedaniel.me/" } } loom { @@ -20,7 +26,6 @@ loom { mods { "packet-ninja" { - sourceSet sourceSets.main sourceSet sourceSets.client } } @@ -39,6 +44,12 @@ dependencies { include(modImplementation("org.reflections:reflections:0.10.2")) include("org.javassist:javassist:3.30.2-GA") + + // mod menu and cloth config + modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}") + modApi("me.shedaniel.cloth:cloth-config-fabric:21.11.153") { + exclude(group: "net.fabricmc.fabric-api") + } } processResources { diff --git a/gradle.properties b/gradle.properties index 5ebd2f2..0d02b12 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,6 @@ mod_version=0.0.5 maven_group=xyz.bitsquidd archives_base_name=packet-ninja # Dependencies -fabric_version=0.140.2+1.21.11 \ No newline at end of file +fabric_version=0.140.2+1.21.11 +# Modmenu +modmenu_version=17.0.0-beta.2 diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java b/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java index 1f3daf0..d06e3df 100644 --- a/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java +++ b/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; import xyz.bitsquidd.ninja.command.PacketInterceptionCommand; +import xyz.bitsquidd.ninja.config.Config; import xyz.bitsquidd.ninja.format.PacketLogger; public final class PacketInterceptorMod implements ClientModInitializer { @@ -30,9 +31,10 @@ public PacketInterceptorMod() { @Override public void onInitializeClient() { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { - PacketInterceptionCommand.register(dispatcher); - }); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + PacketInterceptionCommand.register(dispatcher) + ); + Config.load(); } public @NotNull PacketFilter getPacketFilter() { diff --git a/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java b/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java index 099d783..5afcf24 100644 --- a/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java +++ b/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java @@ -135,7 +135,7 @@ private static int togglePacket(CommandContext ctx) { .append(Component.text(packetName)), ResponseType.ERROR ); - return Command.SINGLE_SUCCESS; + return 0; } filter.togglePacketFilter(handler.getFriendlyName()); diff --git a/src/client/java/xyz/bitsquidd/ninja/config/Config.java b/src/client/java/xyz/bitsquidd/ninja/config/Config.java new file mode 100644 index 0000000..0636d37 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/config/Config.java @@ -0,0 +1,49 @@ +package xyz.bitsquidd.ninja.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import net.fabricmc.loader.api.FabricLoader; + +import xyz.bitsquidd.ninja.PacketInterceptorMod; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class Config { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + private static final Path FILE = FabricLoader.getInstance().getConfigDir().resolve("packetninja.json"); + + public static int packetDelayMs = 500; + + public static void load() { + if (Files.exists(FILE)) { + try { + String json = Files.readString(FILE); + ConfigData data = GSON.fromJson(json, ConfigData.class); + if (data != null) { + packetDelayMs = data.packetDelayMs; + } + } catch (Exception e) { + PacketInterceptorMod.LOGGER.error("Failed to load config, using defaults"); + } + } else { + save(); // generate file on first run + } + } + + public static void save() { + try { + ConfigData data = new ConfigData(); + data.packetDelayMs = packetDelayMs; + + Files.writeString(FILE, GSON.toJson(data)); + } catch (IOException e) { + PacketInterceptorMod.LOGGER.error("Failed to save config"); + } + } + + private static class ConfigData { + int packetDelayMs = 500; + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/config/ConfigMenu.java b/src/client/java/xyz/bitsquidd/ninja/config/ConfigMenu.java new file mode 100644 index 0000000..8345132 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/config/ConfigMenu.java @@ -0,0 +1,11 @@ +package xyz.bitsquidd.ninja.config; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; + +public class ConfigMenu implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return ConfigScreen::create; + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java new file mode 100644 index 0000000..555e9e4 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java @@ -0,0 +1,39 @@ +package xyz.bitsquidd.ninja.config; + +import me.shedaniel.clothconfig2.api.ConfigBuilder; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; + +public class ConfigScreen { + public static Screen create(Screen parent) { + var builder = ConfigBuilder.create() + .setParentScreen(parent) + .setTitle(Component.literal("PacketNinja Settings")); + + var general = builder.getOrCreateCategory(Component.literal("General")); + var entryBuilder = builder.entryBuilder(); + + general.addEntry(entryBuilder + .startIntSlider(Component.literal("Packet Delay (ms)"), + Config.packetDelayMs, 0, 2000) + .setDefaultValue(500) + .setTextGetter(value -> { + int step = 50; + int snapped = (value / step) * step; + return Component.literal(snapped + " ms"); + }) + .setTooltip(Component.literal( + "The minimum delay in milliseconds between two packets required " + + "to actually log a packet, otherwise it'll be replaced with \"...\"" + )) + .setSaveConsumer(newValue -> { + int step = 50; // example + Config.packetDelayMs = (newValue / step) * step; + Config.save(); + }) + .build() + ); + + return builder.build(); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java index 7dc8650..3ad0ff0 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java @@ -9,7 +9,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** * A bundle of information about a packet sent to a client. This structure is used for pretty formatting. @@ -19,16 +18,20 @@ public final class PacketInfoBundle { private final PacketType type; private final Component name; - private final List segments; + private final List rows; - private PacketInfoBundle(PacketType type, Component name, List segments) { + private PacketInfoBundle(PacketType type, Component name, List rows) { this.type = type; this.name = name; - this.segments = segments; + this.rows = rows; } public static PacketInfoBundle of(PacketType type, Component name, List segments) { - return new PacketInfoBundle(type, name, segments); + return ofRows(type, name, new ArrayList<>(segments)); + } + + public static PacketInfoBundle ofRows(PacketType type, Component name, List rows) { + return new PacketInfoBundle(type, name, new ArrayList<>(rows)); } public Component format() { @@ -39,13 +42,10 @@ public Component format() { .decorate(TextDecoration.BOLD) ); - List segmentComponents = segments.stream().map(segment -> Component.empty() - .color(type.secondaryColor) - .append(Component.text(" ↪ ")) - .append(segment.getName()) - .append(Component.text(": ")) - .append(segment.getValue()) - ).collect(Collectors.toList()); + List segmentComponents = new ArrayList<>(); + for (PacketInfoRow row : rows) { + segmentComponents.addAll(row.format(type)); + } List allComponents = new ArrayList<>(List.of(titleComponent)); allComponents.addAll(segmentComponents); diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java new file mode 100644 index 0000000..547f125 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java @@ -0,0 +1,46 @@ +package xyz.bitsquidd.ninja.format; + +import net.kyori.adventure.text.Component; +import org.jspecify.annotations.NullMarked; + +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.ArrayList; +import java.util.List; + +/** + * Displays a titled list of key-value entries inside a packet info bundle. + */ +@NullMarked +public final class PacketInfoList implements PacketInfoRow { + private final Component title; + private final List entries; + + private PacketInfoList(Component title, List entries) { + this.title = title; + this.entries = entries; + } + + public static PacketInfoList of(Component title, List entries) { + return new PacketInfoList(title, entries); + } + + @Override + public List format(PacketType type) { + List lines = new ArrayList<>(); + lines.add( + Component.empty() + .color(type.secondaryColor) + .append(Component.text(" ↪ ")) + .append(title) + .append(Component.text(":")) + ); + + for (int i = 0; i < entries.size(); i++) { + var entry = entries.get(i); + lines.add(entry.formatLine(type, " " + (i + 1) + ". ")); + } + + return lines; + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java new file mode 100644 index 0000000..06cd57f --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java @@ -0,0 +1,12 @@ +package xyz.bitsquidd.ninja.format; + +import net.kyori.adventure.text.Component; + +import xyz.bitsquidd.ninja.handler.PacketType; + +/** + * Represents an element of a [PacketInfoList]. + */ +public interface PacketInfoListElement { + Component formatLine(PacketType type, String prefix); +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java new file mode 100644 index 0000000..645a394 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java @@ -0,0 +1,14 @@ +package xyz.bitsquidd.ninja.format; + +import net.kyori.adventure.text.Component; + +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +/** + * Represents one or more display lines inside a packet info bundle. + */ +public interface PacketInfoRow { + List format(PacketType type); +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java index 9ff5d6e..ba0824b 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java @@ -3,11 +3,15 @@ import net.kyori.adventure.text.Component; import org.jspecify.annotations.NullMarked; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + /** * A segment of information about a packet, e.g. EntityID: 42 */ @NullMarked -public final class PacketInfoSegment { +public final class PacketInfoSegment implements PacketInfoRow, PacketInfoListElement { private final Component name; private final Component value; @@ -20,6 +24,21 @@ public static PacketInfoSegment of(Component name, Component value) { return new PacketInfoSegment(name, value); } + @Override + public Component formatLine(PacketType type, String prefix) { + return Component.empty() + .color(type.secondaryColor) + .append(Component.text(prefix)) + .append(name) + .append(Component.text(": ")) + .append(value); + } + + @Override + public List format(PacketType type) { + return List.of(formatLine(type, " ↪ ")); + } + public Component getName() { return name; } diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java new file mode 100644 index 0000000..08a2790 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java @@ -0,0 +1,38 @@ +package xyz.bitsquidd.ninja.format; + + +import net.kyori.adventure.text.Component; +import org.jspecify.annotations.NullMarked; + +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +/** + * A packet info row that contains a single value. + */ +@NullMarked +public final class PacketInfoValue implements PacketInfoRow, PacketInfoListElement { + private final Component value; + + private PacketInfoValue(Component value) { + this.value = value; + } + + public static PacketInfoValue of(Component value) { + return new PacketInfoValue(value); + } + + @Override + public Component formatLine(PacketType type, String prefix) { + return Component.empty() + .color(type.secondaryColor) + .append(Component.text(prefix)) + .append(value); + } + + @Override + public List format(PacketType type) { + return List.of(formatLine(type, " ↪ ")); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java index 93ce05a..ce69154 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java @@ -2,13 +2,17 @@ import net.kyori.adventure.platform.modcommon.MinecraftClientAudiences; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.client.Minecraft; import net.minecraft.network.protocol.Packet; import org.jspecify.annotations.NullMarked; import xyz.bitsquidd.ninja.PacketRegistry; +import xyz.bitsquidd.ninja.config.Config; import xyz.bitsquidd.ninja.handler.PacketHandler; +import java.time.Duration; import java.time.Instant; /** @@ -23,24 +27,27 @@ public void addPacket(final Packet packet) { PacketHandler handler = PacketRegistry.getHandlerForPacket(packet); if (handler == null) return; - // TODO add a config option for this. - Instant currentTime = Instant.now(); -// if (Duration.between(lastPacketTime, currentTime).compareTo(Duration.ofMillis(500)) < 0) { -// sendChatMessage( -// Component.text("...", NamedTextColor.GRAY) -// .hoverEvent(HoverEvent.showText(Component.text("Too many packets sent within 500ms, hiding.")) -// )); -// } - lastPacketTime = currentTime; + var delayRequired = Config.packetDelayMs; + if(delayRequired > 0) { + Instant currentTime = Instant.now(); + if (Duration.between(lastPacketTime, currentTime).compareTo(Duration.ofMillis(delayRequired)) < 0) { + sendChatMessage( + Component.text("...", NamedTextColor.GRAY) + .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %s, hiding.", delayRequired))) + )); + return; + } + lastPacketTime = currentTime; + } PacketInfoBundle infoBundle = handler.getPacketInfo(packet); sendChatMessage(infoBundle.format()); } public static void sendChatMessage(final Component component) { - Minecraft.getInstance().execute(() -> { - MinecraftClientAudiences.of().audience().sendMessage(component); - }); + Minecraft.getInstance().execute(() -> + MinecraftClientAudiences.of().audience().sendMessage(component) + ); } } \ No newline at end of file diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/PacketHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/PacketHandler.java index 2629c44..d82f0d2 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/PacketHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/PacketHandler.java @@ -7,6 +7,7 @@ @NullMarked public abstract class PacketHandler> { + // TODO: maybe make this configurable too?? protected static final int MAX_DISPLAYED_ENTRIES = 5; diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java new file mode 100644 index 0000000..d9778f9 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java @@ -0,0 +1,61 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoList; +import xyz.bitsquidd.ninja.format.PacketInfoRow; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.ArrayList; +import java.util.List; + +public class CommandSuggestionsResponseHandler extends PacketHandler<@NotNull ClientboundCommandSuggestionsPacket> { + public CommandSuggestionsResponseHandler() { + super( + ClientboundCommandSuggestionsPacket.class, + "CommandSuggestionsResponse", + "Handles command suggestion responses", + PacketType.CLIENTBOUND + ); + } + + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundCommandSuggestionsPacket packet) { + var id = packet.id(); + var suggestions = packet.suggestions(); + var suggestionCount = suggestions.size(); + + List rows = new ArrayList<>(); + rows.add(PacketInfoSegment.of(Component.text("Transaction ID"), Component.text(id))); + rows.add(PacketInfoSegment.of(Component.text("Suggestion Count"), Component.text(suggestionCount))); + + // Display suggestions as a structured list + if (!suggestions.isEmpty()) { + List suggestionSegments = suggestions.stream() + .limit(MAX_DISPLAYED_ENTRIES) + .map(entry -> PacketInfoSegment.of( + Component.text("Suggestion"), + Component.text(entry.text()) + )) + .toList(); + rows.add(PacketInfoList.of(Component.text("Suggestions"), new ArrayList<>(suggestionSegments))); + + int hiddenSuggestions = suggestions.size() - suggestionSegments.size(); + if (hiddenSuggestions > 0) { + rows.add(PacketInfoSegment.of(Component.text("SuggestionsHidden"), Component.text(hiddenSuggestions + " more"))); + } + } + + return PacketInfoBundle.ofRows( + packetType, + Component.text(friendlyName), + rows + ); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java index 6f2bf27..bacc2e1 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java @@ -6,10 +6,13 @@ import xyz.bitsquidd.ninja.format.FormatHelper; import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoList; +import xyz.bitsquidd.ninja.format.PacketInfoRow; import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; +import java.util.ArrayList; import java.util.List; public class ContainerSetContentHandler extends PacketHandler<@NotNull ClientboundContainerSetContentPacket> { @@ -25,19 +28,30 @@ public ContainerSetContentHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundContainerSetContentPacket packet) { - List itemsString = packet.items().stream() - .map(FormatHelper::formatItemStack) + List itemSegments = packet.items().stream() + .limit(MAX_DISPLAYED_ENTRIES) + .map(item -> PacketInfoSegment.of(Component.text("Item"), Component.text(FormatHelper.formatItemStack(item)))) .toList(); - return PacketInfoBundle.of( + List rows = new ArrayList<>(); + rows.add(PacketInfoSegment.of(Component.text("ContainerID"), Component.text(packet.containerId()))); + rows.add(PacketInfoSegment.of(Component.text("StateID"), Component.text(packet.stateId()))); + + if (!itemSegments.isEmpty()) { + rows.add(PacketInfoList.of(Component.text("Items"), new ArrayList<>(itemSegments))); + } + + int hiddenItems = packet.items().size() - itemSegments.size(); + if (hiddenItems > 0) { + rows.add(PacketInfoSegment.of(Component.text("ItemsHidden"), Component.text(hiddenItems + " more"))); + } + + rows.add(PacketInfoSegment.of(Component.text("CarriedItem"), Component.text(FormatHelper.formatItemStack(packet.carriedItem())))); + + return PacketInfoBundle.ofRows( packetType, Component.text(friendlyName), - List.of( - PacketInfoSegment.of(Component.text("ContainerID"), Component.text(packet.containerId())), - PacketInfoSegment.of(Component.text("StateID"), Component.text(packet.stateId())), - PacketInfoSegment.of(Component.text("Items"), Component.text(itemsString.toString())), - PacketInfoSegment.of(Component.text("CarriedItem"), Component.text(FormatHelper.formatItemStack(packet.carriedItem()))) - ) + rows ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java new file mode 100644 index 0000000..6c0327f --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java @@ -0,0 +1,38 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.*; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.ArrayList; + +public class PlayerInfoRemoveHandler extends PacketHandler<@NotNull ClientboundPlayerInfoRemovePacket> { + public PlayerInfoRemoveHandler() { + super( + ClientboundPlayerInfoRemovePacket.class, + "PlayerInfoRemove", + "Handles player removal updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundPlayerInfoRemovePacket packet) { + var removed = packet.profileIds().stream() + .map(uuid -> PacketInfoValue.of(Component.text(uuid.toString()))) + .toList(); + + var rows = new ArrayList(); + rows.add(PacketInfoList.of(Component.text("Removed UUIDs"), removed)); + + return PacketInfoBundle.ofRows( + packetType, + Component.text(friendlyName), + rows + ); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java new file mode 100644 index 0000000..f9bf55f --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java @@ -0,0 +1,89 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import com.mojang.serialization.JsonOps; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.PacketInterceptorMod; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoList; +import xyz.bitsquidd.ninja.format.PacketInfoRow; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.ArrayList; +import java.util.List; + +public class PlayerInfoUpdateHandler extends PacketHandler<@NotNull ClientboundPlayerInfoUpdatePacket> { + public PlayerInfoUpdateHandler() { + super( + ClientboundPlayerInfoUpdatePacket.class, + "PlayerInfoUpdate", + "Handles player info updates", + PacketType.CLIENTBOUND + ); + } + + private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Entry entry) { + var displayName = entry.displayName(); + if(displayName == null) { + return ""; + } + + // here is the fun part: displayName is Minecraft's Component, we want to convert it to MiniMessage + var jsonElement = ComponentSerialization.CODEC.encodeStart(JsonOps.COMPRESSED, displayName) + .resultOrPartial(error -> + PacketInterceptorMod.LOGGER.error("Failed to serialize displayName for player {}: {}", entry.profileId(), error) + ) + .orElse(null); + if(jsonElement == null) { + return ""; + } + + var adventure = GsonComponentSerializer.gson().deserialize(jsonElement.toString()); + return MiniMessage.miniMessage().serialize(adventure); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundPlayerInfoUpdatePacket packet) { + List displayedEntries = packet.entries().stream() + .limit(MAX_DISPLAYED_ENTRIES) + .toList(); + + List rows = new ArrayList<>(); + rows.add(PacketInfoSegment.of(Component.text("EntryCount"), Component.text(displayedEntries.size()))); + + var entryLists = displayedEntries.stream().map(entry -> { + // identity + var displayName = extractDisplayName(entry); + var identity = String.format("displayName=%s, uuid=%s", displayName, entry.profileId()); + var identitySegment = PacketInfoSegment.of(Component.text("Identity"), Component.text(identity)); + + // state + String state = String.format( + "listed=%s, listOrder=%d, showHat=%s, latency=%dms", + entry.listed(), + entry.listOrder(), + entry.showHat(), + entry.latency() + ); + var stateSegment = PacketInfoSegment.of(Component.text("State"), MiniMessage.miniMessage().deserialize(state)); + + String name = entry.profile() != null ? entry.profile().name() : ""; + return PacketInfoList.of(Component.text(name), List.of(identitySegment, stateSegment)); + }).toList(); + + rows.addAll(entryLists); + + return PacketInfoBundle.ofRows( + packetType, + Component.text(friendlyName), + rows + ); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java index 9a973f4..c20f0f1 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java @@ -4,12 +4,14 @@ import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.FormatHelper; import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoList; +import xyz.bitsquidd.ninja.format.PacketInfoRow; import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; +import java.util.ArrayList; import java.util.List; public class RemoveEntitiesHandler extends PacketHandler<@NotNull ClientboundRemoveEntitiesPacket> { @@ -24,15 +26,33 @@ public RemoveEntitiesHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundRemoveEntitiesPacket packet) { - String removedEntityIdList = FormatHelper.formatList(packet.getEntityIds().stream().toList(), MAX_DISPLAYED_ENTRIES); + var allEntityIds = packet.getEntityIds(); + int totalCount = allEntityIds.size(); - return PacketInfoBundle.of( + List displayedIds = allEntityIds.intStream() + .limit(MAX_DISPLAYED_ENTRIES) + .boxed() + .toList(); + + List rows = new ArrayList<>(); + rows.add(PacketInfoSegment.of(Component.text("Count"), Component.text(totalCount))); + + if (!displayedIds.isEmpty()) { + List idSegments = displayedIds.stream() + .map(id -> PacketInfoSegment.of(Component.text("EntityId"), Component.text(id))) + .toList(); + rows.add(PacketInfoList.of(Component.text("EntityIds"), new ArrayList<>(idSegments))); + } + + int hiddenEntities = totalCount - displayedIds.size(); + if (hiddenEntities > 0) { + rows.add(PacketInfoSegment.of(Component.text("EntityIdsHidden"), Component.text(hiddenEntities + " more"))); + } + + return PacketInfoBundle.ofRows( packetType, Component.text(friendlyName), - List.of( - PacketInfoSegment.of(Component.text("Count"), Component.text(packet.getEntityIds().size())), - PacketInfoSegment.of(Component.text("EntityIds"), Component.text(removedEntityIdList)) - ) + rows ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java new file mode 100644 index 0000000..1936589 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java @@ -0,0 +1,50 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.serialization.JsonOps; +import net.kyori.adventure.text.Component; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.protocol.game.ClientboundSetCursorItemPacket; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.PacketInterceptorMod; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class SetCursorItemHandler extends PacketHandler<@NotNull ClientboundSetCursorItemPacket> { + public SetCursorItemHandler() { + super( + ClientboundSetCursorItemPacket.class, + "SetCursorItem", + "Handles cursor item updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundSetCursorItemPacket packet) { + var stack = packet.contents(); + var itemId = BuiltInRegistries.ITEM.getKey(stack.getItem()); + var itemCount = stack.getCount(); + + // serialize nbt as snbt + var encodeResult = ItemStack.CODEC.encodeStart(JsonOps.COMPRESSED, stack); + var json = encodeResult.resultOrPartial(PacketInterceptorMod.LOGGER::error).orElse(new JsonObject()); // return empty on error + + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("ID"), Component.text(itemId.toString())), + PacketInfoSegment.of(Component.text("Count"), Component.text(itemCount)), + PacketInfoSegment.of(Component.text("NBT"), Component.text(json.toString())) + ) + ); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java index 73cb438..e7a8708 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java @@ -4,12 +4,14 @@ import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.FormatHelper; import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoList; +import xyz.bitsquidd.ninja.format.PacketInfoRow; import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -26,16 +28,28 @@ public SetPassengersHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetPassengersPacket packet) { - String passengerIdList = FormatHelper.formatList(packet.getPassengers().length > 0 ? Arrays.stream(packet.getPassengers()).boxed().toList() : List.of(), MAX_DISPLAYED_ENTRIES); + List passengers = Arrays.stream(packet.getPassengers()) + .limit(MAX_DISPLAYED_ENTRIES) + .mapToObj(id -> PacketInfoSegment.of(Component.text("PassengerId"), Component.text(id))) + .toList(); - return PacketInfoBundle.of( + List rows = new ArrayList<>(); + rows.add(PacketInfoSegment.of(Component.text("VehicleId"), Component.text(packet.getVehicle()))); + rows.add(PacketInfoSegment.of(Component.text("PassengerCount"), Component.text(packet.getPassengers().length))); + + if (!passengers.isEmpty()) { + rows.add(PacketInfoList.of(Component.text("Passengers"), passengers)); + } + + int hiddenPassengers = packet.getPassengers().length - passengers.size(); + if (hiddenPassengers > 0) { + rows.add(PacketInfoSegment.of(Component.text("PassengersHidden"), Component.text(hiddenPassengers + " more"))); + } + + return PacketInfoBundle.ofRows( packetType, Component.text(friendlyName), - List.of( - PacketInfoSegment.of(Component.text("VehicleId"), Component.text(packet.getVehicle())), - PacketInfoSegment.of(Component.text("PassengerCount"), Component.text(packet.getPassengers().length)), - PacketInfoSegment.of(Component.text("Passengers"), Component.text(passengerIdList)) - ) + rows ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java index 4f0294c..e524be5 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java @@ -4,8 +4,9 @@ import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.FormatHelper; import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoList; +import xyz.bitsquidd.ninja.format.PacketInfoRow; import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -26,62 +27,74 @@ public SetPlayerTeamHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetPlayerTeamPacket packet) { - List segments = new ArrayList<>(); + List rows = new ArrayList<>(); - segments.add(PacketInfoSegment.of(Component.text("Team"), Component.text(packet.getName()))); + rows.add(PacketInfoSegment.of(Component.text("Team"), Component.text(packet.getName()))); ClientboundSetPlayerTeamPacket.Action teamAction = packet.getTeamAction(); ClientboundSetPlayerTeamPacket.Action playerAction = packet.getPlayerAction(); - segments.add(PacketInfoSegment.of(Component.text("TeamAction"), Component.text(teamAction != null ? teamAction.name() : "null"))); - segments.add(PacketInfoSegment.of(Component.text("PlayerAction"), Component.text(playerAction != null ? playerAction.name() : "null"))); + rows.add(PacketInfoSegment.of(Component.text("TeamAction"), Component.text(teamAction != null ? teamAction.name() : "null"))); + rows.add(PacketInfoSegment.of(Component.text("PlayerAction"), Component.text(playerAction != null ? playerAction.name() : "null"))); + // Add players as structured list if (!packet.getPlayers().isEmpty()) { - segments.add(PacketInfoSegment.of(Component.text("Players"), Component.text(FormatHelper.formatList(packet.getPlayers(), MAX_DISPLAYED_ENTRIES)))); + List playerList = packet.getPlayers().stream() + .limit(MAX_DISPLAYED_ENTRIES) + .toList(); + List playerSegments = playerList.stream() + .map(name -> PacketInfoSegment.of(Component.text("Player"), Component.text(name))) + .toList(); + rows.add(PacketInfoList.of(Component.text("Players"), new ArrayList<>(playerSegments))); + + int hiddenPlayers = packet.getPlayers().size() - playerList.size(); + if (hiddenPlayers > 0) { + rows.add(PacketInfoSegment.of(Component.text("PlayersHidden"), Component.text(hiddenPlayers + " more"))); + } } packet.getParameters().ifPresent(params -> { - segments.add(PacketInfoSegment.of( + rows.add(PacketInfoSegment.of( Component.text("DisplayName"), Component.text(params.getDisplayName().getString()) )); - segments.add(PacketInfoSegment.of( + rows.add(PacketInfoSegment.of( Component.text("Color"), Component.text(params.getColor().getName()) )); - segments.add(PacketInfoSegment.of( + rows.add(PacketInfoSegment.of( Component.text("NTVisibility"), Component.text(params.getNametagVisibility().name) )); - segments.add(PacketInfoSegment.of( + rows.add(PacketInfoSegment.of( Component.text("CollisionRule"), Component.text(params.getCollisionRule().name) )); if (!params.getPlayerPrefix().getString().isEmpty()) { - segments.add(PacketInfoSegment.of( + rows.add(PacketInfoSegment.of( Component.text("Prefix"), Component.text(params.getPlayerPrefix().getString()) )); } if (!params.getPlayerSuffix().getString().isEmpty()) { - segments.add(PacketInfoSegment.of( + rows.add(PacketInfoSegment.of( Component.text("Suffix"), Component.text(params.getPlayerSuffix().getString()) )); } - segments.add(PacketInfoSegment.of(Component.text("Options"), Component.text(String.format("0x%02X", params.getOptions())))); + rows.add(PacketInfoSegment.of(Component.text("Options"), Component.text(String.format("0x%02X", params.getOptions())))); }); - return PacketInfoBundle.of( + return PacketInfoBundle.ofRows( packetType, Component.text(friendlyName), - segments + rows ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java new file mode 100644 index 0000000..edb229d --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java @@ -0,0 +1,39 @@ +package xyz.bitsquidd.ninja.handler.impl.serverbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class CommandSuggestionsRequestHandler extends PacketHandler<@NotNull ServerboundCommandSuggestionPacket> { + public CommandSuggestionsRequestHandler() { + super( + ServerboundCommandSuggestionPacket.class, + "CommandSuggestionsRequest", + "Handles command suggestion requests", + PacketType.SERVERBOUND + ); + } + + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ServerboundCommandSuggestionPacket packet) { + var id = packet.getId(); + var text = packet.getCommand(); + + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("Transaction ID"), Component.text(id)), + PacketInfoSegment.of(Component.text("Text"), Component.text(text)) + ) + ); + } +} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e2c90ca..e7c3993 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -11,13 +11,13 @@ }, "license": "LGPL-3.0", "icon": "assets/packet_ninja/icon.png", - "environment": "*", + "environment": "client", "entrypoints": { - "main": [ - "xyz.bitsquidd.ninja.PacketInterceptor" - ], "client": [ "xyz.bitsquidd.ninja.PacketInterceptorMod" + ], + "modmenu": [ + "xyz.bitsquidd.ninja.config.ConfigMenu" ] }, "mixins": [ From f556f9b0a34c9d1817226a211311a6583ffe7484 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Wed, 25 Mar 2026 13:23:34 +0100 Subject: [PATCH 02/19] Replace JsonOps.COMPRESSED with JsonOps.INSTANCE to fix serialization errors --- .../handler/impl/clientbound/PlayerInfoUpdateHandler.java | 8 ++++---- .../handler/impl/clientbound/SetCursorItemHandler.java | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java index f9bf55f..f25db97 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java @@ -36,7 +36,7 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent } // here is the fun part: displayName is Minecraft's Component, we want to convert it to MiniMessage - var jsonElement = ComponentSerialization.CODEC.encodeStart(JsonOps.COMPRESSED, displayName) + var jsonElement = ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, displayName) .resultOrPartial(error -> PacketInterceptorMod.LOGGER.error("Failed to serialize displayName for player {}: {}", entry.profileId(), error) ) @@ -62,7 +62,7 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent // identity var displayName = extractDisplayName(entry); var identity = String.format("displayName=%s, uuid=%s", displayName, entry.profileId()); - var identitySegment = PacketInfoSegment.of(Component.text("Identity"), Component.text(identity)); + var identitySegment = PacketInfoSegment.of(Component.text("Identity"), MiniMessage.miniMessage().deserialize(identity)); // state String state = String.format( @@ -72,9 +72,9 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent entry.showHat(), entry.latency() ); - var stateSegment = PacketInfoSegment.of(Component.text("State"), MiniMessage.miniMessage().deserialize(state)); + var stateSegment = PacketInfoSegment.of(Component.text("State"), Component.text(state)); - String name = entry.profile() != null ? entry.profile().name() : ""; + String name = entry.profile() != null ? entry.profile().name() : entry.profileId().toString(); return PacketInfoList.of(Component.text(name), List.of(identitySegment, stateSegment)); }).toList(); diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java index 1936589..cc02600 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java @@ -1,6 +1,5 @@ package xyz.bitsquidd.ninja.handler.impl.clientbound; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.serialization.JsonOps; import net.kyori.adventure.text.Component; @@ -34,7 +33,7 @@ public SetCursorItemHandler() { var itemCount = stack.getCount(); // serialize nbt as snbt - var encodeResult = ItemStack.CODEC.encodeStart(JsonOps.COMPRESSED, stack); + var encodeResult = ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, stack); var json = encodeResult.resultOrPartial(PacketInterceptorMod.LOGGER::error).orElse(new JsonObject()); // return empty on error return PacketInfoBundle.of( From 74f0d59d3a5d67279a0563650964f994ec476390 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Wed, 25 Mar 2026 19:39:05 +0100 Subject: [PATCH 03/19] Clean up comments, replace PacketInfoSegment usage with PacketInfoRow when preferred, add clarifying comments, remove AGENTS.md (it was stupid) --- AGENTS.md | 44 ------------------- .../bitsquidd/ninja/config/ConfigScreen.java | 2 +- .../ninja/format/PacketInfoList.java | 2 +- .../clientbound/RemoveEntitiesHandler.java | 9 ++-- .../bitsquidd/ninja/PacketInterceptor.java | 1 + 5 files changed, 6 insertions(+), 52 deletions(-) delete mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 37e4858..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,44 +0,0 @@ -# AGENTS Guide: PacketNinja - -## What this repo is -- Fabric client-side mod (`minecraft` 1.21.11, Java 21) for packet interception/logging. -- Primary runtime logic is in `src/client/java`; `src/main/java` only contains a minimal common initializer. - -## Core architecture (read these first) -- Entrypoints are declared in `src/main/resources/fabric.mod.json`: - - client init: `xyz.bitsquidd.ninja.PacketInterceptorMod` - - Mod Menu config hook: `xyz.bitsquidd.ninja.config.ConfigMenu` -- Packet tap is injected via Mixin in `src/client/java/xyz/bitsquidd/ninja/mixin/MixinConnection.java`: - - intercepts outgoing `Connection#doSendPacket` - - intercepts incoming `Connection#channelRead0` - - unwraps `BundlePacket` and forwards each sub-packet. -- Runtime flow: Mixin -> `PacketInterceptorMod.logPacket(...)` -> `PacketFilter.shouldInterceptPacket(...)` -> `PacketLogger.addPacket(...)` -> chat output. - -## Handler system (project-specific) -- Packet formatters are `PacketHandler` implementations under `src/client/java/xyz/bitsquidd/ninja/handler/impl/**`. -- Registration is reflection-based (`PacketRegistry` + `org.reflections.Reflections`) scanning package `xyz.bitsquidd.ninja.handler.impl`. -- New handlers must have: - - concrete class (not abstract), public no-arg constructor - - `super(PacketClass, "FriendlyName", "Description", PacketType.CLIENTBOUND|SERVERBOUND)` - - `getPacketInfoInternal(...)` returning `PacketInfoBundle` + `PacketInfoSegment` list. -- `/packets filter` suggestions and toggle lookup come from handler `friendlyName` (`PacketRegistry.findHandler`). - -## Formatting and UI conventions -- Chat output uses Adventure components (`PacketLogger`, `PacketInfoBundle`) with custom glyph icons from `src/client/resources/assets/minecraft/font/default.json` and `.../textures/text/font/icons.png`. -- Use `FormatHelper` for repeated formatting patterns (positions, rotations, capped lists, item stacks). -- Packet categories/colors are centralized in `PacketType`; command response styles in `ResponseType`. - -## Config and commands -- Config file is JSON at Fabric config dir: `packetninja.json` (`Config.java`), loaded on client init. -- Mod Menu screen (`ConfigScreen`) currently exposes `packetDelayMs` with 50ms snapping. -- Commands are client-only in `PacketInterceptionCommand`: - - `/packets start`, `/packets stop`, `/packets filter [packetName]`. - -## Build/dev workflow (verified from repo files) -- Build uses Gradle + Fabric Loom (`build.gradle`), Java release target is 21. -- Wrapper script may not be executable in some environments; use `bash ./gradlew ` if needed. -- In this environment, Gradle tasks could not be listed because `JAVA_HOME`/`java` was missing. -- No test sources were found (`**/*Test*.java`). - -## Known implementation watch-outs -- `PacketInterceptorMod.MOD_ID` is `packet-interceptor` while mod id in `fabric.mod.json` is `packet-ninja`. diff --git a/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java index 555e9e4..2b3955f 100644 --- a/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java +++ b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java @@ -27,7 +27,7 @@ public static Screen create(Screen parent) { "to actually log a packet, otherwise it'll be replaced with \"...\"" )) .setSaveConsumer(newValue -> { - int step = 50; // example + int step = 50; Config.packetDelayMs = (newValue / step) * step; Config.save(); }) diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java index 547f125..19fb0a6 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java @@ -9,7 +9,7 @@ import java.util.List; /** - * Displays a titled list of key-value entries inside a packet info bundle. + * Displays a titled list of entries inside a packet info bundle. */ @NullMarked public final class PacketInfoList implements PacketInfoRow { diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java index c20f0f1..56a7ab2 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java @@ -4,10 +4,7 @@ import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoList; -import xyz.bitsquidd.ninja.format.PacketInfoRow; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.format.*; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -38,8 +35,8 @@ public RemoveEntitiesHandler() { rows.add(PacketInfoSegment.of(Component.text("Count"), Component.text(totalCount))); if (!displayedIds.isEmpty()) { - List idSegments = displayedIds.stream() - .map(id -> PacketInfoSegment.of(Component.text("EntityId"), Component.text(id))) + var idSegments = displayedIds.stream() + .map(id -> PacketInfoValue.of(Component.text(id))) .toList(); rows.add(PacketInfoList.of(Component.text("EntityIds"), new ArrayList<>(idSegments))); } diff --git a/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java b/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java index fd1a379..2ff71bc 100644 --- a/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java +++ b/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +// Mester: is this really necessary, considering the mod is client-only and will only ever call the client entry point public class PacketInterceptor implements ModInitializer { public static final String MOD_ID = "packet-ninja"; From 68b8512f1b638e6fd02c9d036e1a231c2be4c783 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Wed, 25 Mar 2026 19:57:32 +0100 Subject: [PATCH 04/19] Readd cloth config and mod menu, add missing reflections library --- build.gradle.kts | 14 ++++++++++++++ gradle/libs.versions.toml | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 5d85447..5c8063b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,6 +18,11 @@ base { repositories { mavenCentral() maven { url = uri("https://jitpack.io") } + maven { + name = "Terraformers" + url = uri("https://maven.terraformersmc.com/releases") + } + maven { url = uri("https://maven.shedaniel.me/") } } loom { @@ -45,7 +50,16 @@ dependencies { modImplementation(rootProject.libs.adventure.platform) modImplementation(rootProject.libs.classgraph) + include(rootProject.libs.javassist) + modImplementation(rootProject.libs.reflections)?.let { + include(it) + } + + modImplementation(rootProject.libs.modmenu) + modApi(rootProject.libs.clothconfig) { + exclude(group = "net.fabricmc.fabric-api") + } } tasks { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c450c3c..6b7020d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,9 +11,13 @@ adventure-platform = { group = "net.kyori", name = "adventure-platform-fabric", classgraph = { group = "io.github.classgraph", name = "classgraph", version = "4.8.179" } javassist = { group = "org.javassist", name = "javassist", version = "3.30.2-GA" } +reflections = { group = "org.reflections", name = "reflections", version = "0.10.2" } errorprone = { group = "com.google.errorprone", name = "error_prone_core", version = "2.45.0" } +modmenu = { group = "com.terraformersmc", name = "modmenu", version = "17.0.0-beta.2"} +clothconfig = { group = "me.shedaniel.cloth", name = "cloth-config-fabric", version = "21.11.153" } + [plugins] fabric-loom = { id = "fabric-loom", version = "1.14-SNAPSHOT" } From dfb9f1b36fa00e4220de177d3de5cd6a37b06942 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Thu, 26 Mar 2026 02:13:14 +0100 Subject: [PATCH 05/19] Move old build.yml to publish.yml, create new build.yml without publishing --- .github/workflows/build.yml | 150 +++---------------------------- .github/workflows/publish.yml | 164 ++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 138 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8349b4..aaa950f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,11 +1,14 @@ -name: Release and Publish - -permissions: - contents: write +name: Build and Test on: + push: + branches: [ master ] + pull_request: workflow_dispatch: +permissions: + contents: read + jobs: build: name: Build Release @@ -25,140 +28,11 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Determine version - id: determine-version - run: | - VERSION=$(grep -E "^mod_version=" gradle.properties | cut -d'=' -f2 | tr -d '[:space:]') - MC_VERSION=$(grep -E "^minecraft_version=" gradle.properties | cut -d'=' -f2 | tr -d '[:space:]') - - if [ -z "$VERSION" ]; then - echo "Could not read version from gradle.properties" - exit 1 - fi - if [ -z "$MC_VERSION" ]; then - echo "Could not read minecraft_version from gradle.properties" - exit 1 - fi - - echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "MC_VERSION=$MC_VERSION" >> $GITHUB_ENV - - name: Build with Gradle - run: ./gradlew build - - - name: Generate Changelog - id: changelog - run: | - export LC_ALL=C.UTF-8 - export LANG=C.UTF-8 - - git fetch --tags --force - - CURRENT_TAG="${{ env.VERSION }}" - PREVIOUS_TAG=$(git tag --sort=-v:refname | grep -vx "$CURRENT_TAG" | head -n1) - - if [ -z "$PREVIOUS_TAG" ]; then - echo "## 🚀 Initial Release $CURRENT_TAG" > changelog.md - echo "" >> changelog.md - echo "This is the first official release." >> changelog.md - else - echo "## 🚀 Release $CURRENT_TAG" > changelog.md - echo "" >> changelog.md - - git log --pretty=format:"%s (%h)" "$PREVIOUS_TAG"..HEAD > all_commits.txt - - FEATURES=$(grep -E "^(✨|:sparkles:)" all_commits.txt || true) - if [ ! -z "$FEATURES" ]; then - echo "### ✨ Features" >> changelog.md - echo "$FEATURES" | sed -E 's/^(✨|:sparkles:) /\* /' >> changelog.md - echo "" >> changelog.md - fi - - BUGFIXES=$(grep -E "^(🐛|:bug:)" all_commits.txt || true) - if [ ! -z "$BUGFIXES" ]; then - echo "### 🐛 Bug Fixes" >> changelog.md - echo "$BUGFIXES" | sed -E 's/^(🐛|:bug:) /\* /' >> changelog.md - echo "" >> changelog.md - fi + run: ./gradlew build --no-daemon --stacktrace - REFACTOR=$(grep -E "^(🎨|:art:)" all_commits.txt || true) - if [ ! -z "$REFACTOR" ]; then - echo "### 🎨 Refactors / Performance" >> changelog.md - echo "$REFACTOR" | sed -E 's/^(🎨|:art:) /\* /' >> changelog.md - echo "" >> changelog.md - fi - - OTHER=$(grep -vE "^(✨|:sparkles:|🐛|:bug:|🎨|:art:|Merge)" all_commits.txt || true) - if [ ! -z "$OTHER" ]; then - echo "### 📦 Other Changes" >> changelog.md - echo "$OTHER" | sed 's/^/\* /' >> changelog.md - echo "" >> changelog.md - fi - - rm -f all_commits.txt - fi - - cat changelog.md - - CHANGELOG=$(cat changelog.md) - echo "changelog<> $GITHUB_OUTPUT - echo "$CHANGELOG" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Locate primary JAR - run: | - PRIMARY=$(ls build/libs/*.jar \ - | grep -v "\-dev\." \ - | grep -v "\-sources\." \ - | grep -v "\-javadoc\." \ - | head -n1) - - if [ -z "$PRIMARY" ]; then - echo "Could not find primary JAR" - exit 1 - fi - echo "PRIMARY_JAR=$PRIMARY" >> $GITHUB_ENV - echo "Found primary JAR: $PRIMARY" - - - name: Create GitHub Release - uses: softprops/action-gh-release@v1 + - name: Upload artifacts + uses: actions/upload-artifact@v4 with: - tag_name: ${{ env.VERSION }} - name: Release ${{ env.VERSION }} - body: ${{ steps.changelog.outputs.changelog }} - draft: false - prerelease: false - files: | - build/libs/*.jar - LICENSE - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish to Modrinth - env: - MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} - CHANGELOG: ${{ steps.changelog.outputs.changelog }} - run: ./gradlew modrinth modrinthSyncBody - - - name: Bump minor version - run: | - CURRENT="${{ env.VERSION }}" - MAJOR=$(echo "$CURRENT" | cut -d'.' -f1) - MID=$(echo "$CURRENT" | cut -d'.' -f2) - MINOR=$(echo "$CURRENT" | cut -d'.' -f3) - - NEW_MINOR=$((MINOR + 1)) - NEW_VERSION="$MAJOR.$MID.$NEW_MINOR" - - sed -i "s/^mod_version=.*/mod_version=$NEW_VERSION/" gradle.properties - - echo "Bumped version: $CURRENT → $NEW_VERSION" - echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV - - - name: Commit version bump - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add gradle.properties - git commit -m "🏷️ Bump version to ${{ env.NEW_VERSION }}" - git push \ No newline at end of file + name: build-artifacts + path: 'build/libs/packet-ninja-*.jar' \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..a692293 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,164 @@ +name: Release and Publish + +permissions: + contents: write + +on: + workflow_dispatch: + +jobs: + build: + name: Build Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Determine version + id: determine-version + run: | + VERSION=$(grep -E "^mod_version=" gradle.properties | cut -d'=' -f2 | tr -d '[:space:]') + MC_VERSION=$(grep -E "^minecraft_version=" gradle.properties | cut -d'=' -f2 | tr -d '[:space:]') + + if [ -z "$VERSION" ]; then + echo "Could not read version from gradle.properties" + exit 1 + fi + if [ -z "$MC_VERSION" ]; then + echo "Could not read minecraft_version from gradle.properties" + exit 1 + fi + + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "MC_VERSION=$MC_VERSION" >> $GITHUB_ENV + + - name: Build with Gradle + run: ./gradlew build --no-daemon --stacktrace + + - name: Generate Changelog + id: changelog + run: | + export LC_ALL=C.UTF-8 + export LANG=C.UTF-8 + + git fetch --tags --force + + CURRENT_TAG="${{ env.VERSION }}" + PREVIOUS_TAG=$(git tag --sort=-v:refname | grep -vx "$CURRENT_TAG" | head -n1) + + if [ -z "$PREVIOUS_TAG" ]; then + echo "## 🚀 Initial Release $CURRENT_TAG" > changelog.md + echo "" >> changelog.md + echo "This is the first official release." >> changelog.md + else + echo "## 🚀 Release $CURRENT_TAG" > changelog.md + echo "" >> changelog.md + + git log --pretty=format:"%s (%h)" "$PREVIOUS_TAG"..HEAD > all_commits.txt + + FEATURES=$(grep -E "^(✨|:sparkles:)" all_commits.txt || true) + if [ ! -z "$FEATURES" ]; then + echo "### ✨ Features" >> changelog.md + echo "$FEATURES" | sed -E 's/^(✨|:sparkles:) /\* /' >> changelog.md + echo "" >> changelog.md + fi + + BUGFIXES=$(grep -E "^(🐛|:bug:)" all_commits.txt || true) + if [ ! -z "$BUGFIXES" ]; then + echo "### 🐛 Bug Fixes" >> changelog.md + echo "$BUGFIXES" | sed -E 's/^(🐛|:bug:) /\* /' >> changelog.md + echo "" >> changelog.md + fi + + REFACTOR=$(grep -E "^(🎨|:art:)" all_commits.txt || true) + if [ ! -z "$REFACTOR" ]; then + echo "### 🎨 Refactors / Performance" >> changelog.md + echo "$REFACTOR" | sed -E 's/^(🎨|:art:) /\* /' >> changelog.md + echo "" >> changelog.md + fi + + OTHER=$(grep -vE "^(✨|:sparkles:|🐛|:bug:|🎨|:art:|Merge)" all_commits.txt || true) + if [ ! -z "$OTHER" ]; then + echo "### 📦 Other Changes" >> changelog.md + echo "$OTHER" | sed 's/^/\* /' >> changelog.md + echo "" >> changelog.md + fi + + rm -f all_commits.txt + fi + + cat changelog.md + + CHANGELOG=$(cat changelog.md) + echo "changelog<> $GITHUB_OUTPUT + echo "$CHANGELOG" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Locate primary JAR + run: | + PRIMARY=$(ls build/libs/*.jar \ + | grep -v "\-dev\." \ + | grep -v "\-sources\." \ + | grep -v "\-javadoc\." \ + | head -n1) + + if [ -z "$PRIMARY" ]; then + echo "Could not find primary JAR" + exit 1 + fi + echo "PRIMARY_JAR=$PRIMARY" >> $GITHUB_ENV + echo "Found primary JAR: $PRIMARY" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ env.VERSION }} + name: Release ${{ env.VERSION }} + body: ${{ steps.changelog.outputs.changelog }} + draft: false + prerelease: false + files: | + build/libs/*.jar + LICENSE + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to Modrinth + env: + MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }} + CHANGELOG: ${{ steps.changelog.outputs.changelog }} + run: ./gradlew modrinth modrinthSyncBody + + - name: Bump minor version + run: | + CURRENT="${{ env.VERSION }}" + MAJOR=$(echo "$CURRENT" | cut -d'.' -f1) + MID=$(echo "$CURRENT" | cut -d'.' -f2) + MINOR=$(echo "$CURRENT" | cut -d'.' -f3) + + NEW_MINOR=$((MINOR + 1)) + NEW_VERSION="$MAJOR.$MID.$NEW_MINOR" + + sed -i "s/^mod_version=.*/mod_version=$NEW_VERSION/" gradle.properties + + echo "Bumped version: $CURRENT → $NEW_VERSION" + echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV + + - name: Commit version bump + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add gradle.properties + git commit -m "🏷️ Bump version to ${{ env.NEW_VERSION }}" + git push \ No newline at end of file From 617aab06faf5876cd765a867a09c9e752e3496a2 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Thu, 26 Mar 2026 11:06:53 +0000 Subject: [PATCH 06/19] =?UTF-8?q?=F0=9F=8E=A8=20Update=20libs.versions.tom?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0ce8a0f..a3311de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,11 +11,10 @@ adventure-platform = { group = "net.kyori", name = "adventure-platform-fabric", classgraph = { group = "io.github.classgraph", name = "classgraph", version = "4.8.179" } javassist = { group = "org.javassist", name = "javassist", version = "3.30.2-GA" } -reflections = { group = "org.reflections", name = "reflections", version = "0.10.2" } errorprone = { group = "com.google.errorprone", name = "error_prone_core", version = "2.45.0" } -modmenu = { group = "com.terraformersmc", name = "modmenu", version = "17.0.0-beta.2"} +modmenu = { group = "com.terraformersmc", name = "modmenu", version = "17.0.0-beta.2" } clothconfig = { group = "me.shedaniel.cloth", name = "cloth-config-fabric", version = "21.11.153" } From 8d79380112f461bca4a22af92c7ac69390b56c33 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Thu, 26 Mar 2026 14:59:14 +0100 Subject: [PATCH 07/19] Begin review changes --- .../xyz/bitsquidd/ninja/PacketInterceptorMod.java | 2 +- .../ninja/command/PacketInterceptionCommand.java | 2 +- .../xyz/bitsquidd/ninja/format/PacketLogger.java | 2 +- .../xyz/bitsquidd/ninja/PacketInterceptor.java | 15 --------------- 4 files changed, 3 insertions(+), 18 deletions(-) delete mode 100644 src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java diff --git a/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java b/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java index d06e3df..5be00e3 100644 --- a/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java +++ b/src/client/java/xyz/bitsquidd/ninja/PacketInterceptorMod.java @@ -31,10 +31,10 @@ public PacketInterceptorMod() { @Override public void onInitializeClient() { + Config.load(); ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> PacketInterceptionCommand.register(dispatcher) ); - Config.load(); } public @NotNull PacketFilter getPacketFilter() { diff --git a/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java b/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java index 5afcf24..099d783 100644 --- a/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java +++ b/src/client/java/xyz/bitsquidd/ninja/command/PacketInterceptionCommand.java @@ -135,7 +135,7 @@ private static int togglePacket(CommandContext ctx) { .append(Component.text(packetName)), ResponseType.ERROR ); - return 0; + return Command.SINGLE_SUCCESS; } filter.togglePacketFilter(handler.getFriendlyName()); diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java index ce69154..bab3039 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java @@ -33,7 +33,7 @@ public void addPacket(final Packet packet) { if (Duration.between(lastPacketTime, currentTime).compareTo(Duration.ofMillis(delayRequired)) < 0) { sendChatMessage( Component.text("...", NamedTextColor.GRAY) - .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %s, hiding.", delayRequired))) + .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %sms, hiding.", delayRequired))) )); return; } diff --git a/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java b/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java deleted file mode 100644 index 2ff71bc..0000000 --- a/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java +++ /dev/null @@ -1,15 +0,0 @@ -package xyz.bitsquidd.ninja; - -import net.fabricmc.api.ModInitializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -// Mester: is this really necessary, considering the mod is client-only and will only ever call the client entry point -public class PacketInterceptor implements ModInitializer { - public static final String MOD_ID = "packet-ninja"; - - public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); - - @Override - public void onInitialize() {} -} \ No newline at end of file From e22f1000a9c19a9f3991ba90933fe76df579c3ee Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Thu, 26 Mar 2026 15:04:20 +0100 Subject: [PATCH 08/19] Comment updates --- .../java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java | 2 +- .../ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java | 2 +- .../ninja/handler/impl/clientbound/SetPlayerTeamHandler.java | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java index 06cd57f..bcc713a 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java @@ -5,7 +5,7 @@ import xyz.bitsquidd.ninja.handler.PacketType; /** - * Represents an element of a [PacketInfoList]. + * Represents an element of a {@link PacketInfoList}. */ public interface PacketInfoListElement { Component formatLine(PacketType type, String prefix); diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java index f25db97..10430b1 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java @@ -35,7 +35,7 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent return ""; } - // here is the fun part: displayName is Minecraft's Component, we want to convert it to MiniMessage + // convert Minecraft's native Component into MiniMessage so we can properly display it var jsonElement = ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, displayName) .resultOrPartial(error -> PacketInterceptorMod.LOGGER.error("Failed to serialize displayName for player {}: {}", entry.profileId(), error) diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java index e524be5..3e52062 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java @@ -37,7 +37,6 @@ public SetPlayerTeamHandler() { rows.add(PacketInfoSegment.of(Component.text("TeamAction"), Component.text(teamAction != null ? teamAction.name() : "null"))); rows.add(PacketInfoSegment.of(Component.text("PlayerAction"), Component.text(playerAction != null ? playerAction.name() : "null"))); - // Add players as structured list if (!packet.getPlayers().isEmpty()) { List playerList = packet.getPlayers().stream() .limit(MAX_DISPLAYED_ENTRIES) From 8f4910b5ba8db3b0333323214f45c84220ec1543 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Thu, 26 Mar 2026 15:05:11 +0100 Subject: [PATCH 09/19] Remove quotes from gradle.properties, causing build failures --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 943d9d6..633a35a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,4 +9,4 @@ fabric_version=0.140.2+1.21.11 # Modmenu modmenu_version=17.0.0-beta.2 # Mod Version -version="0.0.6" \ No newline at end of file +version=0.0.6 \ No newline at end of file From 9ea38ceba14d8f7728cba2ff06bf42fff46bbb04 Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Thu, 26 Mar 2026 15:25:28 +0100 Subject: [PATCH 10/19] Remove PacketInfoBundle.ofRows constructor, fix crash for missing audience platform --- build.gradle.kts | 2 +- .../xyz/bitsquidd/ninja/format/PacketInfoBundle.java | 6 +----- .../CommandSuggestionsResponseHandler.java | 12 ++++-------- .../impl/clientbound/ContainerSetContentHandler.java | 12 ++++-------- .../impl/clientbound/PlayerInfoRemoveHandler.java | 2 +- .../impl/clientbound/PlayerInfoUpdateHandler.java | 2 +- .../impl/clientbound/RemoveEntitiesHandler.java | 2 +- .../impl/clientbound/SetPassengersHandler.java | 2 +- .../impl/clientbound/SetPlayerTeamHandler.java | 2 +- 9 files changed, 15 insertions(+), 27 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c8f08af..c9c74d6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,10 +45,10 @@ dependencies { modImplementation(rootProject.libs.fabric.api) modImplementation(rootProject.libs.adventure.platform) + include(rootProject.libs.adventure.platform) modImplementation(rootProject.libs.bits.api) include(rootProject.libs.bits.api) - include(rootProject.libs.javassist) modImplementation(rootProject.libs.modmenu) diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java index 3ad0ff0..365bf48 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java @@ -26,11 +26,7 @@ private PacketInfoBundle(PacketType type, Component name, List ro this.rows = rows; } - public static PacketInfoBundle of(PacketType type, Component name, List segments) { - return ofRows(type, name, new ArrayList<>(segments)); - } - - public static PacketInfoBundle ofRows(PacketType type, Component name, List rows) { + public static PacketInfoBundle of(PacketType type, Component name, List rows) { return new PacketInfoBundle(type, name, new ArrayList<>(rows)); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java index d9778f9..7e16ffb 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java @@ -4,10 +4,7 @@ import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoList; -import xyz.bitsquidd.ninja.format.PacketInfoRow; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.format.*; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -37,10 +34,9 @@ public CommandSuggestionsResponseHandler() { // Display suggestions as a structured list if (!suggestions.isEmpty()) { - List suggestionSegments = suggestions.stream() + var suggestionSegments = suggestions.stream() .limit(MAX_DISPLAYED_ENTRIES) - .map(entry -> PacketInfoSegment.of( - Component.text("Suggestion"), + .map(entry -> PacketInfoValue.of( Component.text(entry.text()) )) .toList(); @@ -52,7 +48,7 @@ public CommandSuggestionsResponseHandler() { } } - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java index bacc2e1..ec67e28 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java @@ -4,11 +4,7 @@ import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.FormatHelper; -import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoList; -import xyz.bitsquidd.ninja.format.PacketInfoRow; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.format.*; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,9 +24,9 @@ public ContainerSetContentHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundContainerSetContentPacket packet) { - List itemSegments = packet.items().stream() + var itemSegments = packet.items().stream() .limit(MAX_DISPLAYED_ENTRIES) - .map(item -> PacketInfoSegment.of(Component.text("Item"), Component.text(FormatHelper.formatItemStack(item)))) + .map(item -> PacketInfoValue.of(Component.text(FormatHelper.formatItemStack(item)))) .toList(); List rows = new ArrayList<>(); @@ -48,7 +44,7 @@ public ContainerSetContentHandler() { rows.add(PacketInfoSegment.of(Component.text("CarriedItem"), Component.text(FormatHelper.formatItemStack(packet.carriedItem())))); - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java index 6c0327f..ba83b09 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java @@ -29,7 +29,7 @@ public PlayerInfoRemoveHandler() { var rows = new ArrayList(); rows.add(PacketInfoList.of(Component.text("Removed UUIDs"), removed)); - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java index 10430b1..51a7a76 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java @@ -80,7 +80,7 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent rows.addAll(entryLists); - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java index 56a7ab2..06fd6f5 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java @@ -46,7 +46,7 @@ public RemoveEntitiesHandler() { rows.add(PacketInfoSegment.of(Component.text("EntityIdsHidden"), Component.text(hiddenEntities + " more"))); } - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java index e7a8708..47a77e1 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java @@ -46,7 +46,7 @@ public SetPassengersHandler() { rows.add(PacketInfoSegment.of(Component.text("PassengersHidden"), Component.text(hiddenPassengers + " more"))); } - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java index 3e52062..09464ab 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java @@ -90,7 +90,7 @@ public SetPlayerTeamHandler() { rows.add(PacketInfoSegment.of(Component.text("Options"), Component.text(String.format("0x%02X", params.getOptions())))); }); - return PacketInfoBundle.ofRows( + return PacketInfoBundle.of( packetType, Component.text(friendlyName), rows From 6b5b905c5953a7161c04ed7336721eac4771761a Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Fri, 27 Mar 2026 17:48:28 +0100 Subject: [PATCH 11/19] Implement world border packets --- .../InitializeWorldBorderHandler.java | 39 +++++++++++++++++++ .../clientbound/SetBorderCenterHandler.java | 37 ++++++++++++++++++ .../clientbound/SetBorderLerpSizeHandler.java | 35 +++++++++++++++++ .../clientbound/SetBorderSizeHandler.java | 36 +++++++++++++++++ .../SetBorderWarningDelayHandler.java | 36 +++++++++++++++++ .../SetBorderWarningDistanceHandler.java | 36 +++++++++++++++++ 6 files changed, 219 insertions(+) create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java new file mode 100644 index 0000000..cd936b8 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java @@ -0,0 +1,39 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; + +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class InitializeWorldBorderHandler extends PacketHandler { + public InitializeWorldBorderHandler() { + super( + ClientboundInitializeBorderPacket.class, + "InitializeWorldBorder", + "Handles world border initialization", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundInitializeBorderPacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("Location"), Component.text(String.format("X=%s, Z=%s", packet.getNewCenterX(), packet.getNewCenterZ()))), + PacketInfoSegment.of(Component.text("Size"), Component.text(String.format("%s -> %s", packet.getOldSize(), packet.getNewSize()))), + PacketInfoSegment.of(Component.text("Speed"), Component.text(packet.getLerpTime() + " ticks")), + PacketInfoSegment.of(Component.text("Portal boundary"), Component.text(packet.getNewAbsoluteMaxSize())), + PacketInfoSegment.of(Component.text("Warning"), Component.text(String.format("Blocks=%s, time=%s ticks", packet.getWarningBlocks(), packet.getWarningTime()))) + ) + ); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java new file mode 100644 index 0000000..417e4d3 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java @@ -0,0 +1,37 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class SetBorderCenterHandler extends PacketHandler { + + public SetBorderCenterHandler() { + super( + ClientboundSetBorderCenterPacket.class, + "SetBorderCenter", + "Handles world border center updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderCenterPacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("X"), Component.text(packet.getNewCenterX())), + PacketInfoSegment.of(Component.text("Z"), Component.text(packet.getNewCenterZ())) + ) + ); + } + +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java new file mode 100644 index 0000000..7b17606 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java @@ -0,0 +1,35 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class SetBorderLerpSizeHandler extends PacketHandler { + public SetBorderLerpSizeHandler() { + super( + ClientboundSetBorderLerpSizePacket.class, + "SetBorderSize", + "Handles world border size updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderLerpSizePacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("Size"), Component.text(String.format("%s -> %s", packet.getOldSize(), packet.getNewSize()))), + PacketInfoSegment.of(Component.text("Speed"), Component.text(packet.getLerpTime() + " ticks")) + ) + ); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java new file mode 100644 index 0000000..66170c4 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java @@ -0,0 +1,36 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class SetBorderSizeHandler extends PacketHandler { + + public SetBorderSizeHandler() { + super( + ClientboundSetBorderSizePacket.class, + "SetBorderSize", + "Handles world border size updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderSizePacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("Size"), Component.text(packet.getSize())) + ) + ); + } +} + diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java new file mode 100644 index 0000000..89ccb36 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java @@ -0,0 +1,36 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class SetBorderWarningDelayHandler extends PacketHandler { + + public SetBorderWarningDelayHandler() { + super( + ClientboundSetBorderWarningDelayPacket.class, + "SetBorderWarningDelay", + "Handles world border warning delay updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderWarningDelayPacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("Warning Time"), Component.text(packet.getWarningDelay() + " ticks")) + ) + ); + } +} + diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java new file mode 100644 index 0000000..44386e1 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java @@ -0,0 +1,36 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +import net.kyori.adventure.text.Component; +import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; +import org.jetbrains.annotations.NotNull; + +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +import xyz.bitsquidd.ninja.format.PacketInfoSegment; +import xyz.bitsquidd.ninja.handler.PacketHandler; +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.List; + +public class SetBorderWarningDistanceHandler extends PacketHandler { + + public SetBorderWarningDistanceHandler() { + super( + ClientboundSetBorderWarningDistancePacket.class, + "SetBorderWarningDistance", + "Handles world border warning distance updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderWarningDistancePacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfoSegment.of(Component.text("Warning Distance"), Component.text(packet.getWarningBlocks() + " blocks")) + ) + ); + } +} + From e535326b3f27ed33c0bd9b50edc013a418baa5bf Mon Sep 17 00:00:00 2001 From: MesterMan03 Date: Fri, 27 Mar 2026 17:53:33 +0100 Subject: [PATCH 12/19] Fix clashing friendly names --- .../handler/impl/clientbound/SetBorderLerpSizeHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java index 7b17606..fd70295 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java @@ -15,8 +15,8 @@ public class SetBorderLerpSizeHandler extends PacketHandler Date: Fri, 27 Mar 2026 21:02:29 +0000 Subject: [PATCH 13/19] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refined=20use=20of?= =?UTF-8?q?=20Rows,=20Lists=20and=20values=20for=20packet=20formatting.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xyz/bitsquidd/ninja/config/Config.java | 7 +-- .../bitsquidd/ninja/config/ConfigScreen.java | 20 +++++--- .../ninja/format/ListPacketData.java | 39 +++++++++++++++ .../bitsquidd/ninja/format/PacketInfo.java | 34 +++++++++++++ .../ninja/format/PacketInfoBundle.java | 36 +++++--------- .../ninja/format/PacketInfoList.java | 46 ----------------- .../ninja/format/PacketInfoListElement.java | 12 ----- .../bitsquidd/ninja/format/PacketInfoRow.java | 14 ------ .../ninja/format/PacketInfoSegment.java | 49 ------------------- .../ninja/format/PacketInfoValue.java | 38 -------------- .../bitsquidd/ninja/format/PacketLogger.java | 12 ++--- .../ninja/format/SinglePacketData.java | 27 ++++++++++ .../ninja/format/SinglePacketValue.java | 18 +++++++ .../ninja/format/formatter/Formatters.java | 9 ++++ .../impl/clientbound/AddEntityHandler.java | 12 ++--- .../impl/clientbound/BossEventHandler.java | 46 ++++++++--------- .../CommandSuggestionsResponseHandler.java | 18 +++---- .../clientbound/ContainerCloseHandler.java | 4 +- .../ContainerSetContentHandler.java | 20 ++++---- .../clientbound/ContainerSetSlotHandler.java | 10 ++-- .../clientbound/CustomPayloadHandler.java | 10 ++-- .../InitializeWorldBorderHandler.java | 13 +++-- .../impl/clientbound/OpenScreenHandler.java | 8 +-- .../handler/impl/clientbound/PingHandler.java | 4 +- .../clientbound/PlayerInfoRemoveHandler.java | 12 +++-- .../clientbound/PlayerInfoUpdateHandler.java | 22 ++++----- .../clientbound/RemoveEntitiesHandler.java | 14 +++--- .../clientbound/SetBorderCenterHandler.java | 38 +++++++------- .../clientbound/SetBorderLerpSizeHandler.java | 6 +-- .../clientbound/SetBorderSizeHandler.java | 4 +- .../SetBorderWarningDelayHandler.java | 4 +- .../SetBorderWarningDistanceHandler.java | 4 +- .../clientbound/SetCursorItemHandler.java | 8 +-- .../clientbound/SetEntityDataHandler.java | 8 +-- .../clientbound/SetPassengersHandler.java | 18 +++---- .../clientbound/SetPlayerTeamHandler.java | 34 ++++++------- .../impl/clientbound/SystemChatHandler.java | 31 ++++++------ .../clientbound/TrackedWaypointHandler.java | 10 ++-- .../clientbound/UpdateAttributesHandler.java | 6 +-- .../CommandSuggestionsRequestHandler.java | 6 +-- .../impl/serverbound/InteractHandler.java | 4 +- .../impl/serverbound/PlayerActionHandler.java | 6 +-- .../handler/impl/serverbound/PongHandler.java | 4 +- 43 files changed, 354 insertions(+), 391 deletions(-) create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java delete mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java delete mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java delete mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java delete mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java delete mode 100644 src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java create mode 100644 src/client/java/xyz/bitsquidd/ninja/format/formatter/Formatters.java diff --git a/src/client/java/xyz/bitsquidd/ninja/config/Config.java b/src/client/java/xyz/bitsquidd/ninja/config/Config.java index 0636d37..5730526 100644 --- a/src/client/java/xyz/bitsquidd/ninja/config/Config.java +++ b/src/client/java/xyz/bitsquidd/ninja/config/Config.java @@ -9,12 +9,13 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Duration; public class Config { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final Path FILE = FabricLoader.getInstance().getConfigDir().resolve("packetninja.json"); - public static int packetDelayMs = 500; + public static Duration packetDelay = Duration.ofMillis(500); public static void load() { if (Files.exists(FILE)) { @@ -22,7 +23,7 @@ public static void load() { String json = Files.readString(FILE); ConfigData data = GSON.fromJson(json, ConfigData.class); if (data != null) { - packetDelayMs = data.packetDelayMs; + packetDelay = data.packetDelayMs; } } catch (Exception e) { PacketInterceptorMod.LOGGER.error("Failed to load config, using defaults"); @@ -35,7 +36,7 @@ public static void load() { public static void save() { try { ConfigData data = new ConfigData(); - data.packetDelayMs = packetDelayMs; + data.packetDelayMs = packetDelay; Files.writeString(FILE, GSON.toJson(data)); } catch (IOException e) { diff --git a/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java index 2b3955f..3df7528 100644 --- a/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java +++ b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java @@ -4,6 +4,8 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import java.time.Duration; + public class ConfigScreen { public static Screen create(Screen parent) { var builder = ConfigBuilder.create() @@ -14,12 +16,16 @@ public static Screen create(Screen parent) { var entryBuilder = builder.entryBuilder(); general.addEntry(entryBuilder - .startIntSlider(Component.literal("Packet Delay (ms)"), - Config.packetDelayMs, 0, 2000) - .setDefaultValue(500) + .startLongSlider( + Component.literal("Packet Delay (ms)"), + Config.packetDelay.toMillis(), + 0, + 2000L + ) + .setDefaultValue(500L) .setTextGetter(value -> { - int step = 50; - int snapped = (value / step) * step; + long step = 50L; + long snapped = (value / step) * step; return Component.literal(snapped + " ms"); }) .setTooltip(Component.literal( @@ -27,8 +33,8 @@ public static Screen create(Screen parent) { "to actually log a packet, otherwise it'll be replaced with \"...\"" )) .setSaveConsumer(newValue -> { - int step = 50; - Config.packetDelayMs = (newValue / step) * step; + long step = 50L; + Config.packetDelay = Duration.ofMillis((newValue / step) * step); Config.save(); }) .build() diff --git a/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java new file mode 100644 index 0000000..a98dd27 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java @@ -0,0 +1,39 @@ +package xyz.bitsquidd.ninja.format; + +import com.google.common.collect.ImmutableList; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; + +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.Collection; + +/** + * Displays a titled list of entries inside a packet info bundle. + */ +public final class ListPacketData implements PacketInfo { + private final Component name; + private final ImmutableList subInfo; + + ListPacketData(Component name, Collection subInfo) { + this.name = name; + this.subInfo = ImmutableList.copyOf(subInfo); + } + + @Override + public Component format(PacketType type) { + TextComponent.Builder lineBuilder = Component.text(); + + lineBuilder.append(Component.empty() + .append(name.color(type.primaryColor)) + .append(Component.text(": ")) + ); + + subInfo.forEach(info -> lineBuilder + .appendNewline() + .append(Component.text(" ↪ ")) + .append(info.format(type))); + + return lineBuilder.build(); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java new file mode 100644 index 0000000..cfa88de --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java @@ -0,0 +1,34 @@ +package xyz.bitsquidd.ninja.format; + +import net.kyori.adventure.text.Component; + +import xyz.bitsquidd.ninja.handler.PacketType; + +import java.util.Collection; +import java.util.List; + +/** + * Any information that a packet can give. Convenience methods for pretty formatting. + */ +public interface PacketInfo { + Component format(PacketType type); + + + static PacketInfo data(Component name, Object value) { + return new SinglePacketData(name, value); + } + + static PacketInfo value(Component value) { + return new SinglePacketValue(value); + } + + + static PacketInfo list(Component name, PacketInfo... subInfo) { + return list(name, List.of(subInfo)); + } + + static PacketInfo list(Component name, Collection subInfo) { + return new ListPacketData(name, subInfo); + } + +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java index 365bf48..839c253 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java @@ -1,13 +1,12 @@ package xyz.bitsquidd.ninja.format; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; +import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.TextDecoration; import org.jspecify.annotations.NullMarked; import xyz.bitsquidd.ninja.handler.PacketType; -import java.util.ArrayList; import java.util.List; /** @@ -18,35 +17,26 @@ public final class PacketInfoBundle { private final PacketType type; private final Component name; - private final List rows; + private final List info; - private PacketInfoBundle(PacketType type, Component name, List rows) { + private PacketInfoBundle(PacketType type, Component name, List info) { this.type = type; this.name = name; - this.rows = rows; + this.info = info; } - public static PacketInfoBundle of(PacketType type, Component name, List rows) { - return new PacketInfoBundle(type, name, new ArrayList<>(rows)); + public static PacketInfoBundle of(PacketType type, Component name, List info) { + return new PacketInfoBundle(type, name, List.copyOf(info)); } public Component format() { - Component titleComponent = Component.empty() - .append(Component.text(type.icon + " ")) - .append(name - .color(type.primaryColor) - .decorate(TextDecoration.BOLD) - ); - - List segmentComponents = new ArrayList<>(); - for (PacketInfoRow row : rows) { - segmentComponents.addAll(row.format(type)); - } - - List allComponents = new ArrayList<>(List.of(titleComponent)); - allComponents.addAll(segmentComponents); - - return Component.join(JoinConfiguration.newlines(), allComponents); + TextComponent.Builder infoBuilder = Component.text(); + + infoBuilder.append(Component.text(type.icon + " ")); + infoBuilder.append(PacketInfo.list(name.decorate(TextDecoration.BOLD), info).format(type)); + infoBuilder.appendNewline(); + + return infoBuilder.build(); } } diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java deleted file mode 100644 index 19fb0a6..0000000 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoList.java +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.bitsquidd.ninja.format; - -import net.kyori.adventure.text.Component; -import org.jspecify.annotations.NullMarked; - -import xyz.bitsquidd.ninja.handler.PacketType; - -import java.util.ArrayList; -import java.util.List; - -/** - * Displays a titled list of entries inside a packet info bundle. - */ -@NullMarked -public final class PacketInfoList implements PacketInfoRow { - private final Component title; - private final List entries; - - private PacketInfoList(Component title, List entries) { - this.title = title; - this.entries = entries; - } - - public static PacketInfoList of(Component title, List entries) { - return new PacketInfoList(title, entries); - } - - @Override - public List format(PacketType type) { - List lines = new ArrayList<>(); - lines.add( - Component.empty() - .color(type.secondaryColor) - .append(Component.text(" ↪ ")) - .append(title) - .append(Component.text(":")) - ); - - for (int i = 0; i < entries.size(); i++) { - var entry = entries.get(i); - lines.add(entry.formatLine(type, " " + (i + 1) + ". ")); - } - - return lines; - } -} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java deleted file mode 100644 index bcc713a..0000000 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoListElement.java +++ /dev/null @@ -1,12 +0,0 @@ -package xyz.bitsquidd.ninja.format; - -import net.kyori.adventure.text.Component; - -import xyz.bitsquidd.ninja.handler.PacketType; - -/** - * Represents an element of a {@link PacketInfoList}. - */ -public interface PacketInfoListElement { - Component formatLine(PacketType type, String prefix); -} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java deleted file mode 100644 index 645a394..0000000 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoRow.java +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.bitsquidd.ninja.format; - -import net.kyori.adventure.text.Component; - -import xyz.bitsquidd.ninja.handler.PacketType; - -import java.util.List; - -/** - * Represents one or more display lines inside a packet info bundle. - */ -public interface PacketInfoRow { - List format(PacketType type); -} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java deleted file mode 100644 index ba0824b..0000000 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java +++ /dev/null @@ -1,49 +0,0 @@ -package xyz.bitsquidd.ninja.format; - -import net.kyori.adventure.text.Component; -import org.jspecify.annotations.NullMarked; - -import xyz.bitsquidd.ninja.handler.PacketType; - -import java.util.List; - -/** - * A segment of information about a packet, e.g. EntityID: 42 - */ -@NullMarked -public final class PacketInfoSegment implements PacketInfoRow, PacketInfoListElement { - private final Component name; - private final Component value; - - private PacketInfoSegment(Component name, Component value) { - this.name = name; - this.value = value; - } - - public static PacketInfoSegment of(Component name, Component value) { - return new PacketInfoSegment(name, value); - } - - @Override - public Component formatLine(PacketType type, String prefix) { - return Component.empty() - .color(type.secondaryColor) - .append(Component.text(prefix)) - .append(name) - .append(Component.text(": ")) - .append(value); - } - - @Override - public List format(PacketType type) { - return List.of(formatLine(type, " ↪ ")); - } - - public Component getName() { - return name; - } - - public Component getValue() { - return value; - } -} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java deleted file mode 100644 index 08a2790..0000000 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoValue.java +++ /dev/null @@ -1,38 +0,0 @@ -package xyz.bitsquidd.ninja.format; - - -import net.kyori.adventure.text.Component; -import org.jspecify.annotations.NullMarked; - -import xyz.bitsquidd.ninja.handler.PacketType; - -import java.util.List; - -/** - * A packet info row that contains a single value. - */ -@NullMarked -public final class PacketInfoValue implements PacketInfoRow, PacketInfoListElement { - private final Component value; - - private PacketInfoValue(Component value) { - this.value = value; - } - - public static PacketInfoValue of(Component value) { - return new PacketInfoValue(value); - } - - @Override - public Component formatLine(PacketType type, String prefix) { - return Component.empty() - .color(type.secondaryColor) - .append(Component.text(prefix)) - .append(value); - } - - @Override - public List format(PacketType type) { - return List.of(formatLine(type, " ↪ ")); - } -} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java index bab3039..36201a3 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java @@ -27,14 +27,14 @@ public void addPacket(final Packet packet) { PacketHandler handler = PacketRegistry.getHandlerForPacket(packet); if (handler == null) return; - var delayRequired = Config.packetDelayMs; - if(delayRequired > 0) { + Duration delayRequired = Config.packetDelay; + if (delayRequired.isPositive()) { Instant currentTime = Instant.now(); - if (Duration.between(lastPacketTime, currentTime).compareTo(Duration.ofMillis(delayRequired)) < 0) { + if (Duration.between(lastPacketTime, currentTime).compareTo(delayRequired) < 0) { sendChatMessage( Component.text("...", NamedTextColor.GRAY) - .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %sms, hiding.", delayRequired))) - )); + .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %sms, hiding.", delayRequired)))) + ); return; } lastPacketTime = currentTime; @@ -46,7 +46,7 @@ public void addPacket(final Packet packet) { public static void sendChatMessage(final Component component) { Minecraft.getInstance().execute(() -> - MinecraftClientAudiences.of().audience().sendMessage(component) + MinecraftClientAudiences.of().audience().sendMessage(component) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java new file mode 100644 index 0000000..77bdd68 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java @@ -0,0 +1,27 @@ +package xyz.bitsquidd.ninja.format; + +import net.kyori.adventure.text.Component; + +import xyz.bitsquidd.ninja.handler.PacketType; + +/** + * Represents a single bit of packet info. + */ +public class SinglePacketData implements PacketInfo { + private final Component name; + private final Component value; + + // TODO migrate to Object value + Formatters.format(value) rather than pre-formatting. + SinglePacketData(Component name, Component value) { + this.name = name; + this.value = value; + } + + @Override + public Component format(PacketType type) { + return Component.empty() + .append(name.color(type.primaryColor)) + .append(Component.text(": ")) + .append(value.color(type.secondaryColor)); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java new file mode 100644 index 0000000..6446114 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java @@ -0,0 +1,18 @@ +package xyz.bitsquidd.ninja.format; + +import net.kyori.adventure.text.Component; + +import xyz.bitsquidd.ninja.handler.PacketType; + +public class SinglePacketValue implements PacketInfo { + private final Component value; + + public SinglePacketValue(Component value) { + this.value = value; + } + + @Override + public Component format(PacketType type) { + return value.color(type.secondaryColor); + } +} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/formatter/Formatters.java b/src/client/java/xyz/bitsquidd/ninja/format/formatter/Formatters.java new file mode 100644 index 0000000..f9f371b --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/formatter/Formatters.java @@ -0,0 +1,9 @@ +package xyz.bitsquidd.ninja.format.formatter; + +public final class Formatters { + + public static String format(Object value) { + return value.toString(); + } + +} diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/AddEntityHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/AddEntityHandler.java index 2ed9dce..f0fa2e7 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/AddEntityHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/AddEntityHandler.java @@ -5,8 +5,8 @@ import org.jetbrains.annotations.NotNull; import xyz.bitsquidd.ninja.format.FormatHelper; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -29,11 +29,11 @@ public AddEntityHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("EntityID"), Component.text(packet.getId())), - PacketInfoSegment.of(Component.text("Type"), Component.text(packet.getType() + "")), - PacketInfoSegment.of(Component.text("UUID"), Component.text(packet.getUUID() + "")), - PacketInfoSegment.of(Component.text("Pos"), Component.text(FormatHelper.formatPosition(List.of(packet.getX(), packet.getY(), packet.getZ())))), - PacketInfoSegment.of(Component.text("Rot"), Component.text(FormatHelper.formatRotation(packet.getXRot(), packet.getYRot()))) + PacketInfo.data(Component.text("EntityID"), Component.text(packet.getId())), + PacketInfo.data(Component.text("Type"), Component.text(packet.getType() + "")), + PacketInfo.data(Component.text("UUID"), Component.text(packet.getUUID() + "")), + PacketInfo.data(Component.text("Pos"), Component.text(FormatHelper.formatPosition(List.of(packet.getX(), packet.getY(), packet.getZ())))), + PacketInfo.data(Component.text("Rot"), Component.text(FormatHelper.formatRotation(packet.getXRot(), packet.getYRot()))) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/BossEventHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/BossEventHandler.java index 530ad79..003de7d 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/BossEventHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/BossEventHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundBossEventPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,24 +28,24 @@ public BossEventHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundBossEventPacket packet) { - List segments = new ArrayList<>(); + List segments = new ArrayList<>(); try { Field idField = packet.getClass().getDeclaredField("id"); idField.setAccessible(true); UUID id = (UUID)idField.get(packet); - segments.add(PacketInfoSegment.of(Component.text("Boss ID"), Component.text(id.toString()))); + segments.add(PacketInfo.data(Component.text("Boss ID"), Component.text(id.toString()))); Field operationField = packet.getClass().getDeclaredField("operation"); operationField.setAccessible(true); Object operation = operationField.get(packet); String operationType = operation.getClass().getSimpleName(); - segments.add(PacketInfoSegment.of(Component.text("Operation"), Component.text(operationType))); + segments.add(PacketInfo.data(Component.text("Operation"), Component.text(operationType))); extractOperationDetails(operation, segments); } catch (Exception ignored) { - segments.add(PacketInfoSegment.of(Component.text("Error"), Component.text("Failed to extract data"))); + segments.add(PacketInfo.data(Component.text("Error"), Component.text("Failed to extract data"))); } return PacketInfoBundle.of( @@ -55,7 +55,7 @@ public BossEventHandler() { ); } - private void extractOperationDetails(Object operation, List segments) { + private void extractOperationDetails(Object operation, List segments) { try { Field typeField = operation.getClass().getDeclaredField("type"); typeField.setAccessible(true); @@ -73,64 +73,64 @@ private void extractOperationDetails(Object operation, List s } catch (Exception ignored) {} } - private void extractAddOperation(Object operation, List segments) throws Exception { + private void extractAddOperation(Object operation, List segments) throws Exception { Field nameField = operation.getClass().getDeclaredField("name"); nameField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Name"), Component.text(nameField.get(operation).toString()))); + segments.add(PacketInfo.data(Component.text("Name"), Component.text(nameField.get(operation).toString()))); Field progressField = operation.getClass().getDeclaredField("progress"); progressField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Progress"), Component.text(String.valueOf(progressField.get(operation))))); + segments.add(PacketInfo.data(Component.text("Progress"), Component.text(String.valueOf(progressField.get(operation))))); Field colorField = operation.getClass().getDeclaredField("color"); colorField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Color"), Component.text(colorField.get(operation).toString()))); + segments.add(PacketInfo.data(Component.text("Color"), Component.text(colorField.get(operation).toString()))); Field overlayField = operation.getClass().getDeclaredField("overlay"); overlayField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Overlay"), Component.text(overlayField.get(operation).toString()))); + segments.add(PacketInfo.data(Component.text("Overlay"), Component.text(overlayField.get(operation).toString()))); extractBooleanFlags(operation, segments); } - private void extractProgressOperation(Object operation, List segments) throws Exception { + private void extractProgressOperation(Object operation, List segments) throws Exception { Field progressField = operation.getClass().getDeclaredField("progress"); progressField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Progress"), Component.text(String.valueOf(progressField.get(operation))))); + segments.add(PacketInfo.data(Component.text("Progress"), Component.text(String.valueOf(progressField.get(operation))))); } - private void extractNameOperation(Object operation, List segments) throws Exception { + private void extractNameOperation(Object operation, List segments) throws Exception { Field nameField = operation.getClass().getDeclaredField("name"); nameField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Name"), Component.text(nameField.get(operation).toString()))); + segments.add(PacketInfo.data(Component.text("Name"), Component.text(nameField.get(operation).toString()))); } - private void extractStyleOperation(Object operation, List segments) throws Exception { + private void extractStyleOperation(Object operation, List segments) throws Exception { Field colorField = operation.getClass().getDeclaredField("color"); colorField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Color"), Component.text(colorField.get(operation).toString()))); + segments.add(PacketInfo.data(Component.text("Color"), Component.text(colorField.get(operation).toString()))); Field overlayField = operation.getClass().getDeclaredField("overlay"); overlayField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Overlay"), Component.text(overlayField.get(operation).toString()))); + segments.add(PacketInfo.data(Component.text("Overlay"), Component.text(overlayField.get(operation).toString()))); } - private void extractPropertiesOperation(Object operation, List segments) throws Exception { + private void extractPropertiesOperation(Object operation, List segments) throws Exception { extractBooleanFlags(operation, segments); } - private void extractBooleanFlags(Object operation, List segments) throws Exception { + private void extractBooleanFlags(Object operation, List segments) throws Exception { Field darkenField = operation.getClass().getDeclaredField("darkenScreen"); darkenField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Darken Screen"), Component.text(String.valueOf(darkenField.get(operation))))); + segments.add(PacketInfo.data(Component.text("Darken Screen"), Component.text(String.valueOf(darkenField.get(operation))))); Field musicField = operation.getClass().getDeclaredField("playMusic"); musicField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Play Music"), Component.text(String.valueOf(musicField.get(operation))))); + segments.add(PacketInfo.data(Component.text("Play Music"), Component.text(String.valueOf(musicField.get(operation))))); Field fogField = operation.getClass().getDeclaredField("createWorldFog"); fogField.setAccessible(true); - segments.add(PacketInfoSegment.of(Component.text("Create Fog"), Component.text(String.valueOf(fogField.get(operation))))); + segments.add(PacketInfo.data(Component.text("Create Fog"), Component.text(String.valueOf(fogField.get(operation))))); } } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java index 7e16ffb..8fee736 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java @@ -4,7 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.*; +import xyz.bitsquidd.ninja.format.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,23 +29,20 @@ public CommandSuggestionsResponseHandler() { var suggestions = packet.suggestions(); var suggestionCount = suggestions.size(); - List rows = new ArrayList<>(); - rows.add(PacketInfoSegment.of(Component.text("Transaction ID"), Component.text(id))); - rows.add(PacketInfoSegment.of(Component.text("Suggestion Count"), Component.text(suggestionCount))); + List rows = new ArrayList<>(); + rows.add(PacketInfo.data(Component.text("Transaction ID"), Component.text(id))); + rows.add(PacketInfo.data(Component.text("Suggestion Count"), Component.text(suggestionCount))); - // Display suggestions as a structured list if (!suggestions.isEmpty()) { var suggestionSegments = suggestions.stream() .limit(MAX_DISPLAYED_ENTRIES) - .map(entry -> PacketInfoValue.of( - Component.text(entry.text()) - )) + .map(entry -> PacketInfo.value(Component.text(entry.text()))) .toList(); - rows.add(PacketInfoList.of(Component.text("Suggestions"), new ArrayList<>(suggestionSegments))); + rows.add(PacketInfo.list(Component.text("Suggestions"), suggestionSegments)); int hiddenSuggestions = suggestions.size() - suggestionSegments.size(); if (hiddenSuggestions > 0) { - rows.add(PacketInfoSegment.of(Component.text("SuggestionsHidden"), Component.text(hiddenSuggestions + " more"))); + rows.add(PacketInfo.data(Component.text("SuggestionsHidden"), Component.text(hiddenSuggestions + " more"))); } } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerCloseHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerCloseHandler.java index 4575869..3421ca6 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerCloseHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerCloseHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundContainerClosePacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public ContainerCloseHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("ContainerID"), Component.text(packet.getContainerId())) + PacketInfo.data(Component.text("ContainerID"), Component.text(packet.getContainerId())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java index ec67e28..a15132e 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetContentHandler.java @@ -4,7 +4,9 @@ import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.*; +import xyz.bitsquidd.ninja.format.FormatHelper; +import xyz.bitsquidd.ninja.format.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -26,23 +28,23 @@ public ContainerSetContentHandler() { protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundContainerSetContentPacket packet) { var itemSegments = packet.items().stream() .limit(MAX_DISPLAYED_ENTRIES) - .map(item -> PacketInfoValue.of(Component.text(FormatHelper.formatItemStack(item)))) + .map(item -> PacketInfo.value(Component.text(FormatHelper.formatItemStack(item)))) .toList(); - List rows = new ArrayList<>(); - rows.add(PacketInfoSegment.of(Component.text("ContainerID"), Component.text(packet.containerId()))); - rows.add(PacketInfoSegment.of(Component.text("StateID"), Component.text(packet.stateId()))); + List rows = new ArrayList<>(); + rows.add(PacketInfo.data(Component.text("ContainerID"), Component.text(packet.containerId()))); + rows.add(PacketInfo.data(Component.text("StateID"), Component.text(packet.stateId()))); if (!itemSegments.isEmpty()) { - rows.add(PacketInfoList.of(Component.text("Items"), new ArrayList<>(itemSegments))); + rows.add(PacketInfo.list(Component.text("Items"), new ArrayList<>(itemSegments))); } int hiddenItems = packet.items().size() - itemSegments.size(); if (hiddenItems > 0) { - rows.add(PacketInfoSegment.of(Component.text("ItemsHidden"), Component.text(hiddenItems + " more"))); + rows.add(PacketInfo.data(Component.text("ItemsHidden"), Component.text(hiddenItems + " more"))); } - rows.add(PacketInfoSegment.of(Component.text("CarriedItem"), Component.text(FormatHelper.formatItemStack(packet.carriedItem())))); + rows.add(PacketInfo.data(Component.text("CarriedItem"), Component.text(FormatHelper.formatItemStack(packet.carriedItem())))); return PacketInfoBundle.of( packetType, @@ -50,5 +52,5 @@ public ContainerSetContentHandler() { rows ); } - + } \ No newline at end of file diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetSlotHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetSlotHandler.java index 085998e..e0e7017 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetSlotHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/ContainerSetSlotHandler.java @@ -5,8 +5,8 @@ import org.jetbrains.annotations.NotNull; import xyz.bitsquidd.ninja.format.FormatHelper; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -29,10 +29,10 @@ public ContainerSetSlotHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("ContainerID"), Component.text(packet.getContainerId())), - PacketInfoSegment.of(Component.text("StateID"), Component.text(packet.getStateId())), - PacketInfoSegment.of(Component.text("Slot"), Component.text(packet.getSlot())), - PacketInfoSegment.of(Component.text("Item"), Component.text(FormatHelper.formatItemStack(packet.getItem()))) + PacketInfo.data(Component.text("ContainerID"), Component.text(packet.getContainerId())), + PacketInfo.data(Component.text("StateID"), Component.text(packet.getStateId())), + PacketInfo.data(Component.text("Slot"), Component.text(packet.getSlot())), + PacketInfo.data(Component.text("Item"), Component.text(FormatHelper.formatItemStack(packet.getItem()))) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CustomPayloadHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CustomPayloadHandler.java index 89caa10..c839037 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CustomPayloadHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CustomPayloadHandler.java @@ -6,8 +6,8 @@ import net.minecraft.resources.Identifier; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -35,10 +35,10 @@ public CustomPayloadHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Type"), Component.text(typeId.getNamespace() + ":" + typeId.getPath())), - PacketInfoSegment.of(Component.text("Path"), Component.text(typeId.getPath())), - PacketInfoSegment.of(Component.text("PayloadClass"), Component.text(payload.getClass().getSimpleName())), - PacketInfoSegment.of(Component.text("PayloadString"), Component.text(payload.toString())) + PacketInfo.data(Component.text("Type"), Component.text(typeId.getNamespace() + ":" + typeId.getPath())), + PacketInfo.data(Component.text("Path"), Component.text(typeId.getPath())), + PacketInfo.data(Component.text("PayloadClass"), Component.text(payload.getClass().getSimpleName())), + PacketInfo.data(Component.text("PayloadString"), Component.text(payload.toString())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java index cd936b8..fcdcd21 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java @@ -2,11 +2,10 @@ import net.kyori.adventure.text.Component; import net.minecraft.network.protocol.game.ClientboundInitializeBorderPacket; - import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,11 +27,11 @@ public InitializeWorldBorderHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Location"), Component.text(String.format("X=%s, Z=%s", packet.getNewCenterX(), packet.getNewCenterZ()))), - PacketInfoSegment.of(Component.text("Size"), Component.text(String.format("%s -> %s", packet.getOldSize(), packet.getNewSize()))), - PacketInfoSegment.of(Component.text("Speed"), Component.text(packet.getLerpTime() + " ticks")), - PacketInfoSegment.of(Component.text("Portal boundary"), Component.text(packet.getNewAbsoluteMaxSize())), - PacketInfoSegment.of(Component.text("Warning"), Component.text(String.format("Blocks=%s, time=%s ticks", packet.getWarningBlocks(), packet.getWarningTime()))) + PacketInfo.data(Component.text("Location"), Component.text(String.format("X=%s, Z=%s", packet.getNewCenterX(), packet.getNewCenterZ()))), + PacketInfo.data(Component.text("Size"), Component.text(String.format("%s -> %s", packet.getOldSize(), packet.getNewSize()))), + PacketInfo.data(Component.text("Speed"), Component.text(packet.getLerpTime() + " ticks")), + PacketInfo.data(Component.text("Portal boundary"), Component.text(packet.getNewAbsoluteMaxSize())), + PacketInfo.data(Component.text("Warning"), Component.text(String.format("Blocks=%s, time=%s ticks", packet.getWarningBlocks(), packet.getWarningTime()))) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/OpenScreenHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/OpenScreenHandler.java index 253c3d3..7e33c69 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/OpenScreenHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/OpenScreenHandler.java @@ -5,8 +5,8 @@ import net.minecraft.world.inventory.MenuType; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -32,9 +32,9 @@ public OpenScreenHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("ContainerID"), Component.text(packet.getContainerId())), - PacketInfoSegment.of(Component.text("MenuType"), Component.text(typeDesc)), - PacketInfoSegment.of(Component.text("Title"), Component.text(titleDesc)) + PacketInfo.data(Component.text("ContainerID"), Component.text(packet.getContainerId())), + PacketInfo.data(Component.text("MenuType"), Component.text(typeDesc)), + PacketInfo.data(Component.text("Title"), Component.text(titleDesc)) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PingHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PingHandler.java index 2c1d0f1..069d82b 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PingHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PingHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.common.ClientboundPingPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public PingHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("ID"), Component.text(packet.getId())) + PacketInfo.data(Component.text("ID"), Component.text(packet.getId())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java index ba83b09..32c68d7 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java @@ -4,11 +4,13 @@ import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.*; +import xyz.bitsquidd.ninja.format.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; import java.util.ArrayList; +import java.util.List; public class PlayerInfoRemoveHandler extends PacketHandler<@NotNull ClientboundPlayerInfoRemovePacket> { public PlayerInfoRemoveHandler() { @@ -22,12 +24,12 @@ public PlayerInfoRemoveHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundPlayerInfoRemovePacket packet) { + List rows = new ArrayList<>(); + var removed = packet.profileIds().stream() - .map(uuid -> PacketInfoValue.of(Component.text(uuid.toString()))) + .map(uuid -> PacketInfo.value(Component.text(uuid.toString()))) .toList(); - - var rows = new ArrayList(); - rows.add(PacketInfoList.of(Component.text("Removed UUIDs"), removed)); + rows.add(PacketInfo.list(Component.text("Removed UUIDs"), removed)); return PacketInfoBundle.of( packetType, diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java index 51a7a76..7790ca3 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java @@ -9,10 +9,8 @@ import org.jetbrains.annotations.NotNull; import xyz.bitsquidd.ninja.PacketInterceptorMod; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoList; -import xyz.bitsquidd.ninja.format.PacketInfoRow; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -31,17 +29,17 @@ public PlayerInfoUpdateHandler() { private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Entry entry) { var displayName = entry.displayName(); - if(displayName == null) { + if (displayName == null) { return ""; } // convert Minecraft's native Component into MiniMessage so we can properly display it var jsonElement = ComponentSerialization.CODEC.encodeStart(JsonOps.INSTANCE, displayName) .resultOrPartial(error -> - PacketInterceptorMod.LOGGER.error("Failed to serialize displayName for player {}: {}", entry.profileId(), error) + PacketInterceptorMod.LOGGER.error("Failed to serialize displayName for player {}: {}", entry.profileId(), error) ) .orElse(null); - if(jsonElement == null) { + if (jsonElement == null) { return ""; } @@ -51,18 +49,18 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundPlayerInfoUpdatePacket packet) { + List rows = new ArrayList<>(); + List displayedEntries = packet.entries().stream() .limit(MAX_DISPLAYED_ENTRIES) .toList(); - - List rows = new ArrayList<>(); - rows.add(PacketInfoSegment.of(Component.text("EntryCount"), Component.text(displayedEntries.size()))); + rows.add(PacketInfo.data(Component.text("EntryCount"), Component.text(displayedEntries.size()))); var entryLists = displayedEntries.stream().map(entry -> { // identity var displayName = extractDisplayName(entry); var identity = String.format("displayName=%s, uuid=%s", displayName, entry.profileId()); - var identitySegment = PacketInfoSegment.of(Component.text("Identity"), MiniMessage.miniMessage().deserialize(identity)); + var identitySegment = PacketInfo.data(Component.text("Identity"), MiniMessage.miniMessage().deserialize(identity)); // state String state = String.format( @@ -72,10 +70,10 @@ private String extractDisplayName(@NotNull ClientboundPlayerInfoUpdatePacket.Ent entry.showHat(), entry.latency() ); - var stateSegment = PacketInfoSegment.of(Component.text("State"), Component.text(state)); + var stateSegment = PacketInfo.data(Component.text("State"), Component.text(state)); String name = entry.profile() != null ? entry.profile().name() : entry.profileId().toString(); - return PacketInfoList.of(Component.text(name), List.of(identitySegment, stateSegment)); + return PacketInfo.list(Component.text(name), List.of(identitySegment, stateSegment)); }).toList(); rows.addAll(entryLists); diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java index 06fd6f5..63600d3 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/RemoveEntitiesHandler.java @@ -4,7 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; import org.jetbrains.annotations.NotNull; -import xyz.bitsquidd.ninja.format.*; +import xyz.bitsquidd.ninja.format.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -23,6 +24,8 @@ public RemoveEntitiesHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundRemoveEntitiesPacket packet) { + List rows = new ArrayList<>(); + var allEntityIds = packet.getEntityIds(); int totalCount = allEntityIds.size(); @@ -31,19 +34,18 @@ public RemoveEntitiesHandler() { .boxed() .toList(); - List rows = new ArrayList<>(); - rows.add(PacketInfoSegment.of(Component.text("Count"), Component.text(totalCount))); + rows.add(PacketInfo.data(Component.text("Count"), Component.text(totalCount))); if (!displayedIds.isEmpty()) { var idSegments = displayedIds.stream() - .map(id -> PacketInfoValue.of(Component.text(id))) + .map(id -> PacketInfo.value(Component.text(id))) .toList(); - rows.add(PacketInfoList.of(Component.text("EntityIds"), new ArrayList<>(idSegments))); + rows.add(PacketInfo.list(Component.text("EntityIds"), new ArrayList<>(idSegments))); } int hiddenEntities = totalCount - displayedIds.size(); if (hiddenEntities > 0) { - rows.add(PacketInfoSegment.of(Component.text("EntityIdsHidden"), Component.text(hiddenEntities + " more"))); + rows.add(PacketInfo.data(Component.text("EntityIdsHidden"), Component.text(hiddenEntities + " more"))); } return PacketInfoBundle.of( diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java index 417e4d3..2d34e12 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderCenterPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -13,25 +13,25 @@ public class SetBorderCenterHandler extends PacketHandler { - public SetBorderCenterHandler() { - super( - ClientboundSetBorderCenterPacket.class, - "SetBorderCenter", - "Handles world border center updates", - PacketType.CLIENTBOUND - ); - } + public SetBorderCenterHandler() { + super( + ClientboundSetBorderCenterPacket.class, + "SetBorderCenter", + "Handles world border center updates", + PacketType.CLIENTBOUND + ); + } - @Override - protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderCenterPacket packet) { - return PacketInfoBundle.of( - packetType, - Component.text(friendlyName), - List.of( - PacketInfoSegment.of(Component.text("X"), Component.text(packet.getNewCenterX())), - PacketInfoSegment.of(Component.text("Z"), Component.text(packet.getNewCenterZ())) + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderCenterPacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + PacketInfo.data(Component.text("X"), Component.text(packet.getNewCenterX())), + PacketInfo.data(Component.text("Z"), Component.text(packet.getNewCenterZ())) ) - ); - } + ); + } } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java index fd70295..44cbea4 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderLerpSizeHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderLerpSizePacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -27,8 +27,8 @@ public SetBorderLerpSizeHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Size"), Component.text(String.format("%s -> %s", packet.getOldSize(), packet.getNewSize()))), - PacketInfoSegment.of(Component.text("Speed"), Component.text(packet.getLerpTime() + " ticks")) + PacketInfo.data(Component.text("Size"), Component.text(String.format("%s -> %s", packet.getOldSize(), packet.getNewSize()))), + PacketInfo.data(Component.text("Speed"), Component.text(packet.getLerpTime() + " ticks")) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java index 66170c4..d74244f 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderSizeHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderSizePacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public SetBorderSizeHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Size"), Component.text(packet.getSize())) + PacketInfo.data(Component.text("Size"), Component.text(packet.getSize())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java index 89ccb36..49c998b 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDelayHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDelayPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public SetBorderWarningDelayHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Warning Time"), Component.text(packet.getWarningDelay() + " ticks")) + PacketInfo.data(Component.text("Warning Time"), Component.text(packet.getWarningDelay() + " ticks")) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java index 44386e1..31777e2 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderWarningDistanceHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public SetBorderWarningDistanceHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Warning Distance"), Component.text(packet.getWarningBlocks() + " blocks")) + PacketInfo.data(Component.text("Warning Distance"), Component.text(packet.getWarningBlocks() + " blocks")) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java index cc02600..ae07b0f 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java @@ -9,8 +9,8 @@ import org.jetbrains.annotations.NotNull; import xyz.bitsquidd.ninja.PacketInterceptorMod; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -40,9 +40,9 @@ public SetCursorItemHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("ID"), Component.text(itemId.toString())), - PacketInfoSegment.of(Component.text("Count"), Component.text(itemCount)), - PacketInfoSegment.of(Component.text("NBT"), Component.text(json.toString())) + PacketInfo.data(Component.text("ID"), Component.text(itemId.toString())), + PacketInfo.data(Component.text("Count"), Component.text(itemCount)), + PacketInfo.data(Component.text("NBT"), Component.text(json.toString())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetEntityDataHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetEntityDataHandler.java index 9ed8e2d..871b30d 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetEntityDataHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetEntityDataHandler.java @@ -7,8 +7,8 @@ import net.minecraft.world.entity.EntityType; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -41,9 +41,9 @@ public SetEntityDataHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("EntityID"), Component.text(entityId)), - PacketInfoSegment.of(Component.text("Type*"), Component.text(entityType + "")), // Note: Type is not part of the packet, we resolve it for debugging purposes. - PacketInfoSegment.of(Component.text("MetadataCount"), Component.text(items.size())) + PacketInfo.data(Component.text("EntityID"), Component.text(entityId)), + PacketInfo.data(Component.text("Type*"), Component.text(entityType + "")), // Note: Type is not part of the packet, we resolve it for debugging purposes. + PacketInfo.data(Component.text("MetadataCount"), Component.text(items.size())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java index 47a77e1..f5f536e 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPassengersHandler.java @@ -4,10 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoList; -import xyz.bitsquidd.ninja.format.PacketInfoRow; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,22 +26,22 @@ public SetPassengersHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetPassengersPacket packet) { - List passengers = Arrays.stream(packet.getPassengers()) + List passengers = Arrays.stream(packet.getPassengers()) .limit(MAX_DISPLAYED_ENTRIES) - .mapToObj(id -> PacketInfoSegment.of(Component.text("PassengerId"), Component.text(id))) + .mapToObj(id -> PacketInfo.data(Component.text("PassengerId"), Component.text(id))) .toList(); - List rows = new ArrayList<>(); - rows.add(PacketInfoSegment.of(Component.text("VehicleId"), Component.text(packet.getVehicle()))); - rows.add(PacketInfoSegment.of(Component.text("PassengerCount"), Component.text(packet.getPassengers().length))); + List rows = new ArrayList<>(); + rows.add(PacketInfo.data(Component.text("VehicleId"), Component.text(packet.getVehicle()))); + rows.add(PacketInfo.data(Component.text("PassengerCount"), Component.text(packet.getPassengers().length))); if (!passengers.isEmpty()) { - rows.add(PacketInfoList.of(Component.text("Passengers"), passengers)); + rows.add(PacketInfo.list(Component.text("Passengers"), passengers)); } int hiddenPassengers = packet.getPassengers().length - passengers.size(); if (hiddenPassengers > 0) { - rows.add(PacketInfoSegment.of(Component.text("PassengersHidden"), Component.text(hiddenPassengers + " more"))); + rows.add(PacketInfo.data(Component.text("PassengersHidden"), Component.text(hiddenPassengers + " more"))); } return PacketInfoBundle.of( diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java index 09464ab..eb6c0bf 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetPlayerTeamHandler.java @@ -4,10 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoList; -import xyz.bitsquidd.ninja.format.PacketInfoRow; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -27,67 +25,67 @@ public SetPlayerTeamHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetPlayerTeamPacket packet) { - List rows = new ArrayList<>(); + List rows = new ArrayList<>(); - rows.add(PacketInfoSegment.of(Component.text("Team"), Component.text(packet.getName()))); + rows.add(PacketInfo.data(Component.text("Team"), Component.text(packet.getName()))); ClientboundSetPlayerTeamPacket.Action teamAction = packet.getTeamAction(); ClientboundSetPlayerTeamPacket.Action playerAction = packet.getPlayerAction(); - rows.add(PacketInfoSegment.of(Component.text("TeamAction"), Component.text(teamAction != null ? teamAction.name() : "null"))); - rows.add(PacketInfoSegment.of(Component.text("PlayerAction"), Component.text(playerAction != null ? playerAction.name() : "null"))); + rows.add(PacketInfo.data(Component.text("TeamAction"), Component.text(teamAction != null ? teamAction.name() : "null"))); + rows.add(PacketInfo.data(Component.text("PlayerAction"), Component.text(playerAction != null ? playerAction.name() : "null"))); if (!packet.getPlayers().isEmpty()) { List playerList = packet.getPlayers().stream() .limit(MAX_DISPLAYED_ENTRIES) .toList(); - List playerSegments = playerList.stream() - .map(name -> PacketInfoSegment.of(Component.text("Player"), Component.text(name))) + List playerSegments = playerList.stream() + .map(name -> PacketInfo.data(Component.text("Player"), Component.text(name))) .toList(); - rows.add(PacketInfoList.of(Component.text("Players"), new ArrayList<>(playerSegments))); + rows.add(PacketInfo.list(Component.text("Players"), new ArrayList<>(playerSegments))); int hiddenPlayers = packet.getPlayers().size() - playerList.size(); if (hiddenPlayers > 0) { - rows.add(PacketInfoSegment.of(Component.text("PlayersHidden"), Component.text(hiddenPlayers + " more"))); + rows.add(PacketInfo.data(Component.text("PlayersHidden"), Component.text(hiddenPlayers + " more"))); } } packet.getParameters().ifPresent(params -> { - rows.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("DisplayName"), Component.text(params.getDisplayName().getString()) )); - rows.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("Color"), Component.text(params.getColor().getName()) )); - rows.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("NTVisibility"), Component.text(params.getNametagVisibility().name) )); - rows.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("CollisionRule"), Component.text(params.getCollisionRule().name) )); if (!params.getPlayerPrefix().getString().isEmpty()) { - rows.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("Prefix"), Component.text(params.getPlayerPrefix().getString()) )); } if (!params.getPlayerSuffix().getString().isEmpty()) { - rows.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("Suffix"), Component.text(params.getPlayerSuffix().getString()) )); } - rows.add(PacketInfoSegment.of(Component.text("Options"), Component.text(String.format("0x%02X", params.getOptions())))); + rows.add(PacketInfo.data(Component.text("Options"), Component.text(String.format("0x%02X", params.getOptions())))); }); return PacketInfoBundle.of( diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java index dc7619c..aff7926 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java @@ -1,26 +1,26 @@ package xyz.bitsquidd.ninja.handler.impl.clientbound; import com.google.gson.Gson; +import com.mojang.serialization.JsonOps; import net.kyori.adventure.text.Component; import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; import org.jetbrains.annotations.NotNull; -import com.mojang.serialization.JsonOps; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; import java.util.List; -public class SystemChatHandler extends PacketHandler<@NotNull ClientboundSystemChatPacket> { +public class SystemChatHandler extends PacketHandler<@NotNull ClientboundSystemChatPacket> { public SystemChatHandler() { super( - ClientboundSystemChatPacket.class, - "SystemChat", - "Handles system chat messages", - PacketType.CLIENTBOUND + ClientboundSystemChatPacket.class, + "SystemChat", + "Handles system chat messages", + PacketType.CLIENTBOUND ); } @@ -31,14 +31,15 @@ public SystemChatHandler() { final var jsonString = gson.toJson(jsonElement); return PacketInfoBundle.of( - packetType, - Component.text(friendlyName), - List.of( - PacketInfoSegment.of( - Component.text("JSON Message"), - Component.text(jsonString) - ) - ) + packetType, + Component.text(friendlyName), + List.of( + PacketInfo.data( + ( + Component.text("JSON Message"), + Component.text(jsonString) + ) + ) ); } } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/TrackedWaypointHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/TrackedWaypointHandler.java index a5a376e..883c94f 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/TrackedWaypointHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/TrackedWaypointHandler.java @@ -6,8 +6,8 @@ import net.minecraft.world.waypoints.Waypoint; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -34,10 +34,10 @@ public TrackedWaypointHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Operation"), Component.text(packet.operation() + "")), - PacketInfoSegment.of(Component.text("ID"), Component.text(id)), - PacketInfoSegment.of(Component.text("Icon"), Component.text(icon.style.identifier().toString())), - PacketInfoSegment.of(Component.text("Location"), Component.text(extractLocation(waypoint))) + PacketInfo.data(Component.text("Operation"), Component.text(packet.operation() + "")), + PacketInfo.data(Component.text("ID"), Component.text(id)), + PacketInfo.data(Component.text("Icon"), Component.text(icon.style.identifier().toString())), + PacketInfo.data(Component.text("Location"), Component.text(extractLocation(waypoint))) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/UpdateAttributesHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/UpdateAttributesHandler.java index 9ae644f..a99b591 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/UpdateAttributesHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/UpdateAttributesHandler.java @@ -5,8 +5,8 @@ import org.jetbrains.annotations.NotNull; import xyz.bitsquidd.ninja.format.FormatHelper; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -30,8 +30,8 @@ public UpdateAttributesHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("EntityID"), Component.text(packet.getEntityId())), - PacketInfoSegment.of(Component.text("Attributes"), Component.text(FormatHelper.formatList(packet.getValues().stream().map(FormatHelper::formatAttribute).toList(), 10))) + PacketInfo.data(Component.text("EntityID"), Component.text(packet.getEntityId())), + PacketInfo.data(Component.text("Attributes"), Component.text(FormatHelper.formatList(packet.getValues().stream().map(FormatHelper::formatAttribute).toList(), 10))) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java index edb229d..817bf5a 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/CommandSuggestionsRequestHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -31,8 +31,8 @@ public CommandSuggestionsRequestHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Transaction ID"), Component.text(id)), - PacketInfoSegment.of(Component.text("Text"), Component.text(text)) + PacketInfo.data(Component.text("Transaction ID"), Component.text(id)), + PacketInfo.data(Component.text("Text"), Component.text(text)) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/InteractHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/InteractHandler.java index 7138f94..1682e94 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/InteractHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/InteractHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.game.ServerboundInteractPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public InteractHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("IsSecondary"), Component.text(packet.isUsingSecondaryAction())) + PacketInfo.data(Component.text("IsSecondary"), Component.text(packet.isUsingSecondaryAction())) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PlayerActionHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PlayerActionHandler.java index 4fcd08a..1c19bc8 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PlayerActionHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PlayerActionHandler.java @@ -5,8 +5,8 @@ import org.jetbrains.annotations.NotNull; import xyz.bitsquidd.ninja.format.FormatHelper; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -29,8 +29,8 @@ public PlayerActionHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("Action"), Component.text(packet.getAction().toString())), - PacketInfoSegment.of(Component.text("Pos"), Component.text(FormatHelper.formatPosition(packet.getPos()))) + PacketInfo.data(Component.text("Action"), Component.text(packet.getAction().toString())), + PacketInfo.data(Component.text("Pos"), Component.text(FormatHelper.formatPosition(packet.getPos()))) ) ); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PongHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PongHandler.java index 5c63d54..a400952 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PongHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/serverbound/PongHandler.java @@ -4,8 +4,8 @@ import net.minecraft.network.protocol.common.ServerboundPongPacket; import org.jetbrains.annotations.NotNull; +import xyz.bitsquidd.ninja.format.PacketInfo; import xyz.bitsquidd.ninja.format.PacketInfoBundle; -import xyz.bitsquidd.ninja.format.PacketInfoSegment; import xyz.bitsquidd.ninja.handler.PacketHandler; import xyz.bitsquidd.ninja.handler.PacketType; @@ -28,7 +28,7 @@ public PongHandler() { packetType, Component.text(friendlyName), List.of( - PacketInfoSegment.of(Component.text("ID"), Component.text(packet.getId())) + PacketInfo.data(Component.text("ID"), Component.text(packet.getId())) ) ); } From 9a1415552fa7abdc186a85925b6af2fac46ed927 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:41:38 +0000 Subject: [PATCH 14/19] =?UTF-8?q?=F0=9F=90=9B=20Build=20cleanup.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/java/xyz/bitsquidd/ninja/config/Config.java | 6 +++--- src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java | 2 +- .../ninja/handler/impl/clientbound/SystemChatHandler.java | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/client/java/xyz/bitsquidd/ninja/config/Config.java b/src/client/java/xyz/bitsquidd/ninja/config/Config.java index 5730526..7d37b8b 100644 --- a/src/client/java/xyz/bitsquidd/ninja/config/Config.java +++ b/src/client/java/xyz/bitsquidd/ninja/config/Config.java @@ -23,7 +23,7 @@ public static void load() { String json = Files.readString(FILE); ConfigData data = GSON.fromJson(json, ConfigData.class); if (data != null) { - packetDelay = data.packetDelayMs; + packetDelay = Duration.ofMillis(data.packetDelayMs); } } catch (Exception e) { PacketInterceptorMod.LOGGER.error("Failed to load config, using defaults"); @@ -36,7 +36,7 @@ public static void load() { public static void save() { try { ConfigData data = new ConfigData(); - data.packetDelayMs = packetDelay; + data.packetDelayMs = packetDelay.toMillis(); Files.writeString(FILE, GSON.toJson(data)); } catch (IOException e) { @@ -45,6 +45,6 @@ public static void save() { } private static class ConfigData { - int packetDelayMs = 500; + long packetDelayMs = 500; } } diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java index cfa88de..2315597 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfo.java @@ -14,7 +14,7 @@ public interface PacketInfo { Component format(PacketType type); - static PacketInfo data(Component name, Object value) { + static PacketInfo data(Component name, Component value) { return new SinglePacketData(name, value); } diff --git a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java index aff7926..2e7eec6 100644 --- a/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SystemChatHandler.java @@ -35,8 +35,7 @@ public SystemChatHandler() { Component.text(friendlyName), List.of( PacketInfo.data( - ( - Component.text("JSON Message"), + Component.text("JSON Message"), Component.text(jsonString) ) ) From fcbe2b1517fa3816806ec9ab866ec159b1ac6d61 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:57:45 +0000 Subject: [PATCH 15/19] =?UTF-8?q?=F0=9F=8E=A8=20Added=20todo.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..d1d1fd6 --- /dev/null +++ b/TODO @@ -0,0 +1,11 @@ +More refined packet filtering: + [ ] Per-packet customisation e.g. AddEntity range [1000, 99999] + +Better config: + [ ] Nicer menu for packet enabling + [ ] Save packet filtering preferences to config + +More info: + [ ] Hover on message to show more info: + [ ] Timestamp + [ ] Packet size? \ No newline at end of file From 47a58a58f6e6470228a944fcfefe8a2a46bc8e93 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:58:36 +0000 Subject: [PATCH 16/19] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20modmenu=20configur?= =?UTF-8?q?ation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index c9c74d6..8d1debc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -55,6 +55,7 @@ dependencies { modApi(rootProject.libs.clothconfig) { exclude(group = "net.fabricmc.fabric-api") } + include(rootProject.libs.clothconfig) errorprone(rootProject.libs.errorprone) } From 5793e29f49bce2073c44811cf9324e13760e2416 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:58:51 +0000 Subject: [PATCH 17/19] =?UTF-8?q?=F0=9F=8E=A8=20Formatting=20tweaks.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xyz/bitsquidd/ninja/format/ListPacketData.java | 2 +- .../bitsquidd/ninja/format/PacketInfoBundle.java | 2 +- .../xyz/bitsquidd/ninja/format/PacketLogger.java | 13 ++++++------- .../bitsquidd/ninja/format/SinglePacketData.java | 2 +- .../bitsquidd/ninja/format/SinglePacketValue.java | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java index a98dd27..ad36355 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java @@ -31,7 +31,7 @@ public Component format(PacketType type) { subInfo.forEach(info -> lineBuilder .appendNewline() - .append(Component.text(" ↪ ")) + .append(Component.text(" ↪ ")) .append(info.format(type))); return lineBuilder.build(); diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java index 839c253..166577c 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java @@ -30,7 +30,7 @@ public static PacketInfoBundle of(PacketType type, Component name, List packet) { @@ -31,10 +28,12 @@ public void addPacket(final Packet packet) { if (delayRequired.isPositive()) { Instant currentTime = Instant.now(); if (Duration.between(lastPacketTime, currentTime).compareTo(delayRequired) < 0) { - sendChatMessage( - Component.text("...", NamedTextColor.GRAY) - .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %sms, hiding.", delayRequired)))) - ); + // TODO: Displaying that no packet was "sent" should be re-thought. + // This doesn't help if there are lots of packets, it still spams the chat with "..." +// sendChatMessage( +// Component.text("...", NamedTextColor.GRAY) +// .hoverEvent(HoverEvent.showText(Component.text(String.format("Too many packets sent within %sms, hiding.", delayRequired)))) +// ); return; } lastPacketTime = currentTime; diff --git a/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java index 77bdd68..cb55847 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java @@ -22,6 +22,6 @@ public Component format(PacketType type) { return Component.empty() .append(name.color(type.primaryColor)) .append(Component.text(": ")) - .append(value.color(type.secondaryColor)); + .append(value); } } diff --git a/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java index 6446114..c310746 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketValue.java @@ -13,6 +13,6 @@ public SinglePacketValue(Component value) { @Override public Component format(PacketType type) { - return value.color(type.secondaryColor); + return value; } } From 6be1735e2dff647ef32786234d11e51445ccbae0 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:59:36 +0000 Subject: [PATCH 18/19] =?UTF-8?q?=F0=9F=8E=A8=20Added=20TODO=20for=20ListP?= =?UTF-8?q?acketData.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java index ad36355..0cadc9c 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java @@ -8,6 +8,8 @@ import java.util.Collection; +// TODO Use MAX_DISPLAYED_ENTRIES here instead of in building packets. + /** * Displays a titled list of entries inside a packet info bundle. */ From d93be89a61c797afc4afd20fbac12ec26b55f8c7 Mon Sep 17 00:00:00 2001 From: ImBit <151650938+ImBit@users.noreply.github.com> Date: Fri, 27 Mar 2026 23:02:18 +0000 Subject: [PATCH 19/19] =?UTF-8?q?=F0=9F=8E=A8=20Update=20TODO.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index d1d1fd6..4428917 100644 --- a/TODO +++ b/TODO @@ -8,4 +8,11 @@ Better config: More info: [ ] Hover on message to show more info: [ ] Timestamp - [ ] Packet size? \ No newline at end of file + [ ] Packet size? + +Documentation: + [ ] Add better documentation to API methods (see Bits) + [ ] Improve README + [ ] More screenshots + [ ] Better explanation of features + [ ] Example use cases