More work on the Chat Registries

leaving some debug in as I'm still working on this, TODO:

some registries are now 1:1 with what is sended, however, there is some
restructing here as the code doesn't reflect some caveats of how this information
is populated, i.e. fields which where said to not be nullable are actually in fact
nullable, AND, this matters, at least if we wanna ensure that what we send is what
we got

Needs some moving stuff around to factor the above in, overlay section needs dealing with

currently breaks chatting, chances are the registry repopulation is bork somewhere
This commit is contained in:
Shane Freeder 2022-06-11 01:29:12 +01:00
parent 4599d15003
commit 5448f54380
No known key found for this signature in database
GPG Key ID: A3F61EA5A085289C
4 changed files with 128 additions and 31 deletions

View File

@ -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 {

View File

@ -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<String> parameters;
private final List<TextFormat> style;
@Nullable
private final String translationKey;
public List<String> 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<String> parameters, List<TextFormat> style, String translationKey) {
public Decoration(List<String> parameters, List<TextFormat> 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<String> 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<TextFormat> 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<StringBinaryTag> parametersBuilder = ListBinaryTag.builder(BinaryTagTypes.STRING);
parameters.forEach(param -> parametersBuilder.add(StringBinaryTag.of(param)));
compoundBinaryTag.put("parameters", parametersBuilder.build());
}
return compoundBinaryTag.build();
}
}

View File

@ -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<ChatData> fromGameData(ListBinaryTag compound, ProtocolVersion version) {
final ImmutableList.Builder<ChatData> 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();

View File

@ -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);