Update to adventure 4.15 (#10045)
This commit is contained in:
@@ -39,6 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||
+import net.kyori.adventure.text.BlockNBTComponent;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.ComponentLike;
|
||||
+import net.kyori.adventure.text.EntityNBTComponent;
|
||||
+import net.kyori.adventure.text.KeybindComponent;
|
||||
+import net.kyori.adventure.text.NBTComponent;
|
||||
@@ -48,6 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import net.kyori.adventure.text.StorageNBTComponent;
|
||||
+import net.kyori.adventure.text.TextComponent;
|
||||
+import net.kyori.adventure.text.TranslatableComponent;
|
||||
+import net.kyori.adventure.text.TranslationArgument;
|
||||
+import net.kyori.adventure.text.event.ClickEvent;
|
||||
+import net.kyori.adventure.text.event.HoverEvent;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
@@ -76,6 +78,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import static com.mojang.serialization.codecs.RecordCodecBuilder.mapCodec;
|
||||
+import static java.util.function.Function.identity;
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+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;
|
||||
+
|
||||
@@ -246,16 +251,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ return instance.group(Codec.STRING.fieldOf("text").forGetter(TextComponent::content)).apply(instance, Component::text);
|
||||
+ });
|
||||
+ static final Codec<Object> PRIMITIVE_ARG_CODEC = ExtraCodecs.validate(ExtraCodecs.JAVA, TranslatableContents::filterAllowedArguments);
|
||||
+ static final Codec<Component> ARG_CODEC = Codec.either(PRIMITIVE_ARG_CODEC, COMPONENT_CODEC).xmap((primitiveOrComponent) -> {
|
||||
+ // just toString all primitives (not 100% correct to vanilla spec)
|
||||
+ // vanilla allows primitive translatable args, but adventure doesn't (in 4.14)
|
||||
+ return primitiveOrComponent.map(o -> text(String.valueOf(o)), identity());
|
||||
+ }, Either::right);
|
||||
+ static final Codec<TranslationArgument> ARG_CODEC = Codec.either(PRIMITIVE_ARG_CODEC, COMPONENT_CODEC).flatXmap((primitiveOrComponent) -> {
|
||||
+ return primitiveOrComponent.map(o -> {
|
||||
+ final TranslationArgument arg;
|
||||
+ if (o instanceof String s) {
|
||||
+ arg = component(text(s));
|
||||
+ } else if (o instanceof Boolean bool) {
|
||||
+ arg = bool(bool);
|
||||
+ } else if (o instanceof Number num) {
|
||||
+ arg = numeric(num);
|
||||
+ } else {
|
||||
+ return DataResult.error(() -> o + " is not a valid translation argument primitive");
|
||||
+ }
|
||||
+ return DataResult.success(arg);
|
||||
+ }, component -> DataResult.success(component(component)));
|
||||
+ }, translationArgument -> {
|
||||
+ if (translationArgument.value() instanceof Number || translationArgument.value() instanceof Boolean) {
|
||||
+ return DataResult.success(Either.left(translationArgument.value()));
|
||||
+ }
|
||||
+ final Component component = translationArgument.asComponent();
|
||||
+ final @Nullable String collapsed = tryCollapseToString(component);
|
||||
+ if (collapsed != null) {
|
||||
+ return DataResult.success(Either.left(collapsed)); // attempt to collapse all text components to strings
|
||||
+ }
|
||||
+ return DataResult.success(Either.right(component));
|
||||
+ });
|
||||
+ static final MapCodec<TranslatableComponent> TRANSLATABLE_COMPONENT_MAP_CODEC = mapCodec((instance) -> {
|
||||
+ return instance.group(
|
||||
+ Codec.STRING.fieldOf("translate").forGetter(TranslatableComponent::key),
|
||||
+ Codec.STRING.optionalFieldOf("fallback").forGetter(nullableGetter(TranslatableComponent::fallback)),
|
||||
+ strictOptionalField(ARG_CODEC.listOf(), "with").forGetter(c -> c.args().isEmpty() ? Optional.empty() : Optional.of(c.args()))
|
||||
+ strictOptionalField(ARG_CODEC.listOf(), "with").forGetter(c -> c.arguments().isEmpty() ? Optional.empty() : Optional.of(c.arguments()))
|
||||
+ ).apply(instance, (key, fallback, components) -> {
|
||||
+ return Component.translatable(key, components.orElse(Collections.emptyList())).fallback(fallback.orElse(null));
|
||||
+ });
|
||||
@@ -518,6 +543,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+
|
||||
+@SuppressWarnings("UnstableApiUsage")
|
||||
+public final class BossBarImplementationImpl implements BossBar.Listener, BossBarImplementation {
|
||||
+ private final BossBar bar;
|
||||
+ private ServerBossEvent vanilla;
|
||||
@@ -1239,6 +1265,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import java.util.function.BiConsumer;
|
||||
+import java.util.regex.Matcher;
|
||||
+import java.util.regex.Pattern;
|
||||
+import java.util.stream.StreamSupport;
|
||||
+import net.kyori.adventure.bossbar.BossBar;
|
||||
+import net.kyori.adventure.inventory.Book;
|
||||
+import net.kyori.adventure.key.Key;
|
||||
@@ -1246,6 +1273,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import net.kyori.adventure.sound.Sound;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.TranslatableComponent;
|
||||
+import net.kyori.adventure.text.TranslationArgument;
|
||||
+import net.kyori.adventure.text.flattener.ComponentFlattener;
|
||||
+import net.kyori.adventure.text.format.TextColor;
|
||||
+import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||
@@ -1298,7 +1326,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ final @NotNull String translated = Language.getInstance().getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key());
|
||||
+
|
||||
+ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated);
|
||||
+ final List<Component> args = translatable.args();
|
||||
+ final List<TranslationArgument> args = translatable.arguments();
|
||||
+ int argPosition = 0;
|
||||
+ int lastIdx = 0;
|
||||
+ while (matcher.find()) {
|
||||
@@ -1314,7 +1342,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ try {
|
||||
+ final int idx = Integer.parseInt(argIdx) - 1;
|
||||
+ if (idx < args.size()) {
|
||||
+ consumer.accept(args.get(idx));
|
||||
+ consumer.accept(args.get(idx).asComponent());
|
||||
+ }
|
||||
+ } catch (final NumberFormatException ex) {
|
||||
+ // ignore, drop the format placeholder
|
||||
@@ -1322,7 +1350,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ } else {
|
||||
+ final int idx = argPosition++;
|
||||
+ if (idx < args.size()) {
|
||||
+ consumer.accept(args.get(idx));
|
||||
+ consumer.accept(args.get(idx).asComponent());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
@@ -1375,7 +1403,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ return component == null ? Component.empty() : WRAPPER_AWARE_SERIALIZER.deserialize(component);
|
||||
+ }
|
||||
+
|
||||
+ public static ArrayList<Component> asAdventure(final List<net.minecraft.network.chat.Component> vanillas) {
|
||||
+ public static ArrayList<Component> asAdventure(final List<? extends net.minecraft.network.chat.Component> vanillas) {
|
||||
+ final ArrayList<Component> adventures = new ArrayList<>(vanillas.size());
|
||||
+ for (final net.minecraft.network.chat.Component vanilla : vanillas) {
|
||||
+ adventures.add(asAdventure(vanilla));
|
||||
@@ -1405,7 +1433,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ return WRAPPER_AWARE_SERIALIZER.serialize(component);
|
||||
+ }
|
||||
+
|
||||
+ public static List<net.minecraft.network.chat.Component> asVanilla(final List<Component> adventures) {
|
||||
+ public static List<net.minecraft.network.chat.Component> asVanilla(final List<? extends Component> adventures) {
|
||||
+ final List<net.minecraft.network.chat.Component> vanillas = new ArrayList<>(adventures.size());
|
||||
+ for (final Component adventure : adventures) {
|
||||
+ vanillas.add(asVanilla(adventure));
|
||||
@@ -1417,6 +1445,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ return GsonComponentSerializer.gson().serialize(translated(component, locale));
|
||||
+ }
|
||||
+
|
||||
+ public static boolean hasAnyTranslations() {
|
||||
+ return StreamSupport.stream(GlobalTranslator.translator().sources().spliterator(), false)
|
||||
+ .anyMatch(t -> t.hasAnyTranslations().toBooleanOrElse(true));
|
||||
+ }
|
||||
+
|
||||
+ private static final Map<Locale, com.mojang.serialization.Codec<Component>> LOCALIZED_CODECS = new ConcurrentHashMap<>();
|
||||
+
|
||||
+ public static com.mojang.serialization.Codec<Component> localizedCodec(final @Nullable Locale l) {
|
||||
@@ -1434,6 +1467,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+
|
||||
+ private static Component translated(final Component component, final Locale locale) {
|
||||
+ //noinspection ConstantValue
|
||||
+ return GlobalTranslator.render(
|
||||
+ component,
|
||||
+ // play it safe
|
||||
@@ -1452,7 +1486,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+ try {
|
||||
+ return asAdventure(ComponentUtils.updateForEntity(css, asVanilla(component), scoreboardSubject == null ? null : ((CraftEntity) scoreboardSubject).getHandle(), 0));
|
||||
+ } catch (CommandSyntaxException e) {
|
||||
+ } catch (final CommandSyntaxException e) {
|
||||
+ throw new IOException(e);
|
||||
+ } finally {
|
||||
+ if (css != null && previous != null) {
|
||||
@@ -1534,10 +1568,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+
|
||||
+ private static String validateField(final String content, final int length, final String name) {
|
||||
+ if (content == null) {
|
||||
+ return content;
|
||||
+ }
|
||||
+
|
||||
+ final int actual = content.length();
|
||||
+ if (actual > length) {
|
||||
+ throw new IllegalArgumentException("Field '" + name + "' has a maximum length of " + length + " but was passed '" + content + "', which was " + actual + " characters long.");
|
||||
@@ -1805,6 +1835,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import org.jetbrains.annotations.NotNull;
|
||||
+import org.slf4j.LoggerFactory;
|
||||
+
|
||||
+@SuppressWarnings("UnstableApiUsage")
|
||||
+public class ComponentLoggerProviderImpl implements ComponentLoggerProvider {
|
||||
+ @Override
|
||||
+ public @NotNull ComponentLogger logger(@NotNull LoggerHelper helper, @NotNull String name) {
|
||||
@@ -1928,19 +1959,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+package io.papermc.paper.adventure.providers;
|
||||
+
|
||||
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
+import java.io.IOException;
|
||||
+import java.util.UUID;
|
||||
+import net.kyori.adventure.key.Key;
|
||||
+import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.event.HoverEvent;
|
||||
+import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer;
|
||||
+import net.kyori.adventure.text.serializer.json.LegacyHoverEventSerializer;
|
||||
+import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
+import net.kyori.adventure.util.Codec;
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.nbt.Tag;
|
||||
+import net.minecraft.nbt.TagParser;
|
||||
+
|
||||
+import java.io.IOException;
|
||||
+import java.util.UUID;
|
||||
+import org.intellij.lang.annotations.Subst;
|
||||
+
|
||||
+final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer {
|
||||
+ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer();
|
||||
@@ -1963,8 +1994,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ try {
|
||||
+ final CompoundTag contents = SNBT_CODEC.decode(raw);
|
||||
+ final CompoundTag tag = contents.getCompound(ITEM_TAG);
|
||||
+ return HoverEvent.ShowItem.of(
|
||||
+ Key.key(contents.getString(ITEM_TYPE)),
|
||||
+ @Subst("key") final String keyString = contents.getString(ITEM_TYPE);
|
||||
+ return HoverEvent.ShowItem.showItem(
|
||||
+ Key.key(keyString),
|
||||
+ contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1,
|
||||
+ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC)
|
||||
+ );
|
||||
@@ -1978,8 +2010,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ final String raw = PlainTextComponentSerializer.plainText().serialize(input);
|
||||
+ try {
|
||||
+ final CompoundTag contents = SNBT_CODEC.decode(raw);
|
||||
+ return HoverEvent.ShowEntity.of(
|
||||
+ Key.key(contents.getString(ENTITY_TYPE)),
|
||||
+ @Subst("key") final String keyString = contents.getString(ENTITY_TYPE);
|
||||
+ return HoverEvent.ShowEntity.showEntity(
|
||||
+ Key.key(keyString),
|
||||
+ UUID.fromString(contents.getString(ENTITY_ID)),
|
||||
+ componentCodec.decode(contents.getString(ENTITY_NAME))
|
||||
+ );
|
||||
@@ -2004,7 +2037,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder<Component, String, ? extends RuntimeException> componentCodec) throws IOException {
|
||||
+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder<Component, String, ? extends RuntimeException> componentCodec) {
|
||||
+ final CompoundTag tag = new CompoundTag();
|
||||
+ tag.putString(ENTITY_ID, input.id().toString());
|
||||
+ tag.putString(ENTITY_TYPE, input.type().asString());
|
||||
@@ -2290,7 +2323,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ final net.kyori.adventure.text.Component adventureComponent;
|
||||
+ if (input instanceof io.papermc.paper.adventure.AdventureComponent adv) {
|
||||
+ adventureComponent = adv.adventure$component();
|
||||
+ } else if (locale != null && input.getContents() instanceof TranslatableContents) {
|
||||
+ } else if (locale != null && input.getContents() instanceof TranslatableContents && io.papermc.paper.adventure.PaperAdventure.hasAnyTranslations()) {
|
||||
+ adventureComponent = io.papermc.paper.adventure.PaperAdventure.asAdventure(input);
|
||||
+ } else {
|
||||
+ return origCodec.encode(input, ops, prefix);
|
||||
@@ -2768,6 +2801,31 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
private long keepAliveTime;
|
||||
private boolean keepAlivePending;
|
||||
private long keepAliveChallenge;
|
||||
private int latency;
|
||||
private volatile boolean suspendFlushingOnServerThread = false;
|
||||
+ public final java.util.Map<java.util.UUID, net.kyori.adventure.resource.ResourcePackCallback> packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks
|
||||
|
||||
public ServerCommonPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { // CraftBukkit
|
||||
this.server = minecraftserver;
|
||||
@@ -0,0 +0,0 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
ServerCommonPacketListenerImpl.LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), packet.id());
|
||||
this.disconnect(Component.translatable("multiplayer.requiredTexturePrompt.disconnect"));
|
||||
}
|
||||
+ // Paper start - adventure pack callbacks
|
||||
+ // call the callbacks before the previously-existing event so the event has final say
|
||||
+ final net.kyori.adventure.resource.ResourcePackCallback callback;
|
||||
+ if (packet.action().isTerminal()) {
|
||||
+ callback = this.packCallbacks.remove(packet.id());
|
||||
+ } else {
|
||||
+ callback = this.packCallbacks.get(packet.id());
|
||||
+ }
|
||||
+ if (callback != null) {
|
||||
+ callback.packEventReceived(packet.id(), net.kyori.adventure.resource.ResourcePackStatus.valueOf(packet.action().name()), this.getCraftPlayer());
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), packet.id(), PlayerResourcePackStatusEvent.Status.values()[packet.action().ordinal()])); // CraftBukkit
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
|
||||
// CraftBukkit start
|
||||
@@ -4230,6 +4288,42 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ this.getHandle().connection.send(new ClientboundResourcePackPopPacket(Optional.empty()));
|
||||
+ this.getHandle().connection.send(new ClientboundResourcePackPushPacket(uuid, url, hash, force, io.papermc.paper.adventure.PaperAdventure.asVanilla(prompt)));
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings({"unchecked", "rawtypes"})
|
||||
+ void sendBundle(final List<? extends net.minecraft.network.protocol.Packet<? extends net.minecraft.network.protocol.common.ClientCommonPacketListener>> packet) {
|
||||
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundBundlePacket((List) packet));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendResourcePacks(final net.kyori.adventure.resource.ResourcePackRequest request) {
|
||||
+ if (this.getHandle().connection == null) return;
|
||||
+ final List<ClientboundResourcePackPushPacket> packs = new java.util.ArrayList<>(request.packs().size());
|
||||
+ if (request.replace()) {
|
||||
+ this.clearResourcePacks();
|
||||
+ }
|
||||
+ final Component prompt = io.papermc.paper.adventure.PaperAdventure.asVanilla(request.prompt());
|
||||
+ for (final java.util.Iterator<net.kyori.adventure.resource.ResourcePackInfo> iter = request.packs().iterator(); iter.hasNext();) {
|
||||
+ final net.kyori.adventure.resource.ResourcePackInfo pack = iter.next();
|
||||
+ packs.add(new ClientboundResourcePackPushPacket(pack.id(), pack.uri().toASCIIString(), pack.hash(), request.required(), iter.hasNext() ? null : prompt));
|
||||
+ if (request.callback() != net.kyori.adventure.resource.ResourcePackCallback.noOp()) {
|
||||
+ this.getHandle().connection.packCallbacks.put(pack.id(), request.callback()); // just override if there is a previously existing callback
|
||||
+ }
|
||||
+ }
|
||||
+ this.sendBundle(packs);
|
||||
+ super.sendResourcePacks(request);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void removeResourcePacks(final UUID id, final UUID ... others) {
|
||||
+ if (this.getHandle().connection == null) return;
|
||||
+ this.sendBundle(net.kyori.adventure.util.MonkeyBars.nonEmptyArrayToList(pack -> new ClientboundResourcePackPopPacket(Optional.of(pack)), id, others));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void clearResourcePacks() {
|
||||
+ if (this.getHandle().connection == null) return;
|
||||
+ this.getHandle().connection.send(new ClientboundResourcePackPopPacket(Optional.empty()));
|
||||
+ }
|
||||
+ // Paper end - adventure
|
||||
+
|
||||
@Override
|
||||
@@ -5526,6 +5620,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+import static net.kyori.adventure.text.Component.storageNBT;
|
||||
+import static net.kyori.adventure.text.Component.text;
|
||||
+import static net.kyori.adventure.text.Component.translatable;
|
||||
+import static net.kyori.adventure.text.TranslationArgument.bool;
|
||||
+import static net.kyori.adventure.text.TranslationArgument.numeric;
|
||||
+import static net.kyori.adventure.text.event.ClickEvent.openUrl;
|
||||
+import static net.kyori.adventure.text.event.ClickEvent.suggestCommand;
|
||||
+import static net.kyori.adventure.text.event.HoverEvent.showEntity;
|
||||
@@ -5773,6 +5869,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||
+ .key("thisIsA")
|
||||
+ .fallback("This is a test.")
|
||||
+ .build(),
|
||||
+ translatable(key, numeric(5), text("HEY")), // boolean doesn't work in vanilla, can't test here
|
||||
+ translatable(
|
||||
+ key,
|
||||
+ text().content(name)
|
||||
|
||||
Reference in New Issue
Block a user