From a47c19cb7739981e643a78df03d8cb0916936573 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Thu, 7 Dec 2023 11:14:29 -0800 Subject: [PATCH] more adventure codec stuff and fix tests --- patches/server/Add-more-advancement-API.patch | 12 +- ...tial-work-on-native-Adventure-codecs.patch | 290 ++++++++++++------ 2 files changed, 195 insertions(+), 107 deletions(-) diff --git a/patches/server/Add-more-advancement-API.patch b/patches/server/Add-more-advancement-API.patch index 326b755aee..ac5a713b86 100644 --- a/patches/server/Add-more-advancement-API.patch +++ b/patches/server/Add-more-advancement-API.patch @@ -197,7 +197,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.format.TextColor; -+import net.minecraft.advancements.FrameType; ++import net.minecraft.advancements.AdvancementType; +import net.minecraft.network.chat.contents.TranslatableContents; +import org.junit.jupiter.api.Test; + @@ -207,13 +207,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Test + public void test() { -+ for (FrameType nmsFrameType : FrameType.values()) { -+ final TextColor expectedColor = PaperAdventure.asAdventure(nmsFrameType.getChatColor()); -+ final String expectedTranslationKey = ((TranslatableContents) nmsFrameType.getDisplayName().getContents()).getKey(); -+ final var frame = PaperAdvancementDisplay.asPaperFrame(nmsFrameType); ++ for (final AdvancementType advancementType : AdvancementType.values()) { ++ final TextColor expectedColor = PaperAdventure.asAdventure(advancementType.getChatColor()); ++ final String expectedTranslationKey = ((TranslatableContents) advancementType.getDisplayName().getContents()).getKey(); ++ final var frame = PaperAdvancementDisplay.asPaperFrame(advancementType); + assertEquals(expectedTranslationKey, frame.translationKey(), "The translation keys should be the same"); + assertEquals(expectedColor, frame.color(), "The frame colors should be the same"); -+ assertEquals(nmsFrameType.getName(), AdvancementDisplay.Frame.NAMES.key(frame)); ++ assertEquals(advancementType.name(), AdvancementDisplay.Frame.NAMES.key(frame)); + } + } +} diff --git a/patches/server/initial-work-on-native-Adventure-codecs.patch b/patches/server/initial-work-on-native-Adventure-codecs.patch index 46593136d8..075b168eae 100644 --- a/patches/server/initial-work-on-native-Adventure-codecs.patch +++ b/patches/server/initial-work-on-native-Adventure-codecs.patch @@ -17,21 +17,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.adventure; + ++import com.google.common.base.Suppliers; +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; ++import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.MapCodec; ++import com.mojang.serialization.MapLike; ++import com.mojang.serialization.RecordBuilder; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import java.io.IOException; +import java.util.Collections; +import java.util.List; ++import java.util.Locale; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; ++import java.util.function.Supplier; ++import java.util.stream.Stream; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.KeybindComponent; +import net.kyori.adventure.text.ScoreComponent; ++import net.kyori.adventure.text.SelectorComponent; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.event.ClickEvent; @@ -40,6 +48,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; ++import net.kyori.adventure.translation.GlobalTranslator; +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; @@ -56,14 +65,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.checkerframework.framework.qual.DefaultQualifier; +import org.intellij.lang.annotations.Subst; + -+import static java.util.Objects.requireNonNull; +import static net.kyori.adventure.text.Component.text; +import static net.minecraft.util.ExtraCodecs.strictOptionalField; + +@DefaultQualifier(NonNull.class) +public final class AdventureCodecs { + -+ public static final Codec COMPONENT_CODEC = ExtraCodecs.recursive("adventure Component", AdventureCodecs::createCodec); ++ private static final MapCodec COMPONENT_MAP_CODEC = new RecursiveMapCodec<>("adventure Component", c -> createCodec(c, false)); ++ public static final Codec COMPONENT_CODEC = indirectCodec(COMPONENT_MAP_CODEC.codec()); ++ private static final MapCodec RENDERING_COMPONENT_MAP_CODEC = new RecursiveMapCodec<>("rendering adventure Component", c -> createCodec(c, true)); ++ public static final Codec RENDERING_COMPONENT_CODEC = indirectCodec(RENDERING_COMPONENT_MAP_CODEC.codec()); + + private static final Codec TEXT_COLOR_CODEC = Codec.STRING.comapFlatMap(s -> { + if (s.startsWith("#")) { @@ -96,40 +107,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ).apply(instance, ClickEvent::clickEvent); + }); + -+ private static final Codec SHOW_ENTITY_CODEC = RecordCodecBuilder.create((instance) -> { -+ return instance.group( -+ KEY_CODEC.fieldOf("type").forGetter(HoverEvent.ShowEntity::type), -+ UUIDUtil.LENIENT_CODEC.fieldOf("id").forGetter(HoverEvent.ShowEntity::id), -+ strictOptionalField(COMPONENT_CODEC, "name").forGetter(he -> Optional.ofNullable(he.name())) -+ ).apply(instance, (key, uuid, component) -> { -+ return HoverEvent.ShowEntity.showEntity(key, uuid, component.orElse(null)); ++ private static Codec showEntityCodec(final Codec componentCodec) { ++ return RecordCodecBuilder.create((instance) -> { ++ 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())) ++ ).apply(instance, (key, uuid, component) -> { ++ return HoverEvent.ShowEntity.showEntity(key, uuid, component.orElse(null)); ++ }); + }); -+ }); ++ } + -+ private static final Codec SHOW_ITEM_CODEC = net.minecraft.network.chat.HoverEvent.ItemStackInfo.CODEC.xmap(isi -> { -+ @Subst("key") final String typeKey = BuiltInRegistries.ITEM.getKey(isi.item).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())); -+ final ItemStack stack; -+ try { -+ final @Nullable CompoundTag tag = si.nbt() != null ? si.nbt().get(PaperAdventure.NBT_CODEC) : null; -+ stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), si.count(), Optional.ofNullable(tag)); -+ } catch (IOException e) { -+ throw new RuntimeException(e); -+ } -+ return new net.minecraft.network.chat.HoverEvent.ItemStackInfo(stack); -+ }); ++ private 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(); ++ 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())); ++ final ItemStack stack; ++ try { ++ final @Nullable CompoundTag tag = si.nbt() != null ? si.nbt().get(PaperAdventure.NBT_CODEC) : null; ++ stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), si.count(), Optional.ofNullable(tag)); ++ } catch (IOException e) { ++ throw new RuntimeException(e); ++ } ++ return new net.minecraft.network.chat.HoverEvent.ItemStackInfo(stack); ++ }); ++ } + + // TODO legacies -+ private static final HoverEventType SHOW_ENTITY_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_ENTITY_CODEC, HoverEvent.Action.SHOW_ENTITY, "show_entity"); -+ private static final HoverEventType SHOW_ITEM_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_ITEM_CODEC, HoverEvent.Action.SHOW_ITEM, "show_item"); -+ private static final HoverEventType SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(COMPONENT_CODEC, HoverEvent.Action.SHOW_TEXT, "show_text"); ++ private static final HoverEventType SHOW_ENTITY_HOVER_EVENT_TYPE = new HoverEventType<>(AdventureCodecs::showEntityCodec, HoverEvent.Action.SHOW_ENTITY, "show_entity"); ++ private static final HoverEventType SHOW_ITEM_HOVER_EVENT_TYPE = new HoverEventType<>(AdventureCodecs::showItemCodec, HoverEvent.Action.SHOW_ITEM, "show_item"); ++ private static final HoverEventType SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(Function.identity(), HoverEvent.Action.SHOW_TEXT, "show_text"); + private 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 }); + -+ private record HoverEventType(Codec> codec, String id) implements StringRepresentable { -+ private HoverEventType(final Codec contentCodec, final HoverEvent.Action action, final String id) { -+ this(contentCodec.xmap(v -> { ++ private record HoverEventType(Function, Codec>> codec, String id) implements StringRepresentable { ++ private HoverEventType(final Function, Codec> contentCodec, final HoverEvent.Action action, final String id) { ++ this(cc -> contentCodec.apply(cc).xmap(v -> { + return HoverEvent.hoverEvent(action, v); + }, HoverEvent::value), id); + } @@ -139,30 +154,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private static final MapCodec> HOVER_EVENT_MAP_CODEC = HOVER_EVENT_TYPE_CODEC.dispatchMap("action", he -> { -+ if (he.action() == HoverEvent.Action.SHOW_ENTITY) { -+ return SHOW_ENTITY_HOVER_EVENT_TYPE; -+ } else if (he.action() == HoverEvent.Action.SHOW_ITEM) { -+ return SHOW_ITEM_HOVER_EVENT_TYPE; -+ } else if (he.action() == HoverEvent.Action.SHOW_TEXT) { -+ return SHOW_TEXT_HOVER_EVENT_TYPE; -+ } else { -+ throw new IllegalStateException(); -+ } -+ }, HoverEventType::codec); ++ private static MapCodec> hoverEventMapCodec(final Codec componentCodec) { ++ return HOVER_EVENT_TYPE_CODEC.dispatchMap("action", he -> { ++ if (he.action() == HoverEvent.Action.SHOW_ENTITY) { ++ return SHOW_ENTITY_HOVER_EVENT_TYPE; ++ } else if (he.action() == HoverEvent.Action.SHOW_ITEM) { ++ return SHOW_ITEM_HOVER_EVENT_TYPE; ++ } else if (he.action() == HoverEvent.Action.SHOW_TEXT) { ++ return SHOW_TEXT_HOVER_EVENT_TYPE; ++ } else { ++ throw new IllegalStateException(); ++ } ++ }, het -> het.codec.apply(componentCodec)); ++ } + -+ public static final MapCodec