diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/model/chain/v1_19_1/MessageBody.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/model/chain/v1_19_1/MessageBody.java index 18e9f7caa..472523f59 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/model/chain/v1_19_1/MessageBody.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/model/chain/v1_19_1/MessageBody.java @@ -25,7 +25,7 @@ package com.viaversion.viaversion.api.minecraft.signature.model.chain.v1_19_1; import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature; import com.viaversion.viaversion.api.minecraft.signature.model.DecoratableMessage; import com.viaversion.viaversion.api.minecraft.signature.util.DataConsumer; -import net.lenni0451.mcstructs.text.utils.JsonUtils; +import com.viaversion.viaversion.util.GsonUtil; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -62,7 +62,7 @@ public class MessageBody { dataOutputStream.write(this.content.plain().getBytes(StandardCharsets.UTF_8)); dataOutputStream.write(HASH_SEPARATOR_BYTE); if (this.content.isDecorated()) { - dataOutputStream.write(JsonUtils.toSortedString(this.content.decorated(), null).getBytes(StandardCharsets.UTF_8)); + dataOutputStream.write(GsonUtil.sort(this.content.decorated()).toString().getBytes(StandardCharsets.UTF_8)); } for (PlayerMessageSignature lastSeenMessage : this.lastSeenMessages) { diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/storage/ChatSession1_19_0.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/storage/ChatSession1_19_0.java index 105325e1d..e2c306541 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/storage/ChatSession1_19_0.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/signature/storage/ChatSession1_19_0.java @@ -25,7 +25,7 @@ package com.viaversion.viaversion.api.minecraft.signature.storage; import com.viaversion.viaversion.api.minecraft.ProfileKey; import com.viaversion.viaversion.api.minecraft.signature.model.DecoratableMessage; import com.viaversion.viaversion.api.minecraft.signature.model.MessageMetadata; -import net.lenni0451.mcstructs.text.utils.JsonUtils; +import com.viaversion.viaversion.util.GsonUtil; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -48,7 +48,7 @@ public class ChatSession1_19_0 extends ChatSession { buffer.putLong(metadata.sender().getMostSignificantBits()).putLong(metadata.sender().getLeastSignificantBits()); buffer.putLong(metadata.timestamp().getEpochSecond()); signer.accept(data); - signer.accept(JsonUtils.toSortedString(content.decorated(), null).getBytes(StandardCharsets.UTF_8)); + signer.accept(GsonUtil.sort(content.decorated()).toString().getBytes(StandardCharsets.UTF_8)); }); } diff --git a/api/src/main/java/com/viaversion/viaversion/util/GsonUtil.java b/api/src/main/java/com/viaversion/viaversion/util/GsonUtil.java index 4c4313649..f5dfd92b3 100644 --- a/api/src/main/java/com/viaversion/viaversion/util/GsonUtil.java +++ b/api/src/main/java/com/viaversion/viaversion/util/GsonUtil.java @@ -24,6 +24,10 @@ package com.viaversion.viaversion.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import java.util.Comparator; +import net.lenni0451.mcstructs.text.utils.JsonUtils; +import org.checkerframework.checker.nullness.qual.Nullable; public final class GsonUtil { private static final Gson GSON = new GsonBuilder().create(); @@ -37,4 +41,7 @@ public final class GsonUtil { return GSON; } + public static @Nullable JsonElement sort(@Nullable final JsonElement object) { + return JsonUtils.sort(object, Comparator.naturalOrder()); + } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/rewriter/ChatItemRewriter.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/rewriter/ChatItemRewriter.java index 62a3a23f9..9d0c67a2e 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/rewriter/ChatItemRewriter.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_12to1_11_1/rewriter/ChatItemRewriter.java @@ -21,31 +21,31 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import net.lenni0451.mcstructs.snbt.SNbtSerializer; -import net.lenni0451.mcstructs.snbt.exceptions.SNbtDeserializeException; -import net.lenni0451.mcstructs.snbt.exceptions.SNbtSerializeException; -import net.lenni0451.mcstructs.text.ATextComponent; -import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer; +import com.viaversion.viaversion.util.ComponentUtil; +import com.viaversion.viaversion.util.SerializerVersion; +import com.viaversion.viaversion.util.TagUtil; -public class ChatItemRewriter { +public final class ChatItemRewriter { - public static void toClient(JsonElement element) throws SNbtDeserializeException, SNbtSerializeException { + public static void toClient(JsonElement element) { if (element instanceof JsonObject) { JsonObject obj = (JsonObject) element; if (obj.has("hoverEvent")) { - if (obj.get("hoverEvent") instanceof JsonObject) { - final JsonObject hoverEvent = (JsonObject) obj.get("hoverEvent"); - if (hoverEvent.has("action") && hoverEvent.has("value")) { - final String type = hoverEvent.get("action").getAsString(); - final JsonElement value = hoverEvent.get("value"); + if (!(obj.get("hoverEvent") instanceof JsonObject)) { + return; + } - if (type.equals("show_item")) { - final ATextComponent component = TextComponentSerializer.V1_8.deserialize(value); + final JsonObject hoverEvent = (JsonObject) obj.get("hoverEvent"); + if (!hoverEvent.has("action") || !hoverEvent.has("value")) { + return; + } - final CompoundTag compound = SNbtSerializer.V1_8.deserialize(component.asUnformattedString()); - hoverEvent.addProperty("value", SNbtSerializer.V1_12.serialize(compound)); - } - } + final String type = hoverEvent.get("action").getAsString(); + final JsonElement value = hoverEvent.get("value"); + + if (type.equals("show_item")) { + final CompoundTag compound = ComponentUtil.deserializeLegacyShowItem(value, SerializerVersion.V1_8); + hoverEvent.addProperty("value", TagUtil.toSNBT(compound, SerializerVersion.V1_12)); } } else if (obj.has("extra")) { toClient(obj.get("extra")); diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/data/ComponentRewriter1_13.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/data/ComponentRewriter1_13.java index ef0778e88..062937225 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/data/ComponentRewriter1_13.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_13to1_12_2/data/ComponentRewriter1_13.java @@ -30,9 +30,9 @@ import com.viaversion.viaversion.api.protocol.Protocol; import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType; import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2; import com.viaversion.viaversion.rewriter.ComponentRewriter; -import net.lenni0451.mcstructs.snbt.SNbtSerializer; -import net.lenni0451.mcstructs.text.ATextComponent; -import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer; +import com.viaversion.viaversion.util.ComponentUtil; +import com.viaversion.viaversion.util.SerializerVersion; +import com.viaversion.viaversion.util.TagUtil; import java.util.logging.Level; public class ComponentRewriter1_13 extends ComponentRewriter { @@ -50,13 +50,12 @@ public class ComponentRewriter1_13 extends Comp final JsonElement value = hoverEvent.get("value"); if (value == null) return; - final ATextComponent nbt = TextComponentSerializer.V1_12.deserialize(value); CompoundTag tag; try { - tag = SNbtSerializer.V1_12.deserialize(nbt.asUnformattedString()); + tag = ComponentUtil.deserializeLegacyShowItem(value, SerializerVersion.V1_12); } catch (Exception e) { if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) { - Via.getPlatform().getLogger().log(Level.WARNING, "Error reading 1.12.2 NBT in show_item: " + nbt, e); + Via.getPlatform().getLogger().log(Level.WARNING, "Error reading 1.12.2 NBT in show_item: " + value, e); } return; } @@ -84,11 +83,11 @@ public class ComponentRewriter1_13 extends Comp array.add(object); String serializedNBT; try { - serializedNBT = SNbtSerializer.V1_13.serialize(tag); + serializedNBT = TagUtil.toSNBT(tag, SerializerVersion.V1_13); object.addProperty("text", serializedNBT); hoverEvent.add("value", array); } catch (Exception e) { - Via.getPlatform().getLogger().log(Level.WARNING, "Error writing 1.13 NBT in show_item: " + nbt, e); + Via.getPlatform().getLogger().log(Level.WARNING, "Error writing 1.13 NBT in show_item: " + value, e); } } diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_3to1_20_2/rewriter/BlockItemPacketRewriter1_20_3.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_3to1_20_2/rewriter/BlockItemPacketRewriter1_20_3.java index 67f11cf35..d99fc5119 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_3to1_20_2/rewriter/BlockItemPacketRewriter1_20_3.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_3to1_20_2/rewriter/BlockItemPacketRewriter1_20_3.java @@ -41,6 +41,7 @@ import com.viaversion.viaversion.rewriter.BlockRewriter; import com.viaversion.viaversion.rewriter.ItemRewriter; import com.viaversion.viaversion.util.ComponentUtil; import com.viaversion.viaversion.util.Key; +import com.viaversion.viaversion.util.SerializerVersion; import org.checkerframework.checker.nullness.qual.Nullable; public final class BlockItemPacketRewriter1_20_3 extends ItemRewriter { @@ -159,7 +160,7 @@ public final class BlockItemPacketRewriter1_20_3 extends ItemRewriter snbtSerializer; - private final TextComponentCodec codec; - - SerializerVersion(final TextComponentSerializer jsonSerializer, final SNbtSerializer snbtSerializer) { - this.jsonSerializer = jsonSerializer; - this.snbtSerializer = snbtSerializer; - this.codec = null; - } - - SerializerVersion(final TextComponentCodec codec, final SNbtSerializer snbtSerializer) { - this.codec = codec; - this.jsonSerializer = codec.asSerializer(); - this.snbtSerializer = snbtSerializer; - } - - public JsonElement toJson(final ATextComponent component) { - return jsonSerializer.serializeJson(component); - } + public static CompoundTag deserializeLegacyShowItem(final JsonElement element, final SerializerVersion version) { + final ATextComponent component = version.jsonSerializer.deserialize(element); + return TagUtil.fromSNBT(component.asUnformattedString(), version); } } diff --git a/common/src/main/java/com/viaversion/viaversion/util/SerializerVersion.java b/common/src/main/java/com/viaversion/viaversion/util/SerializerVersion.java new file mode 100644 index 000000000..73e6b0f97 --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/util/SerializerVersion.java @@ -0,0 +1,56 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2024 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.util; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.google.gson.JsonElement; +import net.lenni0451.mcstructs.snbt.SNbtSerializer; +import net.lenni0451.mcstructs.text.ATextComponent; +import net.lenni0451.mcstructs.text.serializer.TextComponentCodec; +import net.lenni0451.mcstructs.text.serializer.TextComponentSerializer; + +public enum SerializerVersion { + V1_8(TextComponentSerializer.V1_8, SNbtSerializer.V1_8), + V1_9(TextComponentSerializer.V1_9, SNbtSerializer.V1_8), + V1_12(TextComponentSerializer.V1_12, SNbtSerializer.V1_12), + V1_13(TextComponentSerializer.V1_12, SNbtSerializer.V1_13), + V1_14(TextComponentSerializer.V1_14, SNbtSerializer.V1_14), + V1_15(TextComponentSerializer.V1_15, SNbtSerializer.V1_14), + V1_16(TextComponentSerializer.V1_16, SNbtSerializer.V1_14), + V1_17(TextComponentSerializer.V1_17, SNbtSerializer.V1_14), + V1_18(TextComponentSerializer.V1_18, SNbtSerializer.V1_14), + V1_19_4(TextComponentSerializer.V1_19_4, SNbtSerializer.V1_14), + V1_20_3(TextComponentCodec.V1_20_3, SNbtSerializer.V1_14); + + final TextComponentSerializer jsonSerializer; + final SNbtSerializer snbtSerializer; + + SerializerVersion(final TextComponentSerializer jsonSerializer, final SNbtSerializer snbtSerializer) { + this.jsonSerializer = jsonSerializer; + this.snbtSerializer = snbtSerializer; + } + + SerializerVersion(final TextComponentCodec codec, final SNbtSerializer snbtSerializer) { + this.jsonSerializer = codec.asSerializer(); + this.snbtSerializer = snbtSerializer; + } + + public JsonElement toJson(final ATextComponent component) { + return jsonSerializer.serializeJson(component); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/viaversion/viaversion/util/TagUtil.java b/common/src/main/java/com/viaversion/viaversion/util/TagUtil.java index 28be0a62a..5a06ce966 100644 --- a/common/src/main/java/com/viaversion/viaversion/util/TagUtil.java +++ b/common/src/main/java/com/viaversion/viaversion/util/TagUtil.java @@ -21,6 +21,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import java.util.Map; +import net.lenni0451.mcstructs.snbt.exceptions.SNbtDeserializeException; +import net.lenni0451.mcstructs.snbt.exceptions.SNbtSerializeException; import org.checkerframework.checker.nullness.qual.Nullable; public final class TagUtil { @@ -46,6 +48,22 @@ public final class TagUtil { listTag.getValue().replaceAll(t -> (T) handleDeep(null, t, consumer)); } + public static String toSNBT(final Tag tag, final SerializerVersion version) { + try { + return version.snbtSerializer.serialize(tag); + } catch (final SNbtSerializeException e) { + throw new RuntimeException(e); + } + } + + public static CompoundTag fromSNBT(final String snbt, final SerializerVersion version) { + try { + return version.snbtSerializer.deserialize(snbt); + } catch (final SNbtDeserializeException e) { + throw new RuntimeException(e); + } + } + @FunctionalInterface public interface TagUpdater {