From 9a73213f888b0dd9e4d3777068095747c6cd563d Mon Sep 17 00:00:00 2001 From: Riley Park Date: Mon, 28 Feb 2022 13:38:23 -0800 Subject: [PATCH] Adventure 4.10.0 --- patches/api/0008-Adventure.patch | 13 +- .../0026-Use-ASM-for-event-executors.patch | 4 +- ...low-plugins-to-use-SLF4J-for-logging.patch | 4 +- patches/server/0012-Adventure.patch | 213 +++++++----------- ...nilla-per-world-scoreboard-coloring-.patch | 8 +- 5 files changed, 94 insertions(+), 148 deletions(-) diff --git a/patches/api/0008-Adventure.patch b/patches/api/0008-Adventure.patch index f8d018e17..5ddee589d 100644 --- a/patches/api/0008-Adventure.patch +++ b/patches/api/0008-Adventure.patch @@ -7,14 +7,14 @@ Co-authored-by: zml Co-authored-by: Jake Potrebic diff --git a/build.gradle.kts b/build.gradle.kts -index 55ee0c6330e4dbba22b4044346d1e1dd39c745ce..80fdd05dd593455ca89b66636ed30f1d9facf4ed 100644 +index 55ee0c6330e4dbba22b4044346d1e1dd39c745ce..19b65a9b56b73f873ef646d14a6cf091b69d3873 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,6 +8,19 @@ java { withJavadocJar() } -+val adventureVersion = "4.9.3" ++val adventureVersion = "4.10.0" +val apiAndDocs: Configuration by configurations.creating { + attributes { + attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION)) @@ -30,19 +30,20 @@ index 55ee0c6330e4dbba22b4044346d1e1dd39c745ce..80fdd05dd593455ca89b66636ed30f1d dependencies { // api dependencies are listed transitively to API consumers api("commons-lang:commons-lang:2.6") -@@ -20,6 +33,11 @@ dependencies { +@@ -20,6 +33,12 @@ dependencies { isTransitive = false // includes junit } api("it.unimi.dsi:fastutil:8.5.6") + apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion")) + apiAndDocs("net.kyori:adventure-api") ++ apiAndDocs("net.kyori:adventure-text-minimessage") + apiAndDocs("net.kyori:adventure-text-serializer-gson") + apiAndDocs("net.kyori:adventure-text-serializer-legacy") + apiAndDocs("net.kyori:adventure-text-serializer-plain") // Paper end compileOnly("org.apache.maven:maven-resolver-provider:3.8.4") -@@ -70,10 +88,25 @@ tasks.jar { +@@ -70,10 +89,25 @@ tasks.jar { } tasks.withType { @@ -1126,7 +1127,7 @@ index ac5e263d737973af077e3406a84a84baca4370db..2d91924b7f5ef16a91d40cdc1bfc3d68 + // Paper end } diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 93345eaf4bd987490d32f9e60ab54140dbeda5c4..e9306f581b733b717efa932408cf9d74da4d911d 100644 +index 93345eaf4bd987490d32f9e60ab54140dbeda5c4..ac2d2a5c0a631fda62819714c572217e0f219735 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -21,6 +21,14 @@ import org.bukkit.plugin.PluginDescriptionFile; @@ -1135,7 +1136,7 @@ index 93345eaf4bd987490d32f9e60ab54140dbeda5c4..e9306f581b733b717efa932408cf9d74 public interface UnsafeValues { + // Paper start + net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener(); -+ net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer(); ++ @Deprecated net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer(); + net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer plainTextSerializer(); + net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer(); + net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer(); diff --git a/patches/api/0026-Use-ASM-for-event-executors.patch b/patches/api/0026-Use-ASM-for-event-executors.patch index d9b5f4b49..4851ec487 100644 --- a/patches/api/0026-Use-ASM-for-event-executors.patch +++ b/patches/api/0026-Use-ASM-for-event-executors.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/build.gradle.kts b/build.gradle.kts -index 80fdd05dd593455ca89b66636ed30f1d9facf4ed..d8d459561cc75935136f8f9888ff27b45ad98f9e 100644 +index 19b65a9b56b73f873ef646d14a6cf091b69d3873..bc6f68a0cadeec865401e9cb0dce89460484b148 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -38,6 +38,9 @@ dependencies { +@@ -39,6 +39,9 @@ dependencies { apiAndDocs("net.kyori:adventure-text-serializer-gson") apiAndDocs("net.kyori:adventure-text-serializer-legacy") apiAndDocs("net.kyori:adventure-text-serializer-plain") diff --git a/patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch index e3b4c8b6f..4f28c5222 100644 --- a/patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -14,10 +14,10 @@ it without having to shade it in the plugin and going through several layers of logging abstraction. diff --git a/build.gradle.kts b/build.gradle.kts -index d8d459561cc75935136f8f9888ff27b45ad98f9e..001c2b963205012f340db0d539e4033c748124ce 100644 +index bc6f68a0cadeec865401e9cb0dce89460484b148..d6c4abc30af2b535644707a240b60d1b613785e9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -38,6 +38,8 @@ dependencies { +@@ -39,6 +39,8 @@ dependencies { apiAndDocs("net.kyori:adventure-text-serializer-gson") apiAndDocs("net.kyori:adventure-text-serializer-legacy") apiAndDocs("net.kyori:adventure-text-serializer-plain") diff --git a/patches/server/0012-Adventure.patch b/patches/server/0012-Adventure.patch index 66087b2ec..7258c7ab8 100644 --- a/patches/server/0012-Adventure.patch +++ b/patches/server/0012-Adventure.patch @@ -114,10 +114,10 @@ index 0000000000000000000000000000000000000000..85546e1ac1d1ed7f70c3c0a1bf49937f +} diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java new file mode 100644 -index 0000000000000000000000000000000000000000..0bc2c2ef9312ebcc32dacdd2ba9f17d2ba072586 +index 0000000000000000000000000000000000000000..65b6e260464b2003d6bd172610adb5b8651df169 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +1,228 @@ +@@ -0,0 +1,192 @@ +package io.papermc.paper.adventure; + +import io.papermc.paper.chat.ChatRenderer; @@ -127,9 +127,7 @@ index 0000000000000000000000000000000000000000..0bc2c2ef9312ebcc32dacdd2ba9f17d2 +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ExecutionException; -+import java.util.function.Consumer; +import java.util.regex.Pattern; -+ +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.text.Component; @@ -137,7 +135,6 @@ index 0000000000000000000000000000000000000000..0bc2c2ef9312ebcc32dacdd2ba9f17d2 +import net.kyori.adventure.text.event.ClickEvent; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; -+import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.util.LazyPlayerSet; +import org.bukkit.craftbukkit.util.Waitable; @@ -177,104 +174,70 @@ index 0000000000000000000000000000000000000000..0bc2c2ef9312ebcc32dacdd2ba9f17d2 + this.originalMessage = Component.text(message); + } + -+ @SuppressWarnings({"CodeBlock2Expr", "deprecated"}) ++ @SuppressWarnings("deprecated") + public void process() { -+ this.processingLegacyFirst( -+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent) -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ this.viewersFromLegacy(event.getRecipients()), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent -+ event -> { -+ this.processModern( -+ legacyRenderer(event.getFormat()), -+ this.viewersFromLegacy(event.getRecipients()), -+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()), -+ event.isCancelled() -+ ); -+ }, -+ // no legacy events called, all nice and fresh! -+ () -> { -+ this.processModern( -+ ChatRenderer.defaultRenderer(), -+ new LazyChatAudienceSet(this.server), -+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), -+ false -+ ); -+ } -+ ); -+ } -+ -+ private Set viewersFromLegacy(final Set recipients) { -+ if (recipients instanceof LazyPlayerSet lazyPlayerSet && lazyPlayerSet.isLazy()) { -+ return new LazyChatAudienceSet(this.server); -+ } -+ final HashSet viewers = new HashSet<>(recipients); -+ viewers.add(this.server.console); -+ return viewers; -+ } -+ -+ @SuppressWarnings("deprecation") -+ private void processingLegacyFirst( -+ final Consumer continueAfterAsync, -+ final Consumer continueAfterAsyncAndSync, -+ final Runnable modernOnly -+ ) { -+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList()); -+ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList()); ++ final boolean listenersOnAsyncEvent = canYouHearMe(AsyncPlayerChatEvent.getHandlerList()); ++ final boolean listenersOnSyncEvent = canYouHearMe(PlayerChatEvent.getHandlerList()); + if (listenersOnAsyncEvent || listenersOnSyncEvent) { + final CraftPlayer player = this.player.getBukkitEntity(); + final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server)); -+ post(ae); ++ this.post(ae); + if (listenersOnSyncEvent) { + final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); + se.setCancelled(ae.isCancelled()); // propagate cancelled state + this.queueIfAsyncOrRunImmediately(new Waitable() { + @Override + protected Void evaluate() { -+ post(se); ++ ChatProcessor.this.post(se); + return null; + } + }); -+ continueAfterAsyncAndSync.accept(se); ++ this.processModern( ++ legacyRenderer(se.getFormat()), ++ this.viewersFromLegacy(se.getRecipients()), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(se.getMessage()), ++ se.isCancelled() ++ ); + } else { -+ continueAfterAsync.accept(ae); ++ this.processModern( ++ legacyRenderer(ae.getFormat()), ++ this.viewersFromLegacy(ae.getRecipients()), ++ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(ae.getMessage()), ++ ae.isCancelled() ++ ); + } + } else { -+ modernOnly.run(); ++ this.processModern( ++ ChatRenderer.defaultRenderer(), ++ new LazyChatAudienceSet(this.server), ++ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), ++ false ++ ); + } + } + + private void processModern(final ChatRenderer renderer, final Set viewers, final Component message, final boolean cancelled) { -+ final AsyncChatEvent ae = this.createAsync(renderer, viewers, message); ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final AsyncChatEvent ae = new AsyncChatEvent(this.async, player, viewers, renderer, message, this.originalMessage); + ae.setCancelled(cancelled); // propagate cancelled state -+ post(ae); -+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList()); ++ this.post(ae); ++ final boolean listenersOnSyncEvent = canYouHearMe(ChatEvent.getHandlerList()); + if (listenersOnSyncEvent) { -+ this.continueWithSyncFromWhereAsyncLeftOff(ae); ++ this.queueIfAsyncOrRunImmediately(new Waitable() { ++ @Override ++ protected Void evaluate() { ++ final ChatEvent se = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.originalMessage); ++ se.setCancelled(ae.isCancelled()); // propagate cancelled state ++ ChatProcessor.this.post(se); ++ ChatProcessor.this.complete(se); ++ return null; ++ } ++ }); + } else { + this.complete(ae); + } + } + -+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) { -+ this.queueIfAsyncOrRunImmediately(new Waitable() { -+ @Override -+ protected Void evaluate() { -+ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.viewers(), ae.message()); -+ se.setCancelled(ae.isCancelled()); // propagate cancelled state -+ post(se); -+ ChatProcessor.this.complete(se); -+ return null; -+ } -+ }); -+ } -+ + private void complete(final AbstractChatEvent event) { + if (event.isCancelled()) { + return; @@ -300,12 +263,13 @@ index 0000000000000000000000000000000000000000..0bc2c2ef9312ebcc32dacdd2ba9f17d2 + } + } + -+ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set viewers, final Component message) { -+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), viewers, renderer, message, this.originalMessage); -+ } -+ -+ private ChatEvent createSync(final ChatRenderer renderer, final Set viewers, final Component message) { -+ return new ChatEvent(this.player.getBukkitEntity(), viewers, renderer, message, this.originalMessage); ++ private Set viewersFromLegacy(final Set recipients) { ++ if (recipients instanceof LazyPlayerSet lazyPlayerSet && lazyPlayerSet.isLazy()) { ++ return new LazyChatAudienceSet(this.server); ++ } ++ final HashSet viewers = new HashSet<>(recipients); ++ viewers.add(this.server.console); ++ return viewers; + } + + private static String legacyDisplayName(final CraftPlayer player) { @@ -338,20 +302,20 @@ index 0000000000000000000000000000000000000000..0bc2c2ef9312ebcc32dacdd2ba9f17d2 + } + } + -+ private static void post(final Event event) { -+ Bukkit.getPluginManager().callEvent(event); ++ private void post(final Event event) { ++ this.server.server.getPluginManager().callEvent(event); + } + -+ private static boolean anyListeners(final HandlerList handlers) { ++ private static boolean canYouHearMe(final HandlerList handlers) { + return handlers.getRegisteredListeners().length > 0; + } +} diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java new file mode 100644 -index 0000000000000000000000000000000000000000..bfaf5d3c5aae8a587c2b11d90089c588b2a2aba0 +index 0000000000000000000000000000000000000000..fb23f5b733093384fefc331cd3bef7cf16f09293 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java -@@ -0,0 +1,22 @@ +@@ -0,0 +1,23 @@ +package io.papermc.paper.adventure; + +import net.minecraft.server.level.ServerPlayer; @@ -369,6 +333,7 @@ index 0000000000000000000000000000000000000000..bfaf5d3c5aae8a587c2b11d90089c588 + public static String getLegacy(final ServerPlayer player) { + final String legacy = player.displayName; + if (legacy != null) { ++ // thank you for being worse than wet socks, Bukkit + return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName); + } + return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName); @@ -502,10 +467,10 @@ index 0000000000000000000000000000000000000000..eeedc30a45d9637d68f04f185b3dd90d +} diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java new file mode 100644 -index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9fc7884140 +index 0000000000000000000000000000000000000000..85c9056f92711b985e251f0f06ed551d03deb562 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -0,0 +1,361 @@ +@@ -0,0 +1,341 @@ +package io.papermc.paper.adventure; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -554,7 +519,7 @@ index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9f + public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() + .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { + if (!Language.getInstance().has(translatable.key())) { -+ for (final Translator source : GlobalTranslator.get().sources()) { ++ for (final Translator source : GlobalTranslator.translator().sources()) { + if (source instanceof TranslationRegistry registry && registry.contains(translatable.key())) { + consumer.accept(GlobalTranslator.render(translatable, Locale.US)); + return; @@ -600,6 +565,7 @@ index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9f + }) + .build(); + public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build(); ++ @Deprecated + public static final PlainComponentSerializer PLAIN_COMPONENT = PlainComponentSerializer.builder().flattener(FLATTENER).build(); + public static final PlainTextComponentSerializer PLAIN = PlainTextComponentSerializer.builder().flattener(FLATTENER).build(); + public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder() @@ -639,7 +605,7 @@ index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9f + if (key == null) { + return null; + } -+ return new ResourceLocation(key.namespace(), key.value()); ++ return asVanilla(key); + } + + // Component @@ -687,15 +653,7 @@ index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9f + } + + public static String asJsonString(final Component component, final Locale locale) { -+ return GSON.serialize( -+ GlobalTranslator.render( -+ component, -+ // play it safe -+ locale != null -+ ? locale -+ : Locale.US -+ ) -+ ); ++ return GSON.serialize(translated(component, locale)); + } + + public static String asJsonString(final net.minecraft.network.chat.Component component, final Locale locale) { @@ -706,20 +664,17 @@ index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9f + } + + public static String asPlain(final Component component, final Locale locale) { -+ return PLAIN.serialize( -+ GlobalTranslator.render( -+ component, -+ // play it safe -+ locale != null -+ ? locale -+ : Locale.US -+ ) -+ ); ++ return PLAIN.serialize(translated(component, locale)); + } + -+ // thank you for being worse than wet socks, Bukkit -+ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) { -+ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string); ++ private static Component translated(final Component component, final Locale locale) { ++ return GlobalTranslator.render( ++ component, ++ // play it safe ++ locale != null ++ ? locale ++ : Locale.US ++ ); + } + + // BossBar @@ -809,28 +764,18 @@ index 0000000000000000000000000000000000000000..3661ac5e3bfdebb2911cb1b118942b9f + // Sounds + + public static SoundSource asVanilla(final Sound.Source source) { -+ if (source == Sound.Source.MASTER) { -+ return SoundSource.MASTER; -+ } else if (source == Sound.Source.MUSIC) { -+ return SoundSource.MUSIC; -+ } else if (source == Sound.Source.RECORD) { -+ return SoundSource.RECORDS; -+ } else if (source == Sound.Source.WEATHER) { -+ return SoundSource.WEATHER; -+ } else if (source == Sound.Source.BLOCK) { -+ return SoundSource.BLOCKS; -+ } else if (source == Sound.Source.HOSTILE) { -+ return SoundSource.HOSTILE; -+ } else if (source == Sound.Source.NEUTRAL) { -+ return SoundSource.NEUTRAL; -+ } else if (source == Sound.Source.PLAYER) { -+ return SoundSource.PLAYERS; -+ } else if (source == Sound.Source.AMBIENT) { -+ return SoundSource.AMBIENT; -+ } else if (source == Sound.Source.VOICE) { -+ return SoundSource.VOICE; -+ } -+ throw new IllegalArgumentException(source.name()); ++ return switch (source) { ++ case MASTER -> SoundSource.MASTER; ++ case MUSIC -> SoundSource.MUSIC; ++ case RECORD -> SoundSource.RECORDS; ++ case WEATHER -> SoundSource.WEATHER; ++ case BLOCK -> SoundSource.BLOCKS; ++ case HOSTILE -> SoundSource.HOSTILE; ++ case NEUTRAL -> SoundSource.NEUTRAL; ++ case PLAYER -> SoundSource.PLAYERS; ++ case AMBIENT -> SoundSource.AMBIENT; ++ case VOICE -> SoundSource.VOICE; ++ }; + } + + public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) { diff --git a/patches/server/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch index cb89ae739..f38c57fac 100644 --- a/patches/server/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ b/patches/server/0083-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -26,19 +26,19 @@ index c008f1f7f0a1e1b8bf34f2702cb44c5f9d62f848..97693c33ba5a7efe40f05e0494216ee1 + } } diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index 0bc2c2ef9312ebcc32dacdd2ba9f17d2ba072586..9507ba43cacc31c02423a4f576feda32291101e7 100644 +index 65b6e260464b2003d6bd172610adb5b8651df169..55276e9679dcdc38c6716533e9218f81fc146592 100644 --- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -18,6 +18,8 @@ import net.kyori.adventure.text.event.ClickEvent; +@@ -15,6 +15,8 @@ import net.kyori.adventure.text.TextReplacementConfig; + import net.kyori.adventure.text.event.ClickEvent; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; - import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.util.LazyPlayerSet; import org.bukkit.craftbukkit.util.Waitable; -@@ -189,10 +191,16 @@ public final class ChatProcessor { +@@ -153,10 +155,16 @@ public final class ChatProcessor { } private static String legacyDisplayName(final CraftPlayer player) {