From dd3e4e7bd66c3e94fafd8cf1480d7087f023c89d Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Mon, 1 Aug 2022 12:34:55 -0700 Subject: [PATCH] Initial support for signed messages (#8198) --- patches/api/0005-Adventure.patch | 225 ++++- patches/server/0008-Adventure.patch | 841 ++++++++++++++++-- ...39-Implement-PlayerLocaleChangeEvent.patch | 8 +- ...layer-View-Distance-API-placeholders.patch | 6 +- ...0079-Add-PlayerUseUnknownEntityEvent.patch | 4 +- ...nilla-per-world-scoreboard-coloring-.patch | 16 +- ...19-Properly-fix-item-duplication-bug.patch | 8 +- ...ke-parrots-stay-on-shoulders-despite.patch | 4 +- ...dle-ServerboundKeepAlivePacket-async.patch | 4 +- ...-allowed-colored-signs-to-be-created.patch | 4 +- .../0215-InventoryCloseEvent-Reason-API.patch | 10 +- ...nventory-when-cancelling-PlayerInter.patch | 4 +- ...tator-target-events-and-improve-impl.patch | 4 +- ...77-Reset-players-airTicks-on-respawn.patch | 4 +- .../0300-Limit-Client-Sign-length-more.patch | 4 +- ...ity-Metadata-for-all-tracked-players.patch | 4 +- ...32-Dont-send-unnecessary-sign-update.patch | 4 +- ...-Add-tick-times-API-and-mspt-command.patch | 4 +- ...-Implement-Player-Client-Options-API.patch | 6 +- ...ktraces-in-log-messages-crash-report.patch | 13 - ...implement-PlayerRecipeBookClickEvent.patch | 4 +- ...ld-Difficulty-Remembering-Difficulty.patch | 8 +- patches/server/0475-Brand-support.patch | 10 +- .../server/0535-Limit-recipe-packets.patch | 4 +- ...0537-Player-Chunk-Load-Unload-Events.patch | 4 +- ...-event-not-being-called-in-adventure.patch | 4 +- ...d-RespawnFlags-to-PlayerRespawnEvent.patch | 6 +- ...ditions-to-PlayerGameModeChangeEvent.patch | 10 +- .../0656-Add-PlayerKickEvent-causes.patch | 28 +- ...PlayerDropItemEvent-using-wrong-item.patch | 4 +- .../0677-Adds-PlayerArmSwingEvent.patch | 4 +- .../server/0692-Add-PlayerSetSpawnEvent.patch | 10 +- .../0737-Execute-chunk-tasks-mid-tick.patch | 4 +- ...6-Replace-player-chunk-loader-system.patch | 12 +- ...nt-tile-entity-copies-loading-chunks.patch | 4 +- ...tead-of-display-name-in-PlayerList-g.patch | 4 +- ...s-ServerLevel-for-gamerule-callbacks.patch | 4 +- ...o-not-accept-invalid-client-settings.patch | 4 +- ...-debug-information-to-chat-packet-er.patch | 4 +- ...g-not-using-commands.spam-exclusions.patch | 4 +- ...ck-entities-after-destroy-prediction.patch | 2 +- 41 files changed, 1106 insertions(+), 209 deletions(-) diff --git a/patches/api/0005-Adventure.patch b/patches/api/0005-Adventure.patch index 560a56fd86..30c61b03b0 100644 --- a/patches/api/0005-Adventure.patch +++ b/patches/api/0005-Adventure.patch @@ -77,16 +77,15 @@ index 79bf95d5a19046b142d0162dd6b739b7f0f52e59..84432bf9dd99332098f952ea777ee97d doLast { diff --git a/src/main/java/io/papermc/paper/chat/ChatRenderer.java b/src/main/java/io/papermc/paper/chat/ChatRenderer.java new file mode 100644 -index 0000000000000000000000000000000000000000..2fc47afbb233e6e5727a7b672f61b88ad3bab097 +index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af85e287a6 --- /dev/null +++ b/src/main/java/io/papermc/paper/chat/ChatRenderer.java -@@ -0,0 +1,78 @@ +@@ -0,0 +1,71 @@ +package io.papermc.paper.chat; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + @@ -115,7 +114,11 @@ index 0000000000000000000000000000000000000000..2fc47afbb233e6e5727a7b672f61b88a + */ + @NotNull + static ChatRenderer defaultRenderer() { -+ return viewerUnaware((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message)); ++ return new ViewerUnawareImpl.Default((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message)); ++ } ++ ++ @ApiStatus.Internal ++ sealed interface Default extends ChatRenderer, ViewerUnaware permits ViewerUnawareImpl.Default { + } + + /** @@ -127,17 +130,7 @@ index 0000000000000000000000000000000000000000..2fc47afbb233e6e5727a7b672f61b88a + */ + @NotNull + static ChatRenderer viewerUnaware(final @NotNull ViewerUnaware renderer) { -+ return new ChatRenderer() { -+ private @MonotonicNonNull Component message; -+ -+ @Override -+ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message, final @NotNull Audience viewer) { -+ if (this.message == null) { -+ this.message = renderer.render(source, sourceDisplayName, message); -+ } -+ return this.message; -+ } -+ }; ++ return new ViewerUnawareImpl(renderer); + } + + /** @@ -159,6 +152,50 @@ index 0000000000000000000000000000000000000000..2fc47afbb233e6e5727a7b672f61b88a + Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message); + } +} +diff --git a/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9adeb880f7948f937891d83e256c808b5eb40a27 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java +@@ -0,0 +1,38 @@ ++package io.papermc.paper.chat; ++ ++import net.kyori.adventure.audience.Audience; ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ++import org.jetbrains.annotations.NotNull; ++ ++sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnaware permits ViewerUnawareImpl.Default { ++ ++ private final ViewerUnaware unaware; ++ ++ private @MonotonicNonNull Component message; ++ ++ ViewerUnawareImpl(final ViewerUnaware unaware) { ++ this.unaware = unaware; ++ } ++ ++ @Override ++ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message, final @NotNull Audience viewer) { ++ return this.render(source, sourceDisplayName, message); ++ } ++ ++ @Override ++ public @NotNull Component render(final @NotNull Player source, final @NotNull Component sourceDisplayName, final @NotNull Component message) { ++ if (this.message == null) { ++ this.message = this.unaware.render(source, sourceDisplayName, message); ++ } ++ return this.message; ++ } ++ ++ static final class Default extends ViewerUnawareImpl implements ChatRenderer.Default { ++ ++ Default(final ViewerUnaware unaware) { ++ super(unaware); ++ } ++ } ++} 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..fa03a5cb2d3e3e0a60d84bacc911d96c454f81da @@ -277,6 +314,164 @@ index 0000000000000000000000000000000000000000..fa03a5cb2d3e3e0a60d84bacc911d96c + this.cancelled = cancelled; + } +} +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bd216f7333795fc6bc5bec593f9cc0e3c2c1a27e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatCommandDecorateEvent.java +@@ -0,0 +1,27 @@ ++package io.papermc.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++@ApiStatus.Experimental ++public class AsyncChatCommandDecorateEvent extends AsyncChatDecorateEvent { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ public AsyncChatCommandDecorateEvent(boolean async, @Nullable Player player, @NotNull Component originalMessage, boolean isPreview, @NotNull Component result) { ++ super(async, player, originalMessage, isPreview, result); ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java b/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..347122b12ad98115133ef98db69b271ee0cec194 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/player/AsyncChatDecorateEvent.java +@@ -0,0 +1,119 @@ ++package io.papermc.paper.event.player; ++ ++import net.kyori.adventure.text.Component; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.server.ServerEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * This event is fired when the server decorates a component for chat purposes. It can be called ++ * under the following circumstances: ++ * ++ * @see AsyncChatCommandDecorateEvent for the decoration of messages sent via commands ++ */ ++@ApiStatus.Experimental ++public class AsyncChatDecorateEvent extends ServerEvent implements Cancellable { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ ++ private final Player player; ++ private final Component originalMessage; ++ private final boolean isPreview; ++ private Component result; ++ private boolean cancelled; ++ ++ @ApiStatus.Internal ++ public AsyncChatDecorateEvent(final boolean async, final @Nullable Player player, final @NotNull Component originalMessage, final boolean isPreview, final @NotNull Component result) { ++ super(async); ++ this.player = player; ++ this.originalMessage = originalMessage; ++ this.isPreview = isPreview; ++ this.result = result; ++ } ++ ++ /** ++ * Gets the player (if available) associated with this event. ++ *

++ * Certain commands request decorations without a player context ++ * which is why this is possibly null. ++ * ++ * @return the player or null ++ */ ++ public @Nullable Player player() { ++ return this.player; ++ } ++ ++ /** ++ * Gets the original decoration input ++ * ++ * @return the input ++ */ ++ public @NotNull Component originalMessage() { ++ return this.originalMessage; ++ } ++ ++ /** ++ * Gets the decoration result. This may already be different from ++ * {@link #originalMessage()} if some other listener to this event ++ * OR the legacy preview event ({@link org.bukkit.event.player.AsyncPlayerChatPreviewEvent} ++ * changed the result. ++ * ++ * @return the result ++ */ ++ public @NotNull Component result() { ++ return this.result; ++ } ++ ++ /** ++ * Sets the resulting decorated component. ++ * ++ * @param result the result ++ */ ++ public void result(@NotNull Component result) { ++ this.result = result; ++ } ++ ++ /** ++ * If this decorating is part of a preview request/response. ++ * ++ * @return true if part of previewing ++ */ ++ public boolean isPreview() { ++ return this.isPreview; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; ++ } ++ ++ /** ++ * A cancelled decorating event means that no changes to the result component ++ * will have any effect. The decorated component will be equal to the original ++ * component. ++ */ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancelled = cancel; ++ } ++ ++ @Override ++ public @NotNull HandlerList getHandlers() { ++ return HANDLER_LIST; ++ } ++ ++ public static @NotNull HandlerList getHandlerList() { ++ return HANDLER_LIST; ++ } ++} 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..0d9e3c23027e3af90cb70e4bb6fb0ac1da35fc4d diff --git a/patches/server/0008-Adventure.patch b/patches/server/0008-Adventure.patch index f3571fcee4..6bc95235fe 100644 --- a/patches/server/0008-Adventure.patch +++ b/patches/server/0008-Adventure.patch @@ -98,30 +98,187 @@ index 0000000000000000000000000000000000000000..07cd02c6f9df00844b808218be2afd79 + } + } +} -diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +diff --git a/src/main/java/io/papermc/paper/adventure/ChatDecorationProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatDecorationProcessor.java new file mode 100644 -index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe2467cbbf5f +index 0000000000000000000000000000000000000000..87e791801b624859477025df49824637eb347dec --- /dev/null -+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -0,0 +1,193 @@ ++++ b/src/main/java/io/papermc/paper/adventure/ChatDecorationProcessor.java +@@ -0,0 +1,141 @@ +package io.papermc.paper.adventure; + ++import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent; ++import io.papermc.paper.event.player.AsyncChatDecorateEvent; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.concurrent.CompletableFuture; ++import java.util.regex.Pattern; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.minimessage.MiniMessage; ++import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; ++import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; ++import net.minecraft.Util; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.network.chat.ChatDecorator; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.craftbukkit.util.LazyPlayerSet; ++import org.bukkit.event.Event; ++import org.bukkit.event.player.AsyncPlayerChatPreviewEvent; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++import static io.papermc.paper.adventure.ChatProcessor.DEFAULT_LEGACY_FORMAT; ++import static io.papermc.paper.adventure.ChatProcessor.canYouHearMe; ++import static io.papermc.paper.adventure.ChatProcessor.displayName; ++import static net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection; ++ ++@DefaultQualifier(NonNull.class) ++public final class ChatDecorationProcessor { ++ ++ private static final String DISPLAY_NAME_TAG = "---paper_dn---"; ++ private static final Pattern DISPLAY_NAME_PATTERN = Pattern.compile("%(1\\$)?s"); ++ private static final String CONTENT_TAG = "---paper_content---"; ++ private static final Pattern CONTENT_PATTERN = Pattern.compile("%(2\\$)?s"); ++ ++ final MinecraftServer server; ++ final @Nullable ServerPlayer player; ++ final @Nullable CommandSourceStack commandSourceStack; ++ final Component originalMessage; ++ final boolean isPreview; ++ ++ public ChatDecorationProcessor(final MinecraftServer server, final @Nullable ServerPlayer player, final @Nullable CommandSourceStack commandSourceStack, final net.minecraft.network.chat.Component originalMessage, final boolean isPreview) { ++ this.server = server; ++ this.player = player; ++ this.commandSourceStack = commandSourceStack; ++ this.originalMessage = PaperAdventure.asAdventure(originalMessage); ++ this.isPreview = isPreview; ++ } ++ ++ public CompletableFuture process() { ++ return CompletableFuture.supplyAsync(() -> { ++ ChatDecorator.Result result = new ChatDecorator.ModernResult(this.originalMessage, true, false); ++ if (canYouHearMe(AsyncPlayerChatPreviewEvent.getHandlerList())) { ++ result = this.processLegacy(result); ++ } ++ return this.processModern(result); ++ }, this.server.chatExecutor); ++ } ++ ++ private ChatDecorator.Result processLegacy(final ChatDecorator.Result input) { ++ if (this.player != null) { ++ final CraftPlayer player = this.player.getBukkitEntity(); ++ final String originalMessage = legacySection().serialize(this.originalMessage); ++ final AsyncPlayerChatPreviewEvent event = new AsyncPlayerChatPreviewEvent(true, player, originalMessage, new LazyPlayerSet(this.server)); ++ this.post(event); ++ ++ final boolean isDefaultFormat = DEFAULT_LEGACY_FORMAT.equals(event.getFormat()); ++ if (event.isCancelled() || (isDefaultFormat && originalMessage.equals(event.getMessage()))) { ++ return input; ++ } else { ++ final Component message = legacySection().deserialize(event.getMessage()); ++ final Component component = isDefaultFormat ? message : legacyFormat(event.getFormat(), ((CraftPlayer) event.getPlayer()), legacySection().deserialize(event.getMessage())); ++ return legacy(component, event.getFormat(), new ChatDecorator.MessagePair(message, event.getMessage()), isDefaultFormat); ++ } ++ } ++ return input; ++ } ++ ++ private ChatDecorator.Result processModern(final ChatDecorator.Result input) { ++ final @Nullable CraftPlayer player = Util.mapNullable(this.player, ServerPlayer::getBukkitEntity); ++ ++ final Component initialResult = input.message().component(); ++ final AsyncChatDecorateEvent event; ++ if (this.commandSourceStack != null) { ++ // TODO more command decorate context ++ event = new AsyncChatCommandDecorateEvent(true, player, this.originalMessage, this.isPreview, initialResult); ++ } else { ++ event = new AsyncChatDecorateEvent(true, player, this.originalMessage, this.isPreview, initialResult); ++ } ++ this.post(event); ++ if (!event.isCancelled() && !event.result().equals(initialResult)) { ++ if (input instanceof ChatDecorator.LegacyResult legacyResult) { ++ if (legacyResult.hasNoFormatting()) { ++ /* ++ The MessagePair in the decoration result may be different at this point. This is because the legacy ++ decoration system requires the same modifications be made to the message, so we can't have the initial ++ message value for the legacy chat events be changed by the modern decorate event. ++ */ ++ return noFormatting(event.result(), legacyResult.format(), legacyResult.message().legacyMessage()); ++ } else { ++ final Component formatted = legacyFormat(legacyResult.format(), player, event.result()); ++ return withFormatting(formatted, legacyResult.format(), event.result(), legacyResult.message().legacyMessage()); ++ } ++ } else { ++ return new ChatDecorator.ModernResult(event.result(), true, false); ++ } ++ } ++ return input; ++ } ++ ++ private void post(final Event event) { ++ this.server.server.getPluginManager().callEvent(event); ++ } ++ ++ private static Component legacyFormat(final String format, final @Nullable CraftPlayer player, final Component message) { ++ final List args = new ArrayList<>(player != null ? 2 : 1); ++ if (player != null) { ++ args.add(Placeholder.component(DISPLAY_NAME_TAG, displayName(player))); ++ } ++ args.add(Placeholder.component(CONTENT_TAG, message)); ++ String miniMsg = MiniMessage.miniMessage().serialize(legacySection().deserialize(format)); ++ miniMsg = DISPLAY_NAME_PATTERN.matcher(miniMsg).replaceFirst("<" + DISPLAY_NAME_TAG + ">"); ++ miniMsg = CONTENT_PATTERN.matcher(miniMsg).replaceFirst("<" + CONTENT_TAG + ">"); ++ return MiniMessage.miniMessage().deserialize(miniMsg, TagResolver.resolver(args)); ++ } ++ ++ public static ChatDecorator.LegacyResult legacy(final Component maybeFormatted, final String format, final ChatDecorator.MessagePair message, final boolean hasNoFormatting) { ++ return new ChatDecorator.LegacyResult(maybeFormatted, format, message, hasNoFormatting, false); ++ } ++ ++ public static ChatDecorator.LegacyResult noFormatting(final Component component, final String format, final String legacyMessage) { ++ return new ChatDecorator.LegacyResult(component, format, new ChatDecorator.MessagePair(component, legacyMessage), true, true); ++ } ++ ++ public static ChatDecorator.LegacyResult withFormatting(final Component formatted, final String format, final Component message, final String legacyMessage) { ++ return new ChatDecorator.LegacyResult(formatted, format, new ChatDecorator.MessagePair(message, legacyMessage), false, true); ++ } ++} +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..f8586ae7fe41cce772745bab2a1482c424d0b28f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +@@ -0,0 +1,376 @@ ++package io.papermc.paper.adventure; ++ ++import com.google.common.base.Suppliers; +import io.papermc.paper.chat.ChatRenderer; +import io.papermc.paper.event.player.AbstractChatEvent; +import io.papermc.paper.event.player.AsyncChatEvent; +import io.papermc.paper.event.player.ChatEvent; ++import java.util.BitSet; ++import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ExecutionException; -+import java.util.regex.Pattern; ++import java.util.function.Function; ++import java.util.function.Supplier; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.TextReplacementConfig; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; ++import net.minecraft.Util; ++import net.minecraft.network.chat.ChatDecorator; ++import net.minecraft.network.chat.ChatMessageContent; ++import net.minecraft.network.chat.ChatType; ++import net.minecraft.network.chat.OutgoingPlayerChatMessage; ++import net.minecraft.network.chat.PlayerChatMessage; ++import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.command.CommandSender; ++import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.util.LazyPlayerSet; +import org.bukkit.craftbukkit.util.Waitable; @@ -130,35 +287,54 @@ index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe24 +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerChatEvent; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.checkerframework.framework.qual.DefaultQualifier; + ++import static net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection; ++ ++@DefaultQualifier(NonNull.class) +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 --> -+ private static final String DEFAULT_LEGACY_FORMAT = "<%1$s> %2$s"; // copied from PlayerChatEvent/AsyncPlayerChatEvent ++ static final String DEFAULT_LEGACY_FORMAT = "<%1$s> %2$s"; // copied from PlayerChatEvent/AsyncPlayerChatEvent + final MinecraftServer server; + final ServerPlayer player; -+ final String message; ++ final PlayerChatMessage message; + final boolean async; -+ final Component originalMessage; ++ final String craftbukkit$originalMessage; ++ final Component paper$originalMessage; ++ final OutgoingPlayerChatMessage outgoing; + -+ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final String message, final boolean async) { ++ static final int MESSAGE_CHANGED = 1; ++ static final int FORMAT_CHANGED = 2; ++ static final int SENDER_CHANGED = 3; // Not used ++ // static final int FORCE_PREVIEW_USE = 4; // TODO (future, maybe?) ++ private final BitSet flags = new BitSet(3); ++ ++ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final PlayerChatMessage message, final boolean async) { + this.server = server; + this.player = player; ++ /* ++ CraftBukkit's preview/decoration system relies on both the "decorate" and chat event making the same modifications. If ++ there is unsigned content in the legacyMessage, that is because the player sent the legacyMessage without it being ++ previewed (probably by sending it too quickly). We can just ignore that because the same changes will ++ happen in the chat event. ++ ++ If unsigned content is present, it will be the same as `this.legacyMessage.signedContent().previewResult().component()`. ++ */ + this.message = message; + this.async = async; -+ this.originalMessage = Component.text(message); ++ if (this.message.signedContent().decorationResult().modernized()) { ++ this.craftbukkit$originalMessage = this.message.signedContent().decorationResult().message().legacyMessage(); ++ } else { ++ this.craftbukkit$originalMessage = message.signedContent().plain(); ++ } ++ /* ++ this.paper$originalMessage is the input to paper's chat events. This should be the decorated message component. ++ Even if the legacy preview event modified the format, and the client signed the formatted message, this should ++ still just be the message component. ++ */ ++ this.paper$originalMessage = this.message.signedContent().decorationResult().message().component(); ++ this.outgoing = OutgoingPlayerChatMessage.create(this.message); + } + + @SuppressWarnings("deprecated") @@ -167,7 +343,7 @@ index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe24 + 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)); ++ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.craftbukkit$originalMessage, new LazyPlayerSet(this.server)); + this.post(ae); + if (listenersOnSyncEvent) { + final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients()); @@ -179,33 +355,73 @@ index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe24 + return null; + } + }); ++ this.readLegacyModifications(se.getMessage(), se.getFormat(), se.getPlayer()); + this.processModern( -+ legacyRenderer(se.getFormat()), ++ this.modernRenderer(se.getFormat()), + this.viewersFromLegacy(se.getRecipients()), -+ LegacyComponentSerializer.legacySection().deserialize(se.getMessage()), ++ this.modernMessage(se.getMessage()), ++ se.getPlayer(), + se.isCancelled() + ); + } else { ++ this.readLegacyModifications(ae.getMessage(), ae.getFormat(), ae.getPlayer()); + this.processModern( -+ legacyRenderer(ae.getFormat()), ++ this.modernRenderer(ae.getFormat()), + this.viewersFromLegacy(ae.getRecipients()), -+ LegacyComponentSerializer.legacySection().deserialize(ae.getMessage()), ++ this.modernMessage(ae.getMessage()), ++ ae.getPlayer(), + ae.isCancelled() + ); + } + } else { + this.processModern( -+ ChatRenderer.defaultRenderer(), ++ defaultRenderer(), + new LazyChatAudienceSet(this.server), -+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG), ++ this.paper$originalMessage, ++ this.player.getBukkitEntity(), + false + ); + } + } + -+ private void processModern(final ChatRenderer renderer, final Set viewers, final Component message, final boolean cancelled) { -+ final CraftPlayer player = this.player.getBukkitEntity(); -+ final AsyncChatEvent ae = new AsyncChatEvent(this.async, player, viewers, renderer, message, this.originalMessage); ++ private ChatRenderer modernRenderer(final String format) { ++ if (this.flags.get(FORMAT_CHANGED)) { ++ return legacyRenderer(format); ++ } else if (this.message.signedContent().decorationResult() instanceof ChatDecorator.LegacyResult legacyResult) { ++ return legacyRenderer(legacyResult.format()); ++ } else { ++ return defaultRenderer(); ++ } ++ } ++ ++ private Component modernMessage(final String legacyMessage) { ++ if (this.flags.get(MESSAGE_CHANGED)) { ++ return legacySection().deserialize(legacyMessage); ++ } else if (this.message.unsignedContent().isEmpty() && this.message.signedContent().decorationResult() instanceof ChatDecorator.LegacyResult legacyResult) { ++ return legacyResult.message().component(); ++ } else { ++ return this.paper$originalMessage; ++ } ++ } ++ ++ private void readLegacyModifications(final String message, final String format, final Player playerSender) { ++ final ChatMessageContent content = this.message.signedContent(); ++ if (content.decorationResult() instanceof ChatDecorator.LegacyResult result) { ++ if ((content.isDecorated() || this.message.unsignedContent().isPresent()) && !result.modernized()) { ++ this.flags.set(MESSAGE_CHANGED, !message.equals(result.message().legacyMessage())); ++ } else { ++ this.flags.set(MESSAGE_CHANGED, !message.equals(this.craftbukkit$originalMessage)); ++ } ++ this.flags.set(FORMAT_CHANGED, !format.equals(result.format())); ++ } else { ++ this.flags.set(MESSAGE_CHANGED, !message.equals(this.craftbukkit$originalMessage)); ++ this.flags.set(FORMAT_CHANGED, !format.equals(DEFAULT_LEGACY_FORMAT)); ++ } ++ this.flags.set(SENDER_CHANGED, playerSender != this.player.getBukkitEntity()); ++ } ++ ++ private void processModern(final ChatRenderer renderer, final Set viewers, final Component message, final Player player, final boolean cancelled) { ++ final AsyncChatEvent ae = new AsyncChatEvent(this.async, player, viewers, renderer, message, this.paper$originalMessage); + ae.setCancelled(cancelled); // propagate cancelled state + this.post(ae); + final boolean listenersOnSyncEvent = canYouHearMe(ChatEvent.getHandlerList()); @@ -213,39 +429,145 @@ index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe24 + this.queueIfAsyncOrRunImmediately(new Waitable() { + @Override + protected Void evaluate() { -+ final ChatEvent se = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.originalMessage); ++ final ChatEvent se = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.paper$originalMessage/*, ae.usePreviewComponent()*/); + se.setCancelled(ae.isCancelled()); // propagate cancelled state + ChatProcessor.this.post(se); ++ ChatProcessor.this.readModernModifications(se, renderer); + ChatProcessor.this.complete(se); + return null; + } + }); + } else { ++ this.readModernModifications(ae, renderer); + this.complete(ae); + } + } + ++ private void readModernModifications(final AbstractChatEvent chatEvent, final ChatRenderer originalRenderer) { ++ if (this.message.signedContent().isDecorated()) { ++ this.flags.set(MESSAGE_CHANGED, !chatEvent.message().equals(this.message.signedContent().decorationResult().message().component())); ++ } else { ++ this.flags.set(MESSAGE_CHANGED, !chatEvent.message().equals(this.paper$originalMessage)); ++ } ++ if (originalRenderer != chatEvent.renderer()) { // don't set to false if it hasn't changed ++ this.flags.set(FORMAT_CHANGED, true); ++ } ++ // this.flags.set(FORCE_PREVIEW_USE, chatEvent.usePreviewComponent()); // TODO (future, maybe?) ++ } ++ + private void complete(final AbstractChatEvent event) { + if (event.isCancelled()) { ++ this.outgoing.sendHeadersToRemainingPlayers(this.server.getPlayerList()); + return; + } + -+ final CraftPlayer player = this.player.getBukkitEntity(); ++ final CraftPlayer player = ((CraftPlayer) event.getPlayer()); + final Component displayName = displayName(player); + final Component message = event.message(); + final ChatRenderer renderer = event.renderer(); + + final Set viewers = event.viewers(); ++ final ResourceKey chatTypeKey = renderer instanceof ChatRenderer.Default ? ChatType.CHAT : ChatType.RAW; ++ final ChatType.Bound chatType = ChatType.bind(chatTypeKey, this.player.level.registryAccess(), PaperAdventure.asVanilla(displayName(player))); + -+ if (viewers instanceof LazyChatAudienceSet lazyAudienceSet && lazyAudienceSet.isLazy()) { -+ this.server.console.sendMessage(player, renderer.render(player, displayName, message, this.server.console), MessageType.CHAT); -+ for (final ServerPlayer viewer : this.server.getPlayerList().getPlayers()) { -+ final Player bukkit = viewer.getBukkitEntity(); -+ bukkit.sendMessage(player, renderer.render(player, displayName, message, bukkit), MessageType.CHAT); ++ OutgoingChat outgoingChat = viewers instanceof LazyChatAudienceSet lazyAudienceSet && lazyAudienceSet.isLazy() ? new ServerOutgoingChat() : new ViewersOutgoingChat(); ++ /* if (this.flags.get(FORCE_PREVIEW_USE)) { // TODO (future, maybe?) ++ outgoingChat.sendOriginal(player, viewers, chatType); ++ } else */ ++ if (this.flags.get(FORMAT_CHANGED)) { ++ if (renderer instanceof ChatRenderer.ViewerUnaware unaware) { ++ outgoingChat.sendFormatChangedViewerUnaware(player, PaperAdventure.asVanilla(unaware.render(player, displayName, message)), viewers, chatType); ++ } else { ++ outgoingChat.sendFormatChangedViewerAware(player, displayName, message, renderer, viewers, chatType); + } ++ } else if (this.flags.get(MESSAGE_CHANGED)) { ++ if (!(renderer instanceof ChatRenderer.ViewerUnaware unaware)) { ++ throw new IllegalStateException("BUG: There should not be a non-legacy renderer at this point"); ++ } ++ final Component renderedComponent = chatTypeKey == ChatType.CHAT ? message : unaware.render(player, displayName, message); ++ outgoingChat.sendMessageChanged(player, PaperAdventure.asVanilla(renderedComponent), viewers, chatType); + } else { -+ for (final Audience viewer : viewers) { -+ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT); ++ outgoingChat.sendOriginal(player, viewers, chatType); ++ } ++ } ++ ++ interface OutgoingChat { ++ default void sendFormatChangedViewerUnaware(CraftPlayer player, net.minecraft.network.chat.Component renderedMessage, Set viewers, ChatType.Bound chatType) { ++ this.sendMessageChanged(player, renderedMessage, viewers, chatType); ++ } ++ ++ void sendFormatChangedViewerAware(CraftPlayer player, Component displayName, Component message, ChatRenderer renderer, Set viewers, ChatType.Bound chatType); ++ ++ void sendMessageChanged(CraftPlayer player, net.minecraft.network.chat.Component renderedMessage, Set viewers, ChatType.Bound chatType); ++ ++ void sendOriginal(CraftPlayer player, Set viewers, ChatType.Bound chatType); ++ } ++ ++ final class ServerOutgoingChat implements OutgoingChat { ++ @Override ++ public void sendFormatChangedViewerAware(CraftPlayer player, Component displayName, Component message, ChatRenderer renderer, Set viewers, ChatType.Bound chatType) { ++ ChatProcessor.this.server.getPlayerList().broadcastChatMessage(ChatProcessor.this.message, ChatProcessor.this.player, chatType, viewer -> PaperAdventure.asVanilla(renderer.render(player, displayName, message, viewer))); ++ } ++ ++ @Override ++ public void sendMessageChanged(CraftPlayer player, net.minecraft.network.chat.Component renderedMessage, Set viewers, ChatType.Bound chatType) { ++ ChatProcessor.this.server.getPlayerList().broadcastChatMessage(ChatProcessor.this.message.withUnsignedContent(renderedMessage), ChatProcessor.this.player, chatType); ++ } ++ ++ @Override ++ public void sendOriginal(CraftPlayer player, Set viewers, ChatType.Bound chatType) { ++ ChatProcessor.this.server.getPlayerList().broadcastChatMessage(ChatProcessor.this.message, ChatProcessor.this.player, chatType); ++ } ++ } ++ ++ final class ViewersOutgoingChat implements OutgoingChat { ++ @Override ++ public void sendFormatChangedViewerAware(CraftPlayer player, Component displayName, Component message, ChatRenderer renderer, Set viewers, ChatType.Bound chatType) { ++ this.broadcastToViewers(viewers, player, chatType, v -> PaperAdventure.asVanilla(renderer.render(player, displayName, message, v))); ++ } ++ ++ @Override ++ public void sendMessageChanged(CraftPlayer player, net.minecraft.network.chat.Component renderedMessage, Set viewers, ChatType.Bound chatType) { ++ this.broadcastToViewers(viewers, player, chatType, new ConstantFunction(renderedMessage)); ++ } ++ ++ @Override ++ public void sendOriginal(CraftPlayer player, Set viewers, ChatType.Bound chatType) { ++ this.broadcastToViewers(viewers, player, chatType, null); ++ } ++ ++ private void broadcastToViewers(Collection viewers, final Player source, final ChatType.Bound chatType, final @Nullable Function msgFunction) { ++ final Supplier fallbackSupplier = Suppliers.memoize(() -> PaperAdventure.asAdventure(msgFunction instanceof ConstantFunction constantFunction ? constantFunction.component : ChatProcessor.this.message.serverContent())); ++ final Function audienceMsgFunction = !(msgFunction instanceof ConstantFunction || msgFunction == null) ? msgFunction.andThen(PaperAdventure::asAdventure) : viewer -> fallbackSupplier.get(); ++ for (Audience viewer : viewers) { ++ if (viewer instanceof Player || viewer instanceof ConsoleCommandSender) { ++ // players and console have builtin PlayerChatMessage sending support while other audiences do not ++ this.sendToViewer((CommandSender) viewer, chatType, msgFunction); ++ } else { ++ viewer.sendMessage(source, audienceMsgFunction.apply(viewer), MessageType.CHAT); ++ } ++ } ++ } ++ ++ private void sendToViewer(final CommandSender viewer, final ChatType.Bound chatType, final @Nullable Function msgFunction) { ++ if (viewer instanceof ConsoleCommandSender) { ++ this.sendToServer(chatType, msgFunction); ++ } else if (viewer instanceof CraftPlayer craftPlayer) { ++ craftPlayer.getHandle().sendChatMessage(ChatProcessor.this.outgoing, ChatProcessor.this.player.shouldFilterMessageTo(craftPlayer.getHandle()), chatType, Util.mapNullable(msgFunction, f -> f.apply(viewer))); ++ } else { ++ throw new IllegalStateException("Should only be a Player or Console"); ++ } ++ } ++ ++ private void sendToServer(final ChatType.Bound chatType, final @Nullable Function msgFunction) { ++ final PlayerChatMessage toConsoleMessage = msgFunction == null ? ChatProcessor.this.message : ChatProcessor.this.message.withUnsignedContent(msgFunction.apply(ChatProcessor.this.server.console)); ++ ChatProcessor.this.server.logChatMessage(toConsoleMessage.serverContent(), chatType, ChatProcessor.this.server.getPlayerList().verifyChatTrusted(toConsoleMessage, ChatProcessor.this.player.asChatSender()) ? null : "Not Secure"); ++ } ++ ++ record ConstantFunction(net.minecraft.network.chat.Component component) implements Function { ++ @Override ++ public net.minecraft.network.chat.Component apply(Audience audience) { ++ return this.component; + } + } + } @@ -259,19 +581,27 @@ index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe24 + return viewers; + } + -+ private static String legacyDisplayName(final CraftPlayer player) { ++ static String legacyDisplayName(final CraftPlayer player) { + return player.getDisplayName(); + } + -+ private static Component displayName(final CraftPlayer player) { ++ static Component displayName(final CraftPlayer player) { + return player.displayName(); + } + ++ private static ChatRenderer.Default defaultRenderer() { ++ return (ChatRenderer.Default) ChatRenderer.defaultRenderer(); ++ } ++ + private static ChatRenderer legacyRenderer(final String format) { + if (DEFAULT_LEGACY_FORMAT.equals(format)) { -+ return ChatRenderer.defaultRenderer(); ++ return defaultRenderer(); + } -+ return ChatRenderer.viewerUnaware((player, displayName, message) -> LegacyComponentSerializer.legacySection().deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), LegacyComponentSerializer.legacySection().serialize(message))).replaceText(URL_REPLACEMENT_CONFIG)); ++ return ChatRenderer.viewerUnaware((player, sourceDisplayName, message) -> legacySection().deserialize(legacyFormat(format, player, legacySection().serialize(message)))); ++ } ++ ++ static String legacyFormat(final String format, Player player, String message) { ++ return String.format(format, legacyDisplayName((CraftPlayer) player), message); + } + + private void queueIfAsyncOrRunImmediately(final Waitable waitable) { @@ -293,7 +623,7 @@ index 0000000000000000000000000000000000000000..3526bc0b6ad590776124966ea907fe24 + this.server.server.getPluginManager().callEvent(event); + } + -+ private static boolean canYouHearMe(final HandlerList handlers) { ++ static boolean canYouHearMe(final HandlerList handlers) { + return handlers.getRegisteredListeners().length > 0; + } +} @@ -361,7 +691,7 @@ index 0000000000000000000000000000000000000000..2fd6c3e65354071af71c7d8ebb97b559 +} 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..3f25a9b1a74cfa0c9a4d0379ecda109d99f33db3 +index 0000000000000000000000000000000000000000..6679038054796b9bdfeb6fb4b29e50aa63052101 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java @@ -0,0 +1,331 @@ @@ -384,8 +714,8 @@ index 0000000000000000000000000000000000000000..3f25a9b1a74cfa0c9a4d0379ecda109d +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.flattener.ComponentFlattener; +import net.kyori.adventure.text.format.TextColor; ++import net.kyori.adventure.text.serializer.ComponentSerializer; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import net.kyori.adventure.translation.GlobalTranslator; @@ -474,7 +804,7 @@ index 0000000000000000000000000000000000000000..3f25a9b1a74cfa0c9a4d0379ecda109d + return decoded.toString(); + } + }; -+ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); ++ public static final ComponentSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer(); + + private PaperAdventure() { + } @@ -1090,6 +1420,28 @@ index 98f2def9125d6faf5859572a004fa8d2fa066417..436f381c727cda72c04859c540dce471 @Nullable public static ChatFormatting getById(int colorIndex) { if (colorIndex < 0) { +diff --git a/src/main/java/net/minecraft/commands/arguments/MessageArgument.java b/src/main/java/net/minecraft/commands/arguments/MessageArgument.java +index 6f65ee8bb555dfbfa96363e0a4cf8aadfd92fde3..30a9ff0fd92a1de6c1bce46719549b7803d0c716 100644 +--- a/src/main/java/net/minecraft/commands/arguments/MessageArgument.java ++++ b/src/main/java/net/minecraft/commands/arguments/MessageArgument.java +@@ -88,7 +88,7 @@ public class MessageArgument implements SignedArgument + MinecraftServer minecraftServer = source.getServer(); + source.getChatMessageChainer().append(() -> { + CompletableFuture completableFuture = this.filterPlainText(source, this.signedArgument.signedContent().plain()); +- CompletableFuture completableFuture2 = minecraftServer.getChatDecorator().decorate(source.getPlayer(), this.signedArgument); ++ CompletableFuture completableFuture2 = minecraftServer.getChatDecorator().decorate(source.getPlayer(), source,this.signedArgument); // Paper + return CompletableFuture.allOf(completableFuture, completableFuture2).thenAcceptAsync((void_) -> { + PlayerChatMessage playerChatMessage = completableFuture2.join().filter(completableFuture.join().mask()); + callback.accept(playerChatMessage); +@@ -131,7 +131,7 @@ public class MessageArgument implements SignedArgument + + CompletableFuture resolveDecoratedComponent(CommandSourceStack source) throws CommandSyntaxException { + Component component = this.resolveComponent(source); +- CompletableFuture completableFuture = source.getServer().getChatDecorator().decorate(source.getPlayer(), component); ++ CompletableFuture completableFuture = source.getServer().getChatDecorator().decorate(source.getPlayer(), source, component, true).thenApply(net.minecraft.network.chat.ChatDecorator.Result::component); // Paper + MessageArgument.logResolutionFailure(source, completableFuture); + return completableFuture; + } diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java index c4854debe11b8bb61fa49c76c1854f94c1e7777f..42514a0c7066dc79050c0496d6463528b593f9e4 100644 --- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java @@ -1147,6 +1499,168 @@ index 021a26a6b1c258deffc26c035ab52a4ea027d9a1..00d432bd395e7f7fb6ee24e371818d13 try { int i = friendlyByteBuf.writerIndex(); +diff --git a/src/main/java/net/minecraft/network/chat/ChatDecorator.java b/src/main/java/net/minecraft/network/chat/ChatDecorator.java +index b9cdd89a3871d934a0449ed70766c2e9d6369ab9..52307bdaed93de1c3ddb06477b3a5b434a8f7a68 100644 +--- a/src/main/java/net/minecraft/network/chat/ChatDecorator.java ++++ b/src/main/java/net/minecraft/network/chat/ChatDecorator.java +@@ -10,10 +10,81 @@ public interface ChatDecorator { + return CompletableFuture.completedFuture(message); + }; + ++ @io.papermc.paper.annotation.DoNotUse // Paper + CompletableFuture decorate(@Nullable ServerPlayer sender, Component message); + ++ // Paper start ++ default CompletableFuture decorate(@Nullable ServerPlayer sender, @Nullable net.minecraft.commands.CommandSourceStack commandSourceStack, Component message, boolean isPreview) { ++ throw new UnsupportedOperationException("Must override this implementation"); ++ } ++ ++ static ChatDecorator create(ImprovedChatDecorator delegate) { ++ return new ChatDecorator() { ++ @Override ++ public CompletableFuture decorate(@Nullable ServerPlayer sender, Component message) { ++ return this.decorate(sender, null, message, true).thenApply(Result::component); ++ } ++ ++ @Override ++ public CompletableFuture decorate(@Nullable ServerPlayer sender, @Nullable net.minecraft.commands.CommandSourceStack commandSourceStack, Component message, boolean isPreview) { ++ return delegate.decorate(sender, commandSourceStack, message, isPreview); ++ } ++ }; ++ } ++ ++ @FunctionalInterface ++ interface ImprovedChatDecorator { ++ CompletableFuture decorate(@Nullable ServerPlayer sender, @Nullable net.minecraft.commands.CommandSourceStack commandSourceStack, Component message, boolean isPreview); ++ } ++ ++ interface Result { ++ boolean hasNoFormatting(); ++ ++ Component component(); ++ ++ MessagePair message(); ++ ++ boolean modernized(); ++ } ++ ++ record MessagePair(net.kyori.adventure.text.Component component, String legacyMessage) { } ++ ++ record LegacyResult(Component component, String format, MessagePair message, boolean hasNoFormatting, boolean modernized) implements Result { ++ public LegacyResult(net.kyori.adventure.text.Component component, String format, MessagePair message, boolean hasNoFormatting, boolean modernified) { ++ this(io.papermc.paper.adventure.PaperAdventure.asVanilla(component), format, message, hasNoFormatting, modernified); ++ } ++ public LegacyResult { ++ component = component instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent ? adventureComponent.deepConverted() : component; ++ } ++ } ++ ++ record ModernResult(Component maybeAdventureComponent, boolean hasNoFormatting, boolean modernized) implements Result { ++ public ModernResult(net.kyori.adventure.text.Component component, boolean hasNoFormatting, boolean modernized) { ++ this(io.papermc.paper.adventure.PaperAdventure.asVanilla(component), hasNoFormatting, modernized); ++ } ++ ++ @Override ++ public Component component() { ++ return this.maybeAdventureComponent instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent ? adventureComponent.deepConverted() : this.maybeAdventureComponent; ++ } ++ ++ @Override ++ public MessagePair message() { ++ final net.kyori.adventure.text.Component adventureComponent = io.papermc.paper.adventure.PaperAdventure.WRAPPER_AWARE_SERIALIZER.deserialize(this.maybeAdventureComponent); ++ return new MessagePair(adventureComponent, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(adventureComponent)); ++ } ++ } ++ default CompletableFuture decorate(@Nullable ServerPlayer serverPlayer, @Nullable net.minecraft.commands.CommandSourceStack commandSourceStack, PlayerChatMessage playerChatMessage) { ++ return playerChatMessage.signedContent().isDecorated() ? CompletableFuture.completedFuture(playerChatMessage) : this.decorate(serverPlayer, commandSourceStack, playerChatMessage.serverContent(), false).thenApply(result -> { ++ return new PlayerChatMessage(playerChatMessage.signedHeader(), playerChatMessage.headerSignature(), playerChatMessage.signedBody().withContent(playerChatMessage.signedContent().withDecorationResult(result)), playerChatMessage.unsignedContent(), playerChatMessage.filterMask()).withUnsignedContent(result.component()); ++ }); ++ } ++ ++ // Paper end ++ ++ @io.papermc.paper.annotation.DoNotUse // Paper + default CompletableFuture decorate(@Nullable ServerPlayer serverPlayer, PlayerChatMessage playerChatMessage) { +- return playerChatMessage.signedContent().isDecorated() ? CompletableFuture.completedFuture(playerChatMessage) : this.decorate(serverPlayer, playerChatMessage.serverContent()).thenApply(playerChatMessage::withUnsignedContent); ++ return this.decorate(serverPlayer, null, playerChatMessage); // Paper + } + + static PlayerChatMessage attachIfNotDecorated(PlayerChatMessage playerChatMessage, Component component) { +diff --git a/src/main/java/net/minecraft/network/chat/ChatMessageContent.java b/src/main/java/net/minecraft/network/chat/ChatMessageContent.java +index b1c76ccfb4527337ac2c9ad2d2c7e34df0c4c660..e7caa6380b07f9bd34c2f8c821c0f6d3cb4e7649 100644 +--- a/src/main/java/net/minecraft/network/chat/ChatMessageContent.java ++++ b/src/main/java/net/minecraft/network/chat/ChatMessageContent.java +@@ -3,7 +3,17 @@ package net.minecraft.network.chat; + import java.util.Objects; + import net.minecraft.network.FriendlyByteBuf; + +-public record ChatMessageContent(String plain, Component decorated) { ++// Paper start ++public record ChatMessageContent(String plain, Component decorated, ChatDecorator.Result decorationResult) { ++ ++ public ChatMessageContent(String plain, Component decorated) { ++ this(plain, decorated, new ChatDecorator.ModernResult(decorated, true, false)); ++ } ++ ++ public ChatMessageContent withDecorationResult(ChatDecorator.Result result) { ++ return new ChatMessageContent(this.plain, this.decorated, result); ++ } ++ // Paper end + public ChatMessageContent(String content) { + this(content, Component.literal(content)); + } +diff --git a/src/main/java/net/minecraft/network/chat/ChatPreviewCache.java b/src/main/java/net/minecraft/network/chat/ChatPreviewCache.java +index 85e75f3eb58be03b500e663a128663cbe9331605..487822cc8e491c38a276d0d78db6f5207de8a65b 100644 +--- a/src/main/java/net/minecraft/network/chat/ChatPreviewCache.java ++++ b/src/main/java/net/minecraft/network/chat/ChatPreviewCache.java +@@ -1,27 +1,44 @@ + package net.minecraft.network.chat; + + import javax.annotation.Nullable; ++import net.minecraft.Util; + + public class ChatPreviewCache { + @Nullable + private ChatPreviewCache.Result result; + + public void set(String query, Component preview) { +- this.result = new ChatPreviewCache.Result(query, preview); ++ // Paper start ++ this.set(query, new ChatDecorator.ModernResult(java.util.Objects.requireNonNull(preview), true, false)); ++ } ++ public void set(String query, ChatDecorator.Result decoratorResult) { ++ this.result = new ChatPreviewCache.Result(query, java.util.Objects.requireNonNull(decoratorResult)); ++ // Paper end + } + + @Nullable + public Component pull(String query) { ++ // Paper start ++ return net.minecraft.Util.mapNullable(this.pullFull(query), Result::preview); ++ } ++ public @Nullable Result pullFull(String query) { ++ // Paper end + ChatPreviewCache.Result result = this.result; + if (result != null && result.matches(query)) { + this.result = null; +- return result.preview(); ++ return result; // Paper + } else { + return null; + } + } + +- static record Result(String query, Component preview) { ++ // Paper start ++ public record Result(String query, ChatDecorator.Result decoratorResult) { ++ ++ public Component preview() { ++ return this.decoratorResult.component(); ++ } ++ // Paper end + public boolean matches(String query) { + return this.query.equals(query); + } diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java index 06736982f7625c1a532315afe94e5e0c45ec1331..e7d9e2d8c87ddf3658b1c2e0f2a3e98ef8080cec 100644 --- a/src/main/java/net/minecraft/network/chat/Component.java @@ -1175,6 +1689,54 @@ index 06736982f7625c1a532315afe94e5e0c45ec1331..e7d9e2d8c87ddf3658b1c2e0f2a3e98e JsonObject jsonobject = new JsonObject(); if (!ichatbasecomponent.getStyle().isEmpty()) { +diff --git a/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java b/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java +index 952dfc9ce81bc8ce2efb120884a5723145445f3c..fc43cc6f5bbb3485b9ddcc441a13399e57289586 100644 +--- a/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java ++++ b/src/main/java/net/minecraft/network/chat/OutgoingPlayerChatMessage.java +@@ -13,6 +13,11 @@ public interface OutgoingPlayerChatMessage { + Component serverContent(); + + void sendToPlayer(ServerPlayer serverPlayer, boolean bl, ChatType.Bound bound); ++ // Paper start ++ default void sendToPlayer(ServerPlayer serverPlayer, boolean shouldFilter, ChatType.Bound bound, @javax.annotation.Nullable Component unsigned) { ++ this.sendToPlayer(serverPlayer, shouldFilter, bound); ++ } ++ // Paper end + + void sendHeadersToRemainingPlayers(PlayerList playerManager); + +@@ -34,7 +39,15 @@ public interface OutgoingPlayerChatMessage { + + @Override + public void sendToPlayer(ServerPlayer serverPlayer, boolean bl, ChatType.Bound bound) { ++ // Paper start ++ this.sendToPlayer(serverPlayer, bl, bound, null); ++ } ++ ++ @Override ++ public void sendToPlayer(ServerPlayer serverPlayer, boolean bl, ChatType.Bound bound, @javax.annotation.Nullable Component unsigned) { ++ // Paper end + PlayerChatMessage playerChatMessage = this.message.filter(bl); ++ playerChatMessage = unsigned != null ? playerChatMessage.withUnsignedContent(unsigned) : playerChatMessage; // Paper + if (!playerChatMessage.isFullyFiltered()) { + RegistryAccess registryAccess = serverPlayer.level.registryAccess(); + ChatType.BoundNetwork boundNetwork = bound.toNetwork(registryAccess); +@@ -64,7 +77,15 @@ public interface OutgoingPlayerChatMessage { + + @Override + public void sendToPlayer(ServerPlayer serverPlayer, boolean bl, ChatType.Bound bound) { ++ // Paper start ++ this.sendToPlayer(serverPlayer, bl, bound, null); ++ } ++ ++ @Override ++ public void sendToPlayer(ServerPlayer serverPlayer, boolean bl, ChatType.Bound bound, @javax.annotation.Nullable Component unsigned) { ++ // Paper end + PlayerChatMessage playerChatMessage = this.message.filter(bl); ++ playerChatMessage = unsigned != null ? playerChatMessage.withUnsignedContent(unsigned) : playerChatMessage; // Paper + if (!playerChatMessage.isFullyFiltered()) { + this.playersWithFullMessage.add(serverPlayer); + RegistryAccess registryAccess = serverPlayer.level.registryAccess(); diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java index 02183c810f9968621b9b20c1f7b54258b620c507..32ef3edebe94a2014168b7e438752a80b2687e5f 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java @@ -1326,7 +1888,7 @@ index 762a9392ffac3042356709dddd15bb3516048bed..3544e2dc2522e9d6305d727d56e73490 buf.writeComponent(this.footer); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3aadba90ab32388b9e8ef96f182fa263c760f53b..acc5ce86ae8aa5ada21e6c97f7921caca4b0bd00 100644 +index 20a0a14f331ed891a64bd3ed69ade9cf2d917922..b9a6533afbfe07ff544f9f03f3c254890ee2e068 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -229,6 +229,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- // SPIGOT-7127: Console /say and similar +- if (entityplayer == null) { +- return CompletableFuture.completedFuture(ichatbasecomponent); +- } +- +- return CompletableFuture.supplyAsync(() -> { +- AsyncPlayerChatPreviewEvent event = new AsyncPlayerChatPreviewEvent(true, entityplayer.getBukkitEntity(), CraftChatMessage.fromComponent(ichatbasecomponent), new LazyPlayerSet(this)); +- String originalFormat = event.getFormat(), originalMessage = event.getMessage(); +- this.server.getPluginManager().callEvent(event); +- +- if (originalFormat.equals(event.getFormat()) && originalMessage.equals(event.getMessage()) && event.getPlayer().getName().equalsIgnoreCase(event.getPlayer().getDisplayName())) { +- return ichatbasecomponent; +- } +- +- return CraftChatMessage.fromStringOrNull(String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage())); +- }, chatExecutor); +- }; ++ // Paper start - moved to ChatPreviewProcessor ++ return ChatDecorator.create((sender, commandSourceStack, message, isPreview) -> { ++ final io.papermc.paper.adventure.ChatDecorationProcessor processor = new io.papermc.paper.adventure.ChatDecorationProcessor(this, sender, commandSourceStack, message, isPreview); ++ return processor.process(); ++ }); ++ // Paper end + // CraftBukkit end + } + diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 4759a0eceeccf28b62cb8865b423235d47d07443..58aea845e8ce6e46e52fc3bdfa9c64153c32a750 100644 +index 4759a0eceeccf28b62cb8865b423235d47d07443..bee13e04481f57bf6778b66cd0bc2891e069547a 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -154,6 +154,7 @@ import net.minecraft.world.scores.Score; @@ -1411,7 +2008,22 @@ index 4759a0eceeccf28b62cb8865b423235d47d07443..58aea845e8ce6e46e52fc3bdfa9c6415 this.connection.send(new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), ichatbasecomponent), PacketSendListener.exceptionallySend(() -> { boolean flag1 = true; -@@ -1751,6 +1749,7 @@ public class ServerPlayer extends Player { +@@ -1729,8 +1727,13 @@ public class ServerPlayer extends Player { + } + + public void sendChatMessage(OutgoingPlayerChatMessage message, boolean flag, ChatType.Bound chatmessagetype_a) { ++ // Paper start ++ this.sendChatMessage(message, flag, chatmessagetype_a, null); ++ } ++ public void sendChatMessage(OutgoingPlayerChatMessage message, boolean flag, ChatType.Bound chatmessagetype_a, @Nullable Component unsigned) { ++ // Paper end + if (this.acceptsChatMessages()) { +- message.sendToPlayer(this, flag, chatmessagetype_a); ++ message.sendToPlayer(this, flag, chatmessagetype_a, unsigned); // Paper + } + + } +@@ -1751,6 +1754,7 @@ public class ServerPlayer extends Player { } public String locale = "en_us"; // CraftBukkit - add, lowercase @@ -1419,7 +2031,7 @@ index 4759a0eceeccf28b62cb8865b423235d47d07443..58aea845e8ce6e46e52fc3bdfa9c6415 public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start if (getMainArm() != packet.mainHand()) { -@@ -1762,6 +1761,10 @@ public class ServerPlayer extends Player { +@@ -1762,6 +1766,10 @@ public class ServerPlayer extends Player { this.server.server.getPluginManager().callEvent(event); } this.locale = packet.language; @@ -1431,7 +2043,7 @@ index 4759a0eceeccf28b62cb8865b423235d47d07443..58aea845e8ce6e46e52fc3bdfa9c6415 // CraftBukkit end this.chatVisibility = packet.chatVisibility(); diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 13f996d163739f419b701854b5248a02edfc93c0..59932a4f83461280ab3c097add951e5a138eb53d 100644 +index 13f996d163739f419b701854b5248a02edfc93c0..0620ba3f5e26279e0165d86f589d73f423d633f0 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -187,6 +187,8 @@ import org.apache.commons.lang3.StringUtils; @@ -1512,6 +2124,15 @@ index 13f996d163739f419b701854b5248a02edfc93c0..59932a4f83461280ab3c097add951e5a } // CraftBukkit end this.player.getTextFilter().leave(); +@@ -1877,7 +1884,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + if (this.verifyChatMessage(playerchatmessage)) { + this.chatMessageChain.append(() -> { + CompletableFuture completablefuture = this.filterTextPacket(playerchatmessage.signedContent().plain()); +- CompletableFuture completablefuture1 = this.server.getChatDecorator().decorate(this.player, playerchatmessage); ++ CompletableFuture completablefuture1 = this.server.getChatDecorator().decorate(this.player, null, playerchatmessage); // Paper + + return CompletableFuture.allOf(completablefuture, completablefuture1).thenAcceptAsync((ovoid) -> { + FilterMask filtermask = ((FilteredText) completablefuture.join()).mask(); @@ -2039,7 +2046,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic this.handleCommand(s); } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { @@ -1519,14 +2140,60 @@ index 13f996d163739f419b701854b5248a02edfc93c0..59932a4f83461280ab3c097add951e5a - } else { + // Paper start + } else if (true) { -+ final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async); ++ final ChatProcessor cp = new ChatProcessor(this.server, this.player, original, async); + cp.process(); + // Paper end + } else if (false) { // Paper Player player = this.getCraftPlayer(); AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.server)); String originalFormat = event.getFormat(), originalMessage = event.getMessage(); -@@ -3076,30 +3088,30 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2172,9 +2184,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + } + + private ChatMessageContent getSignedContent(ServerboundChatPacket packet) { +- Component ichatbasecomponent = this.chatPreviewCache.pull(packet.message()); ++ // Paper start ++ final net.minecraft.network.chat.ChatPreviewCache.Result result = this.chatPreviewCache.pullFull(packet.message()); ++ Component ichatbasecomponent = result != null ? result.preview() : null; ++ // Paper end + +- return packet.signedPreview() && ichatbasecomponent != null ? new ChatMessageContent(packet.message(), ichatbasecomponent) : new ChatMessageContent(packet.message()); ++ return packet.signedPreview() && ichatbasecomponent != null ? new ChatMessageContent(packet.message(), ichatbasecomponent, result.decoratorResult()) : new ChatMessageContent(packet.message()); // Paper end + } + + private void broadcastChatMessage(PlayerChatMessage playerchatmessage) { +@@ -2269,14 +2284,17 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + + private CompletableFuture queryChatPreview(String query) { + MutableComponent ichatmutablecomponent = Component.literal(query); +- CompletableFuture completablefuture = this.server.getChatDecorator().decorate(this.player, (Component) ichatmutablecomponent).thenApply((ichatbasecomponent) -> { +- return !ichatmutablecomponent.equals(ichatbasecomponent) ? ichatbasecomponent : null; ++ // Paper start ++ final CompletableFuture result = this.server.getChatDecorator().decorate(this.player, null, ichatmutablecomponent, true); ++ CompletableFuture completablefuture = result.thenApply((res) -> { ++ return !ichatmutablecomponent.equals(res.component()) ? res : null; ++ // Paper end + }); + + completablefuture.thenAcceptAsync((ichatbasecomponent) -> { +- this.chatPreviewCache.set(query, ichatbasecomponent); ++ if (ichatbasecomponent != null) this.chatPreviewCache.set(query, ichatbasecomponent); // Paper + }, this.server); +- return completablefuture; ++ return completablefuture.thenApply(net.minecraft.network.chat.ChatDecorator.Result::component); // paper + } + + private CompletableFuture queryCommandPreview(String query) { +@@ -2285,7 +2303,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic + CompletableFuture completablefuture = this.getPreviewedArgument(commandlistenerwrapper, PreviewableCommand.of(parseresults)); + + completablefuture.thenAcceptAsync((ichatbasecomponent) -> { +- this.chatPreviewCache.set(query, ichatbasecomponent); ++ if (ichatbasecomponent != null) this.chatPreviewCache.set(query, ichatbasecomponent); // Paper + }, this.server); + return completablefuture; + } +@@ -3076,30 +3094,30 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic return; } @@ -1606,7 +2273,7 @@ index 3a587073dbe5e8a599d342c5f758d842b7b6cddb..a426adfba3fccf1815177e0b8065684c @Override diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index ba6f4e9f74a524201390bd0e9106a6cf6afe0375..946b2b7341a10c25fae71d76f7b181b555fe38b6 100644 +index ba6f4e9f74a524201390bd0e9106a6cf6afe0375..68ea3623dedefbc695bbb53e163911d3dfbfbf7e 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -8,6 +8,7 @@ import com.mojang.logging.LogUtils; @@ -1721,6 +2388,52 @@ index ba6f4e9f74a524201390bd0e9106a6cf6afe0375..946b2b7341a10c25fae71d76f7b181b5 } // CraftBukkit end +@@ -1169,14 +1169,25 @@ public abstract class PlayerList { + } + + public void broadcastChatMessage(PlayerChatMessage playerchatmessage, ServerPlayer sender, ChatType.Bound params) { ++ // Paper start ++ this.broadcastChatMessage(playerchatmessage, sender, params, null); ++ } ++ public void broadcastChatMessage(PlayerChatMessage playerchatmessage, ServerPlayer sender, ChatType.Bound params, @Nullable Function unsignedFunction) { ++ // Paper end + Objects.requireNonNull(sender); +- this.broadcastChatMessage(playerchatmessage, sender::shouldFilterMessageTo, sender, sender.asChatSender(), params); ++ this.broadcastChatMessage(playerchatmessage, sender::shouldFilterMessageTo, sender, sender.asChatSender(), params, unsignedFunction); // Paper + } + + private void broadcastChatMessage(PlayerChatMessage playerchatmessage, Predicate shouldSendFiltered, @Nullable ServerPlayer entityplayer, ChatSender chatsender, ChatType.Bound chatmessagetype_a) { ++ // Paper start ++ this.broadcastChatMessage(playerchatmessage, shouldSendFiltered, entityplayer, chatsender, chatmessagetype_a, null); ++ } ++ ++ private void broadcastChatMessage(PlayerChatMessage playerchatmessage, Predicate shouldSendFiltered, @Nullable ServerPlayer entityplayer, ChatSender chatsender, ChatType.Bound chatmessagetype_a, @Nullable Function unsignedFunction) { ++ // Paper end + boolean flag = this.verifyChatTrusted(playerchatmessage, chatsender); + +- this.server.logChatMessage(playerchatmessage.serverContent(), chatmessagetype_a, flag ? null : "Not Secure"); ++ this.server.logChatMessage((unsignedFunction == null ? playerchatmessage : playerchatmessage.withUnsignedContent(unsignedFunction.apply(this.server.console))).serverContent(), chatmessagetype_a, flag ? null : "Not Secure"); // Paper + OutgoingPlayerChatMessage outgoingplayerchatmessage = OutgoingPlayerChatMessage.create(playerchatmessage); + boolean flag1 = playerchatmessage.isFullyFiltered(); + boolean flag2 = false; +@@ -1186,7 +1197,7 @@ public abstract class PlayerList { + ServerPlayer entityplayer1 = (ServerPlayer) iterator.next(); + boolean flag3 = shouldSendFiltered.test(entityplayer1); + +- entityplayer1.sendChatMessage(outgoingplayerchatmessage, flag3, chatmessagetype_a); ++ entityplayer1.sendChatMessage(outgoingplayerchatmessage, flag3, chatmessagetype_a, unsignedFunction == null ? null : unsignedFunction.apply(entityplayer1.getBukkitEntity())); + if (entityplayer != entityplayer1) { + flag2 |= flag1 && flag3; + } +@@ -1213,7 +1224,7 @@ public abstract class PlayerList { + + } + +- private boolean verifyChatTrusted(PlayerChatMessage message, ChatSender profile) { ++ public boolean verifyChatTrusted(PlayerChatMessage message, ChatSender profile) { // Paper - private -> public + return !message.hasExpiredServer(Instant.now()) && message.verify(profile); + } + diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java index 4c62df5a3781ec9df4a5c5f1b528649e6e8a62d1..affd1b8c7589ba59330dc0b6fc803cce4ee57397 100644 --- a/src/main/java/net/minecraft/world/BossEvent.java @@ -2004,7 +2717,7 @@ index 93308369f0bbd1e95569d9d573b8b6f42c8ae5a7..cf7762e76a2d35acdfc12627e9750fbe + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index b05cea49219c6582bacc705f41e72ca7c7eb6a8c..c520e8e53356188ee00dc10a6a74c88b5e2f6e94 100644 +index e8d71985f2e96574081e4f609d62a3b8bded8249..681b58e6de48cccac82c7b6833f6fcea46d83dde 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -19,6 +19,12 @@ public class Main { @@ -2486,7 +3199,7 @@ index 446fdca49a5a6999626a7ee3a1d5c168b15a09dd..f9863e138994f6c7a7975a852f106faa public boolean isOp() { return true; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index cadafdfd3469b6f813f5e0add116640313fb6209..ac6fd14f18f2fa2247db4d2d8c9233f862b85111 100644 +index e9036bbb2ec2862252c3a39a4022e195784291ca..ef5e29e0a66f8d4cb819c4383cf3f1317d4e5bb0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -269,14 +269,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0039-Implement-PlayerLocaleChangeEvent.patch b/patches/server/0039-Implement-PlayerLocaleChangeEvent.patch index b9a9162157..41fbaec734 100644 --- a/patches/server/0039-Implement-PlayerLocaleChangeEvent.patch +++ b/patches/server/0039-Implement-PlayerLocaleChangeEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Implement PlayerLocaleChangeEvent diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 5ff3bf1c436fd69e6129e59c205f626df9d61e8d..a3410c8f89c4b7f68999aafb090555c7e7513316 100644 +index 16c4df6bd5b84b5e7a820ba14f2b2ee80b5b401c..48ffa3fce91ad98d9e4c099aacf6c0a84b2093e4 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1749,7 +1749,7 @@ public class ServerPlayer extends Player { +@@ -1754,7 +1754,7 @@ public class ServerPlayer extends Player { return s; } @@ -17,7 +17,7 @@ index 5ff3bf1c436fd69e6129e59c205f626df9d61e8d..a3410c8f89c4b7f68999aafb090555c7 public java.util.Locale adventure$locale = java.util.Locale.US; // Paper public void updateOptions(ServerboundClientInformationPacket packet) { // CraftBukkit start -@@ -1757,9 +1757,10 @@ public class ServerPlayer extends Player { +@@ -1762,9 +1762,10 @@ public class ServerPlayer extends Player { PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(this.getBukkitEntity(), getMainArm() == HumanoidArm.LEFT ? MainHand.LEFT : MainHand.RIGHT); this.server.server.getPluginManager().callEvent(event); } @@ -30,7 +30,7 @@ index 5ff3bf1c436fd69e6129e59c205f626df9d61e8d..a3410c8f89c4b7f68999aafb090555c7 this.locale = packet.language; // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 46abb31a5330662f46949466e01c404ba2922027..b6d03bdd161da73492fb947cc4ca4f6c1ba172f1 100644 +index 6d2609222afa3cd5f99118281c20281f8c2f792f..9bcffda912e3cc7322043e705dddfe052f4b1273 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1965,8 +1965,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0040-Per-Player-View-Distance-API-placeholders.patch b/patches/server/0040-Per-Player-View-Distance-API-placeholders.patch index 221d8dcfd0..ccdb2bf31b 100644 --- a/patches/server/0040-Per-Player-View-Distance-API-placeholders.patch +++ b/patches/server/0040-Per-Player-View-Distance-API-placeholders.patch @@ -7,10 +7,10 @@ I hope to look at this more in-depth soon. It appears doable. However this should not block the update. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a3410c8f89c4b7f68999aafb090555c7e7513316..b6a19cd2cfd8acfac6dde77033bbb82ef20586d0 100644 +index 48ffa3fce91ad98d9e4c099aacf6c0a84b2093e4..28d8ba2f421245ab6707ea982e76d543916a1e51 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2232,4 +2232,6 @@ public class ServerPlayer extends Player { +@@ -2237,4 +2237,6 @@ public class ServerPlayer extends Player { return (CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -60,7 +60,7 @@ index cf7762e76a2d35acdfc12627e9750fbec766d555..40d6b00fb40db167c6c80b6a3f79eb82 // Spigot start private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index b6d03bdd161da73492fb947cc4ca4f6c1ba172f1..b73b202a3c68ba559b65245186a97025bda25134 100644 +index 9bcffda912e3cc7322043e705dddfe052f4b1273..62a4ae1ee2a0784787b6f45bff6393630e1d4219 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -402,6 +402,46 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0079-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0079-Add-PlayerUseUnknownEntityEvent.patch index 6e717ab751..d4da1e88e3 100644 --- a/patches/server/0079-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0079-Add-PlayerUseUnknownEntityEvent.patch @@ -20,10 +20,10 @@ index 8834ed411a7db86b4d2b88183a1315317107d719..c45b5ab6776f3ac79f856c3a6467c510 static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() { @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 2e9aa7bcdaf86165190d16098d7f6363bfa2f837..680193185185972d3b9112c7b59565bce1b1729a 100644 +index 101dde32d7ad708d4826f0dbf81263f07c31085b..ce3b68275ca399b5900012d5170e70fb35602695 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2613,8 +2613,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2619,8 +2619,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic }); } } 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 4b02783b1c..04ed9957ea 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 @@ -12,29 +12,31 @@ for this on CB at one point but I can't find it. We may need to do this ourselves at some point in the future. diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index 3526bc0b6ad590776124966ea907fe2467cbbf5f..b13d516d91788713768b5c336537ffe31653b074 100644 +index bc37199f1d181f572da518d9b93b2980504024b1..d5e0ed2adba4e22b9842110ddf009f47187840e4 100644 --- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -@@ -16,6 +16,8 @@ import net.kyori.adventure.text.event.ClickEvent; - import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +@@ -24,8 +24,10 @@ import net.minecraft.network.chat.PlayerChatMessage; + import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; +import org.bukkit.ChatColor; + import org.bukkit.command.CommandSender; + import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.util.LazyPlayerSet; import org.bukkit.craftbukkit.util.Waitable; -@@ -154,10 +156,16 @@ public final class ChatProcessor { +@@ -329,10 +331,16 @@ public final class ChatProcessor { } - private static String legacyDisplayName(final CraftPlayer player) { + static String legacyDisplayName(final CraftPlayer player) { + if (((org.bukkit.craftbukkit.CraftWorld) player.getWorld()).getHandle().paperConfig().scoreboards.useVanillaWorldScoreboardNameColoring) { -+ return LegacyComponentSerializer.legacySection().serialize(player.teamDisplayName()) + ChatColor.RESET; ++ return legacySection().serialize(player.teamDisplayName()) + ChatColor.RESET; + } return player.getDisplayName(); } - private static Component displayName(final CraftPlayer player) { + static Component displayName(final CraftPlayer player) { + if (((CraftWorld) player.getWorld()).getHandle().paperConfig().scoreboards.useVanillaWorldScoreboardNameColoring) { + return player.teamDisplayName(); + } diff --git a/patches/server/0119-Properly-fix-item-duplication-bug.patch b/patches/server/0119-Properly-fix-item-duplication-bug.patch index aaf16b075f..4a25d9c776 100644 --- a/patches/server/0119-Properly-fix-item-duplication-bug.patch +++ b/patches/server/0119-Properly-fix-item-duplication-bug.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Properly fix item duplication bug Credit to prplz for figuring out the real issue diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b117a98dea77755bee33f8a141f8df16b587beeb..8f4b8e4911d5c3bb82c9ac246c041c0eb51a3123 100644 +index 9cd5bf2890fbb0bdb8eb79b1659fe7058dbe08e9..b239654eb92f95cb855cd3d750c79f98893f9980 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2189,7 +2189,7 @@ public class ServerPlayer extends Player { +@@ -2194,7 +2194,7 @@ public class ServerPlayer extends Player { @Override public boolean isImmobile() { @@ -19,10 +19,10 @@ index b117a98dea77755bee33f8a141f8df16b587beeb..8f4b8e4911d5c3bb82c9ac246c041c0e @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 50759c53b46b913ac7ff56476d2a49163e54fff4..44daf6210786748f44275a97ecebbd191837b5e5 100644 +index 26e10d245adbac49f9c30ada74729444fe0fedaf..21e1520e30a4655c679b3f3b4f8f8e053f245aca 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3252,7 +3252,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3258,7 +3258,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } public final boolean isDisconnected() { diff --git a/patches/server/0131-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/0131-Add-option-to-make-parrots-stay-on-shoulders-despite.patch index c18bd20fc5..95f44c6c77 100644 --- a/patches/server/0131-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ b/patches/server/0131-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -11,10 +11,10 @@ I suspect Mojang may switch to this behavior before full release. To be converted into a Paper-API event at some point in the future? diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 44daf6210786748f44275a97ecebbd191837b5e5..7bf555082539dc6cc4151df875b048b85fdba020 100644 +index 21e1520e30a4655c679b3f3b4f8f8e053f245aca..7a55caac4bf216484780e243ae2b58798ceea520 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2438,6 +2438,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2444,6 +2444,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic switch (packet.getAction()) { case PRESS_SHIFT_KEY: this.player.setShiftKeyDown(true); diff --git a/patches/server/0157-handle-ServerboundKeepAlivePacket-async.patch b/patches/server/0157-handle-ServerboundKeepAlivePacket-async.patch index 18988ee1e2..7d5c9f0cac 100644 --- a/patches/server/0157-handle-ServerboundKeepAlivePacket-async.patch +++ b/patches/server/0157-handle-ServerboundKeepAlivePacket-async.patch @@ -15,10 +15,10 @@ also adding some additional logging in order to help work out what is causing random disconnections for clients. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f7da31103f75e6bdc06f28a35e3341ec360bd245..49f7840a04f12ae6a28f3e0282d3e4529496c736 100644 +index 12325f4eafb7c7f4fd273464c1244d8c4f99fce7..d2641f1aad42f9e3930e5fe106a3a40f833e3945 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3211,14 +3211,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3217,14 +3217,18 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @Override public void handleKeepAlive(ServerboundKeepAlivePacket packet) { diff --git a/patches/server/0189-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server/0189-Fix-exploit-that-allowed-colored-signs-to-be-created.patch index 22d93ebb58..856af4a308 100644 --- a/patches/server/0189-Fix-exploit-that-allowed-colored-signs-to-be-created.patch +++ b/patches/server/0189-Fix-exploit-that-allowed-colored-signs-to-be-created.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix exploit that allowed colored signs to be created diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index dc3725622f8ae2832ff4329aa78395c5cc67c02f..5bd5cde911520eb0da695b961867a52845ad416f 100644 +index b465bf1a3ffa9fd164592967c6ebbab85f374a73..a0b52f23170cc7b75b556dd8223c16881abd7f3b 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3217,9 +3217,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3223,9 +3223,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic FilteredText filteredtext = (FilteredText) signText.get(i); if (this.player.isTextFilteringEnabled()) { diff --git a/patches/server/0215-InventoryCloseEvent-Reason-API.patch b/patches/server/0215-InventoryCloseEvent-Reason-API.patch index d92c40acec..bb5e6bb71f 100644 --- a/patches/server/0215-InventoryCloseEvent-Reason-API.patch +++ b/patches/server/0215-InventoryCloseEvent-Reason-API.patch @@ -29,7 +29,7 @@ index 3d3926a14229d922fb7b7e76c9babb031bf7d9ab..5029436157fe7279a2a583f06b7d02a0 } // Spigot End diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index a9497e21c87e785631788968bc4922f6261169f9..522c8791edd87feb6cb32ef8e621ae35e53c9cb1 100644 +index dac7d458f161bc7449fee7142ac6cc95bf92388d..c14854f653342a6c4c8e520c3821866472d3c8af 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -610,7 +610,7 @@ public class ServerPlayer extends Player { @@ -75,7 +75,7 @@ index a9497e21c87e785631788968bc4922f6261169f9..522c8791edd87feb6cb32ef8e621ae35 this.doCloseContainer(); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5bd5cde911520eb0da695b961867a52845ad416f..57e3301e5b18d90d6f499fa6a544866a5eca01a9 100644 +index a0b52f23170cc7b75b556dd8223c16881abd7f3b..231e3dfecbc2fee1889f29821201a574f22d73e5 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -216,6 +216,7 @@ import org.bukkit.event.inventory.ClickType; @@ -86,7 +86,7 @@ index 5bd5cde911520eb0da695b961867a52845ad416f..57e3301e5b18d90d6f499fa6a544866a import org.bukkit.event.inventory.InventoryCreativeEvent; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.event.inventory.SmithItemEvent; -@@ -2743,10 +2744,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2749,10 +2750,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @Override public void handleContainerClose(ServerboundContainerClosePacket packet) { @@ -104,7 +104,7 @@ index 5bd5cde911520eb0da695b961867a52845ad416f..57e3301e5b18d90d6f499fa6a544866a this.player.doCloseContainer(); } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 29f761432be28b5089caab9338b3bff41f4f8f07..2ad88d72a9d14c7e73a824544a1ebcb6bb74a127 100644 +index 861f736c32d85abbce8dfade503ec0976aa7a275..a7d7882652c9361f37dfcbaec3872a50e048b4b9 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -507,7 +507,7 @@ public abstract class PlayerList { @@ -173,7 +173,7 @@ index 4ff81744b7c9113f57cf1fa89bb943902711b2dc..404ed5e8f54d70a50de4232c6ea0f616 @Override public boolean isBlocking() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c63831b9ec29ea1589cc87fbe4615f6dfddce473..f5259ada3e21b036fd3e3b96d727f1c8c4a042b8 100644 +index 3ff83fcee396b220cc1977f85ce3af399a4c2802..0c6226292f1928f657ea77529992123ad6f7bc9b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1079,7 +1079,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0217-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server/0217-Refresh-player-inventory-when-cancelling-PlayerInter.patch index 3bb306582c..94dfab8113 100644 --- a/patches/server/0217-Refresh-player-inventory-when-cancelling-PlayerInter.patch +++ b/patches/server/0217-Refresh-player-inventory-when-cancelling-PlayerInter.patch @@ -16,10 +16,10 @@ Refresh the player inventory when PlayerInteractEntityEvent is cancelled to avoid this problem. diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 57e3301e5b18d90d6f499fa6a544866a5eca01a9..15e69839cb1da5f0402e9abd155fb67d323b8f5d 100644 +index 231e3dfecbc2fee1889f29821201a574f22d73e5..b3570e63957efea26e1538f1cb44304c22b84040 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2628,6 +2628,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2634,6 +2634,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } if (event.isCancelled()) { diff --git a/patches/server/0271-Call-player-spectator-target-events-and-improve-impl.patch b/patches/server/0271-Call-player-spectator-target-events-and-improve-impl.patch index b3d594b2dd..bc8632e576 100644 --- a/patches/server/0271-Call-player-spectator-target-events-and-improve-impl.patch +++ b/patches/server/0271-Call-player-spectator-target-events-and-improve-impl.patch @@ -19,10 +19,10 @@ spectate the target entity. Co-authored-by: Spottedleaf diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 1b3188837069622baaba90c80fe387abfbfad10a..f9cd8040f0782c0c0543c8a9f52727ba838f987f 100644 +index 56b1c585d1c330bf9b904ebf8ef0b8be47102aa3..e4f991578d4ee581e65f2edb7d32640ff36a01bd 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -1870,14 +1870,58 @@ public class ServerPlayer extends Player { +@@ -1875,14 +1875,58 @@ public class ServerPlayer extends Player { } public void setCamera(@Nullable Entity entity) { diff --git a/patches/server/0277-Reset-players-airTicks-on-respawn.patch b/patches/server/0277-Reset-players-airTicks-on-respawn.patch index 4263234b5a..604f55e563 100644 --- a/patches/server/0277-Reset-players-airTicks-on-respawn.patch +++ b/patches/server/0277-Reset-players-airTicks-on-respawn.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Reset players airTicks on respawn diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f9cd8040f0782c0c0543c8a9f52727ba838f987f..ca3206ad7c6e4acf31eda406c439fc7c70e47c01 100644 +index e4f991578d4ee581e65f2edb7d32640ff36a01bd..c5120e5e7414a6b870eab877605e9bb52db3e8cb 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2283,6 +2283,7 @@ public class ServerPlayer extends Player { +@@ -2288,6 +2288,7 @@ public class ServerPlayer extends Player { this.setHealth(this.getMaxHealth()); this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset diff --git a/patches/server/0300-Limit-Client-Sign-length-more.patch b/patches/server/0300-Limit-Client-Sign-length-more.patch index 798d1e7df2..f85faa474d 100644 --- a/patches/server/0300-Limit-Client-Sign-length-more.patch +++ b/patches/server/0300-Limit-Client-Sign-length-more.patch @@ -22,7 +22,7 @@ it only impacts data sent from the client. Set -DPaper.maxSignLength=XX to change limit or -1 to disable diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ed272499b40a96efd83f1a09a063e4d65dbe48e8..32c89f89fc9dbcdc9528acf46415b4d7c6475ff3 100644 +index 9c0d8f6cb9e447d33f04535d96f2fc8d11d66cf7..fff1873ee166d9fae98474ee81f6509c561b3b64 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -293,6 +293,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @@ -33,7 +33,7 @@ index ed272499b40a96efd83f1a09a063e4d65dbe48e8..32c89f89fc9dbcdc9528acf46415b4d7 public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player) { this.lastChatTimeStamp = new AtomicReference(Instant.EPOCH); -@@ -3262,7 +3263,19 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3268,7 +3269,19 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @Override public void handleSignUpdate(ServerboundSignUpdatePacket packet) { diff --git a/patches/server/0307-Update-entity-Metadata-for-all-tracked-players.patch b/patches/server/0307-Update-entity-Metadata-for-all-tracked-players.patch index 2558096b58..a716efd34e 100644 --- a/patches/server/0307-Update-entity-Metadata-for-all-tracked-players.patch +++ b/patches/server/0307-Update-entity-Metadata-for-all-tracked-players.patch @@ -22,10 +22,10 @@ index d6f34adbdf45bbef4a39e629dd7cb6d7fcb5db0f..7881176a900daa3306c691454f688c1f this.broadcast.accept(packet); if (this.entity instanceof ServerPlayer) { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 32c89f89fc9dbcdc9528acf46415b4d7c6475ff3..30b65246eacf2955a52bbf46856ca82ae9e1d5cb 100644 +index fff1873ee166d9fae98474ee81f6509c561b3b64..29e6f4726016a62b22588f0efd0284e49fe5a33b 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2703,7 +2703,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2709,7 +2709,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic if (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem) { // Refresh the current entity metadata diff --git a/patches/server/0332-Dont-send-unnecessary-sign-update.patch b/patches/server/0332-Dont-send-unnecessary-sign-update.patch index 8eeda30cd5..f4756b4270 100644 --- a/patches/server/0332-Dont-send-unnecessary-sign-update.patch +++ b/patches/server/0332-Dont-send-unnecessary-sign-update.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Dont send unnecessary sign update diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 83d9eac28a08bc075904d274effed54de77be6bf..00f9b6213a7289ea8d48fcf41d701bde5497006d 100644 +index 4e4af6e79c126a8b21dea16cb0311e80e23f1d66..ae42daea9aaca1f0c19c26232e51e185353fe717 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3307,6 +3307,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3313,6 +3313,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic if (!tileentitysign.isEditable() || !this.player.getUUID().equals(tileentitysign.getPlayerWhoMayEdit())) { ServerGamePacketListenerImpl.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString()); diff --git a/patches/server/0373-Add-tick-times-API-and-mspt-command.patch b/patches/server/0373-Add-tick-times-API-and-mspt-command.patch index 2206f80a2f..6f4253e903 100644 --- a/patches/server/0373-Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/0373-Add-tick-times-API-and-mspt-command.patch @@ -125,7 +125,7 @@ index 6a00f3d38da8107825ab1d405f337fd077b09f72..d31b5ed47cffc61c90c926a0cd2005b7 public static void registerCommands(final MinecraftServer server) { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 19f38a8d66846d859dd46fb53f3224fe0d7f2eb8..f5fc952e119723d7761408d8ffb95e869d01cb81 100644 +index e8b826e431229b80fbba2bcdaed2105e6a9bcbdd..7b646a46d561c3cdb03a488d691e811d40684417 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -237,6 +237,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop queue = Queues.newConcurrentLinkedQueue(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index af2d703fe3cb74ced502ca89c5bf6ca1f47474bb..7ca8941ade15c073939c198334bfba78dfcc3c08 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2527,7 +2527,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java index 648bc209938364a387c3f81dcd073db398e9f864..e42df2956e2d852a5a4c8fdeda395a3efd32c44c 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java diff --git a/patches/server/0438-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/server/0438-Add-and-implement-PlayerRecipeBookClickEvent.patch index 3afe5c911a..58f445f747 100644 --- a/patches/server/0438-Add-and-implement-PlayerRecipeBookClickEvent.patch +++ b/patches/server/0438-Add-and-implement-PlayerRecipeBookClickEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add and implement PlayerRecipeBookClickEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index a42d153d861134a1255e302b44b291f6f36132ce..38f514320de5a2b3c09e288f7fb1b88c1662e9f8 100644 +index 6d4923a8a563918cf9db73f1f6e1ef5699d10a79..651bf74a4d09e2d0611f86a8e865c065cb0e9327 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3204,9 +3204,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3210,9 +3210,15 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic if (!this.player.containerMenu.stillValid(this.player)) { ServerGamePacketListenerImpl.LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu); } else { diff --git a/patches/server/0442-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/0442-Fix-Per-World-Difficulty-Remembering-Difficulty.patch index ddd5e571ee..6b5d169a95 100644 --- a/patches/server/0442-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ b/patches/server/0442-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -8,7 +8,7 @@ makes it so that the server keeps the last difficulty used instead of restoring the server.properties every single load. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e2ba646cf628c3791e8a5b1195f985cb1b3e6916..546ee711f3a11789647b021383841a332cc9c72f 100644 +index aeaa34a17e7d0240a87a62a8a7cc5ca620b16d2b..db490f74834715c8382a9c5ff076d7e89fd4dec3 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -791,7 +791,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { --this.chatSpamTickCount; -@@ -3223,6 +3225,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3229,6 +3231,14 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @Override public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { diff --git a/patches/server/0537-Player-Chunk-Load-Unload-Events.patch b/patches/server/0537-Player-Chunk-Load-Unload-Events.patch index fcd60beef6..f00bed613a 100644 --- a/patches/server/0537-Player-Chunk-Load-Unload-Events.patch +++ b/patches/server/0537-Player-Chunk-Load-Unload-Events.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Player Chunk Load/Unload Events diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 8c6f55efb555c9ca7253ccc1cd9ba615cfb1171c..345091d6ba617c26ac7acfd88eb023f2ec8fae11 100644 +index 6cb4cda5235ca6c54158d6980526e3d5fceae829..5f1ec63ae45cf3f53cb6c5b55ccdb3962b1ebd72 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2129,11 +2129,21 @@ public class ServerPlayer extends Player { +@@ -2134,11 +2134,21 @@ public class ServerPlayer extends Player { public void trackChunk(ChunkPos chunkPos, Packet chunkDataPacket) { this.connection.send(chunkDataPacket); diff --git a/patches/server/0552-Fix-interact-event-not-being-called-in-adventure.patch b/patches/server/0552-Fix-interact-event-not-being-called-in-adventure.patch index 81fb0381c6..a517033341 100644 --- a/patches/server/0552-Fix-interact-event-not-being-called-in-adventure.patch +++ b/patches/server/0552-Fix-interact-event-not-being-called-in-adventure.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Fix interact event not being called in adventure Call PlayerInteractEvent when left-clicking on a block in adventure mode diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 7f91a1129a7702a4cff001de791514a37f9def09..6525d8cee86928158dfd121ff11d18b088898a67 100644 +index a514912127a6a353b98d29c336e9b8d2c0c0ec8b..52e928b0ca0e3b0c31a80cc2b3d3deba07d41da8 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1845,7 +1845,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @@ -18,7 +18,7 @@ index 7f91a1129a7702a4cff001de791514a37f9def09..6525d8cee86928158dfd121ff11d18b0 this.player.swing(enumhand, true); } } -@@ -2591,7 +2591,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2597,7 +2597,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic Vec3 vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3); HitResult movingobjectposition = this.player.level.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); diff --git a/patches/server/0631-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/server/0631-add-RespawnFlags-to-PlayerRespawnEvent.patch index b31b543aa1..460c5868ea 100644 --- a/patches/server/0631-add-RespawnFlags-to-PlayerRespawnEvent.patch +++ b/patches/server/0631-add-RespawnFlags-to-PlayerRespawnEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] add RespawnFlags to PlayerRespawnEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 125cc1951c785fd1a75569f57f779626a1fbe586..035b8a49c3647be3c2e6478767078d6dd14e6208 100644 +index e23c6bad7e0b83c4eae581ac638f2e7b2a32458e..5e8f6f36d259526e97d926ed83ef0e6d7b618021 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2876,7 +2876,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2882,7 +2882,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic case PERFORM_RESPAWN: if (this.player.wonGame) { this.player.wonGame = false; @@ -18,7 +18,7 @@ index 125cc1951c785fd1a75569f57f779626a1fbe586..035b8a49c3647be3c2e6478767078d6d } else { if (this.player.getHealth() > 0.0F) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index f58f35cdab48066688cf4cf16fc4819229d2191d..bdb37391b9df7ec4983728de8324aa3f1ed20f4b 100644 +index 9f50af39555a90fd4e3b9131286107b9ef971270..3adc2fcded1d7bb7cb892eccc96f43facd404045 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -811,6 +811,12 @@ public abstract class PlayerList { diff --git a/patches/server/0644-additions-to-PlayerGameModeChangeEvent.patch b/patches/server/0644-additions-to-PlayerGameModeChangeEvent.patch index a08c959134..e6ee25d000 100644 --- a/patches/server/0644-additions-to-PlayerGameModeChangeEvent.patch +++ b/patches/server/0644-additions-to-PlayerGameModeChangeEvent.patch @@ -45,7 +45,7 @@ index 65089c0e78c9913a92ae9c66d664f48e2112ad92..7882ee2b7813d437d3b7580f046f38e7 } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d8bbab6af9625cdb411df0099261f97f59daacb4..607a44d2db927e579d8be7c52021d7bb205a379c 100644 +index ec46dda11b527e2e31d8025416c83d11153edc8c..705201ced84717180b9b6cfc2111f0557cca56ab 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1810,8 +1810,15 @@ public class ServerPlayer extends Player { @@ -75,7 +75,7 @@ index d8bbab6af9625cdb411df0099261f97f59daacb4..607a44d2db927e579d8be7c52021d7bb } } -@@ -2220,6 +2227,16 @@ public class ServerPlayer extends Player { +@@ -2225,6 +2232,16 @@ public class ServerPlayer extends Player { } public void loadGameTypes(@Nullable CompoundTag nbt) { @@ -126,10 +126,10 @@ index 32746dfbc2fdfc150583676b1bf0762398b76d75..1ad1f958a9b6e1bc21f1c505aa7ea549 } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 035b8a49c3647be3c2e6478767078d6dd14e6208..9ad786bb2fd516e167c3ec55e854155d64dd73a5 100644 +index 5e8f6f36d259526e97d926ed83ef0e6d7b618021..2ee76d9c5fb22e792618d8c865e7fb9a335202a6 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2885,7 +2885,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2891,7 +2891,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic this.player = this.server.getPlayerList().respawn(this.player, false); if (this.server.isHardcore()) { @@ -139,7 +139,7 @@ index 035b8a49c3647be3c2e6478767078d6dd14e6208..9ad786bb2fd516e167c3ec55e854155d } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c6019b688eed5426e21f2950065363268f8285a5..60024a387429a13593f7f709004282d27678cbbe 100644 +index f2af098691d3e6951e17645c3eee019000fb4882..c65621c97f05ee5c7be0fd485b6fb9c703d00406 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1396,7 +1396,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0656-Add-PlayerKickEvent-causes.patch b/patches/server/0656-Add-PlayerKickEvent-causes.patch index f19ccd3c47..c19226712e 100644 --- a/patches/server/0656-Add-PlayerKickEvent-causes.patch +++ b/patches/server/0656-Add-PlayerKickEvent-causes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add PlayerKickEvent causes diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index db60b41f7da9caebfb798ed39ccac51d15bd1324..1376f0aa4ec2c37a64d208168c0160255aa4899b 100644 +index 2ea4e4ecae33ba42d559133453fea064b8359d46..2fb7bdb18f1528fd496971b5f9445339b4239720 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2101,7 +2101,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 200 && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // CraftBukkit end @@ -285,7 +285,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d } } -@@ -2577,7 +2587,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2583,7 +2593,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic private void handleValidationFailure(Set reasons) { ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message from {}, reasons: {}", this.player.getName().getString(), reasons.stream().map(LastSeenMessagesValidator.ErrorCondition::message).collect(Collectors.joining(","))); @@ -294,7 +294,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d } @Override -@@ -2724,7 +2734,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2730,7 +2740,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } if (i > 4096) { @@ -303,7 +303,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d } } -@@ -2739,7 +2749,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2745,7 +2755,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic // Spigot Start if ( entity == this.player && !this.player.isSpectator() ) { @@ -312,7 +312,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d return; } // Spigot End -@@ -2832,7 +2842,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2838,7 +2848,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } // CraftBukkit end } else { @@ -321,7 +321,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d ServerGamePacketListenerImpl.LOGGER.warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString()); } } -@@ -3240,7 +3250,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3246,7 +3256,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic // Paper start if (!org.bukkit.Bukkit.isPrimaryThread()) { if (recipeSpamPackets.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamLimit) { @@ -330,7 +330,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d return; } } -@@ -3443,7 +3453,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3449,7 +3459,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } else if (!this.isSingleplayerOwner()) { // Paper start - This needs to be handled on the main thread for plugins server.submit(() -> { @@ -339,7 +339,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d }); // Paper end } -@@ -3489,7 +3499,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3495,7 +3505,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t register custom payload", ex); @@ -348,7 +348,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d } } else if (packet.identifier.equals(CUSTOM_UNREGISTER)) { try { -@@ -3499,7 +3509,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3505,7 +3515,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t unregister custom payload", ex); @@ -357,7 +357,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d } } else { try { -@@ -3517,7 +3527,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3523,7 +3533,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic this.cserver.getMessenger().dispatchIncomingMessage(this.player.getBukkitEntity(), packet.identifier.toString(), data); } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); @@ -367,7 +367,7 @@ index 2217d9b3bb589278da5b421ffce9e00261d08469..26b0bc810b4b09df9c910e3b8b49c18d } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index bdb37391b9df7ec4983728de8324aa3f1ed20f4b..ca0ad4fd5f4aafacd197494970f2aec3b2a6c4d0 100644 +index 3adc2fcded1d7bb7cb892eccc96f43facd404045..e6a5c5da58403ca5498d8741bc520b8e68c56310 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -720,7 +720,7 @@ public abstract class PlayerList { diff --git a/patches/server/0671-Fix-PlayerDropItemEvent-using-wrong-item.patch b/patches/server/0671-Fix-PlayerDropItemEvent-using-wrong-item.patch index c053f7f56a..fb4745c873 100644 --- a/patches/server/0671-Fix-PlayerDropItemEvent-using-wrong-item.patch +++ b/patches/server/0671-Fix-PlayerDropItemEvent-using-wrong-item.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix PlayerDropItemEvent using wrong item diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 607a44d2db927e579d8be7c52021d7bb205a379c..6e53214042ab515d9c66fb24f6aa1c07d6c3539d 100644 +index 705201ced84717180b9b6cfc2111f0557cca56ab..af1aedd970778e69845f093581ad401da5e99adb 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2196,7 +2196,7 @@ public class ServerPlayer extends Player { +@@ -2201,7 +2201,7 @@ public class ServerPlayer extends Player { if (retainOwnership) { if (!itemstack1.isEmpty()) { diff --git a/patches/server/0677-Adds-PlayerArmSwingEvent.patch b/patches/server/0677-Adds-PlayerArmSwingEvent.patch index c3c42ead1c..d4afb0ed5b 100644 --- a/patches/server/0677-Adds-PlayerArmSwingEvent.patch +++ b/patches/server/0677-Adds-PlayerArmSwingEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Adds PlayerArmSwingEvent diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 685745b853f86fa2eda031ad20317ad321b1379a..c65c72a2dd3c87621c1369c52770b912057eafd2 100644 +index 87cdc22491da7deb4d61809bed6aea8bf44a6fbb..302f7ee99460efba88eabfa661ad6f6a46e92d17 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2618,7 +2618,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2624,7 +2624,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } // Arm swing animation diff --git a/patches/server/0692-Add-PlayerSetSpawnEvent.patch b/patches/server/0692-Add-PlayerSetSpawnEvent.patch index b1aa1739f5..878b72133b 100644 --- a/patches/server/0692-Add-PlayerSetSpawnEvent.patch +++ b/patches/server/0692-Add-PlayerSetSpawnEvent.patch @@ -32,7 +32,7 @@ index ce1c7512cc368e196ae94ee22c6a228c975b4980..1e41de9523c5fa3b9cfced798a5c35a2 String string = resourceKey.location().toString(); if (targets.size() == 1) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f523311e822af9cbef571338fd8fef177b9fc73d..ec713ffb7c4cba53dc983ebde5596e4749107493 100644 +index 5ef42e8e69169995f2c36ec332500f0307e84337..17f7ecafb2b0877b140353323b5972fb90e558e0 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1287,7 +1287,7 @@ public class ServerPlayer extends Player { @@ -44,7 +44,7 @@ index f523311e822af9cbef571338fd8fef177b9fc73d..ec713ffb7c4cba53dc983ebde5596e47 if (this.level.isDay()) { return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); } else { -@@ -2123,12 +2123,33 @@ public class ServerPlayer extends Player { +@@ -2128,12 +2128,33 @@ public class ServerPlayer extends Player { return this.respawnForced; } @@ -80,7 +80,7 @@ index f523311e822af9cbef571338fd8fef177b9fc73d..ec713ffb7c4cba53dc983ebde5596e47 } this.respawnPosition = pos; -@@ -2142,6 +2163,7 @@ public class ServerPlayer extends Player { +@@ -2147,6 +2168,7 @@ public class ServerPlayer extends Player { this.respawnForced = false; } @@ -89,7 +89,7 @@ index f523311e822af9cbef571338fd8fef177b9fc73d..ec713ffb7c4cba53dc983ebde5596e47 public void trackChunk(ChunkPos chunkPos, Packet chunkDataPacket) { diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0354b7e20bbc9f888cf85d6db42ce2b64a25b4c2..76fa5e31701bc0e504d8e7b6ebfa737f3a10dc3b 100644 +index 10231f5a811a8b4510ef063a9de2f8b386570cbe..84b3a86b5fd77dbdedbe4b45f5a67f113e2c8e48 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -896,13 +896,13 @@ public abstract class PlayerList { @@ -129,7 +129,7 @@ index c3e49a781f838e6a46cb89744f3f1846de182275..c2f3d3a09327e7cb7d3167609eb3ce68 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d72e5c06ab4f34742ec74448d1cad892048f159b..fa85a7be4a131b7ae8a5d2aae78a82fcd53e5967 100644 +index aaa50b04ae3dc49fa93ca408442abd540a4e4b7a..05529f795672636ce43c6fbab73f9ada459cdcb9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1216,9 +1216,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0737-Execute-chunk-tasks-mid-tick.patch b/patches/server/0737-Execute-chunk-tasks-mid-tick.patch index ac2df1c4ad..9602f9b1f5 100644 --- a/patches/server/0737-Execute-chunk-tasks-mid-tick.patch +++ b/patches/server/0737-Execute-chunk-tasks-mid-tick.patch @@ -19,7 +19,7 @@ index 23e564b05ba438924180c91f9b19a60731eedd1b..5ec241d49ff5e3a161a39006f05823a5 private MinecraftTimings() {} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a7610894e05c763ce405c0a2d91665b83d02980a..097eb29a9fd94d49ff5df71110d250a03d6e4c45 100644 +index 660e1b6955115d67cb37161ef556f90acc53bdfa..621956c024d64bcaa868e0bb01c485fe4ac11df3 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1303,6 +1303,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - push to main this.disconnect(Component.translatable("multiplayer.disconnect.out_of_order_chat"), org.bukkit.event.player.PlayerKickEvent.Cause.OUT_OF_ORDER_CHAT); // Paper - kick event cause }); // Paper - push to main -@@ -2552,7 +2552,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2555,7 +2555,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic return false; } else { if (message.hasExpiredServer(Instant.now())) { diff --git a/patches/server/0919-Fix-Spigot-Config-not-using-commands.spam-exclusions.patch b/patches/server/0919-Fix-Spigot-Config-not-using-commands.spam-exclusions.patch index 9d90007654..ff5e37f8fc 100644 --- a/patches/server/0919-Fix-Spigot-Config-not-using-commands.spam-exclusions.patch +++ b/patches/server/0919-Fix-Spigot-Config-not-using-commands.spam-exclusions.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix Spigot Config not using commands.spam-exclusions diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index cdf7ed204cf6216337ab9667158b33143c82a819..72864ca3f0fa94512d7f57b4e05929be7d2912cd 100644 +index c384e715a54248e3bf2e1dc02acc118ec9fcfa1d..736ef6024285866fd372e5449b5eb55633e7ddf9 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2573,7 +2573,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2576,7 +2576,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } // Spigot end // this.chatSpamTickCount += 20; diff --git a/patches/server/0924-Send-block-entities-after-destroy-prediction.patch b/patches/server/0924-Send-block-entities-after-destroy-prediction.patch index c5f9f02261..d83705065c 100644 --- a/patches/server/0924-Send-block-entities-after-destroy-prediction.patch +++ b/patches/server/0924-Send-block-entities-after-destroy-prediction.patch @@ -57,7 +57,7 @@ index 9378e83a67a70dbb1fb4f05b33f1e553d008e62b..5a60f5dc202c44b06ca34e9a19d45cb7 } } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index adb9cde74295830e74241e522ae5766d436aadb1..ff7df8026f85b7ad51458a0b720a8baf71cd9bd1 100644 +index 8e32bf0deacd966a1bfeef7c57455be4ccfdadda..01a498536497db7ab0f3ebac80fb022b356385c8 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -1873,8 +1873,28 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic