New chat events for better Adventure support (#5289)

Bump Adventure to 4.6.0

fixes #5216
fixes #5261
fixes #5287
This commit is contained in:
Riley Park 2021-03-01 19:07:12 -08:00 committed by GitHub
parent 06900aef5e
commit 9907cedecb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
140 changed files with 588 additions and 253 deletions

View File

@ -7,7 +7,7 @@ Co-authored-by: zml <zml@stellardrift.ca>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/pom.xml b/pom.xml
index 58fc279186e01a4703102227f387e96272fcf0a7..efcd00a8f25a9e82512b090f54a337fed734dfb5 100644
index 58fc279186e01a4703102227f387e96272fcf0a7..6397486ac7027a679d70d388066e4dac55936f5c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,7 +48,39 @@
@ -20,7 +20,7 @@ index 58fc279186e01a4703102227f387e96272fcf0a7..efcd00a8f25a9e82512b090f54a337fe
+ <dependency>
+ <groupId>net.kyori</groupId>
+ <artifactId>adventure-bom</artifactId>
+ <version>4.5.1</version> <!-- keep this version in synch with javadoc section below! -->
+ <version>4.6.0</version> <!-- keep this version in synch with javadoc section below! -->
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
@ -55,10 +55,10 @@ index 58fc279186e01a4703102227f387e96272fcf0a7..efcd00a8f25a9e82512b090f54a337fe
<link>https://javadoc.io/doc/org.jetbrains/annotations-java5/20.1.0/</link>
<link>https://javadoc.io/doc/net.md-5/bungeecord-chat/1.16-R0.4/</link>
+ <!-- Paper start -->
+ <link>https://jd.adventure.kyori.net/api/4.5.1/</link>
+ <link>https://jd.adventure.kyori.net/text-serializer-gson/4.5.1/</link>
+ <link>https://jd.adventure.kyori.net/text-serializer-legacy/4.5.1/</link>
+ <link>https://jd.adventure.kyori.net/text-serializer-plain/4.5.1/</link>
+ <link>https://jd.adventure.kyori.net/api/4.6.0/</link>
+ <link>https://jd.adventure.kyori.net/text-serializer-gson/4.6.0/</link>
+ <link>https://jd.adventure.kyori.net/text-serializer-legacy/4.6.0/</link>
+ <link>https://jd.adventure.kyori.net/text-serializer-plain/4.6.0/</link>
+ <!-- Paper end -->
</links>
</configuration>
@ -94,6 +94,214 @@ index ef58a6c00f444bd498a2d8fc4e457236f393954f..ecd149157d4fb80444f34bf5633d74bc
+ }
+ // Paper end
}
diff --git a/src/main/java/io/papermc/paper/chat/ChatFormatter.java b/src/main/java/io/papermc/paper/chat/ChatFormatter.java
new file mode 100644
index 0000000000000000000000000000000000000000..9873a97d472e000d2d996fc2b6a46db25cdd397b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/chat/ChatFormatter.java
@@ -0,0 +1,24 @@
+package io.papermc.paper.chat;
+
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A chat formatter is responsible for the formatting of chat messages sent by {@link Player}s to the server.
+ */
+@FunctionalInterface
+public interface ChatFormatter {
+ // This format might be different than the CraftBukkit one?
+ ChatFormatter DEFAULT = (displayName, message) -> Component.translatable("chat.type.text", displayName, message);
+
+ /**
+ * Formats a chat message.
+ *
+ * @param displayName the display name of the {@link Player} sending the message
+ * @param message the chat message
+ * @return a formatted chat message
+ */
+ @NotNull
+ Component chat(final @NotNull Component displayName, final @NotNull Component message);
+}
diff --git a/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cac60a004a71963221dc4e5fc595eeba3055be7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/AbstractChatEvent.java
@@ -0,0 +1,95 @@
+package io.papermc.paper.event.player;
+
+import io.papermc.paper.chat.ChatFormatter;
+import java.util.Objects;
+import java.util.Set;
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * An abstract implementation of a chat event, handling shared logic.
+ */
+public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable {
+ private final Set<Player> recipients;
+ private boolean cancelled = false;
+ private ChatFormatter formatter;
+ private Component message;
+
+ AbstractChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set<Player> recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) {
+ super(player, async);
+ this.recipients = recipients;
+ this.formatter = formatter;
+ this.message = message;
+ }
+
+ /**
+ * Gets a set of recipients that this chat message will be displayed to.
+ *
+ * <p>The set returned is not guaranteed to be mutable and may auto-populate
+ * on access. Any listener accessing the returned set should be aware that
+ * it may reduce performance for a lazy set implementation.</p>
+ *
+ * <p>Listeners should be aware that modifying the list may throw {@link
+ * UnsupportedOperationException} if the event caller provides an
+ * unmodifiable set.</p>
+ *
+ * @return a set of players who will receive the chat message
+ */
+ @NotNull
+ public final Set<Player> recipients() {
+ return this.recipients;
+ }
+
+ /**
+ * Gets the chat formatter.
+ *
+ * @return the chat formatter
+ */
+ @NotNull
+ public final ChatFormatter formatter() {
+ return this.formatter;
+ }
+
+ /**
+ * Sets the chat formatter.
+ *
+ * @param formatter the chat formatter
+ * @throws NullPointerException if {@code formatter} is {@code null}
+ */
+ public final void formatter(final @NotNull ChatFormatter formatter) {
+ this.formatter = Objects.requireNonNull(formatter, "formatter");
+ }
+
+ /**
+ * Gets the user-supplied message.
+ *
+ * @return the user-supplied message
+ */
+ @NotNull
+ public final Component message() {
+ return this.message;
+ }
+
+ /**
+ * Sets the user-supplied message.
+ *
+ * @param message the user-supplied message
+ * @throws NullPointerException if {@code message} is {@code null}
+ */
+ public final void message(final @NotNull Component message) {
+ this.message = Objects.requireNonNull(message, "message");
+ }
+
+ @Override
+ public final boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public final void setCancelled(final boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..baaa0451fec6b2d9a601f355984adce6c74d11f6
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/AsyncChatEvent.java
@@ -0,0 +1,30 @@
+package io.papermc.paper.event.player;
+
+import io.papermc.paper.chat.ChatFormatter;
+import java.util.Set;
+import net.kyori.adventure.text.Component;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * An event fired when a {@link Player} sends a chat message to the server.
+ */
+public final class AsyncChatEvent extends AbstractChatEvent {
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ public AsyncChatEvent(final boolean async, final @NotNull Player player, final @NotNull Set<Player> recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) {
+ super(async, player, recipients, formatter, message);
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/event/player/ChatEvent.java b/src/main/java/io/papermc/paper/event/player/ChatEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..04ee20906e104e15d730899477ae983d3255cb18
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/ChatEvent.java
@@ -0,0 +1,35 @@
+package io.papermc.paper.event.player;
+
+import io.papermc.paper.chat.ChatFormatter;
+import java.util.Set;
+import net.kyori.adventure.text.Component;
+import org.bukkit.Warning;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * An event fired when a {@link Player} sends a chat message to the server.
+ *
+ * @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. It is recommended to use {@link AsyncChatEvent} instead, wherever possible.
+ */
+@Deprecated
+@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.")
+public final class ChatEvent extends AbstractChatEvent {
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ public ChatEvent(final @NotNull Player player, final @NotNull Set<Player> recipients, final @NotNull ChatFormatter formatter, final @NotNull Component message) {
+ super(false, player, recipients, formatter, message);
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return HANDLERS;
+ }
+}
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 7c715fdc11ab7837552b1fe3ffd08b31cec0a63b..426b1e83226e674ee4bf3ec05ddcd3ac4376b06d 100644
--- a/src/main/java/org/bukkit/Bukkit.java
@ -601,6 +809,18 @@ index 768f35c19c4557236bded5f4a85f48a2b2b2a9e6..d0ce64412276512cde133937a85a3340
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/Warning.java b/src/main/java/org/bukkit/Warning.java
index efb97712cc9dc7c1e12a59f5b94e4f2ad7c6b7d8..3024468af4c073324e536c1cb26beffb1e09f3f4 100644
--- a/src/main/java/org/bukkit/Warning.java
+++ b/src/main/java/org/bukkit/Warning.java
@@ -67,6 +67,7 @@ public @interface Warning {
* </ul>
*/
public boolean printFor(@Nullable Warning warning) {
+ if (Boolean.getBoolean("paper.alwaysPrintWarningState")) return true; // Paper
if (this == DEFAULT) {
return warning == null || warning.value();
}
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index b8a33ac504da73ec990550bdd23e4548f6ccba95..27faaf8d1101f8522b728e3d73833e4dddbf1715 100644
--- a/src/main/java/org/bukkit/World.java
@ -1502,6 +1722,22 @@ index f1e9bc9bc797b7216336d3470e3c696a06f2b21a..090d22bd30f7947103771aaaf09a2398
public String getDefaultTitle() {
return title;
}
diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java
index 9c68c3f2d61500479f48b80264f625aaae2f3204..399afcd19fcb6acd24857ed6ab48cf0d105a01a3 100644
--- a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java
+++ b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java
@@ -22,7 +22,11 @@ import org.jetbrains.annotations.NotNull;
* <p>
* Care should be taken to check {@link #isAsynchronous()} and treat the event
* appropriately.
+ *
+ * @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead
*/
+@Deprecated // Paper
+@org.bukkit.Warning(value = false, reason = "Don't nag on old event yet") // Paper
public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;
diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java
index c8384da69af61e1970f254a3a9c206ee81d7a989..992d1025ca02020e87a9ab5db83d249427f41d69 100644
--- a/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java
@ -1633,6 +1869,31 @@ index c8384da69af61e1970f254a3a9c206ee81d7a989..992d1025ca02020e87a9ab5db83d2494
}
/**
diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java
index 8ea56aac752544f798728b429e7152afbee497e4..213837794c603cb9f152f917941b912326a08030 100644
--- a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java
+++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java
@@ -18,6 +18,7 @@ import org.jetbrains.annotations.NotNull;
* Listening to this event forces chat to wait for the main thread which
* causes delays for chat. {@link AsyncPlayerChatEvent} is the encouraged
* alternative for thread safe implementations.
+ * @deprecated use {@link io.papermc.paper.event.player.ChatEvent} instead
*/
@Deprecated
@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.")
diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java
index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..f6d3b817de3001f04ea4554c7c39a1290af3fd6d 100644
--- a/src/main/java/org/bukkit/event/player/PlayerEvent.java
+++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java
@@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event {
player = who;
}
- PlayerEvent(@NotNull final Player who, boolean async) {
+ public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - public
super(async);
player = who;
diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java
index d06684aba7688ce06777dbd837a46856a9d7767f..4af1d064fcb57773dfa8f6ad40d6482973f8e1a8 100644
--- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java

View File

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 27 Apr 2020 02:40:34 -0400
Subject: [PATCH] Make PlayerEvent public
diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java
index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..b7c8f2c31731960124ae4d67e935d2baaaae9e27 100644
--- a/src/main/java/org/bukkit/event/player/PlayerEvent.java
+++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java
@@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event {
player = who;
}
- PlayerEvent(@NotNull final Player who, boolean async) {
+ public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - wtf?
super(async);
player = who;

View File

@ -5,7 +5,7 @@ Subject: [PATCH] PlayerDeathEvent#shouldDropExperience
diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
index 831c2aeca95f813b675603af8173e2a20b740052..fa30689cc3555020a0989dd0b667644158578754 100644
index 7b78afe9281681cb9262fa044c1069a6121358eb..46917615ac4734bf5fa4ddea497132466eb5cc35 100644
--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
@@ -1,6 +1,8 @@

View File

@ -47,7 +47,7 @@ index 0000000000000000000000000000000000000000..df05153397b42930cd53d37b30824c7e
+ }
+}
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index b1b12cd1c53ca4666d0f2e77853f3a11441d24e5..301c8b34329e410df4f99c8617f768c48e4ea99d 100644
index 6441d4e45e5d5f008f95233cdc34048b8be38592..e20d863d1308b470a294cb7ab022aac4b9a91f71 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -70,6 +70,12 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Better AnnotationTest printout
diff --git a/pom.xml b/pom.xml
index 1b9b4349e303a17e96ce0a09e8776b6635092e57..0d922ea17c675d6e3a7106937918d2a818814fba 100644
index 650dbfd69281ada120c9cd9b04934f493c65977c..af17cd24b44c601f300e3ad5d6c57d810768b5e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -255,6 +255,19 @@

View File

@ -104,6 +104,221 @@ index 0000000000000000000000000000000000000000..a2acd31dce4461338a8baa96e03df36a
+ }
+ }
+}
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..d7945e7340f406fbf21a1bd67f9c167a309d0fb7
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
@@ -0,0 +1,209 @@
+package io.papermc.paper.adventure;
+
+import io.papermc.paper.chat.ChatFormatter;
+import io.papermc.paper.event.player.AbstractChatEvent;
+import io.papermc.paper.event.player.AsyncChatEvent;
+import io.papermc.paper.event.player.ChatEvent;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextReplacementConfig;
+import net.kyori.adventure.text.event.ClickEvent;
+import net.minecraft.server.EntityPlayer;
+import net.minecraft.server.IChatBaseComponent;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.craftbukkit.util.LazyPlayerSet;
+import org.bukkit.craftbukkit.util.Waitable;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.PlayerChatEvent;
+
+public final class ChatProcessor {
+ // <-- copied from adventure-text-serializer-legacy
+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?");
+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:");
+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder()
+ .match(DEFAULT_URL_PATTERN)
+ .replacement(url -> {
+ String clickUrl = url.content();
+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) {
+ clickUrl = "http://" + clickUrl;
+ }
+ return url.clickEvent(ClickEvent.openUrl(clickUrl));
+ })
+ .build();
+ // copied from adventure-text-serializer-legacy -->
+ final MinecraftServer server;
+ final EntityPlayer player;
+ final String message;
+ final boolean async;
+
+ public ChatProcessor(final MinecraftServer server, final EntityPlayer player, final String message, final boolean async) {
+ this.server = server;
+ this.player = player;
+ this.message = message;
+ this.async = async;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void process() {
+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList());
+
+ this.processLegacy(
+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent)
+ event -> {
+ final AsyncChatEvent ae = this.createAsync(
+ legacyFormatter(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()),
+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage())
+ );
+ ae.setCancelled(event.isCancelled()); // propagate cancelled state
+ post(ae);
+ if (listenersOnSyncEvent) {
+ this.continueWithSyncFromWhereAsyncLeftOff(ae);
+ } else {
+ this.complete(ae);
+ }
+ },
+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent
+ event -> {
+ this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
+ @Override
+ protected Void evaluate() {
+ final ChatEvent se = ChatProcessor.this.createSync(
+ legacyFormatter(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()),
+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage())
+ );
+ se.setCancelled(event.isCancelled()); // propagate cancelled state
+ post(se);
+ ChatProcessor.this.complete(se);
+ return null;
+ }
+ });
+ },
+ // no legacy events called, all nice and fresh!
+ () -> {
+ final AsyncChatEvent ae = this.createAsync(ChatFormatter.DEFAULT, Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG));
+ post(ae);
+ if (listenersOnSyncEvent) {
+ this.continueWithSyncFromWhereAsyncLeftOff(ae);
+ } else {
+ this.complete(ae);
+ }
+ }
+ );
+ }
+
+ private static Component displayName(final CraftPlayer player) {
+ return player.displayName();
+ }
+
+ private static ChatFormatter legacyFormatter(final String format, final String legacyDisplayName, final String legacyMessage) {
+ return (displayName, message) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName, legacyMessage)).replaceText(URL_REPLACEMENT_CONFIG);
+ }
+
+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) {
+ this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
+ @Override
+ protected Void evaluate() {
+ final ChatEvent se = ChatProcessor.this.createSync(ae.formatter(), 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;
+ }
+
+ final CraftPlayer player = this.player.getBukkitEntity();
+
+ final Component message = event.formatter().chat(
+ displayName(player),
+ event.message()
+ );
+
+ this.server.console.sendMessage(message);
+
+ if (((LazyPlayerSet) event.recipients()).isLazy()) {
+ final IChatBaseComponent vanilla = PaperAdventure.asVanilla(message);
+ for(final EntityPlayer recipient : this.server.getPlayerList().players) {
+ recipient.sendMessage(vanilla, this.player.getUniqueID());
+ }
+ } else {
+ for(final Player recipient : event.recipients()) {
+ recipient.sendMessage(player, message);
+ }
+ }
+ }
+
+ private AsyncChatEvent createAsync(final ChatFormatter formatter, final Component message) {
+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), new LazyPlayerSet(this.server), formatter, message);
+ }
+
+ private ChatEvent createSync(final ChatFormatter formatter, final Component message) {
+ return new ChatEvent(this.player.getBukkitEntity(), new LazyPlayerSet(this.server), formatter, message);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void processLegacy(
+ final Consumer<AsyncPlayerChatEvent> continueAfterAsync,
+ final Consumer<PlayerChatEvent> continueAfterAsyncAndSync,
+ final Runnable modernOnly
+ ) {
+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList());
+ final boolean listenersOnSyncEvent = anyListeners(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);
+ 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<Void>() {
+ @Override
+ protected Void evaluate() {
+ post(se);
+ return null;
+ }
+ });
+ continueAfterAsyncAndSync.accept(se);
+ } else if (!ae.isCancelled()) {
+ continueAfterAsync.accept(ae);
+ }
+ } else {
+ modernOnly.run();
+ }
+ }
+
+ private void queueIfAsyncOrRunImmediately(final Waitable<Void> waitable) {
+ if (this.async) {
+ this.server.processQueue.add(waitable);
+ } else {
+ waitable.run();
+ }
+ try {
+ waitable.get();
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt(); // tag, you're it
+ } catch (final ExecutionException e) {
+ throw new RuntimeException("Exception processing chat", e.getCause());
+ }
+ }
+
+ private static void post(final Event event) {
+ Bukkit.getPluginManager().callEvent(event);
+ }
+
+ private static boolean anyListeners(final HandlerList handlers) {
+ return handlers.getRegisteredListeners().length > 0;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..64fcc77eb2ce8979ae756696d98f1d3a91326ba6
@ -537,73 +752,6 @@ index 0000000000000000000000000000000000000000..59dd2a453dbfc538431a3414ab35d183
+ this.action.accept(PacketPlayOutBoss.Action.UPDATE_PROPERTIES);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java b/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f1f839da11058cffae8b29ad2820dc4cc1b1e10
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java
@@ -0,0 +1,61 @@
+package io.papermc.paper.adventure;
+
+import java.util.function.BiFunction;
+import java.util.regex.MatchResult;
+import java.util.regex.Pattern;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.ComponentLike;
+import net.kyori.adventure.text.TextComponent;
+import net.kyori.adventure.text.TextReplacementConfig;
+import net.kyori.adventure.text.event.ClickEvent;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+
+public class VanillaChatMessageLogic {
+ // <-- copied from adventure-text-serializer-legacy
+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?");
+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:");
+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder()
+ .match(DEFAULT_URL_PATTERN)
+ .replacement(url -> {
+ String clickUrl = url.content();
+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) {
+ clickUrl = "http://" + clickUrl;
+ }
+ return url.clickEvent(ClickEvent.openUrl(clickUrl));
+ })
+ .build();
+ // copied from adventure-text-serializer-legacy -->
+
+ public static Component displayNameForChat(final CraftPlayer player) {
+ return player.displayName();
+ }
+
+ public static Component formatChat(final Component displayName, final String format, final String message) {
+ final class Replacement implements BiFunction<MatchResult, TextComponent.Builder, ComponentLike> {
+ private int index = 0;
+
+ @Override
+ public ComponentLike apply(final MatchResult result, final TextComponent.Builder builder) {
+ if (this.index == 0) {
+ this.index++;
+ return displayName;
+ } else if (this.index == 1) {
+ this.index++;
+ return PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message).mergeStyle(builder.asComponent()).replaceText(URL_REPLACEMENT_CONFIG);
+ } else {
+ return builder;
+ }
+ }
+ }
+ final Replacement replacement = new Replacement();
+ if (format.contains("%2$s") && !format.contains("%1$s")) {
+ replacement.index = 1;
+ }
+ return PaperAdventure.LEGACY_SECTION_UXRC.deserialize(format)
+ .replaceText(config -> {
+ config.times(2);
+ config.match("%(\\d+\\$)?s");
+ config.replacement(replacement);
+ });
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1de7376cd4d3601f39d1f73b143c4244fe8480a3
@ -1129,15 +1277,15 @@ index 055555cb5ce63d41cb9a7f4114341b0685879b9e..7875d4c08969b3adc6f95504686cc9fe
@Override
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index d34e91887cd73009bf852fb849e495a8affed7a9..5fa4afb75d46a32d91402c5ca850d17d11990b8d 100644
index d34e91887cd73009bf852fb849e495a8affed7a9..5636a76f1a893dc0609f16a240ae559396a4b46d 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -25,6 +25,8 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// CraftBukkit start
+import io.papermc.paper.adventure.ChatProcessor; // Paper
+import io.papermc.paper.adventure.PaperAdventure; // Paper
+import io.papermc.paper.adventure.VanillaChatMessageLogic; // Paper
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import org.bukkit.Location;
@ -1199,57 +1347,23 @@ index d34e91887cd73009bf852fb849e495a8affed7a9..5fa4afb75d46a32d91402c5ca850d17d
}
// CraftBukkit end
ITextFilter itextfilter = this.player.Q();
@@ -1721,15 +1727,20 @@ public class PlayerConnection implements PacketListenerPlayIn {
return null;
}
@@ -1703,8 +1709,13 @@ public class PlayerConnection implements PacketListenerPlayIn {
this.handleCommand(s);
} else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) {
// Do nothing, this is coming from a plugin
- } else {
- Player player = this.getPlayer();
+ // Paper start
+ } else if (true) {
+ final ChatProcessor cp = new ChatProcessor(this.minecraftServer, this.player, s, async);
+ cp.process();
+ // Paper end
+ } else if (false) { // Paper
+ Player player = this.getPlayer(); // Paper
AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer));
this.server.getPluginManager().callEvent(event);
- String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage());
- PlayerConnection.this.minecraftServer.console.sendMessage(message);
+ final net.kyori.adventure.text.Component adventure$msg = VanillaChatMessageLogic.formatChat(VanillaChatMessageLogic.displayNameForChat((CraftPlayer) player), queueEvent.getFormat(), queueEvent.getMessage()); // Paper
+ //String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage()); // Paper - comment
+ //PlayerConnection.this.minecraftServer.console.sendMessage(message); // Paper - comment
+ PlayerConnection.this.minecraftServer.console.sendMessage(adventure$msg); // Paper
if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) {
+ final IChatBaseComponent vanilla$msg = PaperAdventure.asVanilla(adventure$msg); // Paper
for (Object player : PlayerConnection.this.minecraftServer.getPlayerList().players) {
- ((EntityPlayer) player).sendMessage(PlayerConnection.this.player.getUniqueID(), CraftChatMessage.fromString(message));
+ //((EntityPlayer) player).sendMessage(PlayerConnection.this.player.getUniqueID(), CraftChatMessage.fromString(message)); // Paper - comment
+ ((EntityPlayer) player).sendMessage(vanilla$msg, PlayerConnection.this.player.getUniqueID());
}
} else {
for (Player player : queueEvent.getRecipients()) {
- player.sendMessage(PlayerConnection.this.player.getUniqueID(), message);
+ //player.sendMessage(PlayerConnection.this.player.getUniqueID(), message); // Paper - comment
+ player.sendMessage(PlayerConnection.this.player.getBukkitEntity(), adventure$msg); // Paper
}
}
return null;
@@ -1751,15 +1762,20 @@ public class PlayerConnection implements PacketListenerPlayIn {
return;
}
- s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
- minecraftServer.console.sendMessage(s);
+ final net.kyori.adventure.text.Component adventure$msg = VanillaChatMessageLogic.formatChat(VanillaChatMessageLogic.displayNameForChat((CraftPlayer) player), event.getFormat(), event.getMessage()); // Paper
+ //s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage()); // Paper - comment
+ //minecraftServer.console.sendMessage(s); // Paper - comment
+ minecraftServer.console.sendMessage(adventure$msg); // Paper
if (((LazyPlayerSet) event.getRecipients()).isLazy()) {
+ final IChatBaseComponent vanilla$msg = PaperAdventure.asVanilla(adventure$msg); // Paper
for (Object recipient : minecraftServer.getPlayerList().players) {
- ((EntityPlayer) recipient).sendMessage(PlayerConnection.this.player.getUniqueID(), CraftChatMessage.fromString(s));
+ //((EntityPlayer) recipient).sendMessage(PlayerConnection.this.player.getUniqueID(), CraftChatMessage.fromString(s)); // Paper - comment
+ ((EntityPlayer) recipient).sendMessage(vanilla$msg, PlayerConnection.this.player.getUniqueID()); // Paper
}
} else {
for (Player recipient : event.getRecipients()) {
- recipient.sendMessage(PlayerConnection.this.player.getUniqueID(), s);
+ //recipient.sendMessage(PlayerConnection.this.player.getUniqueID(), s); // Paper - comment
+ recipient.sendMessage(PlayerConnection.this.player.getBukkitEntity(), adventure$msg); // Paper
}
}
}
@@ -2511,21 +2527,20 @@ public class PlayerConnection implements PacketListenerPlayIn {
@@ -2511,21 +2522,20 @@ public class PlayerConnection implements PacketListenerPlayIn {
return;
}
@ -1762,7 +1876,7 @@ index 81f6bf5533288ed90e2f1f4d421d54195d9650c7..d742f72215f6a9a2b562182fd57fd9ac
IChatBaseComponent[] components = new IChatBaseComponent[4];
diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..8495632d99137b89e4dd4543c2ea721dacfc9ee2 100644
index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..af986adfdb547cb61fbd52f0f89858f1a9e52cc3 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co
@ -1773,7 +1887,7 @@ index 089fe4a3458ed3106fa214f89a7004a5d3c6bb95..8495632d99137b89e4dd4543c2ea721d
+ // Paper start
+ @Override
+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) {
+ this.sendRawMessage(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(message));
+ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message)));
+ }
+ // Paper end
}

View File

@ -14,7 +14,7 @@ big slowdown in execution but throwing an exception at same time to raise awaren
that it is happening so that plugin authors can fix their code to stop executing commands async.
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 5fa4afb75d46a32d91402c5ca850d17d11990b8d..0dec3e50fcaf4505dcd7800c8ec985ae302c1da2 100644
index 5636a76f1a893dc0609f16a240ae559396a4b46d..bb74049fb2baffbe67f9e34cc0ee0b83180d02eb 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -1706,6 +1706,29 @@ public class PlayerConnection implements PacketListenerPlayIn {
@ -48,7 +48,7 @@ index 5fa4afb75d46a32d91402c5ca850d17d11990b8d..0dec3e50fcaf4505dcd7800c8ec985ae
} else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) {
// Do nothing, this is coming from a plugin
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 390714fa5822a61f64f6b3b8731397e9dae77cfd..e78182508ccd05bcb934a29eb495ff9c884d3a55 100644
index 4fdc38de35ce2f3ec20c6892bc9eb39ec0366498..66cbc94b8d5cb9e435e0fb32596f8f3cef0a49a5 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -762,6 +762,29 @@ public final class CraftServer implements Server {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Complete resource pack API
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 0dec3e50fcaf4505dcd7800c8ec985ae302c1da2..c1d0aa8248af19124b1c94313602cd4dadcc95df 100644
index bb74049fb2baffbe67f9e34cc0ee0b83180d02eb..9a9847c217a6f7a2e2bc09b68b3d2821fcecbbc3 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -1457,7 +1457,11 @@ public class PlayerConnection implements PacketListenerPlayIn {

View File

@ -18,10 +18,10 @@ index 49c911e54eb3b20d820f3e1895c057eead6d312b..09c757a3bb1d9a49343cf58e18f736e1
private Vec3D c;
private EnumHand d;
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index c1d0aa8248af19124b1c94313602cd4dadcc95df..3aa6cae8b7f27264ee5f910d13df876b568968e4 100644
index 2436ee100bdf7cb2166595f41af61af806ecdd46..f021568601198ddcf4c1c312eb5d3eef4b9eb5e5 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -2057,6 +2057,16 @@ public class PlayerConnection implements PacketListenerPlayIn {
@@ -2052,6 +2052,16 @@ public class PlayerConnection implements PacketListenerPlayIn {
}
}
}

View File

@ -25,48 +25,27 @@ index db2dddd12f54e6d15916c4cee623676541de37fb..1942f5224aaebb18adb591d6f70a419c
+ useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false);
+ }
}
diff --git a/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java b/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java
index 5f1f839da11058cffae8b29ad2820dc4cc1b1e10..b62d573db85dcc59f9a2704c9142bde6bd5105c9 100644
--- a/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java
+++ b/src/main/java/io/papermc/paper/adventure/VanillaChatMessageLogic.java
@@ -8,6 +8,8 @@ import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
index d7945e7340f406fbf21a1bd67f9c167a309d0fb7..63085b09eb4d7dc5ebbad9f3d8d6309990473b45 100644
--- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
@@ -13,7 +13,9 @@ import net.kyori.adventure.text.event.ClickEvent;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.IChatBaseComponent;
import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.ScoreboardTeam;
import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.util.LazyPlayerSet;
import org.bukkit.craftbukkit.util.Waitable;
@@ -99,6 +101,9 @@ public final class ChatProcessor {
}
public class VanillaChatMessageLogic {
@@ -27,6 +29,9 @@ public class VanillaChatMessageLogic {
// copied from adventure-text-serializer-legacy -->
public static Component displayNameForChat(final CraftPlayer player) {
private static Component displayName(final CraftPlayer player) {
+ if (((CraftWorld) player.getWorld()).getHandle().paperConfig.useVanillaScoreboardColoring) {
+ return PaperAdventure.asAdventure(ScoreboardTeam.a(player.getHandle().getScoreboardTeam(), player.getHandle().getDisplayName()));
+ }
return player.displayName();
}
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 3aa6cae8b7f27264ee5f910d13df876b568968e4..5d6214b00633b64a769384e6e01eba58cc7d0e6a 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -1737,7 +1737,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
} else if (this.player.getChatFlags() == EnumChatVisibility.SYSTEM) {
// Do nothing, this is coming from a plugin
} else {
- Player player = this.getPlayer();
+ CraftPlayer player = this.getPlayer(); // Paper
AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(minecraftServer));
this.server.getPluginManager().callEvent(event);
@@ -1754,7 +1754,7 @@ public class PlayerConnection implements PacketListenerPlayIn {
return null;
}
- final net.kyori.adventure.text.Component adventure$msg = VanillaChatMessageLogic.formatChat(VanillaChatMessageLogic.displayNameForChat((CraftPlayer) player), queueEvent.getFormat(), queueEvent.getMessage()); // Paper
+ final net.kyori.adventure.text.Component adventure$msg = VanillaChatMessageLogic.formatChat(VanillaChatMessageLogic.displayNameForChat(player), queueEvent.getFormat(), queueEvent.getMessage()); // Paper
//String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage()); // Paper - comment
//PlayerConnection.this.minecraftServer.console.sendMessage(message); // Paper - comment
PlayerConnection.this.minecraftServer.console.sendMessage(adventure$msg); // Paper

Some files were not shown because too many files have changed in this diff Show More