diff --git a/TODO b/TODO new file mode 100644 index 0000000..4428917 --- /dev/null +++ b/TODO @@ -0,0 +1,18 @@ +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? + +Documentation: + [ ] Add better documentation to API methods (see Bits) + [ ] Improve README + [ ] More screenshots + [ ] Better explanation of features + [ ] Example use cases diff --git a/build.gradle.kts b/build.gradle.kts index d08def4..8d1debc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,6 +18,11 @@ repositories { mavenCentral() mavenLocal() maven { url = uri("https://jitpack.io") } + maven { + name = "Terraformers" + url = uri("https://maven.terraformersmc.com/releases") + } + maven { url = uri("https://maven.shedaniel.me/") } } loom { @@ -40,12 +45,18 @@ 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) + modApi(rootProject.libs.clothconfig) { + exclude(group = "net.fabricmc.fabric-api") + } + include(rootProject.libs.clothconfig) + errorprone(rootProject.libs.errorprone) } diff --git a/gradle.properties b/gradle.properties index 5657bb1..633a35a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,7 @@ yarn_mappings=1.21.11+build.3 archives_base_name=packet-ninja # Dependencies 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 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d5f5c4c..a3311de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,6 +14,9 @@ javassist = { group = "org.javassist", name = "javassist", version = "3.30.2-GA" 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" } 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..5be00e3 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); - }); + Config.load(); + ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> + PacketInterceptionCommand.register(dispatcher) + ); } public @NotNull PacketFilter getPacketFilter() { 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..7d37b8b --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/config/Config.java @@ -0,0 +1,50 @@ +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; +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 Duration packetDelay = Duration.ofMillis(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) { + packetDelay = Duration.ofMillis(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 = packetDelay.toMillis(); + + Files.writeString(FILE, GSON.toJson(data)); + } catch (IOException e) { + PacketInterceptorMod.LOGGER.error("Failed to save config"); + } + } + + private static class ConfigData { + long 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..3df7528 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/config/ConfigScreen.java @@ -0,0 +1,45 @@ +package xyz.bitsquidd.ninja.config; + +import me.shedaniel.clothconfig2.api.ConfigBuilder; +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() + .setParentScreen(parent) + .setTitle(Component.literal("PacketNinja Settings")); + + var general = builder.getOrCreateCategory(Component.literal("General")); + var entryBuilder = builder.entryBuilder(); + + general.addEntry(entryBuilder + .startLongSlider( + Component.literal("Packet Delay (ms)"), + Config.packetDelay.toMillis(), + 0, + 2000L + ) + .setDefaultValue(500L) + .setTextGetter(value -> { + long step = 50L; + long 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 -> { + long step = 50L; + Config.packetDelay = Duration.ofMillis((newValue / step) * step); + Config.save(); + }) + .build() + ); + + return builder.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..0cadc9c --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/format/ListPacketData.java @@ -0,0 +1,41 @@ +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; + +// TODO Use MAX_DISPLAYED_ENTRIES here instead of in building packets. + +/** + * 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..2315597 --- /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, Component 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 7dc8650..166577c 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoBundle.java @@ -1,15 +1,13 @@ 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; -import java.util.stream.Collectors; /** * A bundle of information about a packet sent to a client. This structure is used for pretty formatting. @@ -19,38 +17,26 @@ public final class PacketInfoBundle { private final PacketType type; private final Component name; - private final List segments; + private final List info; - private PacketInfoBundle(PacketType type, Component name, List segments) { + private PacketInfoBundle(PacketType type, Component name, List info) { this.type = type; this.name = name; - this.segments = segments; + this.info = info; } - public static PacketInfoBundle of(PacketType type, Component name, List segments) { - return new PacketInfoBundle(type, name, segments); + 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 = 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 allComponents = new ArrayList<>(List.of(titleComponent)); - allComponents.addAll(segmentComponents); - - return Component.join(JoinConfiguration.newlines(), allComponents); + TextComponent.Builder infoBuilder = Component.text().color(type.secondaryColor); + + 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/PacketInfoSegment.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java deleted file mode 100644 index 9ff5d6e..0000000 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketInfoSegment.java +++ /dev/null @@ -1,30 +0,0 @@ -package xyz.bitsquidd.ninja.format; - -import net.kyori.adventure.text.Component; -import org.jspecify.annotations.NullMarked; - -/** - * A segment of information about a packet, e.g. EntityID: 42 - */ -@NullMarked -public final class PacketInfoSegment { - 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); - } - - public Component getName() { - return name; - } - - public Component getValue() { - return value; - } -} diff --git a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java index 93ce05a..7ceb585 100644 --- a/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java +++ b/src/client/java/xyz/bitsquidd/ninja/format/PacketLogger.java @@ -7,8 +7,10 @@ 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; /** @@ -16,31 +18,35 @@ */ @NullMarked public final class PacketLogger { - private Instant lastPacketTime = Instant.EPOCH; 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; + Duration delayRequired = Config.packetDelay; + if (delayRequired.isPositive()) { + Instant currentTime = Instant.now(); + if (Duration.between(lastPacketTime, currentTime).compareTo(delayRequired) < 0) { + // 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; + } 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/format/SinglePacketData.java b/src/client/java/xyz/bitsquidd/ninja/format/SinglePacketData.java new file mode 100644 index 0000000..cb55847 --- /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); + } +} 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..c310746 --- /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; + } +} 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/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/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 new file mode 100644 index 0000000..8fee736 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/CommandSuggestionsResponseHandler.java @@ -0,0 +1,55 @@ +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.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 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(PacketInfo.data(Component.text("Transaction ID"), Component.text(id))); + rows.add(PacketInfo.data(Component.text("Suggestion Count"), Component.text(suggestionCount))); + + if (!suggestions.isEmpty()) { + var suggestionSegments = suggestions.stream() + .limit(MAX_DISPLAYED_ENTRIES) + .map(entry -> PacketInfo.value(Component.text(entry.text()))) + .toList(); + rows.add(PacketInfo.list(Component.text("Suggestions"), suggestionSegments)); + + int hiddenSuggestions = suggestions.size() - suggestionSegments.size(); + if (hiddenSuggestions > 0) { + rows.add(PacketInfo.data(Component.text("SuggestionsHidden"), Component.text(hiddenSuggestions + " more"))); + } + } + + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + rows + ); + } +} 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 6f2bf27..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 @@ -5,11 +5,12 @@ 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; +import java.util.ArrayList; import java.util.List; public class ContainerSetContentHandler extends PacketHandler<@NotNull ClientboundContainerSetContentPacket> { @@ -25,20 +26,31 @@ public ContainerSetContentHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundContainerSetContentPacket packet) { - List itemsString = packet.items().stream() - .map(FormatHelper::formatItemStack) + var itemSegments = packet.items().stream() + .limit(MAX_DISPLAYED_ENTRIES) + .map(item -> PacketInfo.value(Component.text(FormatHelper.formatItemStack(item)))) .toList(); + 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(PacketInfo.list(Component.text("Items"), new ArrayList<>(itemSegments))); + } + + int hiddenItems = packet.items().size() - itemSegments.size(); + if (hiddenItems > 0) { + rows.add(PacketInfo.data(Component.text("ItemsHidden"), Component.text(hiddenItems + " more"))); + } + + rows.add(PacketInfo.data(Component.text("CarriedItem"), Component.text(FormatHelper.formatItemStack(packet.carriedItem())))); + return PacketInfoBundle.of( 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 ); } - + } \ 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 new file mode 100644 index 0000000..fcdcd21 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/InitializeWorldBorderHandler.java @@ -0,0 +1,38 @@ +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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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( + 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 new file mode 100644 index 0000000..32c68d7 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoRemoveHandler.java @@ -0,0 +1,40 @@ +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.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() { + super( + ClientboundPlayerInfoRemovePacket.class, + "PlayerInfoRemove", + "Handles player removal updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(@NotNull ClientboundPlayerInfoRemovePacket packet) { + List rows = new ArrayList<>(); + + var removed = packet.profileIds().stream() + .map(uuid -> PacketInfo.value(Component.text(uuid.toString()))) + .toList(); + rows.add(PacketInfo.list(Component.text("Removed UUIDs"), removed)); + + 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 new file mode 100644 index 0000000..7790ca3 --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/PlayerInfoUpdateHandler.java @@ -0,0 +1,87 @@ +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.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 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 ""; + } + + // 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) + ) + .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 rows = new ArrayList<>(); + + List displayedEntries = packet.entries().stream() + .limit(MAX_DISPLAYED_ENTRIES) + .toList(); + 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 = PacketInfo.data(Component.text("Identity"), MiniMessage.miniMessage().deserialize(identity)); + + // state + String state = String.format( + "listed=%s, listOrder=%d, showHat=%s, latency=%dms", + entry.listed(), + entry.listOrder(), + entry.showHat(), + entry.latency() + ); + var stateSegment = PacketInfo.data(Component.text("State"), Component.text(state)); + + String name = entry.profile() != null ? entry.profile().name() : entry.profileId().toString(); + return PacketInfo.list(Component.text(name), List.of(identitySegment, stateSegment)); + }).toList(); + + rows.addAll(entryLists); + + 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 9a973f4..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,12 +4,12 @@ import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; 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; +import java.util.ArrayList; import java.util.List; public class RemoveEntitiesHandler extends PacketHandler<@NotNull ClientboundRemoveEntitiesPacket> { @@ -24,15 +24,34 @@ public RemoveEntitiesHandler() { @Override protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundRemoveEntitiesPacket packet) { - String removedEntityIdList = FormatHelper.formatList(packet.getEntityIds().stream().toList(), MAX_DISPLAYED_ENTRIES); + List rows = new ArrayList<>(); + + var allEntityIds = packet.getEntityIds(); + int totalCount = allEntityIds.size(); + + List displayedIds = allEntityIds.intStream() + .limit(MAX_DISPLAYED_ENTRIES) + .boxed() + .toList(); + + rows.add(PacketInfo.data(Component.text("Count"), Component.text(totalCount))); + + if (!displayedIds.isEmpty()) { + var idSegments = displayedIds.stream() + .map(id -> PacketInfo.value(Component.text(id))) + .toList(); + rows.add(PacketInfo.list(Component.text("EntityIds"), new ArrayList<>(idSegments))); + } + + int hiddenEntities = totalCount - displayedIds.size(); + if (hiddenEntities > 0) { + rows.add(PacketInfo.data(Component.text("EntityIdsHidden"), Component.text(hiddenEntities + " more"))); + } return PacketInfoBundle.of( 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/SetBorderCenterHandler.java b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetBorderCenterHandler.java new file mode 100644 index 0000000..2d34e12 --- /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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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( + 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 new file mode 100644 index 0000000..44cbea4 --- /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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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, + "SetBorderLerpSize", + "Handles world border size lerp updates", + PacketType.CLIENTBOUND + ); + } + + @Override + protected @NotNull PacketInfoBundle getPacketInfoInternal(ClientboundSetBorderLerpSizePacket packet) { + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + 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 new file mode 100644 index 0000000..d74244f --- /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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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( + 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 new file mode 100644 index 0000000..49c998b --- /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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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( + 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 new file mode 100644 index 0000000..31777e2 --- /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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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( + 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 new file mode 100644 index 0000000..ae07b0f --- /dev/null +++ b/src/client/java/xyz/bitsquidd/ninja/handler/impl/clientbound/SetCursorItemHandler.java @@ -0,0 +1,49 @@ +package xyz.bitsquidd.ninja.handler.impl.clientbound; + +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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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.INSTANCE, stack); + var json = encodeResult.resultOrPartial(PacketInterceptorMod.LOGGER::error).orElse(new JsonObject()); // return empty on error + + return PacketInfoBundle.of( + packetType, + Component.text(friendlyName), + List.of( + 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 73cb438..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,12 +4,12 @@ import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; 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; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -26,16 +26,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 -> PacketInfo.data(Component.text("PassengerId"), Component.text(id))) + .toList(); + + 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(PacketInfo.list(Component.text("Passengers"), passengers)); + } + + int hiddenPassengers = packet.getPassengers().length - passengers.size(); + if (hiddenPassengers > 0) { + rows.add(PacketInfo.data(Component.text("PassengersHidden"), Component.text(hiddenPassengers + " more"))); + } return PacketInfoBundle.of( 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..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,9 +4,8 @@ import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; 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; @@ -26,62 +25,73 @@ 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(PacketInfo.data(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(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()) { - 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 -> PacketInfo.data(Component.text("Player"), Component.text(name))) + .toList(); + rows.add(PacketInfo.list(Component.text("Players"), new ArrayList<>(playerSegments))); + + int hiddenPlayers = packet.getPlayers().size() - playerList.size(); + if (hiddenPlayers > 0) { + rows.add(PacketInfo.data(Component.text("PlayersHidden"), Component.text(hiddenPlayers + " more"))); + } } packet.getParameters().ifPresent(params -> { - segments.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("DisplayName"), Component.text(params.getDisplayName().getString()) )); - segments.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("Color"), Component.text(params.getColor().getName()) )); - segments.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("NTVisibility"), Component.text(params.getNametagVisibility().name) )); - segments.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("CollisionRule"), Component.text(params.getCollisionRule().name) )); if (!params.getPlayerPrefix().getString().isEmpty()) { - segments.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( Component.text("Prefix"), Component.text(params.getPlayerPrefix().getString()) )); } if (!params.getPlayerSuffix().getString().isEmpty()) { - segments.add(PacketInfoSegment.of( + rows.add(PacketInfo.data( 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(PacketInfo.data(Component.text("Options"), Component.text(String.format("0x%02X", params.getOptions())))); }); return PacketInfoBundle.of( packetType, Component.text(friendlyName), - segments + rows ); } 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..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 @@ -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,14 @@ 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 new file mode 100644 index 0000000..817bf5a --- /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.PacketInfo; +import xyz.bitsquidd.ninja.format.PacketInfoBundle; +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( + 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())) ) ); } 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 fd1a379..0000000 --- a/src/main/java/xyz/bitsquidd/ninja/PacketInterceptor.java +++ /dev/null @@ -1,14 +0,0 @@ -package xyz.bitsquidd.ninja; - -import net.fabricmc.api.ModInitializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -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 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": [