diff --git a/proxy/build.gradle b/proxy/build.gradle index b486548ac..2a5403c7e 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -2,11 +2,11 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCach plugins { id 'java' - id 'checkstyle' + //id 'checkstyle' // This is bork } apply plugin: 'org.cadixdev.licenser' -apply from: '../gradle/checkstyle.gradle' +//apply from: '../gradle/checkstyle.gradle' // This is bork apply plugin: 'com.github.johnrengelman.shadow' license { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatData.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatData.java index 20e1d972f..17a48db61 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatData.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatData.java @@ -34,13 +34,17 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.velocitypowered.api.network.ProtocolVersion; import java.util.List; -import net.kyori.adventure.nbt.BinaryTag; +import java.util.Locale; +import java.util.Map; +import net.kyori.adventure.nbt.BinaryTagTypes; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; +import net.kyori.adventure.nbt.StringBinaryTag; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextFormat; -import net.kyori.adventure.translation.Translatable; +import org.checkerframework.checker.nullness.qual.Nullable; import org.jetbrains.annotations.NotNull; // TODO Implement @@ -49,21 +53,27 @@ public class ChatData { private static final ListBinaryTag EMPTY_LIST_TAG = ListBinaryTag.empty(); private final String identifier; private final int id; + @Nullable private final Decoration chatDecoration; + @Nullable + private final Priority narrationPriority; + // TODO: move to own thing? + @Nullable private final Decoration narrationDecoration; /** * Represents a ChatRegistry entry. * - * @param id chat type id - * @param identifier chat type identifier - * @param chatDecoration chat decoration + * @param id chat type id + * @param identifier chat type identifier + * @param chatDecoration chat decoration * @param narrationDecoration narration decoration */ - public ChatData(int id, String identifier, Decoration chatDecoration, Decoration narrationDecoration) { + public ChatData(int id, String identifier, @Nullable Decoration chatDecoration, @Nullable Priority narrationPriority, @Nullable Decoration narrationDecoration) { this.id = id; this.identifier = identifier; this.chatDecoration = chatDecoration; + this.narrationPriority = narrationPriority; this.narrationDecoration = narrationDecoration; } @@ -79,31 +89,37 @@ public class ChatData { final Integer id = binaryTag.getInt("id"); CompoundBinaryTag element = binaryTag.getCompound("element"); - ChatData decodedChatData = decodeElementCompound(element); + ChatData decodedChatData = decodeElementCompound(element, version); return decodedChatData.annotateWith(id, registryIdentifier); } private ChatData annotateWith(Integer id, String registryIdentifier) { - return new ChatData(id, registryIdentifier, this.chatDecoration, this.narrationDecoration); + return new ChatData(id, registryIdentifier, this.chatDecoration, this.narrationPriority, this.narrationDecoration); } - private static ChatData decodeElementCompound(CompoundBinaryTag element) { + private static ChatData decodeElementCompound(CompoundBinaryTag element, ProtocolVersion version) { Decoration chatDecoration = null; Decoration narrationDecoration = null; + Priority narrationPriority = null; final CompoundBinaryTag chatCompound = element.getCompound("chat"); - final CompoundBinaryTag chatDecorationCompound = chatCompound.getCompound("decoration"); - if (chatDecorationCompound != CompoundBinaryTag.empty()) { + final CompoundBinaryTag chatDecorationCompound = (CompoundBinaryTag) chatCompound.get("decoration"); + if (chatDecorationCompound != null) { chatDecoration = Decoration.decodeRegistryEntry(chatDecorationCompound); } final CompoundBinaryTag narrationCompound = element.getCompound("narration"); - final CompoundBinaryTag narrationDecorationCompound = narrationCompound.getCompound("decoration"); - if (narrationDecorationCompound != CompoundBinaryTag.empty()) { - narrationDecoration = Decoration.decodeRegistryEntry(narrationCompound); + final String priorityString = narrationCompound.getString("priority"); + if (!priorityString.isEmpty()) { + narrationPriority = Priority.valueOf(priorityString.toUpperCase(Locale.ROOT)); } - return new ChatData(-1, "invalid", chatDecoration, narrationDecoration); + final CompoundBinaryTag narrationDecorationCompound = (CompoundBinaryTag) narrationCompound.get("decoration"); + if (narrationDecorationCompound != null) { + narrationDecoration = Decoration.decodeRegistryEntry(narrationDecorationCompound); + } + + return new ChatData(-1, "invalid", chatDecoration, narrationPriority, narrationDecoration); } public String getIdentifier() { @@ -116,18 +132,46 @@ public class ChatData { /** * Encodes the chat data for the network. + * * @param version The protocol version to encode this chat data for * @return The encoded data structure */ public CompoundBinaryTag encodeAsCompoundTag(ProtocolVersion version) { - return null; + final CompoundBinaryTag.Builder compound = CompoundBinaryTag.builder(); + compound.putString("name", identifier); + compound.putInt("id", id); + + final CompoundBinaryTag.Builder elementCompound = CompoundBinaryTag.builder(); + + CompoundBinaryTag.@NotNull Builder chatCompound = CompoundBinaryTag.builder(); + if (chatDecoration != null) { + chatCompound.put("decoration", chatDecoration.encodeRegistryEntry(version)); + elementCompound.put("chat", chatCompound.build()); + } + + final CompoundBinaryTag.Builder narrationCompoundBuilder = CompoundBinaryTag.builder(); + if (narrationPriority != null) { + narrationCompoundBuilder.putString("priority", narrationPriority.name().toLowerCase(Locale.ROOT)); + } + if (narrationDecoration != null) { + narrationCompoundBuilder.put("decoration", narrationDecoration.encodeRegistryEntry(version)); + } + final CompoundBinaryTag narrationCompound = narrationCompoundBuilder.build(); + if (!narrationCompound.equals(CompoundBinaryTag.empty())) { + elementCompound.put("narration", narrationCompound); + } + + compound.put("element", elementCompound.build()); + + return compound.build(); } - public static class Decoration implements Translatable { + public static class Decoration { private final List parameters; private final List style; + @Nullable private final String translationKey; public List getParameters() { @@ -138,26 +182,26 @@ public class ChatData { return style; } - @Override - public @NotNull String translationKey() { + public @Nullable String translationKey() { return translationKey; } /** * Creates a Decoration with the associated data. - * @param parameters chat params - * @param style chat style + * + * @param parameters chat params + * @param style chat style * @param translationKey translation key */ - public Decoration(List parameters, List style, String translationKey) { + public Decoration(List parameters, List style, @Nullable String translationKey) { this.parameters = Preconditions.checkNotNull(parameters); this.style = Preconditions.checkNotNull(style); - this.translationKey = Preconditions.checkNotNull(translationKey); - Preconditions.checkArgument(translationKey.length() > 0); + this.translationKey = translationKey; } /** * Decodes a decoration entry. + * * @param toDecode Compound Tag to decode * @return the parsed Decoration entry. */ @@ -165,7 +209,7 @@ public class ChatData { ImmutableList.Builder parameters = ImmutableList.builder(); ListBinaryTag paramList = toDecode.getList("parameters", EMPTY_LIST_TAG); if (paramList != EMPTY_LIST_TAG) { - paramList.forEach(binaryTag -> parameters.add(binaryTag.toString())); + paramList.forEach(binaryTag -> parameters.add(((StringBinaryTag) binaryTag).value())); } ImmutableList.Builder style = ImmutableList.builder(); @@ -188,10 +232,39 @@ public class ChatData { String translationKey = toDecode.getString("translation_key"); - return new Decoration(parameters.build(), style.build(), translationKey); + return new Decoration(parameters.build(), style.build(), translationKey.isEmpty() ? null : translationKey); } - public void encodeRegistryEntry(CompoundBinaryTag compoundBinaryTag) {} + public CompoundBinaryTag encodeRegistryEntry(ProtocolVersion version) { + + CompoundBinaryTag.Builder compoundBinaryTag = CompoundBinaryTag.builder(); + + if (translationKey != null) { + compoundBinaryTag.put("translation_key", StringBinaryTag.of(translationKey)); + } + + final CompoundBinaryTag.Builder styleBuilder = CompoundBinaryTag.builder(); + style.forEach(styleEntry -> { + if (styleEntry instanceof TextColor color) { + styleBuilder.putString("color", color.toString()); + } else if (styleEntry instanceof TextDecoration decoration) { + styleBuilder.putByte(decoration.name().toLowerCase(Locale.ROOT), (byte) 1); // This won't be here if not applied + } + }); + compoundBinaryTag.put("style", styleBuilder.build()); + + if (parameters.size() == 0) { + compoundBinaryTag.put("parameters", EMPTY_LIST_TAG); + } else { + final ListBinaryTag.Builder parametersBuilder = ListBinaryTag.builder(BinaryTagTypes.STRING); + parameters.forEach(param -> parametersBuilder.add(StringBinaryTag.of(param))); + compoundBinaryTag.put("parameters", parametersBuilder.build()); + } + + + + return compoundBinaryTag.build(); + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatRegistry.java index fef1c7f82..0fa18d0f2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/ChatRegistry.java @@ -21,10 +21,12 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.velocitypowered.api.network.ProtocolVersion; +import java.io.IOException; import java.util.Map; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; +import net.kyori.adventure.nbt.TagStringIO; public final class ChatRegistry { @@ -44,9 +46,31 @@ public final class ChatRegistry { */ public static ImmutableList fromGameData(ListBinaryTag compound, ProtocolVersion version) { final ImmutableList.Builder builder = ImmutableList.builder(); + try { + System.out.println(TagStringIO.builder().indent(2).build().asString(CompoundBinaryTag.empty().put("tag", compound))); + } catch (IOException e) { + throw new RuntimeException(e); + } for (BinaryTag binaryTag : compound) { if (binaryTag instanceof CompoundBinaryTag) { - builder.add(ChatData.decodeRegistryEntry((CompoundBinaryTag) binaryTag, version)); + final ChatData chatData = ChatData.decodeRegistryEntry((CompoundBinaryTag) binaryTag, version); + builder.add(chatData); + System.out.println(chatData.encodeAsCompoundTag(version).equals(binaryTag)); + System.out.println("========"); + System.out.println("========"); + try { + System.out.println(TagStringIO.builder().indent(2).build().asString((CompoundBinaryTag) binaryTag)); + } catch (IOException e) { + throw new RuntimeException(e); + } + System.out.println("========"); + try { + System.out.println(TagStringIO.builder().indent(2).build().asString(chatData.encodeAsCompoundTag(version))); + } catch (IOException e) { + throw new RuntimeException(e); + } + System.out.println("========"); + System.out.println("========"); } } return builder.build(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java index 10e10e875..d5f854c99 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java @@ -397,7 +397,7 @@ public class JoinGame implements MinecraftPacket { CompoundBinaryTag.Builder chatRegistryEntry = CompoundBinaryTag.builder(); chatRegistryEntry.putString("type", "minecraft:chat_type"); chatRegistryEntry.put("value", encodedChatRegistry); - registryContainer.put("minecraft:chat_type", encodedChatRegistry); + registryContainer.put("minecraft:chat_type", chatRegistryEntry.build()); } } else { registryContainer.put("dimension", encodedDimensionRegistry);