From ef057bba7d2522b73dce50be95cbacd4e84d8099 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Tue, 23 Apr 2024 11:32:19 -0700 Subject: [PATCH] work on Adventure patch --- patches/server/0010-Adventure.patch | 688 +++++++++++++--------------- 1 file changed, 320 insertions(+), 368 deletions(-) diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index b91e0bfc2..e1fb6cc1d 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -14,24 +14,33 @@ Co-authored-by: Jake Potrebic diff --git a/src/main/java/io/papermc/paper/adventure/AdventureCodecs.java b/src/main/java/io/papermc/paper/adventure/AdventureCodecs.java new file mode 100644 -index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6ea17d1f4 +index 0000000000000000000000000000000000000000..b33e394d88517c7afc2f549bae5a2063316ada73 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/AdventureCodecs.java -@@ -0,0 +1,418 @@ +@@ -0,0 +1,458 @@ +package io.papermc.paper.adventure; + ++import com.google.gson.JsonElement; ++import com.google.gson.JsonParser; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.datafixers.util.Either; ++import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; ++import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.Encoder; ++import com.mojang.serialization.JsonOps; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; ++import io.netty.buffer.ByteBuf; ++import io.netty.handler.codec.DecoderException; ++import io.netty.handler.codec.EncoderException; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; ++import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; @@ -61,15 +70,23 @@ index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6 +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtAccounter; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; +import net.minecraft.nbt.TagParser; ++import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.network.chat.contents.KeybindContents; +import net.minecraft.network.chat.contents.ScoreContents; +import net.minecraft.network.chat.contents.TranslatableContents; ++import net.minecraft.network.codec.ByteBufCodecs; ++import net.minecraft.network.codec.StreamCodec; ++import net.minecraft.resources.RegistryOps; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; @@ -81,13 +98,13 @@ index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6 +import static net.kyori.adventure.text.TranslationArgument.bool; +import static net.kyori.adventure.text.TranslationArgument.component; +import static net.kyori.adventure.text.TranslationArgument.numeric; -+import static net.minecraft.util.ExtraCodecs.recursive; -+import static net.minecraft.util.ExtraCodecs.strictOptionalField; ++import static com.mojang.serialization.Codec.recursive; + +@DefaultQualifier(NonNull.class) +public final class AdventureCodecs { + + public static final Codec COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec); ++ public static final StreamCodec STREAM_COMPONENT_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(COMPONENT_CODEC); + + static final Codec TEXT_COLOR_CODEC = Codec.STRING.comapFlatMap(s -> { + if (s.startsWith("#")) { @@ -125,7 +142,7 @@ index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6 + return instance.group( + KEY_CODEC.fieldOf("type").forGetter(HoverEvent.ShowEntity::type), + UUIDUtil.LENIENT_CODEC.fieldOf("id").forGetter(HoverEvent.ShowEntity::id), -+ strictOptionalField(componentCodec, "name").forGetter(he -> Optional.ofNullable(he.name())) ++ componentCodec.lenientOptionalFieldOf("name").forGetter(he -> Optional.ofNullable(he.name())) + ).apply(instance, (key, uuid, component) -> { + return HoverEvent.ShowEntity.showEntity(key, uuid, component.orElse(null)); + }); @@ -134,7 +151,7 @@ index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6 + + static Codec showItemCodec(final Codec componentCodec) { + return net.minecraft.network.chat.HoverEvent.ItemStackInfo.CODEC.xmap(isi -> { -+ @Subst("key") final String typeKey = BuiltInRegistries.ITEM.getKey(isi.item).toString(); ++ @Subst("key") final String typeKey = isi.item.unwrapKey().orElseThrow().toString(); + return HoverEvent.ShowItem.showItem(Key.key(typeKey), isi.count, PaperAdventure.asBinaryTagHolder(isi.tag.orElse(null))); + }, si -> { + final Item itemType = BuiltInRegistries.ITEM.get(PaperAdventure.asVanilla(si.item())); @@ -154,36 +171,59 @@ index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6 + static final HoverEventType SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(identity(), HoverEvent.Action.SHOW_TEXT, "show_text", DataResult::success); + static final Codec> HOVER_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new HoverEventType[]{ SHOW_ENTITY_HOVER_EVENT_TYPE, SHOW_ITEM_HOVER_EVENT_TYPE, SHOW_TEXT_HOVER_EVENT_TYPE }); + -+ static DataResult legacyDeserializeEntity(final Component text) { ++ static DataResult legacyDeserializeEntity(final Component component, final @Nullable RegistryOps ops, final Codec componentCodec) { + try { -+ final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(text)); -+ final @Nullable Component entityName = GsonComponentSerializer.gson().deserializeOrNull(tag.getString("name")); ++ final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(component)); ++ final DynamicOps dynamicOps = ops != null ? ops.withParent(JsonOps.INSTANCE) : JsonOps.INSTANCE; ++ final DataResult entityNameResult = componentCodec.parse(dynamicOps, JsonParser.parseString(tag.getString("name"))); + @Subst("key") final String keyString = tag.getString("type"); + final UUID entityUUID = UUID.fromString(tag.getString("id")); -+ return DataResult.success(HoverEvent.ShowEntity.showEntity(Key.key(keyString), entityUUID, entityName)); ++ return entityNameResult.map(name -> HoverEvent.ShowEntity.showEntity(Key.key(keyString), entityUUID, name)); + } catch (final Exception ex) { + return DataResult.error(() -> "Failed to parse tooltip: " + ex.getMessage()); + } + } + -+ static DataResult legacyDeserializeItem(final Component text) { ++ static DataResult legacyDeserializeItem(final Component component, final @Nullable RegistryOps ops, final Codec componentCodec) { + try { -+ final ItemStack stack = ItemStack.of(TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(text))); -+ @Subst("key") final String keyString = BuiltInRegistries.ITEM.getKey(stack.getItem()).toString(); -+ return DataResult.success(HoverEvent.ShowItem.showItem(Key.key(keyString), stack.getCount(), stack.getTag() != null ? BinaryTagHolder.encode(stack.getTag(), PaperAdventure.NBT_CODEC) : null)); ++ final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(component)); ++ final DynamicOps dynamicOps = ops != null ? ops.withParent(NbtOps.INSTANCE) : NbtOps.INSTANCE; ++ final DataResult stackResult = ItemStack.CODEC.parse(dynamicOps, tag).map(CraftItemStack::asCraftMirror); ++ return stackResult.map(stack -> { ++ return HoverEvent.ShowItem.showItem(stack.getType().key(), stack.getAmount(), /* TODO */); ++ }); + } catch (final CommandSyntaxException | IOException ex) { + return DataResult.error(() -> "Failed to parse item tag: " + ex.getMessage()); + } + } + -+ record HoverEventType(Function, Codec>> codec, String id, Function, Codec>> legacyCodec) implements StringRepresentable { -+ HoverEventType(final Function, Codec> contentCodec, final HoverEvent.Action action, final String id, final Function> legacyDeserializer) { -+ this(cc -> contentCodec.apply(cc).xmap(v -> HoverEvent.hoverEvent(action, v), HoverEvent::value).fieldOf("contents").codec(), ++ @FunctionalInterface ++ interface LegacyDeserializer { ++ DataResult apply(Component component, @Nullable RegistryOps ops, Codec componentCodec); ++ } ++ ++ record HoverEventType(Function, MapCodec>> codec, String id, Function, MapCodec>> legacyCodec) implements StringRepresentable { ++ HoverEventType(final Function, Codec> contentCodec, final HoverEvent.Action action, final String id, final LegacyDeserializer legacyDeserializer) { ++ this(cc -> contentCodec.apply(cc).xmap(v -> HoverEvent.hoverEvent(action, v), HoverEvent::value).fieldOf("contents"), + id, -+ codec -> Codec.of( -+ Encoder.error("Can't encode in legacy format"), -+ codec.flatMap(legacyDeserializer).map(text -> HoverEvent.hoverEvent(action, text)) -+ ) ++ codec -> (new Codec>() { ++ public DataResult, D>> decode(final DynamicOps dynamicOps, final D object) { ++ return codec.decode(dynamicOps, object).flatMap(pair -> { ++ final DataResult dataResult; ++ if (dynamicOps instanceof final RegistryOps registryOps) { ++ dataResult = legacyDeserializer.apply(pair.getFirst(), registryOps, codec); ++ } else { ++ dataResult = legacyDeserializer.apply(pair.getFirst(), null, codec); ++ } ++ ++ return dataResult.map(value -> Pair.of(HoverEvent.hoverEvent(action, value), pair.getSecond())); ++ }); ++ } ++ ++ public DataResult encode(final HoverEvent hoverEvent, final DynamicOps dynamicOps, final D object) { ++ return DataResult.error(() -> "Can't encode in legacy format"); ++ } ++ }).fieldOf("value") + ); + } + @Override @@ -203,23 +243,23 @@ index 0000000000000000000000000000000000000000..9090b0ebcd3ceecb14f83b274ad364d6 + throw new IllegalStateException(); + } + }; -+ static final Codec> HOVER_EVENT_CODEC = Codec.either( ++ static final Codec> HOVER_EVENT_CODEC = Codec.withAlternative( + HOVER_EVENT_TYPE_CODEC.>dispatchMap("action", GET_HOVER_EVENT_TYPE, het -> het.codec.apply(COMPONENT_CODEC)).codec(), + HOVER_EVENT_TYPE_CODEC.>dispatchMap("action", GET_HOVER_EVENT_TYPE, het -> het.legacyCodec.apply(COMPONENT_CODEC)).codec() -+ ).xmap(either -> either.map(identity(), identity()), Either::left); ++ ); + + public static final MapCodec