PaperMC/patches/server/0010-Adventure.patch
Nassim Jahnke 17f71ac87b
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#5904)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
70d24eb8 SPIGOT-6587: Update documentation/error of drop chance API

CraftBukkit Changes:
470050ad SPIGOT-6587: Update documentation/error of drop chance API
1c39efa3 Fix Inventory#getViewers on the player inventory not returning the player first time their inventory is opened
d161627d Fix PrepareItemCraftEvent#isRepair
aa1fae73 SPIGOT-6586: EntityChangeBlockEvent for falling block does not cancel properly
8a04072e SPIGOT-6583: Throwing eggs doesn't make sounds

Spigot Changes:
f773da84 Remove redundant patch
cd367234 Rebuild patches
2021-06-20 21:25:59 +02:00

3198 lines
157 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Riley Park <riley.park@meino.net>
Date: Fri, 29 Jan 2021 17:54:03 +0100
Subject: [PATCH] Adventure
Co-authored-by: zml <zml@stellardrift.ca>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 1d03a79e9010bc514b72a81ba0ad4a62aeff1bb7..429b74474ced04d8dd8f038b8590b8dfe178bf4d 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -217,4 +217,9 @@ public class PaperConfig {
" - Length: " + timeSummary(Timings.getHistoryLength() / 20) +
" - Server Name: " + timingsServerName);
}
+
+ public static boolean useDisplayNameInQuit = false;
+ private static void useDisplayNameInQuit() {
+ useDisplayNameInQuit = getBoolean("use-display-name-in-quit-message", useDisplayNameInQuit);
+ }
}
diff --git a/src/main/java/io/papermc/paper/adventure/AdventureComponent.java b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e597a90def72c5903382d7169fb7a2fb667b8a69
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/AdventureComponent.java
@@ -0,0 +1,82 @@
+package io.papermc.paper.adventure;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Type;
+import java.util.List;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextComponent;
+import net.minecraft.network.chat.MutableComponent;
+import net.minecraft.network.chat.Style;
+import net.minecraft.util.FormattedCharSequence;
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public final class AdventureComponent implements net.minecraft.network.chat.Component {
+ final Component wrapped;
+ private net.minecraft.network.chat.@MonotonicNonNull Component converted;
+
+ public AdventureComponent(final Component wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ public net.minecraft.network.chat.Component deepConverted() {
+ net.minecraft.network.chat.Component converted = this.converted;
+ if (converted == null) {
+ converted = PaperAdventure.WRAPPER_AWARE_SERIALIZER.serialize(this.wrapped);
+ this.converted = converted;
+ }
+ return converted;
+ }
+
+ public net.minecraft.network.chat.@Nullable Component deepConvertedIfPresent() {
+ return this.converted;
+ }
+
+ @Override
+ public Style getStyle() {
+ return this.deepConverted().getStyle();
+ }
+
+ @Override
+ public String getContents() {
+ if (this.wrapped instanceof TextComponent) {
+ return ((TextComponent) this.wrapped).content();
+ } else {
+ return this.deepConverted().getContents();
+ }
+ }
+
+ @Override
+ public String getString() {
+ return PaperAdventure.PLAIN.serialize(this.wrapped);
+ }
+
+ @Override
+ public List<net.minecraft.network.chat.Component> getSiblings() {
+ return this.deepConverted().getSiblings();
+ }
+
+ @Override
+ public MutableComponent plainCopy() {
+ return this.deepConverted().plainCopy();
+ }
+
+ @Override
+ public MutableComponent copy() {
+ return this.deepConverted().copy();
+ }
+
+ @Override
+ public FormattedCharSequence getVisualOrderText() {
+ return this.deepConverted().getVisualOrderText();
+ }
+
+ public static class Serializer implements JsonSerializer<AdventureComponent> {
+ @Override
+ public JsonElement serialize(final AdventureComponent src, final Type type, final JsonSerializationContext context) {
+ return PaperAdventure.GSON.serializer().toJsonTree(src.wrapped, Component.class);
+ }
+ }
+}
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..4e9e0a39b876c900fdee1343d04a7046f5b3f80e
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java
@@ -0,0 +1,224 @@
+package io.papermc.paper.adventure;
+
+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.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+
+import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.audience.MessageType;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextReplacementConfig;
+import net.kyori.adventure.text.event.ClickEvent;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerPlayer;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+import org.bukkit.craftbukkit.util.LazyPlayerSet;
+import org.bukkit.craftbukkit.util.Waitable;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.AsyncPlayerChatEvent;
+import org.bukkit.event.player.PlayerChatEvent;
+
+public final class ChatProcessor {
+ // <-- copied from adventure-text-serializer-legacy
+ private static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(?:(https?)://)?([-\\w_.]+\\.\\w{2,})(/\\S*)?");
+ private static final Pattern URL_SCHEME_PATTERN = Pattern.compile("^[a-z][a-z0-9+\\-.]*:");
+ private static final TextReplacementConfig URL_REPLACEMENT_CONFIG = TextReplacementConfig.builder()
+ .match(DEFAULT_URL_PATTERN)
+ .replacement(url -> {
+ String clickUrl = url.content();
+ if (!URL_SCHEME_PATTERN.matcher(clickUrl).find()) {
+ clickUrl = "http://" + clickUrl;
+ }
+ return url.clickEvent(ClickEvent.openUrl(clickUrl));
+ })
+ .build();
+ // copied from adventure-text-serializer-legacy -->
+ final MinecraftServer server;
+ final ServerPlayer player;
+ final String message;
+ final boolean async;
+ final Component originalMessage;
+
+ public ChatProcessor(final MinecraftServer server, final ServerPlayer player, final String message, final boolean async) {
+ this.server = server;
+ this.player = player;
+ this.message = message;
+ this.async = async;
+ this.originalMessage = Component.text(message);
+ }
+
+ @SuppressWarnings({"CodeBlock2Expr", "deprecated"})
+ public void process() {
+ this.processingLegacyFirst(
+ // continuing from AsyncPlayerChatEvent (without PlayerChatEvent)
+ event -> {
+ this.processModern(
+ legacyRenderer(event.getFormat()),
+ this.viewersFromLegacy(event.getRecipients()),
+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()),
+ event.isCancelled()
+ );
+ },
+ // continuing from AsyncPlayerChatEvent and PlayerChatEvent
+ event -> {
+ this.processModern(
+ legacyRenderer(event.getFormat()),
+ this.viewersFromLegacy(event.getRecipients()),
+ PaperAdventure.LEGACY_SECTION_UXRC.deserialize(event.getMessage()),
+ event.isCancelled()
+ );
+ },
+ // no legacy events called, all nice and fresh!
+ () -> {
+ this.processModern(
+ ChatRenderer.defaultRenderer(),
+ new LazyChatAudienceSet(this.server),
+ Component.text(this.message).replaceText(URL_REPLACEMENT_CONFIG),
+ false
+ );
+ }
+ );
+ }
+
+ private Set<Audience> viewersFromLegacy(final Set<Player> recipients) {
+ if (recipients instanceof LazyPlayerSet lazyPlayerSet && lazyPlayerSet.isLazy()) {
+ return new LazyChatAudienceSet(this.server);
+ }
+ final HashSet<Audience> viewers = new HashSet<>(recipients);
+ viewers.add(this.server.console);
+ return viewers;
+ }
+
+ @SuppressWarnings("deprecation")
+ private void processingLegacyFirst(
+ final Consumer<AsyncPlayerChatEvent> continueAfterAsync,
+ final Consumer<PlayerChatEvent> continueAfterAsyncAndSync,
+ final Runnable modernOnly
+ ) {
+ final boolean listenersOnAsyncEvent = anyListeners(AsyncPlayerChatEvent.getHandlerList());
+ final boolean listenersOnSyncEvent = anyListeners(PlayerChatEvent.getHandlerList());
+ if (listenersOnAsyncEvent || listenersOnSyncEvent) {
+ final CraftPlayer player = this.player.getBukkitEntity();
+ final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.message, new LazyPlayerSet(this.server));
+ post(ae);
+ if (listenersOnSyncEvent) {
+ final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients());
+ se.setCancelled(ae.isCancelled()); // propagate cancelled state
+ this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
+ @Override
+ protected Void evaluate() {
+ post(se);
+ return null;
+ }
+ });
+ continueAfterAsyncAndSync.accept(se);
+ } else {
+ continueAfterAsync.accept(ae);
+ }
+ } else {
+ modernOnly.run();
+ }
+ }
+
+ private void processModern(final ChatRenderer renderer, final Set<Audience> viewers, final Component message, final boolean cancelled) {
+ final AsyncChatEvent ae = this.createAsync(renderer, viewers, message);
+ ae.setCancelled(cancelled); // propagate cancelled state
+ post(ae);
+ final boolean listenersOnSyncEvent = anyListeners(ChatEvent.getHandlerList());
+ if (listenersOnSyncEvent) {
+ this.continueWithSyncFromWhereAsyncLeftOff(ae);
+ } else {
+ this.complete(ae);
+ }
+ }
+
+ private void continueWithSyncFromWhereAsyncLeftOff(final AsyncChatEvent ae) {
+ this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
+ @Override
+ protected Void evaluate() {
+ final ChatEvent se = ChatProcessor.this.createSync(ae.renderer(), ae.viewers(), ae.message());
+ se.setCancelled(ae.isCancelled()); // propagate cancelled state
+ post(se);
+ ChatProcessor.this.complete(se);
+ return null;
+ }
+ });
+ }
+
+ private void complete(final AbstractChatEvent event) {
+ if (event.isCancelled()) {
+ return;
+ }
+
+ final CraftPlayer player = this.player.getBukkitEntity();
+ final Component displayName = displayName(player);
+ final Component message = event.message();
+ final ChatRenderer renderer = event.renderer();
+
+ final Set<Audience> viewers = event.viewers();
+
+ 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);
+ }
+ } else {
+ for (final Audience viewer : viewers) {
+ viewer.sendMessage(player, renderer.render(player, displayName, message, viewer), MessageType.CHAT);
+ }
+ }
+ }
+
+ private AsyncChatEvent createAsync(final ChatRenderer renderer, final Set<Audience> viewers, final Component message) {
+ return new AsyncChatEvent(this.async, this.player.getBukkitEntity(), viewers, renderer, message, this.originalMessage);
+ }
+
+ private ChatEvent createSync(final ChatRenderer renderer, final Set<Audience> viewers, final Component message) {
+ return new ChatEvent(this.player.getBukkitEntity(), viewers, renderer, message, this.originalMessage);
+ }
+
+ private static String legacyDisplayName(final CraftPlayer player) {
+ return player.getDisplayName();
+ }
+
+ private static Component displayName(final CraftPlayer player) {
+ return player.displayName();
+ }
+
+ private static ChatRenderer legacyRenderer(final String format) {
+ return (player, displayName, message, recipient) -> PaperAdventure.LEGACY_SECTION_UXRC.deserialize(String.format(format, legacyDisplayName((CraftPlayer) player), PaperAdventure.LEGACY_SECTION_UXRC.serialize(message))).replaceText(URL_REPLACEMENT_CONFIG);
+ }
+
+ private void queueIfAsyncOrRunImmediately(final Waitable<Void> waitable) {
+ if (this.async) {
+ this.server.processQueue.add(waitable);
+ } else {
+ waitable.run();
+ }
+ try {
+ waitable.get();
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt(); // tag, you're it
+ } catch (final ExecutionException e) {
+ throw new RuntimeException("Exception processing chat", e.getCause());
+ }
+ }
+
+ private static void post(final Event event) {
+ Bukkit.getPluginManager().callEvent(event);
+ }
+
+ private static boolean anyListeners(final HandlerList handlers) {
+ return handlers.getRegisteredListeners().length > 0;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/DisplayNames.java b/src/main/java/io/papermc/paper/adventure/DisplayNames.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfaf5d3c5aae8a587c2b11d90089c588b2a2aba0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/DisplayNames.java
@@ -0,0 +1,22 @@
+package io.papermc.paper.adventure;
+
+import net.minecraft.server.level.ServerPlayer;
+import org.bukkit.ChatColor;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+
+public final class DisplayNames {
+ private DisplayNames() {
+ }
+
+ public static String getLegacy(final CraftPlayer player) {
+ return getLegacy(player.getHandle());
+ }
+
+ public static String getLegacy(final ServerPlayer player) {
+ final String legacy = player.displayName;
+ if (legacy != null) {
+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName) + ChatColor.getLastColors(player.displayName);
+ }
+ return PaperAdventure.LEGACY_SECTION_UXRC.serialize(player.adventure$displayName);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fd6c3e65354071af71c7d8ebb97b559b6e105ce
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/LazyChatAudienceSet.java
@@ -0,0 +1,26 @@
+package io.papermc.paper.adventure;
+
+import java.util.HashSet;
+import java.util.Set;
+import net.kyori.adventure.audience.Audience;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.util.LazyHashSet;
+import org.bukkit.craftbukkit.util.LazyPlayerSet;
+import org.bukkit.entity.Player;
+
+final class LazyChatAudienceSet extends LazyHashSet<Audience> {
+ private final MinecraftServer server;
+
+ public LazyChatAudienceSet(final MinecraftServer server) {
+ this.server = server;
+ }
+
+ @Override
+ protected Set<Audience> makeReference() {
+ final Set<Player> playerSet = LazyPlayerSet.makePlayerSet(this.server);
+ final HashSet<Audience> audiences = new HashSet<>(playerSet);
+ audiences.add(Bukkit.getConsoleSender());
+ return audiences;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..eeedc30a45d9637d68f04f185b3dd90dd711b9e0
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/NBTLegacyHoverEventSerializer.java
@@ -0,0 +1,88 @@
+package io.papermc.paper.adventure;
+
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import java.io.IOException;
+import java.util.UUID;
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.nbt.api.BinaryTagHolder;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.event.HoverEvent;
+import net.kyori.adventure.text.serializer.gson.LegacyHoverEventSerializer;
+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
+import net.kyori.adventure.util.Codec;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.Tag;
+import net.minecraft.nbt.TagParser;
+
+final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer {
+ public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer();
+ private static final Codec<CompoundTag, String, CommandSyntaxException, RuntimeException> SNBT_CODEC = Codec.of(TagParser::parseTag, Tag::toString);
+
+ static final String ITEM_TYPE = "id";
+ static final String ITEM_COUNT = "Count";
+ static final String ITEM_TAG = "tag";
+
+ static final String ENTITY_NAME = "name";
+ static final String ENTITY_TYPE = "type";
+ static final String ENTITY_ID = "id";
+
+ NBTLegacyHoverEventSerializer() {
+ }
+
+ @Override
+ public HoverEvent.ShowItem deserializeShowItem(final Component input) throws IOException {
+ final String raw = PlainComponentSerializer.plain().serialize(input);
+ try {
+ final CompoundTag contents = SNBT_CODEC.decode(raw);
+ final CompoundTag tag = contents.getCompound(ITEM_TAG);
+ return HoverEvent.ShowItem.of(
+ Key.key(contents.getString(ITEM_TYPE)),
+ contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1,
+ tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC)
+ );
+ } catch (final CommandSyntaxException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ @Override
+ public HoverEvent.ShowEntity deserializeShowEntity(final Component input, final Codec.Decoder<Component, String, ? extends RuntimeException> componentCodec) throws IOException {
+ final String raw = PlainComponentSerializer.plain().serialize(input);
+ try {
+ final CompoundTag contents = SNBT_CODEC.decode(raw);
+ return HoverEvent.ShowEntity.of(
+ Key.key(contents.getString(ENTITY_TYPE)),
+ UUID.fromString(contents.getString(ENTITY_ID)),
+ componentCodec.decode(contents.getString(ENTITY_NAME))
+ );
+ } catch (final CommandSyntaxException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ @Override
+ public Component serializeShowItem(final HoverEvent.ShowItem input) throws IOException {
+ final CompoundTag tag = new CompoundTag();
+ tag.putString(ITEM_TYPE, input.item().asString());
+ tag.putByte(ITEM_COUNT, (byte) input.count());
+ if (input.nbt() != null) {
+ try {
+ tag.put(ITEM_TAG, input.nbt().get(SNBT_CODEC));
+ } catch (final CommandSyntaxException ex) {
+ throw new IOException(ex);
+ }
+ }
+ return Component.text(SNBT_CODEC.encode(tag));
+ }
+
+ @Override
+ public Component serializeShowEntity(final HoverEvent.ShowEntity input, final Codec.Encoder<Component, String, ? extends RuntimeException> componentCodec) throws IOException {
+ final CompoundTag tag = new CompoundTag();
+ tag.putString(ENTITY_ID, input.id().toString());
+ tag.putString(ENTITY_TYPE, input.type().asString());
+ if (input.name() != null) {
+ tag.putString(ENTITY_NAME, componentCodec.encode(input.name()));
+ }
+ return Component.text(SNBT_CODEC.encode(tag));
+ }
+}
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..d24c569f00786b2bde953429aad57025abee72d6
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java
@@ -0,0 +1,342 @@
+package io.papermc.paper.adventure;
+
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import io.netty.util.AttributeKey;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.kyori.adventure.bossbar.BossBar;
+import net.kyori.adventure.inventory.Book;
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.nbt.api.BinaryTagHolder;
+import net.kyori.adventure.sound.Sound;
+import net.kyori.adventure.text.Component;
+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.gson.GsonComponentSerializer;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
+import net.kyori.adventure.translation.GlobalTranslator;
+import net.kyori.adventure.util.Codec;
+import net.minecraft.ChatFormatting;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
+import net.minecraft.nbt.StringTag;
+import net.minecraft.nbt.TagParser;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.world.BossEvent;
+import net.minecraft.world.item.ItemStack;
+import org.bukkit.ChatColor;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public final class PaperAdventure {
+ public static final AttributeKey<Locale> LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale");
+ private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s");
+ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder()
+ .complexMapper(TranslatableComponent.class, (translatable, consumer) -> {
+ final @NonNull String translated = net.minecraft.locale.Language.getInstance().getOrDefault(translatable.key());
+
+ final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated);
+ final List<Component> args = translatable.args();
+ int argPosition = 0;
+ int lastIdx = 0;
+ while (matcher.find()) {
+ // append prior
+ if (lastIdx < matcher.start()) {
+ consumer.accept(Component.text(translated.substring(lastIdx, matcher.start())));
+ }
+ lastIdx = matcher.end();
+
+ final @Nullable String argIdx = matcher.group(1);
+ // calculate argument position
+ if (argIdx != null) {
+ try {
+ final int idx = Integer.parseInt(argIdx) - 1;
+ if (idx < args.size()) {
+ consumer.accept(args.get(idx));
+ }
+ } catch (final NumberFormatException ex) {
+ // ignore, drop the format placeholder
+ }
+ } else {
+ final int idx = argPosition++;
+ if (idx < args.size()) {
+ consumer.accept(args.get(idx));
+ }
+ }
+ }
+
+ // append tail
+ if (lastIdx < translated.length()) {
+ consumer.accept(Component.text(translated.substring(lastIdx)));
+ }
+ })
+ .build();
+ public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build();
+ public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build();
+ public static final GsonComponentSerializer GSON = GsonComponentSerializer.builder()
+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE)
+ .build();
+ public static final GsonComponentSerializer COLOR_DOWNSAMPLING_GSON = GsonComponentSerializer.builder()
+ .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE)
+ .downsampleColors()
+ .build();
+ private static final Codec<CompoundTag, String, IOException, IOException> NBT_CODEC = new Codec<CompoundTag, String, IOException, IOException>() {
+ @Override
+ public @NonNull CompoundTag decode(final @NonNull String encoded) throws IOException {
+ try {
+ return TagParser.parseTag(encoded);
+ } catch (final CommandSyntaxException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public @NonNull String encode(final @NonNull CompoundTag decoded) {
+ return decoded.toString();
+ }
+ };
+ static final WrapperAwareSerializer WRAPPER_AWARE_SERIALIZER = new WrapperAwareSerializer();
+
+ private PaperAdventure() {
+ }
+
+ // Key
+
+ public static ResourceLocation asVanilla(final Key key) {
+ return new ResourceLocation(key.namespace(), key.value());
+ }
+
+ public static ResourceLocation asVanillaNullable(final Key key) {
+ if (key == null) {
+ return null;
+ }
+ return new ResourceLocation(key.namespace(), key.value());
+ }
+
+ // Component
+
+ public static Component asAdventure(final net.minecraft.network.chat.Component component) {
+ return component == null ? Component.empty() : GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(component), Component.class);
+ }
+
+ public static ArrayList<Component> asAdventure(final List<net.minecraft.network.chat.Component> vanillas) {
+ final ArrayList<Component> adventures = new ArrayList<>(vanillas.size());
+ for (final net.minecraft.network.chat.Component vanilla : vanillas) {
+ adventures.add(asAdventure(vanilla));
+ }
+ return adventures;
+ }
+
+ public static ArrayList<Component> asAdventureFromJson(final List<String> jsonStrings) {
+ final ArrayList<Component> adventures = new ArrayList<>(jsonStrings.size());
+ for (final String json : jsonStrings) {
+ adventures.add(GsonComponentSerializer.gson().deserialize(json));
+ }
+ return adventures;
+ }
+
+ public static List<String> asJson(final List<Component> adventures) {
+ final List<String> jsons = new ArrayList<>(adventures.size());
+ for (final Component component : adventures) {
+ jsons.add(GsonComponentSerializer.gson().serialize(component));
+ }
+ return jsons;
+ }
+
+ public static net.minecraft.network.chat.Component asVanilla(final Component component) {
+ if (true) return new AdventureComponent(component);
+ return net.minecraft.network.chat.Component.Serializer.fromJson(GSON.serializer().toJsonTree(component));
+ }
+
+ public static List<net.minecraft.network.chat.Component> asVanilla(final List<Component> adventures) {
+ final List<net.minecraft.network.chat.Component> vanillas = new ArrayList<>(adventures.size());
+ for (final Component adventure : adventures) {
+ vanillas.add(asVanilla(adventure));
+ }
+ return vanillas;
+ }
+
+ public static String asJsonString(final Component component, final Locale locale) {
+ return GSON.serialize(
+ GlobalTranslator.render(
+ component,
+ // play it safe
+ locale != null
+ ? locale
+ : Locale.US
+ )
+ );
+ }
+
+ public static String asJsonString(final net.minecraft.network.chat.Component component, final Locale locale) {
+ if (component instanceof AdventureComponent) {
+ return asJsonString(((AdventureComponent) component).wrapped, locale);
+ }
+ return net.minecraft.network.chat.Component.Serializer.toJson(component);
+ }
+
+ // thank you for being worse than wet socks, Bukkit
+ public static String superHackyLegacyRepresentationOfComponent(final Component component, final String string) {
+ return LEGACY_SECTION_UXRC.serialize(component) + ChatColor.getLastColors(string);
+ }
+
+ // BossBar
+
+ public static BossEvent.BossBarColor asVanilla(final BossBar.Color color) {
+ if (color == BossBar.Color.PINK) {
+ return BossEvent.BossBarColor.PINK;
+ } else if (color == BossBar.Color.BLUE) {
+ return BossEvent.BossBarColor.BLUE;
+ } else if (color == BossBar.Color.RED) {
+ return BossEvent.BossBarColor.RED;
+ } else if (color == BossBar.Color.GREEN) {
+ return BossEvent.BossBarColor.GREEN;
+ } else if (color == BossBar.Color.YELLOW) {
+ return BossEvent.BossBarColor.YELLOW;
+ } else if (color == BossBar.Color.PURPLE) {
+ return BossEvent.BossBarColor.PURPLE;
+ } else if (color == BossBar.Color.WHITE) {
+ return BossEvent.BossBarColor.WHITE;
+ }
+ throw new IllegalArgumentException(color.name());
+ }
+
+ public static BossBar.Color asAdventure(final BossEvent.BossBarColor color) {
+ if(color == BossEvent.BossBarColor.PINK) {
+ return BossBar.Color.PINK;
+ } else if(color == BossEvent.BossBarColor.BLUE) {
+ return BossBar.Color.BLUE;
+ } else if(color == BossEvent.BossBarColor.RED) {
+ return BossBar.Color.RED;
+ } else if(color == BossEvent.BossBarColor.GREEN) {
+ return BossBar.Color.GREEN;
+ } else if(color == BossEvent.BossBarColor.YELLOW) {
+ return BossBar.Color.YELLOW;
+ } else if(color == BossEvent.BossBarColor.PURPLE) {
+ return BossBar.Color.PURPLE;
+ } else if(color == BossEvent.BossBarColor.WHITE) {
+ return BossBar.Color.WHITE;
+ }
+ throw new IllegalArgumentException(color.name());
+ }
+
+ public static BossEvent.BossBarOverlay asVanilla(final BossBar.Overlay overlay) {
+ if (overlay == BossBar.Overlay.PROGRESS) {
+ return BossEvent.BossBarOverlay.PROGRESS;
+ } else if (overlay == BossBar.Overlay.NOTCHED_6) {
+ return BossEvent.BossBarOverlay.NOTCHED_6;
+ } else if (overlay == BossBar.Overlay.NOTCHED_10) {
+ return BossEvent.BossBarOverlay.NOTCHED_10;
+ } else if (overlay == BossBar.Overlay.NOTCHED_12) {
+ return BossEvent.BossBarOverlay.NOTCHED_12;
+ } else if (overlay == BossBar.Overlay.NOTCHED_20) {
+ return BossEvent.BossBarOverlay.NOTCHED_20;
+ }
+ throw new IllegalArgumentException(overlay.name());
+ }
+
+ public static BossBar.Overlay asAdventure(final BossEvent.BossBarOverlay overlay) {
+ if (overlay == BossEvent.BossBarOverlay.PROGRESS) {
+ return BossBar.Overlay.PROGRESS;
+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_6) {
+ return BossBar.Overlay.NOTCHED_6;
+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_10) {
+ return BossBar.Overlay.NOTCHED_10;
+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_12) {
+ return BossBar.Overlay.NOTCHED_12;
+ } else if (overlay == BossEvent.BossBarOverlay.NOTCHED_20) {
+ return BossBar.Overlay.NOTCHED_20;
+ }
+ throw new IllegalArgumentException(overlay.name());
+ }
+
+ public static void setFlag(final BossBar bar, final BossBar.Flag flag, final boolean value) {
+ if (value) {
+ bar.addFlag(flag);
+ } else {
+ bar.removeFlag(flag);
+ }
+ }
+
+ // Book
+
+ public static ItemStack asItemStack(final Book book, final Locale locale) {
+ final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1);
+ final CompoundTag tag = item.getOrCreateTag();
+ tag.putString("title", asJsonString(book.title(), locale));
+ tag.putString("author", asJsonString(book.author(), locale));
+ final ListTag pages = new ListTag();
+ for (final Component page : book.pages()) {
+ pages.add(StringTag.valueOf(asJsonString(page, locale)));
+ }
+ tag.put("pages", pages);
+ return item;
+ }
+
+ // Sounds
+
+ public static SoundSource asVanilla(final Sound.Source source) {
+ if (source == Sound.Source.MASTER) {
+ return SoundSource.MASTER;
+ } else if (source == Sound.Source.MUSIC) {
+ return SoundSource.MUSIC;
+ } else if (source == Sound.Source.RECORD) {
+ return SoundSource.RECORDS;
+ } else if (source == Sound.Source.WEATHER) {
+ return SoundSource.WEATHER;
+ } else if (source == Sound.Source.BLOCK) {
+ return SoundSource.BLOCKS;
+ } else if (source == Sound.Source.HOSTILE) {
+ return SoundSource.HOSTILE;
+ } else if (source == Sound.Source.NEUTRAL) {
+ return SoundSource.NEUTRAL;
+ } else if (source == Sound.Source.PLAYER) {
+ return SoundSource.PLAYERS;
+ } else if (source == Sound.Source.AMBIENT) {
+ return SoundSource.AMBIENT;
+ } else if (source == Sound.Source.VOICE) {
+ return SoundSource.VOICE;
+ }
+ throw new IllegalArgumentException(source.name());
+ }
+
+ public static @Nullable SoundSource asVanillaNullable(final Sound.@Nullable Source source) {
+ if (source == null) {
+ return null;
+ }
+ return asVanilla(source);
+ }
+
+ // NBT
+
+ public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable CompoundTag tag) {
+ if (tag == null) {
+ return null;
+ }
+ try {
+ return BinaryTagHolder.encode(tag, NBT_CODEC);
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ // Colors
+
+ public static @NonNull TextColor asAdventure(ChatFormatting minecraftColor) {
+ if (minecraftColor.getColor() == null) {
+ throw new IllegalArgumentException("Not a valid color");
+ }
+ return TextColor.color(minecraftColor.getColor());
+ }
+
+ public static @Nullable ChatFormatting asVanilla(TextColor color) {
+ return ChatFormatting.getByHexValue(color.value());
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..7493efba31403cbe7f26e493f165f1b83aa847bb
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/VanillaBossBarListener.java
@@ -0,0 +1,44 @@
+package io.papermc.paper.adventure;
+
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import net.kyori.adventure.bossbar.BossBar;
+import net.kyori.adventure.text.Component;
+import net.minecraft.network.protocol.game.ClientboundBossEventPacket;
+import net.minecraft.world.BossEvent;
+import org.checkerframework.checker.nullness.qual.NonNull;
+
+public final class VanillaBossBarListener implements BossBar.Listener {
+ private final Consumer<Function<BossEvent, ClientboundBossEventPacket>> action;
+
+ public VanillaBossBarListener(final Consumer<Function<BossEvent, ClientboundBossEventPacket>> action) {
+ this.action = action;
+ }
+
+ @Override
+ public void bossBarNameChanged(final @NonNull BossBar bar, final @NonNull Component oldName, final @NonNull Component newName) {
+ this.action.accept(ClientboundBossEventPacket::createUpdateNamePacket);
+ }
+
+ @Override
+ public void bossBarProgressChanged(final @NonNull BossBar bar, final float oldProgress, final float newProgress) {
+ this.action.accept(ClientboundBossEventPacket::createUpdateProgressPacket);
+ }
+
+ @Override
+ public void bossBarColorChanged(final @NonNull BossBar bar, final BossBar.@NonNull Color oldColor, final BossBar.@NonNull Color newColor) {
+ this.action.accept(ClientboundBossEventPacket::createUpdateStylePacket);
+ }
+
+ @Override
+ public void bossBarOverlayChanged(final @NonNull BossBar bar, final BossBar.@NonNull Overlay oldOverlay, final BossBar.@NonNull Overlay newOverlay) {
+ this.action.accept(ClientboundBossEventPacket::createUpdateStylePacket);
+ }
+
+ @Override
+ public void bossBarFlagsChanged(final @NonNull BossBar bar, final @NonNull Set<BossBar.Flag> flagsAdded, final @NonNull Set<BossBar.Flag> flagsRemoved) {
+ this.action.accept(ClientboundBossEventPacket::createUpdatePropertiesPacket);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b202f4b3ddbe1f5dde188136f39414dc68ae4e4
--- /dev/null
+++ b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java
@@ -0,0 +1,19 @@
+package io.papermc.paper.adventure;
+
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.serializer.ComponentSerializer;
+
+final class WrapperAwareSerializer implements ComponentSerializer<Component, Component, net.minecraft.network.chat.Component> {
+ @Override
+ public Component deserialize(final net.minecraft.network.chat.Component input) {
+ if (input instanceof AdventureComponent) {
+ return ((AdventureComponent) input).wrapped;
+ }
+ return PaperAdventure.GSON.serializer().fromJson(net.minecraft.network.chat.Component.Serializer.toJsonTree(input), Component.class);
+ }
+
+ @Override
+ public net.minecraft.network.chat.Component serialize(final Component component) {
+ return net.minecraft.network.chat.Component.Serializer.fromJson(PaperAdventure.GSON.serializer().toJsonTree(component));
+ }
+}
diff --git a/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java
new file mode 100644
index 0000000000000000000000000000000000000000..2dc92d8d2764d3e9b621d5c7d5e30c30367b3117
--- /dev/null
+++ b/src/main/java/net/kyori/adventure/bossbar/HackyBossBarPlatformBridge.java
@@ -0,0 +1,36 @@
+package net.kyori.adventure.bossbar;
+
+import io.papermc.paper.adventure.PaperAdventure;
+import io.papermc.paper.adventure.VanillaBossBarListener;
+import net.minecraft.server.level.ServerBossEvent;
+import org.bukkit.craftbukkit.entity.CraftPlayer;
+
+public abstract class HackyBossBarPlatformBridge {
+ public ServerBossEvent vanilla$bar;
+ private VanillaBossBarListener vanilla$listener;
+
+ public final void paper$playerShow(final CraftPlayer player) {
+ if (this.vanilla$bar == null) {
+ final BossBar $this = (BossBar) this;
+ this.vanilla$bar = new ServerBossEvent(
+ PaperAdventure.asVanilla($this.name()),
+ PaperAdventure.asVanilla($this.color()),
+ PaperAdventure.asVanilla($this.overlay())
+ );
+ this.vanilla$bar.adventure = $this;
+ this.vanilla$listener = new VanillaBossBarListener(this.vanilla$bar::broadcast);
+ $this.addListener(this.vanilla$listener);
+ }
+ this.vanilla$bar.addPlayer(player.getHandle());
+ }
+
+ public final void paper$playerHide(final CraftPlayer player) {
+ if (this.vanilla$bar != null) {
+ this.vanilla$bar.removePlayer(player.getHandle());
+ if (this.vanilla$bar.getPlayers().isEmpty()) {
+ ((BossBar) this).removeListener(this.vanilla$listener);
+ this.vanilla$bar = null;
+ }
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/ChatFormatting.java b/src/main/java/net/minecraft/ChatFormatting.java
index b82b218be1bd849fa280ea1fe0336e279bebfc18..2fb444653118816f1250841cb4c6c486e67c642b 100644
--- a/src/main/java/net/minecraft/ChatFormatting.java
+++ b/src/main/java/net/minecraft/ChatFormatting.java
@@ -110,6 +110,18 @@ public enum ChatFormatting {
return name == null ? null : FORMATTING_BY_NAME.get(cleanName(name));
}
+ // Paper start
+ @Nullable public static ChatFormatting getByHexValue(int i) {
+ for (ChatFormatting value : values()) {
+ if (value.getColor() != null && value.getColor() == i) {
+ return value;
+ }
+ }
+
+ return null;
+ }
+ // Paper end
+
@Nullable
public static ChatFormatting getById(int colorIndex) {
if (colorIndex < 0) {
diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
index 0ae24c8080391410756f101a1e40c2eef887c739..cbc968d0d514f01b26888f3ff8264d8689d9381a 100644
--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java
+++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java
@@ -14,6 +14,7 @@ import io.netty.handler.codec.EncoderException;
import io.netty.util.ByteProcessor;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -61,6 +62,7 @@ public class FriendlyByteBuf extends ByteBuf {
private static final int MAX_VARLONG_SIZE = 10;
private static final int DEFAULT_NBT_QUOTA = 2097152;
private final ByteBuf source;
+ public java.util.Locale adventure$locale; // Paper
public static final short MAX_STRING_LENGTH = 32767;
public static final int MAX_COMPONENT_STRING_LENGTH = 262144;
@@ -326,8 +328,15 @@ public class FriendlyByteBuf extends ByteBuf {
return Component.Serializer.fromJson(this.readUtf(262144));
}
+ // Paper start
+ public FriendlyByteBuf writeComponent(final net.kyori.adventure.text.Component component) {
+ return this.writeUtf(PaperAdventure.asJsonString(component, this.adventure$locale), 262144);
+ }
+ // Paper end
+
public FriendlyByteBuf writeComponent(Component text) {
- return this.writeUtf(Component.Serializer.toJson(text), 262144);
+ //return this.a(IChatBaseComponent.ChatSerializer.a(ichatbasecomponent), 262144); // Paper - comment
+ return this.writeUtf(PaperAdventure.asJsonString(text, this.adventure$locale), 262144); // Paper
}
public <T extends Enum<T>> T readEnum(Class<T> enumClass) {
diff --git a/src/main/java/net/minecraft/network/PacketEncoder.java b/src/main/java/net/minecraft/network/PacketEncoder.java
index 83e99af925c87433b59f9bed30dfbf4e490c1b84..b8a0c0411fd2caab21672de7f3e721645b61a8ba 100644
--- a/src/main/java/net/minecraft/network/PacketEncoder.java
+++ b/src/main/java/net/minecraft/network/PacketEncoder.java
@@ -3,6 +3,7 @@ package net.minecraft.network;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import java.io.IOException;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
@@ -36,6 +37,7 @@ public class PacketEncoder extends MessageToByteEncoder<Packet<?>> {
} else {
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(byteBuf);
friendlyByteBuf.writeVarInt(integer);
+ friendlyByteBuf.adventure$locale = channelHandlerContext.channel().attr(PaperAdventure.LOCALE_ATTRIBUTE).get(); // Paper
try {
int i = friendlyByteBuf.writerIndex();
diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java
index d9aac575213f3bda9c44ea2b3b6d1969ff82f09d..5ba1636bbb938373e43c1f3ac561368fc9cffd43 100644
--- a/src/main/java/net/minecraft/network/chat/Component.java
+++ b/src/main/java/net/minecraft/network/chat/Component.java
@@ -1,6 +1,7 @@
package net.minecraft.network.chat;
import com.google.common.collect.Lists;
+import io.papermc.paper.adventure.AdventureComponent; // Paper
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
@@ -161,6 +162,7 @@ public interface Component extends Message, FormattedText, Iterable<Component> {
GsonBuilder gsonbuilder = new GsonBuilder();
gsonbuilder.disableHtmlEscaping();
+ gsonbuilder.registerTypeAdapter(AdventureComponent.class, new AdventureComponent.Serializer()); // Paper
gsonbuilder.registerTypeHierarchyAdapter(Component.class, new Component.Serializer());
gsonbuilder.registerTypeHierarchyAdapter(Style.class, new Style.Serializer());
gsonbuilder.registerTypeAdapterFactory(new LowerCaseEnumTypeAdapterFactory());
@@ -320,6 +322,7 @@ public interface Component extends Message, FormattedText, Iterable<Component> {
}
public JsonElement serialize(Component ichatbasecomponent, Type type, JsonSerializationContext jsonserializationcontext) {
+ if (ichatbasecomponent instanceof AdventureComponent) return jsonserializationcontext.serialize(ichatbasecomponent); // Paper
JsonObject jsonobject = new JsonObject();
if (!ichatbasecomponent.getStyle().isEmpty()) {
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java
index d63a712126973fd1bea547d30c7d116c622669ee..1f5050e6c1d932aa196ab9524f7f1f9bd1b45fce 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundChatPacket.java
@@ -10,6 +10,7 @@ import net.minecraft.network.protocol.Packet;
public class ClientboundChatPacket implements Packet<ClientGamePacketListener> {
private final Component message;
+ public net.kyori.adventure.text.Component adventure$message; // Paper
public net.md_5.bungee.api.chat.BaseComponent[] components; // Spigot
private final ChatType type;
private final UUID sender;
@@ -28,6 +29,11 @@ public class ClientboundChatPacket implements Packet<ClientGamePacketListener> {
@Override
public void write(FriendlyByteBuf buf) {
+ // Paper start
+ if (this.adventure$message != null) {
+ buf.writeComponent(this.adventure$message);
+ } else
+ // Paper end
// Spigot start
if (this.components != null) {
buf.writeUtf(net.md_5.bungee.chat.ComponentSerializer.toString(components));
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
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetActionBarTextPacket.java
@@ -6,6 +6,7 @@ import net.minecraft.network.protocol.Packet;
public class ClientboundSetActionBarTextPacket implements Packet<ClientGamePacketListener> {
private final Component text;
+ public net.kyori.adventure.text.Component adventure$text; // Paper
public ClientboundSetActionBarTextPacket(Component message) {
this.text = message;
@@ -17,6 +18,11 @@ public class ClientboundSetActionBarTextPacket implements Packet<ClientGamePacke
@Override
public void write(FriendlyByteBuf buf) {
+ // Paper start
+ if (this.adventure$text != null) {
+ buf.writeComponent(this.adventure$text);
+ } else
+ // Paper end
buf.writeComponent(this.text);
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket.java
index bea682c52a95863c474b8283bd4ae795e525a94f..c44a276d201fdfa5144d45d319d7761583c60639 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetSubtitleTextPacket.java
@@ -6,6 +6,7 @@ import net.minecraft.network.protocol.Packet;
public class ClientboundSetSubtitleTextPacket implements Packet<ClientGamePacketListener> {
private final Component text;
+ public net.kyori.adventure.text.Component adventure$text; // Paper
public ClientboundSetSubtitleTextPacket(Component subtitle) {
this.text = subtitle;
@@ -17,6 +18,11 @@ public class ClientboundSetSubtitleTextPacket implements Packet<ClientGamePacket
@Override
public void write(FriendlyByteBuf buf) {
+ // Paper start
+ if (this.adventure$text != null) {
+ buf.writeComponent(this.adventure$text);
+ } else
+ // Paper end
buf.writeComponent(this.text);
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket.java
index 1fb62779527a228f748b49a4d2ddfc57ccb80cf8..bd808eb312ade7122973a47f4b96505829511da5 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetTitleTextPacket.java
@@ -6,6 +6,7 @@ import net.minecraft.network.protocol.Packet;
public class ClientboundSetTitleTextPacket implements Packet<ClientGamePacketListener> {
private final Component text;
+ public net.kyori.adventure.text.Component adventure$text; // Paper
public ClientboundSetTitleTextPacket(Component title) {
this.text = title;
@@ -17,6 +18,11 @@ public class ClientboundSetTitleTextPacket implements Packet<ClientGamePacketLis
@Override
public void write(FriendlyByteBuf buf) {
+ // Paper start
+ if (this.adventure$text != null) {
+ buf.writeComponent(this.adventure$text);
+ } else
+ // Paper end
buf.writeComponent(this.text);
}
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundTabListPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundTabListPacket.java
index 762a9392ffac3042356709dddd15bb3516048bed..3544e2dc2522e9d6305d727d56e73490015662c2 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundTabListPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundTabListPacket.java
@@ -7,6 +7,10 @@ import net.minecraft.network.protocol.Packet;
public class ClientboundTabListPacket implements Packet<ClientGamePacketListener> {
public final Component header;
public final Component footer;
+ // Paper start
+ public net.kyori.adventure.text.Component adventure$header;
+ public net.kyori.adventure.text.Component adventure$footer;
+ // Paper end
public ClientboundTabListPacket(Component header, Component footer) {
this.header = header;
@@ -20,6 +24,13 @@ public class ClientboundTabListPacket implements Packet<ClientGamePacketListener
@Override
public void write(FriendlyByteBuf buf) {
+ // Paper start
+ if (this.adventure$header != null && this.adventure$footer != null) {
+ buf.writeComponent(this.adventure$header);
+ buf.writeComponent(this.adventure$footer);
+ return;
+ }
+ // Paper end
buf.writeComponent(this.header);
buf.writeComponent(this.footer);
}
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index ee9eefc6ed85aea4801b5588e797a247fc747c49..fff24cae9cbde5e0ca417ea368f8572e6d8e511a 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -145,6 +145,7 @@ import net.minecraft.world.scores.Score;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.Team;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -216,6 +217,7 @@ public class ServerPlayer extends Player {
// CraftBukkit start
public String displayName;
+ public net.kyori.adventure.text.Component adventure$displayName; // Paper
public Component listName;
public org.bukkit.Location compassTarget;
public int newExp = 0;
@@ -301,6 +303,7 @@ public class ServerPlayer extends Player {
// CraftBukkit start
this.displayName = this.getScoreboardName();
+ this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper
this.bukkitPickUpLoot = true;
this.maxHealthCache = this.getMaxHealth();
}
@@ -736,23 +739,17 @@ public class ServerPlayer extends Player {
Component defaultMessage = this.getCombatTracker().getDeathMessage();
- String deathmessage = defaultMessage.getString();
- org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory);
+ org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, PaperAdventure.asAdventure(defaultMessage), defaultMessage.getString(), keepInventory); // Paper - Adventure
// SPIGOT-943 - only call if they have an inventory open
if (this.containerMenu != this.inventoryMenu) {
this.closeContainer();
}
- String deathMessage = event.getDeathMessage();
+ net.kyori.adventure.text.Component deathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure
- if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override?
- Component ichatbasecomponent;
- if (deathMessage.equals(deathmessage)) {
- ichatbasecomponent = this.getCombatTracker().getDeathMessage();
- } else {
- ichatbasecomponent = org.bukkit.craftbukkit.util.CraftChatMessage.fromStringOrNull(deathMessage);
- }
+ if (deathMessage != null && deathMessage != net.kyori.adventure.text.Component.empty() && flag) { // Paper - Adventure // TODO: allow plugins to override?
+ Component ichatbasecomponent = PaperAdventure.asVanilla(deathMessage); // Paper - Adventure
this.connection.send((Packet) (new ClientboundPlayerCombatKillPacket(this.getCombatTracker(), ichatbasecomponent)), (future) -> {
if (!future.isSuccess()) {
@@ -1702,6 +1699,7 @@ public class ServerPlayer extends Player {
}
public String locale = "en_us"; // CraftBukkit - add, lowercase
+ public java.util.Locale adventure$locale = java.util.Locale.US; // Paper
public void updateOptions(ServerboundClientInformationPacket packet) {
// CraftBukkit start
if (getMainArm() != packet.getMainHand()) {
@@ -1713,6 +1711,10 @@ public class ServerPlayer extends Player {
this.server.server.getPluginManager().callEvent(event);
}
this.locale = packet.language;
+ // Paper start
+ this.adventure$locale = net.kyori.adventure.translation.Translator.parseLocale(this.locale);
+ this.connection.connection.channel.attr(PaperAdventure.LOCALE_ATTRIBUTE).set(this.adventure$locale);
+ // Paper end
this.clientViewDistance = packet.viewDistance;
// CraftBukkit end
this.chatVisibility = packet.getChatVisibility();
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index cf9cc3ef64ec95e1061fc109e7268c2b4bb1b942..4fc871595a2449cb22bceb8ed279fe91166597f9 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -162,6 +162,8 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// CraftBukkit start
+import io.papermc.paper.adventure.ChatProcessor; // Paper
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import net.minecraft.world.inventory.AbstractContainerMenu;
@@ -385,21 +387,24 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
return this.server.isSingleplayerOwner(this.player.getGameProfile());
}
- // CraftBukkit start
- @Deprecated
- public void disconnect(Component reason) {
- this.disconnect(CraftChatMessage.fromComponent(reason));
+ public void disconnect(String s) {
+ // Paper start
+ this.disconnect(PaperAdventure.LEGACY_SECTION_UXRC.deserialize(s));
}
- // CraftBukkit end
- public void disconnect(String s) {
+ public void disconnect(final Component reason) {
+ this.disconnect(PaperAdventure.asAdventure(reason));
+ }
+
+ public void disconnect(net.kyori.adventure.text.Component reason) {
+ // Paper end
// CraftBukkit start - fire PlayerKickEvent
if (this.processedDisconnect) {
return;
}
- String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game.";
+ net.kyori.adventure.text.Component leaveMessage = net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, this.player.getBukkitEntity().displayName()); // Paper - Adventure
- PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), s, leaveMessage);
+ PlayerKickEvent event = new PlayerKickEvent(this.player.getBukkitEntity(), reason, leaveMessage); // Paper - Adventure
if (this.cserver.getServer().isRunning()) {
this.cserver.getPluginManager().callEvent(event);
@@ -410,8 +415,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
return;
}
// Send the possibly modified leave message
- s = event.getReason();
- final Component ichatbasecomponent = CraftChatMessage.fromString(s, true)[0];
+ final Component ichatbasecomponent = PaperAdventure.asVanilla(event.reason()); // Paper - Adventure
// CraftBukkit end
this.connection.send(new ClientboundDisconnectPacket(ichatbasecomponent), (future) -> {
@@ -1672,9 +1676,11 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
*/
this.player.disconnect();
- String quitMessage = this.server.getPlayerList().disconnect(this.player);
- if ((quitMessage != null) && (quitMessage.length() > 0)) {
- this.server.getPlayerList().sendMessage(CraftChatMessage.fromString(quitMessage));
+ // Paper start - Adventure
+ net.kyori.adventure.text.Component quitMessage = this.server.getPlayerList().disconnect(this.player);
+ if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) {
+ this.server.getPlayerList().broadcastMessage(PaperAdventure.asVanilla(quitMessage), ChatType.SYSTEM, Util.NIL_UUID);
+ // Paper end
}
// CraftBukkit end
this.player.getTextFilter().leave();
@@ -1856,7 +1862,12 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
this.handleCommand(s);
} else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) {
// Do nothing, this is coming from a plugin
- } else {
+ // Paper start
+ } else if (true) {
+ final ChatProcessor cp = new ChatProcessor(this.server, this.player, s, async);
+ cp.process();
+ // Paper end
+ } else if (false) { // Paper
Player player = this.getCraftPlayer();
AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.server));
this.cserver.getPluginManager().callEvent(event);
@@ -2646,30 +2657,28 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
return;
}
- // CraftBukkit start
+ // CraftBukkit start // Paper start - Adventure
Player player = this.player.getBukkitEntity();
int x = packetplayinupdatesign.getPos().getX();
int y = packetplayinupdatesign.getPos().getY();
int z = packetplayinupdatesign.getPos().getZ();
- String[] lines = new String[4];
+ List<net.kyori.adventure.text.Component> lines = new java.util.ArrayList<>();
for (int i = 0; i < list.size(); ++i) {
- TextFilter.FilteredText itextfilter_a = (TextFilter.FilteredText) list.get(i);
-
if (this.player.isTextFilteringEnabled()) {
- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(itextfilter_a.getFiltered())).getString());
+ lines.add(net.kyori.adventure.text.Component.text(list.get(i).getFiltered()));
} else {
- lines[i] = ChatFormatting.stripFormatting(new TextComponent(ChatFormatting.stripFormatting(itextfilter_a.getRaw())).getString());
+ lines.add(net.kyori.adventure.text.Component.text(list.get(i).getRaw()));
}
}
SignChangeEvent event = new SignChangeEvent((org.bukkit.craftbukkit.block.CraftBlock) player.getWorld().getBlockAt(x, y, z), this.player.getBukkitEntity(), lines);
this.cserver.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
- Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.getLines());
- for (int i = 0; i < components.length; i++) {
- tileentitysign.setMessage(i, components[i]);
+ for (int i = 0; i < 4; i++) {
+ tileentitysign.setMessage(i, PaperAdventure.asVanilla(event.line(i)));
}
+ // Paper end
tileentitysign.isEditable = false;
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
index e61752f3d00c6e2324745b92c880ee494f366765..75118458840caadfa82aa0fa2efd8a753b585ef2 100644
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -36,6 +36,7 @@ import net.minecraft.world.entity.player.Player;
import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerPreLoginEvent;
@@ -315,7 +316,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
final PlayerPreLoginEvent event = new PlayerPreLoginEvent(playerName, address, uniqueId);
if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage());
+ event.disallow(asyncEvent.getResult(), asyncEvent.kickMessage()); // Paper - Adventure
}
Waitable<PlayerPreLoginEvent.Result> waitable = new Waitable<PlayerPreLoginEvent.Result>() {
@Override
@@ -326,12 +327,12 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener
ServerLoginPacketListenerImpl.this.server.processQueue.add(waitable);
if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) {
- ServerLoginPacketListenerImpl.this.disconnect(event.getKickMessage());
+ ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
return;
}
} else {
if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
- ServerLoginPacketListenerImpl.this.disconnect(asyncEvent.getKickMessage());
+ ServerLoginPacketListenerImpl.this.disconnect(PaperAdventure.asVanilla(asyncEvent.kickMessage())); // Paper - Adventure
return;
}
}
diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
index b632280e057ae6893bf5ebcde75cefac3ee62a09..9baa56d6da9c24706f1dbc8851fd68ca752cab26 100644
--- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java
@@ -55,7 +55,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene
CraftIconCache icon = server.server.getServerIcon();
ServerListPingEvent() {
- super(((InetSocketAddress) ServerStatusPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(), ServerStatusPacketListenerImpl.this.server.getMotd(), ServerStatusPacketListenerImpl.this.server.getPlayerList().getMaxPlayers());
+ super(((InetSocketAddress) ServerStatusPacketListenerImpl.this.connection.getRemoteAddress()).getAddress(), ServerStatusPacketListenerImpl.this.server.server.getMotd(), ServerStatusPacketListenerImpl.this.server.getPlayerList().getMaxPlayers()); // Paper - Adventure
}
@Override
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 524428ee32d18c76c0e9c46bbac3664888b1b35c..186c745401a3320432f4aadfadfc6ef4b1d8041c 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.authlib.GameProfile;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.Dynamic;
import io.netty.buffer.Unpooled;
+import io.papermc.paper.adventure.PaperAdventure;
import java.io.File;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
@@ -89,6 +90,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// CraftBukkit start
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import com.google.common.base.Predicate;
import java.util.stream.Collectors;
import net.minecraft.server.dedicated.DedicatedServer;
@@ -256,7 +258,7 @@ public abstract class PlayerList {
}
// CraftBukkit start
chatmessage.withStyle(ChatFormatting.YELLOW);
- String joinMessage = CraftChatMessage.fromComponent(chatmessage);
+ Component joinMessage = chatmessage; // Paper - Adventure
playerconnection.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
this.players.add(player);
@@ -270,19 +272,18 @@ public abstract class PlayerList {
// Ensure that player inventory is populated with its viewer
player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
- PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, joinMessage);
+ PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(bukkitPlayer, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure
this.cserver.getPluginManager().callEvent(playerJoinEvent);
if (!player.connection.connection.isConnected()) {
return;
}
- joinMessage = playerJoinEvent.getJoinMessage();
+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
- if (joinMessage != null && joinMessage.length() > 0) {
- for (Component line : org.bukkit.craftbukkit.util.CraftChatMessage.fromString(joinMessage)) {
- this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(line, ChatType.SYSTEM, Util.NIL_UUID));
- }
+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
+ joinMessage = PaperAdventure.asVanilla(jm); // Paper - Adventure
+ this.server.getPlayerList().broadcastAll(new ClientboundChatPacket(joinMessage, ChatType.SYSTEM, Util.NIL_UUID)); // Paper - Adventure
}
// CraftBukkit end
@@ -479,7 +480,7 @@ public abstract class PlayerList {
}
- public String disconnect(ServerPlayer entityplayer) { // CraftBukkit - return string
+ public net.kyori.adventure.text.Component disconnect(ServerPlayer entityplayer) { // Paper - return Component
ServerLevel worldserver = entityplayer.getLevel();
entityplayer.awardStat(Stats.LEAVE_GAME);
@@ -490,7 +491,7 @@ public abstract class PlayerList {
entityplayer.closeContainer();
}
- PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), "\u00A7e" + entityplayer.getScoreboardName() + " left the game");
+ PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, com.destroystokyo.paper.PaperConfig.useDisplayNameInQuit ? entityplayer.getBukkitEntity().displayName() : net.kyori.adventure.text.Component.text(entityplayer.getScoreboardName())));
this.cserver.getPluginManager().callEvent(playerQuitEvent);
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());
@@ -543,7 +544,7 @@ public abstract class PlayerList {
this.cserver.getScoreboardManager().removePlayer(entityplayer.getBukkitEntity());
// CraftBukkit end
- return playerQuitEvent.getQuitMessage(); // CraftBukkit
+ return playerQuitEvent.quitMessage(); // Paper - Adventure
}
// CraftBukkit start - Whole method, SocketAddress to LoginListener, added hostname to signature, return EntityPlayer
@@ -589,10 +590,10 @@ public abstract class PlayerList {
}
// return chatmessage;
- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage));
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure
} else if (!this.isWhiteListed(gameprofile)) {
chatmessage = new TranslatableComponent("multiplayer.disconnect.not_whitelisted");
- event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot
+ event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.whitelistMessage)); // Spigot // Paper - Adventure
} else if (this.getIpBans().isBanned(socketaddress) && !this.getIpBans().get(socketaddress).hasExpired()) {
IpBanListEntry ipbanentry = this.ipBans.get(socketaddress);
@@ -602,17 +603,17 @@ public abstract class PlayerList {
}
// return chatmessage;
- event.disallow(PlayerLoginEvent.Result.KICK_BANNED, CraftChatMessage.fromComponent(chatmessage));
+ event.disallow(PlayerLoginEvent.Result.KICK_BANNED, PaperAdventure.asAdventure(chatmessage)); // Paper - Adventure
} else {
// return this.players.size() >= this.maxPlayers && !this.d(gameprofile) ? new ChatMessage("multiplayer.disconnect.server_full") : null;
if (this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(gameprofile)) {
- event.disallow(PlayerLoginEvent.Result.KICK_FULL, org.spigotmc.SpigotConfig.serverFullMessage); // Spigot
+ event.disallow(PlayerLoginEvent.Result.KICK_FULL, PaperAdventure.LEGACY_SECTION_UXRC.deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure
}
}
this.cserver.getPluginManager().callEvent(event);
if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) {
- loginlistener.disconnect(event.getKickMessage());
+ loginlistener.disconnect(PaperAdventure.asVanilla(event.kickMessage())); // Paper - Adventure
return null;
}
return entity;
@@ -1115,7 +1116,7 @@ public abstract class PlayerList {
public void removeAll() {
// CraftBukkit start - disconnect safely
for (ServerPlayer player : this.players) {
- player.connection.disconnect(this.server.server.getShutdownMessage()); // CraftBukkit - add custom shutdown message
+ player.connection.disconnect(this.server.server.shutdownMessage()); // CraftBukkit - add custom shutdown message // Paper - Adventure
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/BossEvent.java b/src/main/java/net/minecraft/world/BossEvent.java
index d289e8321a62f7c8d1e5b83f038e7331a26fc24e..658aff27155b32a0323f55152c7315fdc7b4a82d 100644
--- a/src/main/java/net/minecraft/world/BossEvent.java
+++ b/src/main/java/net/minecraft/world/BossEvent.java
@@ -1,5 +1,6 @@
package net.minecraft.world;
+import io.papermc.paper.adventure.PaperAdventure;
import java.util.UUID;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
@@ -13,6 +14,7 @@ public abstract class BossEvent {
protected boolean darkenScreen;
protected boolean playBossMusic;
protected boolean createWorldFog;
+ public net.kyori.adventure.bossbar.BossBar adventure; // Paper
public BossEvent(UUID uuid, Component name, BossEvent.BossBarColor color, BossEvent.BossBarOverlay style) {
this.id = uuid;
diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
index 7a0e7961df1e62b311ea2ecc76d7343a8646723b..6859fafa42527d45366018f737c19e6c3777d152 100644
--- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
+++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
@@ -33,6 +33,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
// CraftBukkit start
+import io.papermc.paper.adventure.PaperAdventure; // Paper
import java.util.UUID;
import org.bukkit.Bukkit;
@@ -599,7 +600,7 @@ public class MapItemSavedData extends SavedData {
for (org.bukkit.map.MapCursor cursor : render.cursors) {
if (cursor.isVisible()) {
- icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption())));
+ icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), PaperAdventure.asVanilla(cursor.caption()))); // Paper - Adventure
}
}
collection = icons;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0a194d6d73a048897d7d8c41cdefc87c85db155c..4df54b9d778133a5868c9ce3975579beb301e31b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -564,8 +564,10 @@ public final class CraftServer implements Server {
}
@Override
+ @Deprecated // Paper start
public int broadcastMessage(String message) {
return this.broadcast(message, BROADCAST_CHANNEL_USERS);
+ // Paper end
}
@Override
@@ -1305,7 +1307,15 @@ public final class CraftServer implements Server {
return this.configuration.getInt("settings.spawn-radius", -1);
}
+ // Paper start
@Override
+ public net.kyori.adventure.text.Component shutdownMessage() {
+ String msg = getShutdownMessage();
+ return msg != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(msg) : null;
+ }
+ // Paper end
+ @Override
+ @Deprecated // Paper
public String getShutdownMessage() {
return this.configuration.getString("settings.shutdown-message");
}
@@ -1422,7 +1432,20 @@ public final class CraftServer implements Server {
}
@Override
+ @Deprecated // Paper
public int broadcast(String message, String permission) {
+ // Paper start - Adventure
+ return this.broadcast(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(message), permission);
+ }
+
+ @Override
+ public int broadcast(net.kyori.adventure.text.Component message) {
+ return this.broadcast(message, BROADCAST_CHANNEL_USERS);
+ }
+
+ @Override
+ public int broadcast(net.kyori.adventure.text.Component message, String permission) {
+ // Paper end
Set<CommandSender> recipients = new HashSet<>();
for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) {
if (permissible instanceof CommandSender && permissible.hasPermission(permission)) {
@@ -1430,14 +1453,14 @@ public final class CraftServer implements Server {
}
}
- BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients);
+ BroadcastMessageEvent broadcastMessageEvent = new BroadcastMessageEvent(!Bukkit.isPrimaryThread(), message, recipients); // Paper - Adventure
this.getPluginManager().callEvent(broadcastMessageEvent);
if (broadcastMessageEvent.isCancelled()) {
return 0;
}
- message = broadcastMessageEvent.getMessage();
+ message = broadcastMessageEvent.message(); // Paper - Adventure
for (CommandSender recipient : recipients) {
recipient.sendMessage(message);
@@ -1663,6 +1686,14 @@ public final class CraftServer implements Server {
return CraftInventoryCreator.INSTANCE.createInventory(owner, type);
}
+ // Paper start
+ @Override
+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type);
+ return CraftInventoryCreator.INSTANCE.createInventory(owner, type, title);
+ }
+ // Paper end
+
@Override
public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) {
Validate.isTrue(type.isCreatable(), "Cannot open an inventory of type ", type);
@@ -1675,13 +1706,28 @@ public final class CraftServer implements Server {
return CraftInventoryCreator.INSTANCE.createInventory(owner, size);
}
+ // Paper start
+ @Override
+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) throws IllegalArgumentException {
+ Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")");
+ return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title);
+ }
+ // Paper end
+
@Override
public Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException {
Validate.isTrue(9 <= size && size <= 54 && size % 9 == 0, "Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got " + size + ")");
return CraftInventoryCreator.INSTANCE.createInventory(owner, size, title);
}
+ // Paper start
+ @Override
+ public Merchant createMerchant(net.kyori.adventure.text.Component title) {
+ return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title);
+ }
+ // Paper end
@Override
+ @Deprecated // Paper
public Merchant createMerchant(String title) {
return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title);
}
@@ -1725,6 +1771,12 @@ public final class CraftServer implements Server {
return Thread.currentThread().equals(console.serverThread) || this.console.hasStopped() || !org.spigotmc.AsyncCatcher.enabled; // All bets are off if we have shut down (e.g. due to watchdog)
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component motd() {
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(new net.minecraft.network.chat.TextComponent(console.getMotd()));
+ }
+ // Paper end
@Override
public String getMotd() {
return this.console.getMotd();
@@ -2153,5 +2205,15 @@ public final class CraftServer implements Server {
return null;
}
}
+
+ // Paper start
+ private Iterable<? extends net.kyori.adventure.audience.Audience> adventure$audiences;
+ @Override
+ public Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
+ if (this.adventure$audiences == null) {
+ this.adventure$audiences = com.google.common.collect.Iterables.concat(java.util.Collections.singleton(this.getConsoleSender()), this.getOnlinePlayers());
+ }
+ return this.adventure$audiences;
+ }
// Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index ce548fe73dcef10adb99045b06ce58135935aee6..3fd48807c554b176cd8e925bdcd68e7f808e5881 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 {
public static boolean useConsole = true;
public static void main(String[] args) {
+ // Paper start
+ final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected");
+ if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) {
+ System.setProperty(warnWhenLegacyFormattingDetected, String.valueOf(true));
+ }
+ // Paper end
// Todo: Installation script
OptionParser parser = new OptionParser() {
{
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
index 95b8d32adedf579172187c594e18177f3a84850e..5abf219e86c6b4cf0c6b2e8ea72d7ed7b4f612e3 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java
@@ -70,6 +70,19 @@ public class CraftBeacon extends CraftBlockEntityState<BeaconBlockEntity> implem
this.getSnapshot().secondaryPower = (effect != null) ? MobEffect.byId(effect.getId()) : null;
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component customName() {
+ final BeaconBlockEntity be = this.getSnapshot();
+ return be.name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.name) : null;
+ }
+
+ @Override
+ public void customName(final net.kyori.adventure.text.Component customName) {
+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null);
+ }
+ // Paper end
+
@Override
public String getCustomName() {
BeaconBlockEntity beacon = this.getSnapshot();
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java
index 16a0f6e390a7415635e3573c1f79f7d78e5ef859..b1edc96d7e0444e72b79f190982de1d1bb5987f3 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java
@@ -32,6 +32,19 @@ public abstract class CraftContainer<T extends BaseContainerBlockEntity> extends
this.getSnapshot().lockKey = (key == null) ? LockCode.NO_LOCK : new LockCode(key);
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component customName() {
+ final T be = this.getSnapshot();
+ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null;
+ }
+
+ @Override
+ public void customName(final net.kyori.adventure.text.Component customName) {
+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null);
+ }
+ // Paper end
+
@Override
public String getCustomName() {
T container = this.getSnapshot();
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java
index add5b68d5fbd887e3fc2d226eff9ab00ed01ce73..2c3d6ba06d876df168aae4cc09b7b4400e2fa33d 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java
@@ -16,6 +16,19 @@ public class CraftEnchantingTable extends CraftBlockEntityState<EnchantmentTable
super(material, te);
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component customName() {
+ final EnchantmentTableBlockEntity be = this.getSnapshot();
+ return be.hasCustomName() ? io.papermc.paper.adventure.PaperAdventure.asAdventure(be.getCustomName()) : null;
+ }
+
+ @Override
+ public void customName(final net.kyori.adventure.text.Component customName) {
+ this.getSnapshot().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null);
+ }
+ // Paper end
+
@Override
public String getCustomName() {
EnchantmentTableBlockEntity enchant = this.getSnapshot();
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
index 2509a39bec5edd38b54709fec241c7c18e0d1c26..6e89b039479a034d98d1ec183b06d5418ab51733 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
@@ -12,8 +12,10 @@ import org.bukkit.craftbukkit.util.CraftChatMessage;
public class CraftSign extends CraftBlockEntityState<SignBlockEntity> implements Sign {
// Lazily initialized only if requested:
- private String[] originalLines = null;
- private String[] lines = null;
+ // Paper start
+ private java.util.ArrayList<net.kyori.adventure.text.Component> originalLines = null; // ArrayList for RandomAccess
+ private java.util.ArrayList<net.kyori.adventure.text.Component> lines = null; // ArrayList for RandomAccess
+ // Paper end
public CraftSign(final Block block) {
super(block, SignBlockEntity.class);
@@ -23,27 +25,51 @@ public class CraftSign extends CraftBlockEntityState<SignBlockEntity> implements
super(material, te);
}
+ // Paper start
@Override
- public String[] getLines() {
- if (this.lines == null) {
- // Lazy initialization:
- SignBlockEntity sign = this.getSnapshot();
- this.lines = new String[sign.messages.length];
- System.arraycopy(CraftSign.revertComponents(sign.messages), 0, lines, 0, lines.length);
- this.originalLines = new String[lines.length];
- System.arraycopy(lines, 0, originalLines, 0, originalLines.length);
- }
+ public java.util.List<net.kyori.adventure.text.Component> lines() {
+ this.loadLines();
return this.lines;
}
+ @Override
+ public net.kyori.adventure.text.Component line(int index) {
+ this.loadLines();
+ return this.lines.get(index);
+ }
+
+ @Override
+ public void line(int index, net.kyori.adventure.text.Component line) {
+ this.loadLines();
+ this.lines.set(index, line);
+ }
+
+ private void loadLines() {
+ if (lines != null) {
+ return;
+ }
+ // Lazy initialization:
+ SignBlockEntity sign = this.getSnapshot();
+ lines = io.papermc.paper.adventure.PaperAdventure.asAdventure(com.google.common.collect.Lists.newArrayList(sign.messages));
+ originalLines = new java.util.ArrayList<>(lines);
+ }
+ // Paper end
+ @Override
+ public String[] getLines() {
+ this.loadLines();
+ return this.lines.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).toArray(String[]::new); // Paper
+ }
+
@Override
public String getLine(int index) throws IndexOutOfBoundsException {
- return this.getLines()[index];
+ this.loadLines();
+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(this.lines.get(index)); // Paper
}
@Override
public void setLine(int index, String line) throws IndexOutOfBoundsException {
- this.getLines()[index] = line;
+ this.loadLines();
+ this.lines.set(index, line != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(line) : net.kyori.adventure.text.Component.empty()); // Paper
}
@Override
@@ -81,16 +107,32 @@ public class CraftSign extends CraftBlockEntityState<SignBlockEntity> implements
super.applyTo(sign);
if (this.lines != null) {
- for (int i = 0; i < lines.length; i++) {
- String line = (this.lines[i] == null) ? "" : this.lines[i];
- if (line.equals(this.originalLines[i])) {
+ // Paper start
+ for (int i = 0; i < this.lines.size(); ++i) {
+ net.kyori.adventure.text.Component component = this.lines.get(i);
+ net.kyori.adventure.text.Component origComp = this.originalLines.get(i);
+ if (component.equals(origComp)) {
continue; // The line contents are still the same, skip.
}
- sign.setMessage(i, CraftChatMessage.fromString(line)[0]);
+ sign.messages[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(component);
}
+ // Paper end
}
}
+ // Paper start
+ public static Component[] sanitizeLines(java.util.List<net.kyori.adventure.text.Component> lines) {
+ Component[] components = new Component[4];
+ for (int i = 0; i < 4; i++) {
+ if (i < lines.size() && lines.get(i) != null) {
+ components[i] = io.papermc.paper.adventure.PaperAdventure.asVanilla(lines.get(i));
+ } else {
+ components[i] = new TextComponent("");
+ }
+ }
+ return components;
+ }
+ // Paper end
public static Component[] sanitizeLines(String[] lines) {
Component[] components = new Component[4];
diff --git a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
index 8bf9dd8f83c5e17447d8603fa5551e1fea06705d..a885eb537d6475eefe7d06f8312ecf0a278c5a00 100644
--- a/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
+++ b/src/main/java/org/bukkit/craftbukkit/command/CraftConsoleCommandSender.java
@@ -80,4 +80,11 @@ public class CraftConsoleCommandSender extends ServerCommandSender implements Co
public boolean isConversing() {
return this.conversationTracker.isConversing();
}
+
+ // Paper start
+ @Override
+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) {
+ this.sendRawMessage(org.bukkit.craftbukkit.util.CraftChatMessage.fromComponent(io.papermc.paper.adventure.PaperAdventure.asVanilla(message)));
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
index cf69a45f038c2b8336010f5fe277313fd0513b5b..eb99e0c2462a2d1ab4508a5c3f1580b6e31d7465 100644
--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
+++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
@@ -187,6 +187,12 @@ public class CraftEnchantment extends Enchantment {
CraftEnchantment ench = (CraftEnchantment) other;
return !this.target.isCompatibleWith(ench.target);
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component displayName(int level) {
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getFullname(level));
+ }
+ // Paper end
public net.minecraft.world.item.enchantment.Enchantment getHandle() {
return this.target;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 78d1621c1b5f1870829d92720e2151e9f9d9a8b5..6722d97d498fb2951b7dd8af3b68dd771ce8f5c1 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -808,6 +808,19 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return this.getHandle().getVehicle().getBukkitEntity();
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component customName() {
+ final Component name = this.getHandle().getCustomName();
+ return name != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(name) : null;
+ }
+
+ @Override
+ public void customName(final net.kyori.adventure.text.Component customName) {
+ this.getHandle().setCustomName(customName != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(customName) : null);
+ }
+ // Paper end
+
@Override
public void setCustomName(String name) {
// sane limit for name length
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index d4ea706d5456e709b95e34be8220a0d39be2c8f4..2db149bf57c561d7f8f49341fbefafb5d3ecab54 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -317,9 +317,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
container = CraftEventFactory.callInventoryOpenEvent(player, container);
if (container == null) return;
- String title = container.getBukkitView().getTitle();
+ //String title = container.getBukkitView().getTitle(); // Paper - comment
+ net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper
+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(container.getBukkitView().getTitle()); // Paper
- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0]));
+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper // Paper - comment
+ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper
player.containerMenu = container;
player.initMenu(container);
}
@@ -388,8 +391,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
// Now open the window
MenuType<?> windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory());
- String title = inventory.getTitle();
- player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0]));
+
+ //String title = inventory.getTitle(); // Paper - comment
+ net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper
+ if (adventure$title == null) adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(inventory.getTitle()); // Paper
+ //player.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
+ player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper
player.containerMenu = container;
player.initMenu(container);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 969d5071dbf3356b80da38526351d488ab936c08..bc901793055db9481ec32e668386ba33696bc0a5 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -244,14 +244,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public String getDisplayName() {
+ if(true) return io.papermc.paper.adventure.DisplayNames.getLegacy(this); // Paper
return this.getHandle().displayName;
}
@Override
public void setDisplayName(final String name) {
+ this.getHandle().adventure$displayName = name != null ? io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(name) : net.kyori.adventure.text.Component.text(this.getName()); // Paper
this.getHandle().displayName = name == null ? getName() : name;
}
+ // Paper start
+ @Override
+ public void playerListName(net.kyori.adventure.text.Component name) {
+ getHandle().listName = name == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(name);
+ for (ServerPlayer player : server.getHandle().players) {
+ if (player.getBukkitEntity().canSee(this)) {
+ player.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, getHandle()));
+ }
+ }
+ }
+ @Override
+ public net.kyori.adventure.text.Component playerListName() {
+ return getHandle().listName == null ? net.kyori.adventure.text.Component.text(getName()) : io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().listName);
+ }
+ @Override
+ public net.kyori.adventure.text.Component playerListHeader() {
+ return playerListHeader;
+ }
+ @Override
+ public net.kyori.adventure.text.Component playerListFooter() {
+ return playerListFooter;
+ }
+ // Paper end
@Override
public String getPlayerListName() {
return this.getHandle().listName == null ? getName() : CraftChatMessage.fromComponent(this.getHandle().listName);
@@ -270,42 +295,42 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
}
- private Component playerListHeader;
- private Component playerListFooter;
+ private net.kyori.adventure.text.Component playerListHeader; // Paper - Adventure
+ private net.kyori.adventure.text.Component playerListFooter; // Paper - Adventure
@Override
public String getPlayerListHeader() {
- return (this.playerListHeader == null) ? null : CraftChatMessage.fromComponent(playerListHeader);
+ return (this.playerListHeader == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListHeader);
}
@Override
public String getPlayerListFooter() {
- return (this.playerListFooter == null) ? null : CraftChatMessage.fromComponent(playerListFooter);
+ return (this.playerListFooter == null) ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(playerListFooter); // Paper - Adventure
}
@Override
public void setPlayerListHeader(String header) {
- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true);
+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure
this.updatePlayerListHeaderFooter();
}
@Override
public void setPlayerListFooter(String footer) {
- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true);
+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure
this.updatePlayerListHeaderFooter();
}
@Override
public void setPlayerListHeaderFooter(String header, String footer) {
- this.playerListHeader = CraftChatMessage.fromStringOrNull(header, true);
- this.playerListFooter = CraftChatMessage.fromStringOrNull(footer, true);
+ this.playerListHeader = header == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(header); // Paper - Adventure
+ this.playerListFooter = footer == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(footer); // Paper - Adventure
this.updatePlayerListHeaderFooter();
}
private void updatePlayerListHeaderFooter() {
if (this.getHandle().connection == null) return;
- ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? new TextComponent("") : this.playerListHeader, (this.playerListFooter == null) ? new TextComponent("") : this.playerListFooter);
+ ClientboundTabListPacket packet = new ClientboundTabListPacket((this.playerListHeader == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListHeader), (this.playerListFooter == null) ? new TextComponent("") : io.papermc.paper.adventure.PaperAdventure.asVanilla(this.playerListFooter));
this.getHandle().connection.send(packet);
}
@@ -337,6 +362,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().connection.disconnect(message == null ? "" : message);
}
+ // Paper start
+ @Override
+ public void kick(final net.kyori.adventure.text.Component message) {
+ org.spigotmc.AsyncCatcher.catchOp("player kick");
+ final ServerGamePacketListenerImpl connection = this.getHandle().connection;
+ if (connection != null) {
+ connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message);
+ }
+ }
+ // Paper end
+
@Override
public void setCompassTarget(Location loc) {
if (this.getHandle().connection == null) return;
@@ -571,6 +607,36 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().connection.send(packet);
}
+ // Paper start
+ @Override
+ public void sendSignChange(Location loc, List<net.kyori.adventure.text.Component> lines) {
+ this.sendSignChange(loc, lines, org.bukkit.DyeColor.BLACK);
+ }
+ @Override
+ public void sendSignChange(Location loc, List<net.kyori.adventure.text.Component> lines, DyeColor dyeColor) {
+ if (getHandle().connection == null) {
+ return;
+ }
+ if (lines == null) {
+ lines = new java.util.ArrayList<>(4);
+ }
+ Validate.notNull(loc, "Location cannot be null");
+ Validate.notNull(dyeColor, "DyeColor cannot be null");
+ if (lines.size() < 4) {
+ throw new IllegalArgumentException("Must have at least 4 lines");
+ }
+ Component[] components = CraftSign.sanitizeLines(lines);
+ this.sendSignChange0(components, loc, dyeColor);
+ }
+
+ private void sendSignChange0(Component[] components, Location loc, DyeColor dyeColor) {
+ SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState());
+ sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData()));
+ System.arraycopy(components, 0, sign.messages, 0, sign.messages.length);
+
+ getHandle().connection.send(sign.getUpdatePacket());
+ }
+ // Paper end
@Override
public void sendSignChange(Location loc, String[] lines) {
this.sendSignChange(loc, lines, DyeColor.BLACK);
@@ -593,13 +659,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
Component[] components = CraftSign.sanitizeLines(lines);
- SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState());
- sign.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData()));
- for (int i = 0; i < components.length; i++) {
- sign.setMessage(i, components[i]);
- }
+ /*SignBlockEntity sign = new SignBlockEntity(new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()), Blocks.OAK_SIGN.defaultBlockState());
+ sign.setColor(EnumColor.fromColorIndex(dyeColor.getWoolData()));
+ System.arraycopy(components, 0, sign.lines, 0, sign.lines.length);
- this.getHandle().connection.send(sign.getUpdatePacket());
+ this.getHandle().connection.send(sign.getUpdatePacket());*/ // Paper
+ this.sendSignChange0(components, loc, dyeColor); // Paper
}
@Override
@@ -1699,6 +1764,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return (this.getHandle().clientViewDistance == null) ? Bukkit.getViewDistance() : this.getHandle().clientViewDistance;
}
+ // Paper start
+ @Override
+ public java.util.Locale locale() {
+ return getHandle().adventure$locale;
+ }
+ // Paper end
@Override
public int getPing() {
return this.getHandle().latency;
@@ -1727,6 +1798,158 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
getInventory().setItemInMainHand(hand);
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component displayName() {
+ return this.getHandle().adventure$displayName;
+ }
+
+ @Override
+ public void displayName(final net.kyori.adventure.text.Component displayName) {
+ this.getHandle().adventure$displayName = displayName != null ? displayName : net.kyori.adventure.text.Component.text(this.getName());
+ this.getHandle().displayName = null;
+ }
+
+ @Override
+ public void sendMessage(final net.kyori.adventure.identity.Identity identity, final net.kyori.adventure.text.Component message, final net.kyori.adventure.audience.MessageType type) {
+ final ClientboundChatPacket packet = new ClientboundChatPacket(null, type == net.kyori.adventure.audience.MessageType.CHAT ? net.minecraft.network.chat.ChatType.CHAT : net.minecraft.network.chat.ChatType.SYSTEM, identity.uuid());
+ packet.adventure$message = message;
+ this.getHandle().connection.send(packet);
+ }
+
+ @Override
+ public void sendActionBar(final net.kyori.adventure.text.Component message) {
+ final net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket packet = new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket((net.minecraft.network.chat.Component) null);
+ packet.adventure$text = message;
+ this.getHandle().connection.send(packet);
+ }
+
+ @Override
+ public void sendPlayerListHeader(final net.kyori.adventure.text.Component header) {
+ this.playerListHeader = header;
+ this.adventure$sendPlayerListHeaderAndFooter();
+ }
+
+ @Override
+ public void sendPlayerListFooter(final net.kyori.adventure.text.Component footer) {
+ this.playerListFooter = footer;
+ this.adventure$sendPlayerListHeaderAndFooter();
+ }
+
+ @Override
+ public void sendPlayerListHeaderAndFooter(final net.kyori.adventure.text.Component header, final net.kyori.adventure.text.Component footer) {
+ this.playerListHeader = header;
+ this.playerListFooter = footer;
+ this.adventure$sendPlayerListHeaderAndFooter();
+ }
+
+ private void adventure$sendPlayerListHeaderAndFooter() {
+ final ServerGamePacketListenerImpl connection = this.getHandle().connection;
+ if (connection == null) return;
+ final ClientboundTabListPacket packet = new ClientboundTabListPacket(null, null);
+ packet.adventure$header = (this.playerListHeader == null) ? net.kyori.adventure.text.Component.empty() : this.playerListHeader;
+ packet.adventure$footer = (this.playerListFooter == null) ? net.kyori.adventure.text.Component.empty() : this.playerListFooter;
+ connection.send(packet);
+ }
+
+ @Override
+ public void showTitle(final net.kyori.adventure.title.Title title) {
+ final ServerGamePacketListenerImpl connection = this.getHandle().connection;
+ final net.kyori.adventure.title.Title.Times times = title.times();
+ if (times != null) {
+ connection.send(new ClientboundSetTitlesAnimationPacket(ticks(times.fadeIn()), ticks(times.stay()), ticks(times.fadeOut())));
+ }
+ final ClientboundSetSubtitleTextPacket sp = new ClientboundSetSubtitleTextPacket((net.minecraft.network.chat.Component) null);
+ sp.adventure$text = title.subtitle();
+ connection.send(sp);
+ final ClientboundSetTitleTextPacket tp = new ClientboundSetTitleTextPacket((net.minecraft.network.chat.Component) null);
+ tp.adventure$text = title.title();
+ connection.send(tp);
+ }
+
+ private static int ticks(final java.time.Duration duration) {
+ if (duration == null) {
+ return -1;
+ }
+ return (int) (duration.toMillis() / 50L);
+ }
+
+ @Override
+ public void clearTitle() {
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundClearTitlesPacket(false));
+ }
+
+ // resetTitle implemented above
+
+ @Override
+ public void showBossBar(final net.kyori.adventure.bossbar.BossBar bar) {
+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerShow(this);
+ }
+
+ @Override
+ public void hideBossBar(final net.kyori.adventure.bossbar.BossBar bar) {
+ ((net.kyori.adventure.bossbar.HackyBossBarPlatformBridge) bar).paper$playerHide(this);
+ }
+
+ @Override
+ public void playSound(final net.kyori.adventure.sound.Sound sound) {
+ final Vec3 pos = this.getHandle().position();
+ this.playSound(sound, pos.x, pos.y, pos.z);
+ }
+
+ @Override
+ public void playSound(final net.kyori.adventure.sound.Sound sound, final double x, final double y, final double z) {
+ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name());
+ final java.util.Optional<net.minecraft.sounds.SoundEvent> event = net.minecraft.core.Registry.SOUND_EVENT.getOptional(name);
+ if (event.isPresent()) {
+ this.getHandle().connection.send(new ClientboundSoundPacket(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), x, y, z, sound.volume(), sound.pitch()));
+ } else {
+ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), new Vec3(x, y, z), sound.volume(), sound.pitch()));
+ }
+ }
+
+ @Override
+ public void playSound(final net.kyori.adventure.sound.Sound sound, final net.kyori.adventure.sound.Sound.Emitter emitter) {
+ final Entity entity;
+ if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) {
+ entity = this.getHandle();
+ } else if (emitter instanceof org.bukkit.entity.Entity) {
+ entity = ((CraftEntity) emitter).getHandle();
+ } else {
+ throw new IllegalArgumentException("Sound emitter must be an Entity or self(), but was: " + emitter);
+ }
+
+ final ResourceLocation name = io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.name());
+ final java.util.Optional<net.minecraft.sounds.SoundEvent> event = net.minecraft.core.Registry.SOUND_EVENT.getOptional(name);
+ if (event.isPresent()) {
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSoundEntityPacket(event.get(), io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), entity, sound.volume(), sound.pitch()));
+ } else {
+ this.getHandle().connection.send(new ClientboundCustomSoundPacket(name, io.papermc.paper.adventure.PaperAdventure.asVanilla(sound.source()), entity.position(), sound.volume(), sound.pitch()));
+ }
+ }
+
+ @Override
+ public void stopSound(final net.kyori.adventure.sound.SoundStop stop) {
+ this.getHandle().connection.send(new ClientboundStopSoundPacket(
+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.sound()),
+ io.papermc.paper.adventure.PaperAdventure.asVanillaNullable(stop.source())
+ ));
+ }
+
+ @Override
+ public void openBook(final net.kyori.adventure.inventory.Book book) {
+ final java.util.Locale locale = this.getHandle().adventure$locale;
+ final net.minecraft.world.item.ItemStack item = io.papermc.paper.adventure.PaperAdventure.asItemStack(book, locale);
+ final ServerPlayer player = this.getHandle();
+ final ServerGamePacketListenerImpl connection = player.connection;
+ final net.minecraft.world.entity.player.Inventory inventory = player.getInventory();
+ final int slot = inventory.items.size() + inventory.selected;
+ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, item));
+ connection.send(new net.minecraft.network.protocol.game.ClientboundOpenBookPacket(net.minecraft.world.InteractionHand.MAIN_HAND));
+ connection.send(new net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket(0, slot, inventory.getSelected()));
+ }
+ // Paper end
+
// Spigot start
private final Player.Spigot spigot = new Player.Spigot()
{
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e260366ca4f0ba7f37b7e78e3b46a05d91079d8d..ae12d4a7b56ec70ac5f529e0f336019e97f667ce 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -787,9 +787,9 @@ public class CraftEventFactory {
return event;
}
- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List<org.bukkit.inventory.ItemStack> drops, String deathMessage, boolean keepInventory) {
+ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, List<org.bukkit.inventory.ItemStack> drops, net.kyori.adventure.text.Component deathMessage, String stringDeathMessage, boolean keepInventory) { // Paper - Adventure
CraftPlayer entity = victim.getBukkitEntity();
- PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage);
+ PlayerDeathEvent event = new PlayerDeathEvent(entity, drops, victim.getExpReward(), 0, deathMessage, stringDeathMessage); // Paper - Adventure
event.setKeepInventory(keepInventory);
org.bukkit.World world = entity.getWorld();
Bukkit.getServer().getPluginManager().callEvent(event);
@@ -813,7 +813,7 @@ public class CraftEventFactory {
* Server methods
*/
public static ServerListPingEvent callServerListPingEvent(Server craftServer, InetAddress address, String motd, int numPlayers, int maxPlayers) {
- ServerListPingEvent event = new ServerListPingEvent(address, motd, numPlayers, maxPlayers);
+ ServerListPingEvent event = new ServerListPingEvent(address, craftServer.motd(), numPlayers, maxPlayers); // Paper - Adventure
craftServer.getPluginManager().callEvent(event);
return event;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
index ceada296118643c79dfb94f08288ddbeca50c9dd..99d52dc4a3619200e8eb864e8ed8f4a6e469b443 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
@@ -69,6 +69,13 @@ public class CraftContainer extends AbstractContainerMenu {
return inventory.getType();
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component title() {
+ return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle());
+ }
+ // Paper end
+
@Override
public String getTitle() {
return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle();
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.javaED5zI7 b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.javaED5zI7
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
index 6486a76466691f958349a4706d7c9caff9cb8f64..08fc05836b26f5f93ae74324705d5f593b57315a 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
@@ -19,6 +19,12 @@ public class CraftInventoryCustom extends CraftInventory {
super(new MinecraftInventory(owner, type));
}
+ // Paper start
+ public CraftInventoryCustom(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ super(new MinecraftInventory(owner, type, title));
+ }
+ // Paper end
+
public CraftInventoryCustom(InventoryHolder owner, InventoryType type, String title) {
super(new MinecraftInventory(owner, type, title));
}
@@ -27,6 +33,12 @@ public class CraftInventoryCustom extends CraftInventory {
super(new MinecraftInventory(owner, size));
}
+ // Paper start
+ public CraftInventoryCustom(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) {
+ super(new MinecraftInventory(owner, size, title));
+ }
+ // Paper end
+
public CraftInventoryCustom(InventoryHolder owner, int size, String title) {
super(new MinecraftInventory(owner, size, title));
}
@@ -36,9 +48,17 @@ public class CraftInventoryCustom extends CraftInventory {
private int maxStack = MAX_STACK;
private final List<HumanEntity> viewers;
private final String title;
+ private final net.kyori.adventure.text.Component adventure$title; // Paper
private InventoryType type;
private final InventoryHolder owner;
+ // Paper start
+ public MinecraftInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ this(owner, type.getDefaultSize(), title);
+ this.type = type;
+ }
+ // Paper end
+
public MinecraftInventory(InventoryHolder owner, InventoryType type) {
this(owner, type.getDefaultSize(), type.getDefaultTitle());
this.type = type;
@@ -57,11 +77,24 @@ public class CraftInventoryCustom extends CraftInventory {
Validate.notNull(title, "Title cannot be null");
this.items = NonNullList.withSize(size, ItemStack.EMPTY);
this.title = title;
+ this.adventure$title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(title);
this.viewers = new ArrayList<HumanEntity>();
this.owner = owner;
this.type = InventoryType.CHEST;
}
+ // Paper start
+ public MinecraftInventory(final InventoryHolder owner, final int size, final net.kyori.adventure.text.Component title) {
+ Validate.notNull(title, "Title cannot be null");
+ this.items = NonNullList.withSize(size, ItemStack.EMPTY);
+ this.title = io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title);
+ this.adventure$title = title;
+ this.viewers = new ArrayList<HumanEntity>();
+ this.owner = owner;
+ this.type = InventoryType.CHEST;
+ }
+ // Paper end
+
@Override
public int getContainerSize() {
return this.items.size();
@@ -183,6 +216,12 @@ public class CraftInventoryCustom extends CraftInventory {
return null;
}
+ // Paper start
+ public net.kyori.adventure.text.Component title() {
+ return this.adventure$title;
+ }
+ // Paper end
+
public String getTitle() {
return this.title;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java
index 6a64fbb8b4937f39d5fdc2e2cbec26c83c74c486..7d6b5fdb00a5c1614849735634262a36a4efbd66 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java
@@ -64,6 +64,13 @@ public class CraftInventoryView extends InventoryView {
return CraftItemStack.asCraftMirror(this.container.getSlot(slot).getItem());
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component title() {
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.container.getTitle());
+ }
+ // Paper end
+
@Override
public String getTitle() {
return CraftChatMessage.fromComponent(this.container.getTitle());
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
index 27bbec5f779e7193818e546dbf02a761ff950719..8f05c6832fc968666f0e6e0a19f6dd74d92d0c28 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -337,4 +337,17 @@ public final class CraftItemFactory implements ItemFactory {
public Material updateMaterial(ItemMeta meta, Material material) throws IllegalArgumentException {
return ((CraftMetaItem) meta).updateMaterial(material);
}
+
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op) {
+ final net.minecraft.nbt.CompoundTag tag = CraftItemStack.asNMSCopy(item).getTag();
+ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.of(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asBinaryTagHolder(tag))));
+ }
+
+ @Override
+ public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) {
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName());
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
index b7cb3c94d88b2753fd1fc17c2842607576fd7874..f40d6a0048ad5b3f6e31d83894ee89f5ca64fb3a 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
@@ -14,10 +14,17 @@ import org.apache.commons.lang.Validate;
public class CraftMerchantCustom extends CraftMerchant {
+ @Deprecated // Paper - Adventure
public CraftMerchantCustom(String title) {
super(new MinecraftMerchant(title));
this.getMerchant().craftMerchant = this;
}
+ // Paper start
+ public CraftMerchantCustom(net.kyori.adventure.text.Component title) {
+ super(new MinecraftMerchant(title));
+ getMerchant().craftMerchant = this;
+ }
+ // Paper end
@Override
public String toString() {
@@ -37,10 +44,17 @@ public class CraftMerchantCustom extends CraftMerchant {
private Level tradingWorld;
protected CraftMerchant craftMerchant;
+ @Deprecated // Paper - Adventure
public MinecraftMerchant(String title) {
Validate.notNull(title, "Title cannot be null");
this.title = new TextComponent(title);
}
+ // Paper start
+ public MinecraftMerchant(net.kyori.adventure.text.Component title) {
+ Validate.notNull(title, "Title cannot be null");
+ this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title);
+ }
+ // Paper end
@Override
public CraftMerchant getCraftMerchant() {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
index ca359cb1ac5f48d4f75d33946fcddedb270407c2..a33dd184ea51df7e59ed08e5e2b0ea4ed9dadff5 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
@@ -1,8 +1,9 @@
package org.bukkit.craftbukkit.inventory;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Lists;
+
+import com.google.common.collect.ImmutableMap; // Paper
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -17,9 +18,11 @@ import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.BookMeta.Generation;
+import org.checkerframework.checker.nullness.qual.NonNull;
// Spigot start
import static org.spigotmc.ValidateUtils.*;
+
import java.util.AbstractList;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
@@ -269,6 +272,141 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
this.generation = (generation == null) ? null : generation.ordinal();
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component title() {
+ return this.title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.title);
+ }
+
+ @Override
+ public org.bukkit.inventory.meta.BookMeta title(net.kyori.adventure.text.Component title) {
+ this.setTitle(title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title));
+ return this;
+ }
+
+ @Override
+ public net.kyori.adventure.text.Component author() {
+ return this.author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(this.author);
+ }
+
+ @Override
+ public org.bukkit.inventory.meta.BookMeta author(net.kyori.adventure.text.Component author) {
+ this.setAuthor(author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author));
+ return this;
+ }
+
+ @Override
+ public net.kyori.adventure.text.Component page(final int page) {
+ Validate.isTrue(isValidPage(page), "Invalid page number");
+ return this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(pages.get(page - 1)) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(pages.get(page - 1));
+ }
+
+ @Override
+ public void page(final int page, net.kyori.adventure.text.Component data) {
+ if (!isValidPage(page)) {
+ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size());
+ }
+ if (data == null) {
+ data = net.kyori.adventure.text.Component.empty();
+ }
+ pages.set(page - 1, this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(data) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(data));
+ }
+
+ @Override
+ public List<net.kyori.adventure.text.Component> pages() {
+ if (this.pages == null) return ImmutableList.of();
+ if (this instanceof CraftMetaBookSigned)
+ return pages.stream().map(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson()::deserialize).collect(ImmutableList.toImmutableList());
+ else
+ return pages.stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::deserialize).collect(ImmutableList.toImmutableList());
+ }
+
+ @Override
+ public BookMeta pages(List<net.kyori.adventure.text.Component> pages) {
+ if (this.pages != null) this.pages.clear();
+ for (net.kyori.adventure.text.Component page : pages) {
+ addPages(page);
+ }
+ return this;
+ }
+
+ @Override
+ public BookMeta pages(net.kyori.adventure.text.Component... pages) {
+ if (this.pages != null) this.pages.clear();
+ addPages(pages);
+ return this;
+ }
+
+ @Override
+ public void addPages(net.kyori.adventure.text.Component... pages) {
+ if (this.pages == null) this.pages = new ArrayList<>();
+ for (net.kyori.adventure.text.Component page : pages) {
+ if (this.pages.size() >= MAX_PAGES) {
+ return;
+ }
+
+ if (page == null) {
+ page = net.kyori.adventure.text.Component.empty();
+ }
+
+ this.pages.add(this instanceof CraftMetaBookSigned ? net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(page) : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(page));
+ }
+ }
+
+ private CraftMetaBook(net.kyori.adventure.text.Component title, net.kyori.adventure.text.Component author, List<net.kyori.adventure.text.Component> pages) {
+ super((org.bukkit.craftbukkit.inventory.CraftMetaItem) org.bukkit.Bukkit.getItemFactory().getItemMeta(org.bukkit.Material.WRITABLE_BOOK));
+ this.title = title == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(title);
+ this.author = author == null ? null : io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.serialize(author);
+ this.pages = pages.subList(0, Math.min(MAX_PAGES, pages.size())).stream().map(io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC::serialize).collect(java.util.stream.Collectors.toList());
+ }
+
+ static final class CraftMetaBookBuilder implements BookMetaBuilder {
+ private net.kyori.adventure.text.Component title = null;
+ private net.kyori.adventure.text.Component author = null;
+ private final List<net.kyori.adventure.text.Component> pages = new java.util.ArrayList<>();
+
+ @Override
+ public BookMetaBuilder title(net.kyori.adventure.text.Component title) {
+ this.title = title;
+ return this;
+ }
+
+ @Override
+ public BookMetaBuilder author(net.kyori.adventure.text.Component author) {
+ this.author = author;
+ return this;
+ }
+
+ @Override
+ public BookMetaBuilder addPage(net.kyori.adventure.text.Component page) {
+ this.pages.add(page);
+ return this;
+ }
+
+ @Override
+ public BookMetaBuilder pages(net.kyori.adventure.text.Component... pages) {
+ java.util.Collections.addAll(this.pages, pages);
+ return this;
+ }
+
+ @Override
+ public BookMetaBuilder pages(java.util.Collection<net.kyori.adventure.text.Component> pages) {
+ this.pages.addAll(pages);
+ return this;
+ }
+
+ @Override
+ public BookMeta build() {
+ return new CraftMetaBook(title, author, pages);
+ }
+ }
+
+ @Override
+ public BookMetaBuilder toBuilder() {
+ return new CraftMetaBookBuilder();
+ }
+
+ // Paper end
@Override
public String getPage(final int page) {
Validate.isTrue(this.isValidPage(page), "Invalid page number");
@@ -413,7 +551,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
}
@Override
- Builder<String, Object> serialize(Builder<String, Object> builder) {
+ ImmutableMap.Builder<String, Object> serialize(ImmutableMap.Builder<String, Object> builder) {
super.serialize(builder);
if (this.hasTitle()) {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java
index 00445fc7373c70f4cecc4114f9bcfb4b6f27c0e8..0cf60eb9b6ba1a79c9b603c4349debd478101f9a 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java
@@ -1,6 +1,6 @@
package org.bukkit.craftbukkit.inventory;
-import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableMap; // Paper
import java.util.Map;
import net.minecraft.nbt.CompoundTag;
import org.bukkit.Material;
@@ -84,7 +84,7 @@ class CraftMetaBookSigned extends CraftMetaBook implements BookMeta {
}
@Override
- Builder<String, Object> serialize(Builder<String, Object> builder) {
+ ImmutableMap.Builder<String, Object> serialize(ImmutableMap.Builder<String, Object> builder) {
super.serialize(builder);
return builder;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 2d775fe575e61a6503aee1bc9623aebce75143cc..970fa1e98c873ea4dfd4b58c56b7ea88283b0512 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -745,6 +745,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
return !(this.hasDisplayName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isUnbreakable() || this.hasDamage() || this.hasAttributeModifiers());
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component displayName() {
+ return displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(displayName);
+ }
+
+ @Override
+ public void displayName(final net.kyori.adventure.text.Component displayName) {
+ this.displayName = displayName == null ? null : net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(displayName);
+ }
+ // Paper end
+
@Override
public String getDisplayName() {
return CraftChatMessage.fromJSONComponent(displayName);
@@ -780,6 +792,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
return this.lore != null && !this.lore.isEmpty();
}
+ // Paper start
+ @Override
+ public List<net.kyori.adventure.text.Component> lore() {
+ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventureFromJson(this.lore) : null;
+ }
+
+ @Override
+ public void lore(final List<net.kyori.adventure.text.Component> lore) {
+ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asJson(lore) : null;
+ }
+ // Paper end
+
@Override
public boolean hasRepairCost() {
return this.repairCost > 0;
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java
index ed4415f6dd588c08c922efd5beebb3b124beb9d6..78a7ac47f20e84ccd67ff44d0bc7a2f2faa0d476 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftCustomInventoryConverter.java
@@ -12,6 +12,13 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve
return new CraftInventoryCustom(holder, type);
}
+ // Paper start
+ @Override
+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ return new CraftInventoryCustom(owner, type, title);
+ }
+ // Paper end
+
@Override
public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) {
return new CraftInventoryCustom(owner, type, title);
@@ -21,6 +28,12 @@ public class CraftCustomInventoryConverter implements CraftInventoryCreator.Inve
return new CraftInventoryCustom(owner, size);
}
+ // Paper start
+ public Inventory createInventory(InventoryHolder owner, int size, net.kyori.adventure.text.Component title) {
+ return new CraftInventoryCustom(owner, size, title);
+ }
+ // Paper end
+
public Inventory createInventory(InventoryHolder owner, int size, String title) {
return new CraftInventoryCustom(owner, size, title);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java
index 4e705b7367b78c2da98d0b174807ecbce75f3a59..0899afd175f969da0df9371d96d3b5e1de4c8533 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftInventoryCreator.java
@@ -43,6 +43,17 @@ public final class CraftInventoryCreator {
return this.converterMap.get(type).createInventory(holder, type);
}
+ // Paper start
+ public Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title) {
+ // Paper start
+ if (holder != null) {
+ return DEFAULT_CONVERTER.createInventory(holder, type, title);
+ }
+ //noinspection ConstantConditions // Paper end
+ return converterMap.get(type).createInventory(holder, type, title);
+ }
+ // Paper end
+
public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) {
return this.converterMap.get(type).createInventory(holder, type, title);
}
@@ -51,6 +62,12 @@ public final class CraftInventoryCreator {
return this.DEFAULT_CONVERTER.createInventory(holder, size);
}
+ // Paper start
+ public Inventory createInventory(InventoryHolder holder, int size, net.kyori.adventure.text.Component title) {
+ return DEFAULT_CONVERTER.createInventory(holder, size, title);
+ }
+ // Paper end
+
public Inventory createInventory(InventoryHolder holder, int size, String title) {
return this.DEFAULT_CONVERTER.createInventory(holder, size, title);
}
@@ -59,6 +76,10 @@ public final class CraftInventoryCreator {
Inventory createInventory(InventoryHolder holder, InventoryType type);
+ // Paper start
+ Inventory createInventory(InventoryHolder holder, InventoryType type, net.kyori.adventure.text.Component title);
+ // Paper end
+
Inventory createInventory(InventoryHolder holder, InventoryType type, String title);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
index 1980240d3dc0331ddf2ff56e163e2bfbd3b231ab..7a7f3f53aef601f124d474d9890e23d87dd96900 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java
@@ -31,6 +31,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
return this.getInventory(this.getTileEntity());
}
+ // Paper start
+ @Override
+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ Container te = getTileEntity();
+ if (te instanceof RandomizableContainerBlockEntity) {
+ ((RandomizableContainerBlockEntity) te).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title));
+ }
+
+ return getInventory(te);
+ }
+ // Paper end
+
@Override
public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) {
Container te = this.getTileEntity();
@@ -53,6 +65,15 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
return furnace;
}
+ // Paper start
+ @Override
+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ Container tileEntity = getTileEntity();
+ ((AbstractFurnaceBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title));
+ return getInventory(tileEntity);
+ }
+ // Paper end
+
@Override
public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) {
Container tileEntity = this.getTileEntity();
@@ -73,6 +94,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat
return new BrewingStandBlockEntity(BlockPos.ZERO, Blocks.BREWING_STAND.defaultBlockState());
}
+ // Paper start
+ @Override
+ public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) {
+ // BrewingStand does not extend TileEntityLootable
+ Container tileEntity = getTileEntity();
+ if (tileEntity instanceof BrewingStandBlockEntity) {
+ ((BrewingStandBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title));
+ }
+ return getInventory(tileEntity);
+ }
+ // Paper end
+
@Override
public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) {
// BrewingStand does not extend TileEntityLootable
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
index c80424fa0494272900ee141eefbf2522ee66d657..2477bb1f2b37406e2c73f18956201762a61ca324 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
@@ -30,6 +30,21 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective
return this.objective.getName();
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException {
+ CraftScoreboard scoreboard = checkState();
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(objective.getDisplayName());
+ }
+ @Override
+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException {
+ if (displayName == null) {
+ displayName = net.kyori.adventure.text.Component.empty();
+ }
+ CraftScoreboard scoreboard = checkState();
+ objective.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName));
+ }
+ // Paper end
@Override
public String getDisplayName() throws IllegalStateException {
CraftScoreboard scoreboard = this.checkState();
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
index 589cb3bebb4bb193477cc5064c66830eec3e9138..68aa66c340b7a686a353e2a15084d811a3955a0a 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
@@ -27,6 +27,27 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
public CraftObjective registerNewObjective(String name, String criteria) throws IllegalArgumentException {
return this.registerNewObjective(name, criteria, name);
}
+ // Paper start
+ @Override
+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName) {
+ return registerNewObjective(name, criteria, displayName, org.bukkit.scoreboard.RenderType.INTEGER);
+ }
+ @Override
+ public CraftObjective registerNewObjective(String name, String criteria, net.kyori.adventure.text.Component displayName, RenderType renderType) {
+ if (displayName == null) {
+ displayName = net.kyori.adventure.text.Component.empty();
+ }
+ Validate.notNull(name, "Objective name cannot be null");
+ Validate.notNull(criteria, "Criteria cannot be null");
+ Validate.notNull(displayName, "Display name cannot be null");
+ Validate.notNull(renderType, "RenderType cannot be null");
+ Validate.isTrue(name.length() <= 16, "The name '" + name + "' is longer than the limit of 16 characters");
+ Validate.isTrue(board.getObjective(name) == null, "An objective of name '" + name + "' already exists");
+ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria);
+ net.minecraft.world.scores.Objective objective = board.addObjective(name, craftCriteria.criteria, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
+ return new CraftObjective(this, objective);
+ }
+ // Paper end
@Override
public CraftObjective registerNewObjective(String name, String criteria, String displayName) throws IllegalArgumentException {
@@ -35,7 +56,7 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
@Override
public CraftObjective registerNewObjective(String name, String criteria, String displayName, RenderType renderType) throws IllegalArgumentException {
- Validate.notNull(name, "Objective name cannot be null");
+ /*Validate.notNull(name, "Objective name cannot be null"); // Paper
Validate.notNull(criteria, "Criteria cannot be null");
Validate.notNull(displayName, "Display name cannot be null");
Validate.notNull(renderType, "RenderType cannot be null");
@@ -45,7 +66,11 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria);
net.minecraft.world.scores.Objective objective = this.board.addObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
- return new CraftObjective(this, objective);
+
+ CraftCriteria craftCriteria = CraftCriteria.getFromBukkit(criteria);
+ ScoreboardObjective objective = board.registerObjective(name, craftCriteria.criteria, CraftChatMessage.fromStringOrNull(displayName), CraftScoreboardTranslations.fromBukkitRender(renderType));
+ return new CraftObjective(this, objective);*/ // Paper
+ return registerNewObjective(name, criteria, io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC.deserialize(displayName), renderType); // Paper
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
index 81f16dc1ed6e102af298600db75cab21a09bc00f..f86776aa42bd5520f8aaeaa46bb93ec4d5b4e27d 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
@@ -28,6 +28,55 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
return this.team.getName();
}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.Component displayName() throws IllegalStateException {
+ CraftScoreboard scoreboard = checkState();
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getDisplayName());
+ }
+ @Override
+ public void displayName(net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException {
+ if (displayName == null) displayName = net.kyori.adventure.text.Component.empty();
+ CraftScoreboard scoreboard = checkState();
+ team.setDisplayName(io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName));
+ }
+ @Override
+ public net.kyori.adventure.text.Component prefix() throws IllegalStateException {
+ CraftScoreboard scoreboard = checkState();
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerPrefix());
+ }
+ @Override
+ public void prefix(net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException {
+ if (prefix == null) prefix = net.kyori.adventure.text.Component.empty();
+ CraftScoreboard scoreboard = checkState();
+ team.setPlayerPrefix(io.papermc.paper.adventure.PaperAdventure.asVanilla(prefix));
+ }
+ @Override
+ public net.kyori.adventure.text.Component suffix() throws IllegalStateException {
+ CraftScoreboard scoreboard = checkState();
+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(team.getPlayerSuffix());
+ }
+ @Override
+ public void suffix(net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException {
+ if (suffix == null) suffix = net.kyori.adventure.text.Component.empty();
+ CraftScoreboard scoreboard = checkState();
+ team.setPlayerSuffix(io.papermc.paper.adventure.PaperAdventure.asVanilla(suffix));
+ }
+ @Override
+ public net.kyori.adventure.text.format.TextColor color() throws IllegalStateException {
+ CraftScoreboard scoreboard = checkState();
+ if (team.getColor().getColor() == null) throw new IllegalStateException("Team colors must have hex values");
+ net.kyori.adventure.text.format.TextColor color = net.kyori.adventure.text.format.TextColor.color(team.getColor().getColor());
+ if (!(color instanceof net.kyori.adventure.text.format.NamedTextColor)) throw new IllegalStateException("Team doesn't have a NamedTextColor");
+ return (net.kyori.adventure.text.format.NamedTextColor) color;
+ }
+ @Override
+ public void color(net.kyori.adventure.text.format.NamedTextColor color) {
+ if (color == null) color = net.kyori.adventure.text.format.NamedTextColor.WHITE;
+ CraftScoreboard scoreboard = checkState();
+ team.setColor(io.papermc.paper.adventure.PaperAdventure.asVanilla(color));
+ }
+ // Paper end
@Override
public String getDisplayName() throws IllegalStateException {
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
index f9b7b8f7ccc95b73967a51420fd6ce88d80d75fe..0de5a46423ae0403dcbfca630dfd7c5ac1e1761d 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java
@@ -290,6 +290,7 @@ public final class CraftChatMessage {
public static String fromComponent(Component component) {
if (component == null) return "";
+ if (component instanceof io.papermc.paper.adventure.AdventureComponent) component = ((io.papermc.paper.adventure.AdventureComponent) component).deepConverted();
StringBuilder out = new StringBuilder();
boolean hadFormat = false;
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 0f0ffedd2cc3cf1b30b338d8ae3a8ad388dfde53..409515c406f5b5cfac9872f925dbc67159a5d41f 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -57,6 +57,33 @@ public final class CraftMagicNumbers implements UnsafeValues {
private CraftMagicNumbers() {}
+ // Paper start
+ @Override
+ public net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener() {
+ return io.papermc.paper.adventure.PaperAdventure.FLATTENER;
+ }
+
+ @Override
+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer() {
+ return io.papermc.paper.adventure.PaperAdventure.COLOR_DOWNSAMPLING_GSON;
+ }
+
+ @Override
+ public net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer() {
+ return io.papermc.paper.adventure.PaperAdventure.GSON;
+ }
+
+ @Override
+ public net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer() {
+ return io.papermc.paper.adventure.PaperAdventure.PLAIN;
+ }
+
+ @Override
+ public net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer() {
+ return io.papermc.paper.adventure.PaperAdventure.LEGACY_SECTION_UXRC;
+ }
+ // Paper end
+
public static BlockState getBlock(MaterialData material) {
return CraftMagicNumbers.getBlock(material.getItemType(), material.getData());
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java
index 62c66e3179b9557cdba46242df0fb15bce7e7710..73a37638abacdffbff8274291a64ea6cd0be7a5e 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyHashSet.java
@@ -80,7 +80,7 @@ public abstract class LazyHashSet<E> implements Set<E> {
return this.reference = this.makeReference();
}
- abstract Set<E> makeReference();
+ protected abstract Set<E> makeReference(); // Paper - protected
public boolean isLazy() {
return this.reference == null;
diff --git a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
index 838d5b877c01be3ef353f434d98e27b46c0a3fb4..5c4c0ba05f10d2d83b22d3e86805cfa85c3b50a9 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/LazyPlayerSet.java
@@ -15,11 +15,17 @@ public class LazyPlayerSet extends LazyHashSet<Player> {
}
@Override
- HashSet<Player> makeReference() {
+ protected HashSet<Player> makeReference() { // Paper - protected
if (reference != null) {
throw new IllegalStateException("Reference already created!");
}
List<ServerPlayer> players = this.server.getPlayerList().players;
+ // Paper start
+ return makePlayerSet(this.server);
+ }
+ public static HashSet<Player> makePlayerSet(final MinecraftServer server) {
+ // Paper end
+ List<ServerPlayer> players = server.getPlayerList().players;
HashSet<Player> reference = new HashSet<Player>(players.size());
for (ServerPlayer player : players) {
reference.add(player.getBukkitEntity());