Adventure

Co-authored-by: zml <zml@stellardrift.ca>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Yannick Lamprecht <yannicklamprecht@live.de>
This commit is contained in:
Riley Park 2021-01-29 17:21:55 +01:00
parent 8888031206
commit 15081a5912
70 changed files with 3298 additions and 160 deletions

View File

@ -11,6 +11,18 @@ java {
val annotationsVersion = "24.1.0"
val bungeeCordChatVersion = "1.20-R0.2"
val adventureVersion = "4.17.0"
val apiAndDocs: Configuration by configurations.creating {
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named(DocsType.SOURCES))
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
}
}
configurations.api {
extendsFrom(apiAndDocs)
}
// Paper start - configure mockito agent that is needed in newer java versions
val mockitoAgent = configurations.register("mockitoAgent")
@ -28,7 +40,11 @@ dependencies {
// api dependencies are listed transitively to API consumers
api("com.google.guava:guava:33.3.1-jre")
api("com.google.code.gson:gson:2.11.0")
api("net.md-5:bungeecord-chat:$bungeeCordChatVersion")
// Paper start - adventure
api("net.md-5:bungeecord-chat:$bungeeCordChatVersion-deprecated+build.19") {
exclude("com.google.guava", "guava")
}
// Paper - adventure
api("org.yaml:snakeyaml:2.2")
api("org.joml:joml:1.10.8") {
isTransitive = false // https://github.com/JOML-CI/JOML/issues/352
@ -38,6 +54,13 @@ dependencies {
isTransitive = false // includes junit
}
api("it.unimi.dsi:fastutil:8.5.15")
apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion"))
apiAndDocs("net.kyori:adventure-api")
apiAndDocs("net.kyori:adventure-text-minimessage")
apiAndDocs("net.kyori:adventure-text-serializer-gson")
apiAndDocs("net.kyori:adventure-text-serializer-legacy")
apiAndDocs("net.kyori:adventure-text-serializer-plain")
apiAndDocs("net.kyori:adventure-text-logger-slf4j")
// Paper end
compileOnly("org.apache.maven:maven-resolver-provider:3.9.6")
@ -115,15 +138,32 @@ tasks.withType<Javadoc> {
"https://guava.dev/releases/33.3.1-jre/api/docs/",
"https://javadoc.io/doc/org.yaml/snakeyaml/2.2/",
"https://javadoc.io/doc/org.jetbrains/annotations/$annotationsVersion/", // Paper - we don't want Java 5 annotations
"https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/",
// "https://javadoc.io/doc/net.md-5/bungeecord-chat/$bungeeCordChatVersion/", // Paper - don't link to bungee chat
// Paper start - add missing javadoc links
"https://javadoc.io/doc/org.joml/joml/1.10.8/index.html",
"https://www.javadoc.io/doc/com.google.code.gson/gson/2.11.0",
"https://jspecify.dev/docs/api/",
// Paper end
// Paper start
"https://jd.advntr.dev/api/$adventureVersion/",
"https://jd.advntr.dev/key/$adventureVersion/",
"https://jd.advntr.dev/text-minimessage/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-gson/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/",
"https://jd.advntr.dev/text-serializer-plain/$adventureVersion/",
"https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/",
// Paper end
)
options.tags("apiNote:a:API Note:")
inputs.files(apiAndDocs).ignoreEmptyDirectories().withPropertyName(apiAndDocs.name + "-configuration")
doFirst {
options.addStringOption(
"sourcepath",
apiAndDocs.elements.get().map { it.asFile }.joinToString(separator = File.pathSeparator, transform = File::getPath)
)
}
// workaround for https://github.com/gradle/gradle/issues/4046
inputs.dir("src/main/javadoc").withPropertyName("javadoc-sourceset")
doLast {

View File

@ -0,0 +1,70 @@
package io.papermc.paper.chat;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* A chat renderer is responsible for rendering chat messages sent by {@link Player}s to the server.
*/
@NullMarked
@FunctionalInterface
public interface ChatRenderer {
/**
* Renders a chat message. This will be called once for each receiving {@link Audience}.
*
* @param source the message source
* @param sourceDisplayName the display name of the source player
* @param message the chat message
* @param viewer the receiving {@link Audience}
* @return a rendered chat message
*/
@ApiStatus.OverrideOnly
Component render(Player source, Component sourceDisplayName, Component message, Audience viewer);
/**
* Create a new instance of the default {@link ChatRenderer}.
*
* @return a new {@link ChatRenderer}
*/
static ChatRenderer defaultRenderer() {
return new ViewerUnawareImpl.Default((source, sourceDisplayName, message) -> Component.translatable("chat.type.text", sourceDisplayName, message));
}
@ApiStatus.Internal
sealed interface Default extends ChatRenderer, ViewerUnaware permits ViewerUnawareImpl.Default {
}
/**
* Creates a new viewer-unaware {@link ChatRenderer}, which will render the chat message a single time,
* displaying the same rendered message to every viewing {@link Audience}.
*
* @param renderer the viewer unaware renderer
* @return a new {@link ChatRenderer}
*/
static ChatRenderer viewerUnaware(final ViewerUnaware renderer) {
return new ViewerUnawareImpl(renderer);
}
/**
* Similar to {@link ChatRenderer}, but without knowledge of the message viewer.
*
* @see ChatRenderer#viewerUnaware(ViewerUnaware)
*/
interface ViewerUnaware {
/**
* Renders a chat message.
*
* @param source the message source
* @param sourceDisplayName the display name of the source player
* @param message the chat message
* @return a rendered chat message
*/
@ApiStatus.OverrideOnly
Component render(Player source, Component sourceDisplayName, Component message);
}
}

View File

@ -0,0 +1,38 @@
package io.papermc.paper.chat;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
@NullMarked
sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnaware permits ViewerUnawareImpl.Default {
private final ViewerUnaware unaware;
private @Nullable Component message;
ViewerUnawareImpl(final ViewerUnaware unaware) {
this.unaware = unaware;
}
@Override
public Component render(final Player source, final Component sourceDisplayName, final Component message, final Audience viewer) {
return this.render(source, sourceDisplayName, message);
}
@Override
public Component render(final Player source, final Component sourceDisplayName, final Component message) {
if (this.message == null) {
this.message = this.unaware.render(source, sourceDisplayName, message);
}
return this.message;
}
static final class Default extends ViewerUnawareImpl implements ChatRenderer.Default {
Default(final ViewerUnaware unaware) {
super(unaware);
}
}
}

View File

@ -0,0 +1,122 @@
package io.papermc.paper.event.player;
import io.papermc.paper.chat.ChatRenderer;
import java.util.Set;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.chat.SignedMessage;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import static java.util.Objects.requireNonNull;
/**
* An abstract implementation of a chat event, handling shared logic.
*/
@ApiStatus.NonExtendable
@NullMarked
public abstract class AbstractChatEvent extends PlayerEvent implements Cancellable {
private final Set<Audience> viewers;
private final Component originalMessage;
private final SignedMessage signedMessage;
private ChatRenderer renderer;
private Component message;
private boolean cancelled;
AbstractChatEvent(final boolean async, final Player player, final Set<Audience> viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) {
super(player, async);
this.viewers = viewers;
this.renderer = renderer;
this.message = message;
this.originalMessage = originalMessage;
this.signedMessage = signedMessage;
}
/**
* Gets a set of {@link Audience audiences} that this chat message will be displayed to.
*
* <p>The set returned may auto-populate on access. Any listener accessing the returned set should be aware that
* it may reduce performance for a lazy set implementation.</p>
*
* @return a mutable set of {@link Audience audiences} who will receive the chat message
*/
public final Set<Audience> viewers() {
return this.viewers;
}
/**
* Sets the chat renderer.
*
* @param renderer the chat renderer
* @throws NullPointerException if {@code renderer} is {@code null}
*/
public final void renderer(final ChatRenderer renderer) {
this.renderer = requireNonNull(renderer, "renderer");
}
/**
* Gets the chat renderer.
*
* @return the chat renderer
*/
public final ChatRenderer renderer() {
return this.renderer;
}
/**
* Gets the user-supplied message.
* The return value will reflect changes made using {@link #message(Component)}.
*
* @return the user-supplied message
*/
public final Component message() {
return this.message;
}
/**
* Sets the user-supplied message.
*
* @param message the user-supplied message
* @throws NullPointerException if {@code message} is {@code null}
*/
public final void message(final Component message) {
this.message = requireNonNull(message, "message");
}
/**
* Gets the original and unmodified user-supplied message.
* The return value will <b>not</b> reflect changes made using
* {@link #message(Component)}.
*
* @return the original user-supplied message
*/
public final Component originalMessage() {
return this.originalMessage;
}
/**
* Gets the signed message.
* Changes made in this event will <b>not</b> update
* the signed message.
*
* @return the signed message
*/
public final SignedMessage signedMessage() {
return this.signedMessage;
}
@Override
public final boolean isCancelled() {
return this.cancelled;
}
@Override
public final void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}
}

View File

@ -0,0 +1,29 @@
package io.papermc.paper.event.player;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@ApiStatus.Experimental
@NullMarked
public class AsyncChatCommandDecorateEvent extends AsyncChatDecorateEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@ApiStatus.Internal
public AsyncChatCommandDecorateEvent(final @Nullable Player player, final Component originalMessage) {
super(player, originalMessage);
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,105 @@
package io.papermc.paper.event.player;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.server.ServerEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* This event is fired when the server decorates a component for chat purposes. This is called
* before {@link AsyncChatEvent} and the other chat events. It is recommended that you modify the
* message here, and use the chat events for modifying receivers and later the chat type. If you
* want to keep the message as "signed" for the clients who get it, be sure to include the entire
* original message somewhere in the final message.
* <br>
* See {@link AsyncChatCommandDecorateEvent} for the decoration of messages sent via commands
*/
@ApiStatus.Experimental
@NullMarked
public class AsyncChatDecorateEvent extends ServerEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();
private final @Nullable Player player;
private final Component originalMessage;
private Component result;
private boolean cancelled;
@ApiStatus.Internal
public AsyncChatDecorateEvent(final @Nullable Player player, final Component originalMessage) {
super(true);
this.player = player;
this.originalMessage = originalMessage;
this.result = originalMessage;
}
/**
* Gets the player (if available) associated with this event.
* <p>
* Certain commands request decorations without a player context
* which is why this is possibly null.
*
* @return the player or {@code null}
*/
public @Nullable Player player() {
return this.player;
}
/**
* Gets the original decoration input
*
* @return the input
*/
public Component originalMessage() {
return this.originalMessage;
}
/**
* Gets the decoration result. This may already be different from
* {@link #originalMessage()} if some other listener to this event
* changed the result.
*
* @return the result
*/
public Component result() {
return this.result;
}
/**
* Sets the resulting decorated component.
*
* @param result the result
*/
public void result(final Component result) {
this.result = result;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
/**
* A cancelled decorating event means that no changes to the result component
* will have any effect. The decorated component will be equal to the original
* component.
*/
@Override
public void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,44 @@
package io.papermc.paper.event.player;
import io.papermc.paper.chat.ChatRenderer;
import java.util.Set;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.chat.SignedMessage;
import net.kyori.adventure.text.Component;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* An event fired when a {@link Player} sends a chat message to the server.
* <p>
* This event will sometimes fire synchronously, depending on how it was
* triggered.
* <p>
* If a player is the direct cause of this event by an incoming packet, this
* event will be asynchronous. If a plugin triggers this event by compelling a
* player to chat, this event will be synchronous.
* <p>
* Care should be taken to check {@link #isAsynchronous()} and treat the event
* appropriately.
*/
@NullMarked
public final class AsyncChatEvent extends AbstractChatEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@ApiStatus.Internal
public AsyncChatEvent(final boolean async, final Player player, final Set<Audience> viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) {
super(async, player, viewers, renderer, message, originalMessage, signedMessage);
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,40 @@
package io.papermc.paper.event.player;
import io.papermc.paper.chat.ChatRenderer;
import java.util.Set;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.chat.SignedMessage;
import net.kyori.adventure.text.Component;
import org.bukkit.Warning;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* An event fired when a {@link Player} sends a chat message to the server.
*
* @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages.
* It is recommended to use {@link AsyncChatEvent} instead, wherever possible.
*/
@Deprecated
@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.")
@NullMarked
public final class ChatEvent extends AbstractChatEvent {
private static final HandlerList HANDLER_LIST = new HandlerList();
@ApiStatus.Internal
public ChatEvent(final Player player, final Set<Audience> viewers, final ChatRenderer renderer, final Component message, final Component originalMessage, final SignedMessage signedMessage) {
super(false, player, viewers, renderer, message, originalMessage, signedMessage);
}
@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}

View File

@ -0,0 +1,180 @@
package io.papermc.paper.text;
import java.io.IOException;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.flattener.ComponentFlattener;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Paper API-specific methods for working with {@link Component}s and related.
*/
@NullMarked
public final class PaperComponents {
private PaperComponents() {
throw new RuntimeException("PaperComponents is not to be instantiated!");
}
/**
* Resolves a component with a specific command sender and subject.
* <p>
* Note that in Vanilla, elevated permissions are usually required to use
* '@' selectors in various component types, but this method should not
* check such permissions from the sender.
* <p>
* A {@link CommandSender} argument is required to resolve:
* <ul>
* <li>{@link net.kyori.adventure.text.NBTComponent}</li>
* <li>{@link net.kyori.adventure.text.ScoreComponent}</li>
* <li>{@link net.kyori.adventure.text.SelectorComponent}</li>
* </ul>
* A {@link Entity} argument is optional to help resolve:
* <ul>
* <li>{@link net.kyori.adventure.text.ScoreComponent}</li>
* </ul>
* {@link net.kyori.adventure.text.TranslatableComponent}s don't require any extra arguments.
*
* @param input the component to resolve
* @param context the command sender to resolve with
* @param scoreboardSubject the scoreboard subject to use (for use with {@link net.kyori.adventure.text.ScoreComponent}s)
* @return the resolved component
* @throws IOException if a syntax error tripped during resolving
*/
public static Component resolveWithContext(final Component input, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject) throws IOException {
return resolveWithContext(input, context, scoreboardSubject, true);
}
/**
* Resolves a component with a specific command sender and subject.
* <p>
* Note that in Vanilla, elevated permissions are required to use
* '@' selectors in various component types. If the boolean {@code bypassPermissions}
* argument is {@code false}, the {@link CommandSender} argument will be used to query
* those permissions.
* <p>
* A {@link CommandSender} argument is required to resolve:
* <ul>
* <li>{@link net.kyori.adventure.text.NBTComponent}</li>
* <li>{@link net.kyori.adventure.text.ScoreComponent}</li>
* <li>{@link net.kyori.adventure.text.SelectorComponent}</li>
* </ul>
* A {@link Entity} argument is optional to help resolve:
* <ul>
* <li>{@link net.kyori.adventure.text.ScoreComponent}</li>
* </ul>
* {@link net.kyori.adventure.text.TranslatableComponent}s don't require any extra arguments.
*
* @param input the component to resolve
* @param context the command sender to resolve with
* @param scoreboardSubject the scoreboard subject to use (for use with {@link net.kyori.adventure.text.ScoreComponent}s)
* @param bypassPermissions true to bypass permissions checks for resolving components
* @return the resolved component
* @throws IOException if a syntax error tripped during resolving
*/
@SuppressWarnings("deprecation") // using unsafe as a bridge
public static Component resolveWithContext(final Component input, final @Nullable CommandSender context, final @Nullable Entity scoreboardSubject, final boolean bypassPermissions) throws IOException {
return Bukkit.getUnsafe().resolveWithContext(input, context, scoreboardSubject, bypassPermissions);
}
/**
* Return a component flattener that can use game data to resolve extra information about components.
*
* @return a component flattener
*/
@SuppressWarnings("deprecation") // using unsafe as a bridge
public static ComponentFlattener flattener() {
return Bukkit.getUnsafe().componentFlattener();
}
/**
* Get a serializer for {@link Component}s that will convert components to
* a plain-text string.
*
* <p>Implementations may provide a serializer capable of processing any
* information that requires access to implementation details.</p>
*
* @return a serializer to plain text
* @deprecated will be removed in adventure 5.0.0, use {@link PlainTextComponentSerializer#plainText()}
*/
@Deprecated(forRemoval = true, since = "1.18.1")
public static PlainComponentSerializer plainSerializer() {
return Bukkit.getUnsafe().plainComponentSerializer();
}
/**
* Get a serializer for {@link Component}s that will convert components to
* a plain-text string.
*
* <p>Implementations may provide a serializer capable of processing any
* information that requires access to implementation details.</p>
*
* @return a serializer to plain text
* @deprecated use {@link PlainTextComponentSerializer#plainText()}
*/
@Deprecated(forRemoval = true, since = "1.18.2")
public static PlainTextComponentSerializer plainTextSerializer() {
return Bukkit.getUnsafe().plainTextSerializer();
}
/**
* Get a serializer for {@link Component}s that will convert to and from the
* standard JSON serialization format using Gson.
*
* <p>Implementations may provide a serializer capable of processing any
* information that requires implementation details, such as legacy
* (pre-1.16) hover events.</p>
*
* @return a json component serializer
* @deprecated use {@link GsonComponentSerializer#gson()}
*/
@Deprecated(forRemoval = true, since = "1.18.2")
public static GsonComponentSerializer gsonSerializer() {
return Bukkit.getUnsafe().gsonComponentSerializer();
}
/**
* Get a serializer for {@link Component}s that will convert to and from the
* standard JSON serialization format using Gson, downsampling any RGB colors
* to their nearest {@link NamedTextColor} counterpart.
*
* <p>Implementations may provide a serializer capable of processing any
* information that requires implementation details, such as legacy
* (pre-1.16) hover events.</p>
*
* @return a json component serializer
* @deprecated use {@link GsonComponentSerializer#colorDownsamplingGson()}
*/
@Deprecated(forRemoval = true, since = "1.18.2")
public static GsonComponentSerializer colorDownsamplingGsonSerializer() {
return Bukkit.getUnsafe().colorDownsamplingGsonComponentSerializer();
}
/**
* Get a serializer for {@link Component}s that will convert to and from the
* legacy component format used by Bukkit. This serializer uses the
* {@link LegacyComponentSerializer.Builder#useUnusualXRepeatedCharacterHexFormat()}
* option to match upstream behavior.
*
* <p>This legacy serializer uses the standard section symbol to mark
* formatting characters.</p>
*
* <p>Implementations may provide a serializer capable of processing any
* information that requires access to implementation details.</p>
*
* @return a section serializer
* @deprecated use {@link LegacyComponentSerializer#legacySection()}
*/
@Deprecated(forRemoval = true, since = "1.18.2")
public static LegacyComponentSerializer legacySectionSerializer() {
return Bukkit.getUnsafe().legacyComponentSerializer();
}
}

View File

@ -423,7 +423,9 @@ public final class Bukkit {
*
* @param message the message
* @return the number of players
* @deprecated in favour of {@link Server#broadcast(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public static int broadcastMessage(@NotNull String message) {
return server.broadcastMessage(message);
}
@ -1227,6 +1229,19 @@ public final class Bukkit {
server.shutdown();
}
// Paper start
/**
* Broadcast a message to all players.
* <p>
* This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component,
* java.lang.String)} with the {@link Server#BROADCAST_CHANNEL_USERS} permission.
*
* @param message the message
* @return the number of players
*/
public static int broadcast(net.kyori.adventure.text.@NotNull Component message) {
return server.broadcast(message);
}
/**
* Broadcasts the specified message to every user with the given
* permission name.
@ -1236,6 +1251,21 @@ public final class Bukkit {
* permissibles} must have to receive the broadcast
* @return number of message recipients
*/
public static int broadcast(net.kyori.adventure.text.@NotNull Component message, @NotNull String permission) {
return server.broadcast(message, permission);
}
// Paper end
/**
* Broadcasts the specified message to every user with the given
* permission name.
*
* @param message message to broadcast
* @param permission the required permission {@link Permissible
* permissibles} must have to receive the broadcast
* @return number of message recipients
* @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)}
*/
@Deprecated // Paper
public static int broadcast(@NotNull String message, @NotNull String permission) {
return server.broadcast(message, permission);
}
@ -1497,6 +1527,7 @@ public final class Bukkit {
return server.createInventory(owner, type);
}
// Paper start
/**
* Creates an empty inventory with the specified type and title. If the type
* is {@link InventoryType#CHEST}, the new inventory has a size of 27;
@ -1522,6 +1553,38 @@ public final class Bukkit {
* @see InventoryType#isCreatable()
*/
@NotNull
public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, net.kyori.adventure.text.@NotNull Component title) {
return server.createInventory(owner, type, title);
}
// Paper end
/**
* Creates an empty inventory with the specified type and title. If the type
* is {@link InventoryType#CHEST}, the new inventory has a size of 27;
* otherwise the new inventory has the normal size for its type.<br>
* It should be noted that some inventory types do not support titles and
* may not render with said titles on the Minecraft client.
* <br>
* {@link InventoryType#WORKBENCH} will not process crafting recipes if
* created with this method. Use
* {@link Player#openWorkbench(Location, boolean)} instead.
* <br>
* {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s
* for possible enchanting results. Use
* {@link Player#openEnchanting(Location, boolean)} instead.
*
* @param owner The holder of the inventory; can be null if there's no holder.
* @param type The type of inventory to create.
* @param title The title of the inventory, to be displayed when it is viewed.
* @return The new inventory.
* @throws IllegalArgumentException if the {@link InventoryType} cannot be
* viewed.
* @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)}
*
* @see InventoryType#isCreatable()
*/
@Deprecated // Paper
@NotNull
public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) {
return server.createInventory(owner, type, title);
}
@ -1540,6 +1603,7 @@ public final class Bukkit {
return server.createInventory(owner, size);
}
// Paper start
/**
* Creates an empty inventory of type {@link InventoryType#CHEST} with the
* specified size and title.
@ -1552,10 +1616,30 @@ public final class Bukkit {
* @throws IllegalArgumentException if the size is not a multiple of 9
*/
@NotNull
public static Inventory createInventory(@Nullable InventoryHolder owner, int size, net.kyori.adventure.text.@NotNull Component title) throws IllegalArgumentException {
return server.createInventory(owner, size, title);
}
// Paper end
/**
* Creates an empty inventory of type {@link InventoryType#CHEST} with the
* specified size and title.
*
* @param owner the holder of the inventory, or null to indicate no holder
* @param size a multiple of 9 as the size of inventory to create
* @param title the title of the inventory, displayed when inventory is
* viewed
* @return a new inventory
* @throws IllegalArgumentException if the size is not a multiple of 9
* @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
@NotNull
public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException {
return server.createInventory(owner, size, title);
}
// Paper start
/**
* Creates an empty merchant.
*
@ -1563,7 +1647,20 @@ public final class Bukkit {
* when the merchant inventory is viewed
* @return a new merchant
*/
public static @NotNull Merchant createMerchant(net.kyori.adventure.text.@Nullable Component title) {
return server.createMerchant(title);
}
// Paper start
/**
* Creates an empty merchant.
*
* @param title the title of the corresponding merchant inventory, displayed
* when the merchant inventory is viewed
* @return a new merchant
* @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)}
*/
@NotNull
@Deprecated // Paper
public static Merchant createMerchant(@Nullable String title) {
return server.createMerchant(title);
}
@ -1680,12 +1777,43 @@ public final class Bukkit {
return server.isPrimaryThread();
}
// Paper start
/**
* Gets the message that is displayed on the server list.
*
* @return the server's MOTD
*/
@NotNull public static net.kyori.adventure.text.Component motd() {
return server.motd();
}
/**
* Set the message that is displayed on the server list.
*
* @param motd The message to be displayed
*/
public static void motd(final net.kyori.adventure.text.@NotNull Component motd) {
server.motd(motd);
}
/**
* Gets the default message that is displayed when the server is stopped.
*
* @return the shutdown message
*/
public static net.kyori.adventure.text.@Nullable Component shutdownMessage() {
return server.shutdownMessage();
}
// Paper end
/**
* Gets the message that is displayed on the server list.
*
* @return the servers MOTD
* @deprecated in favour of {@link #motd()}
*/
@NotNull
@Deprecated // Paper
public static String getMotd() {
return server.getMotd();
}
@ -1694,7 +1822,9 @@ public final class Bukkit {
* Set the message that is displayed on the server list.
*
* @param motd The message to be displayed
* @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public static void setMotd(@NotNull String motd) {
server.setMotd(motd);
}
@ -1714,8 +1844,10 @@ public final class Bukkit {
* Gets the default message that is displayed when the server is stopped.
*
* @return the shutdown message
* @deprecated in favour of {@link #shutdownMessage()}
*/
@Nullable
@Deprecated // Paper
public static String getShutdownMessage() {
return server.getShutdownMessage();
}

View File

@ -10,7 +10,9 @@ import org.jetbrains.annotations.Nullable;
/**
* All supported color values for chat
* @deprecated ChatColor has been deprecated in favor of <a href="https://docs.advntr.dev/text.html">Adventure</a> API. See {@link net.kyori.adventure.text.format.NamedTextColor} for the adventure equivalent of pre-defined text colors
*/
@Deprecated // Paper
public enum ChatColor {
/**
* Represents black

View File

@ -33,4 +33,14 @@ public interface JukeboxSong extends Keyed, Translatable {
private static JukeboxSong get(@NotNull String key) {
return Registry.JUKEBOX_SONG.getOrThrow(NamespacedKey.minecraft(key));
}
// Paper start - adventure
/**
* @deprecated this method assumes that jukebox song description will
* always be a translatable component which is not guaranteed.
*/
@Override
@Deprecated(forRemoval = true)
@org.jetbrains.annotations.NotNull String getTranslationKey();
// Paper end - adventure
}

View File

@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
/**
* Represents an object which has a {@link NamespacedKey} attached to it.
*/
public interface Keyed {
public interface Keyed extends net.kyori.adventure.key.Keyed { // Paper -- extend Adventure Keyed
/**
* Return the namespaced identifier for this object.
@ -14,4 +14,16 @@ public interface Keyed {
*/
@NotNull
NamespacedKey getKey();
// Paper start
/**
* Returns the unique identifier for this object.
*
* @return this object's key
*/
@Override
default net.kyori.adventure.key.@NotNull Key key() {
return this.getKey();
}
// Paper end
}

View File

@ -7,6 +7,30 @@ import org.jetbrains.annotations.Nullable;
*/
public interface Nameable {
// Paper start
/**
* Gets the custom name.
*
* <p>This value has no effect on players, they will always use their real name.</p>
*
* @return the custom name
*/
net.kyori.adventure.text.@Nullable Component customName();
/**
* Sets the custom name.
*
* <p>This name will be used in death messages and can be sent to the client as a nameplate over the mob.</p>
*
* <p>Setting the name to {@code null} will clear it.</p>
*
* <p>This value has no effect on players, they will always use their real name.</p>
*
* @param customName the custom name to set
*/
void customName(final net.kyori.adventure.text.@Nullable Component customName);
// Paper end
/**
* Gets the custom name on a mob or block. If there is no name this method
* will return null.
@ -14,8 +38,10 @@ public interface Nameable {
* This value has no effect on players, they will always use their real
* name.
*
* @deprecated in favour of {@link #customName()}
* @return name of the mob/block or null
*/
@Deprecated // Paper
@Nullable
public String getCustomName();
@ -28,7 +54,9 @@ public interface Nameable {
* This value has no effect on players, they will always use their real
* name.
*
* @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)}
* @param name the name to set
*/
@Deprecated // Paper
public void setCustomName(@Nullable String name);
}

View File

@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable;
* underscores, hyphens, and forward slashes.
*
*/
public final class NamespacedKey {
public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key
/**
* The namespace representing all inbuilt keys.
@ -130,10 +130,11 @@ public final class NamespacedKey {
@Override
public int hashCode() {
int hash = 5;
hash = 47 * hash + this.namespace.hashCode();
hash = 47 * hash + this.key.hashCode();
return hash;
// Paper start
int result = this.namespace.hashCode();
result = (31 * result) + this.key.hashCode();
return result;
// Paper end
}
@Override
@ -141,11 +142,10 @@ public final class NamespacedKey {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final NamespacedKey other = (NamespacedKey) obj;
return this.namespace.equals(other.namespace) && this.key.equals(other.key);
// Paper start
if (!(obj instanceof net.kyori.adventure.key.Key key)) return false;
return this.namespace.equals(key.namespace()) && this.key.equals(key.value());
// Paper end
}
@Override
@ -248,4 +248,24 @@ public final class NamespacedKey {
public static NamespacedKey fromString(@NotNull String key) {
return fromString(key, null);
}
// Paper start
@NotNull
@Override
public String namespace() {
return this.getNamespace();
}
@NotNull
@Override
public String value() {
return this.getKey();
}
@NotNull
@Override
public String asString() {
return this.namespace + ':' + this.key;
}
// Paper end
}

View File

@ -66,13 +66,13 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents a server implementation.
*/
public interface Server extends PluginMessageRecipient {
public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper
/**
* Used for all administrative messages, such as an operator using a
* command.
* <p>
* For use in {@link #broadcast(java.lang.String, java.lang.String)}.
* For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}.
*/
public static final String BROADCAST_CHANNEL_ADMINISTRATIVE = "bukkit.broadcast.admin";
@ -80,7 +80,7 @@ public interface Server extends PluginMessageRecipient {
* Used for all announcement messages, such as informing users that a
* player has joined.
* <p>
* For use in {@link #broadcast(java.lang.String, java.lang.String)}.
* For use in {@link #broadcast(net.kyori.adventure.text.Component, java.lang.String)}.
*/
public static final String BROADCAST_CHANNEL_USERS = "bukkit.broadcast.user";
@ -356,7 +356,9 @@ public interface Server extends PluginMessageRecipient {
*
* @param message the message
* @return the number of players
* @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public int broadcastMessage(@NotNull String message);
/**
@ -1053,8 +1055,33 @@ public interface Server extends PluginMessageRecipient {
* @param permission the required permission {@link Permissible
* permissibles} must have to receive the broadcast
* @return number of message recipients
* @deprecated in favour of {@link #broadcast(net.kyori.adventure.text.Component, String)}
*/
@Deprecated // Paper
public int broadcast(@NotNull String message, @NotNull String permission);
// Paper start
/**
* Broadcast a message to all players.
* <p>
* This is the same as calling {@link #broadcast(net.kyori.adventure.text.Component,
* java.lang.String)} with the {@link #BROADCAST_CHANNEL_USERS} permission.
*
* @param message the message
* @return the number of players
*/
int broadcast(net.kyori.adventure.text.@NotNull Component message);
/**
* Broadcasts the specified message to every user with the given
* permission name.
*
* @param message message to broadcast
* @param permission the required permission {@link Permissible
* permissibles} must have to receive the broadcast
* @return number of message recipients
*/
int broadcast(net.kyori.adventure.text.@NotNull Component message, @NotNull String permission);
// Paper end
/**
* Gets the player by the given name, regardless if they are offline or
@ -1271,6 +1298,7 @@ public interface Server extends PluginMessageRecipient {
@NotNull
Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type);
// Paper start
/**
* Creates an empty inventory with the specified type and title. If the type
* is {@link InventoryType#CHEST}, the new inventory has a size of 27;
@ -1296,6 +1324,36 @@ public interface Server extends PluginMessageRecipient {
* @see InventoryType#isCreatable()
*/
@NotNull
Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, net.kyori.adventure.text.@NotNull Component title);
// Paper end
/**
* Creates an empty inventory with the specified type and title. If the type
* is {@link InventoryType#CHEST}, the new inventory has a size of 27;
* otherwise the new inventory has the normal size for its type.<br>
* It should be noted that some inventory types do not support titles and
* may not render with said titles on the Minecraft client.
* <br>
* {@link InventoryType#WORKBENCH} will not process crafting recipes if
* created with this method. Use
* {@link Player#openWorkbench(Location, boolean)} instead.
* <br>
* {@link InventoryType#ENCHANTING} will not process {@link ItemStack}s
* for possible enchanting results. Use
* {@link Player#openEnchanting(Location, boolean)} instead.
*
* @param owner The holder of the inventory; can be null if there's no holder.
* @param type The type of inventory to create.
* @param title The title of the inventory, to be displayed when it is viewed.
* @return The new inventory.
* @throws IllegalArgumentException if the {@link InventoryType} cannot be
* viewed.
* @deprecated in favour of {@link #createInventory(InventoryHolder, InventoryType, net.kyori.adventure.text.Component)}
*
* @see InventoryType#isCreatable()
*/
@Deprecated // Paper
@NotNull
Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title);
/**
@ -1310,6 +1368,7 @@ public interface Server extends PluginMessageRecipient {
@NotNull
Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException;
// Paper start
/**
* Creates an empty inventory of type {@link InventoryType#CHEST} with the
* specified size and title.
@ -1322,8 +1381,26 @@ public interface Server extends PluginMessageRecipient {
* @throws IllegalArgumentException if the size is not a multiple of 9
*/
@NotNull
Inventory createInventory(@Nullable InventoryHolder owner, int size, net.kyori.adventure.text.@NotNull Component title) throws IllegalArgumentException;
// Paper end
/**
* Creates an empty inventory of type {@link InventoryType#CHEST} with the
* specified size and title.
*
* @param owner the holder of the inventory, or null to indicate no holder
* @param size a multiple of 9 as the size of inventory to create
* @param title the title of the inventory, displayed when inventory is
* viewed
* @return a new inventory
* @throws IllegalArgumentException if the size is not a multiple of 9
* @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
@NotNull
Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException;
// Paper start
/**
* Creates an empty merchant.
*
@ -1331,7 +1408,18 @@ public interface Server extends PluginMessageRecipient {
* when the merchant inventory is viewed
* @return a new merchant
*/
@NotNull Merchant createMerchant(net.kyori.adventure.text.@Nullable Component title);
// Paper start
/**
* Creates an empty merchant.
*
* @param title the title of the corresponding merchant inventory, displayed
* when the merchant inventory is viewed
* @return a new merchant
* @deprecated in favour of {@link #createMerchant(net.kyori.adventure.text.Component)}
*/
@NotNull
@Deprecated // Paper
Merchant createMerchant(@Nullable String title);
/**
@ -1427,19 +1515,46 @@ public interface Server extends PluginMessageRecipient {
*/
boolean isPrimaryThread();
// Paper start
/**
* Gets the message that is displayed on the server list.
*
* @return the servers MOTD
* @return the server's MOTD
*/
@NotNull
String getMotd();
net.kyori.adventure.text.@NotNull Component motd();
/**
* Set the message that is displayed on the server list.
*
* @param motd The message to be displayed
*/
void motd(final net.kyori.adventure.text.@NotNull Component motd);
/**
* Gets the default message that is displayed when the server is stopped.
*
* @return the shutdown message
*/
net.kyori.adventure.text.@Nullable Component shutdownMessage();
// Paper end
/**
* Gets the message that is displayed on the server list.
*
* @return the servers MOTD
* @deprecated in favour of {@link #motd()}
*/
@NotNull
@Deprecated // Paper
String getMotd();
/**
* Set the message that is displayed on the server list.
*
* @param motd The message to be displayed
* @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setMotd(@NotNull String motd);
/**
@ -1455,8 +1570,10 @@ public interface Server extends PluginMessageRecipient {
* Gets the default message that is displayed when the server is stopped.
*
* @return the shutdown message
* @deprecated in favour of {@link #shutdownMessage()}
*/
@Nullable
@Deprecated // Paper
String getShutdownMessage();
/**
@ -1865,7 +1982,9 @@ public interface Server extends PluginMessageRecipient {
* Sends the component to the player
*
* @param component the components to send
* @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -1874,7 +1993,9 @@ public interface Server extends PluginMessageRecipient {
* Sends an array of components as a single message to the player
*
* @param components the components to send
* @deprecated use {@link #broadcast(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
throw new UnsupportedOperationException("Not supported yet.");
}

View File

@ -50,13 +50,27 @@ public interface ServerLinks {
@NotNull
ServerLink addLink(@NotNull Type type, @NotNull URI url);
// Paper start - Adventure
/**
* Adds the given link to the list of links.
*
* @param displayName link name / display text Component
* @param url link url
* @return the added link
*/
@NotNull
ServerLink addLink(@NotNull net.kyori.adventure.text.Component displayName, @NotNull URI url);
// Paper end - Adventure
/**
* Adds the given link to the list of links.
*
* @param displayName link name / display text
* @param url link url
* @return the added link
* @deprecated in favour of {@link ServerLinks#addLink(net.kyori.adventure.text.Component, URI)}
*/
@Deprecated // Paper - Adventure
@NotNull
ServerLink addLink(@NotNull String displayName, @NotNull URI url);
@ -89,11 +103,23 @@ public interface ServerLinks {
@Nullable
Type getType();
// Paper start - Adventure
/**
* Gets the display name/text Component of this link.
*
* @return display name Component
*/
@NotNull
net.kyori.adventure.text.Component displayName();
// Paper end - Adventure
/**
* Gets the display name/text of this link.
*
* @return display name
* @deprecated in favour of {@link ServerLink#displayName()}
*/
@Deprecated // Paper - Adventure
@NotNull
String getDisplayName();

View File

@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull;
* guarantee values will not be removed from this interface. As such, you should not
* depend on the ordinal values of this class.
*/
public interface Sound extends OldEnum<Sound>, Keyed {
public interface Sound extends OldEnum<Sound>, Keyed, net.kyori.adventure.sound.Sound.Type { // Paper - implement Sound.Type
Sound AMBIENT_BASALT_DELTAS_ADDITIONS = getSound("ambient.basalt_deltas.additions");
Sound AMBIENT_BASALT_DELTAS_LOOP = getSound("ambient.basalt_deltas.loop");
@ -1713,4 +1713,11 @@ public interface Sound extends OldEnum<Sound>, Keyed {
static Sound[] values() {
return Lists.newArrayList(Registry.SOUNDS).toArray(new Sound[0]);
}
// Paper start
@Override
default net.kyori.adventure.key.@NotNull Key key() {
return this.getKey();
}
// Paper end
}

View File

@ -3,7 +3,7 @@ package org.bukkit;
/**
* An Enum of categories for sounds.
*/
public enum SoundCategory {
public enum SoundCategory implements net.kyori.adventure.sound.Sound.Source.Provider { // Paper - implement Sound.Source.Provider
MASTER,
MUSIC,
@ -15,4 +15,22 @@ public enum SoundCategory {
PLAYERS,
AMBIENT,
VOICE;
// Paper start - implement Sound.Source.Provider
@Override
public net.kyori.adventure.sound.Sound.@org.jetbrains.annotations.NotNull Source soundSource() {
return switch (this) {
case MASTER -> net.kyori.adventure.sound.Sound.Source.MASTER;
case MUSIC -> net.kyori.adventure.sound.Sound.Source.MUSIC;
case RECORDS -> net.kyori.adventure.sound.Sound.Source.RECORD;
case WEATHER -> net.kyori.adventure.sound.Sound.Source.WEATHER;
case BLOCKS -> net.kyori.adventure.sound.Sound.Source.BLOCK;
case HOSTILE -> net.kyori.adventure.sound.Sound.Source.HOSTILE;
case NEUTRAL -> net.kyori.adventure.sound.Sound.Source.NEUTRAL;
case PLAYERS -> net.kyori.adventure.sound.Sound.Source.PLAYER;
case AMBIENT -> net.kyori.adventure.sound.Sound.Source.AMBIENT;
case VOICE -> net.kyori.adventure.sound.Sound.Source.VOICE;
};
}
// Paper end
}

View File

@ -31,6 +31,15 @@ import org.jetbrains.annotations.Nullable;
*/
@Deprecated(since = "1.7.2")
public interface UnsafeValues {
// Paper start
net.kyori.adventure.text.flattener.ComponentFlattener componentFlattener();
@Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.plain.PlainComponentSerializer plainComponentSerializer();
@Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer plainTextSerializer();
@Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.gson.GsonComponentSerializer gsonComponentSerializer();
@Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.gson.GsonComponentSerializer colorDownsamplingGsonComponentSerializer();
@Deprecated(forRemoval = true) net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer legacyComponentSerializer();
net.kyori.adventure.text.Component resolveWithContext(net.kyori.adventure.text.Component component, org.bukkit.command.CommandSender context, org.bukkit.entity.Entity scoreboardSubject, boolean bypassPermissions) throws java.io.IOException;
// Paper end
Material toLegacy(Material material);

View File

@ -68,6 +68,7 @@ public @interface Warning {
* </ul>
*/
public boolean printFor(@Nullable Warning warning) {
if (Boolean.getBoolean("paper.alwaysPrintWarningState")) return true; // Paper
if (this == DEFAULT) {
return warning == null || warning.value();
}

View File

@ -47,7 +47,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents a world, which may contain entities, chunks and blocks
*/
public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed {
public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient, Metadatable, PersistentDataHolder, Keyed, net.kyori.adventure.audience.ForwardingAudience { // Paper
/**
* Gets the {@link Block} at the given coordinates
@ -644,6 +644,14 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
@NotNull
public List<Player> getPlayers();
// Paper start
@NotNull
@Override
default Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
return this.getPlayers();
}
// Paper end
/**
* Returns a list of entities within a bounding box centered around a
* Location.

View File

@ -33,7 +33,9 @@ public interface CommandBlock extends TileState {
* by default is "@".
*
* @return Name of this CommandBlock.
* @deprecated in favour of {@link #name()}
*/
@Deprecated // Paper
@NotNull
public String getName();
@ -43,6 +45,28 @@ public interface CommandBlock extends TileState {
* same as setting it to "@".
*
* @param name New name for this CommandBlock.
* @deprecated in favour of {@link #name(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setName(@Nullable String name);
// Paper start
/**
* Gets the name of this CommandBlock. The name is used with commands
* that this CommandBlock executes. This name will never be null, and
* by default is a {@link net.kyori.adventure.text.TextComponent} containing {@code @}.
*
* @return Name of this CommandBlock.
*/
public net.kyori.adventure.text.@NotNull Component name();
/**
* Sets the name of this CommandBlock. The name is used with commands
* that this CommandBlock executes. Setting the name to null is the
* same as setting it to a {@link net.kyori.adventure.text.TextComponent} containing {@code @}.
*
* @param name New name for this CommandBlock.
*/
public void name(net.kyori.adventure.text.@Nullable Component name);
// Paper end
}

View File

@ -12,12 +12,51 @@ import org.jetbrains.annotations.Nullable;
* Represents a captured state of either a SignPost or a WallSign.
*/
public interface Sign extends TileState, Colorable {
// Paper start
/**
* Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
*
* @return List of components containing each line of text
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
*/
@NotNull
@Deprecated
public java.util.List<net.kyori.adventure.text.Component> lines();
/**
* Gets the line of text at the specified index on the {@link Side#FRONT}.
* <p>
* For example, getLine(0) will return the first line of text.
*
* @param index Line number to get the text from, starting at 0
* @throws IndexOutOfBoundsException Thrown when the line does not exist
* @return Text on the given line
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}.
*/
@NotNull
@Deprecated
public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException;
/**
* Sets the line of text at the specified index on the {@link Side#FRONT}.
* <p>
* For example, setLine(0, "Line One") will set the first line of text to
* "Line One".
*
* @param index Line number to set the text at, starting from 0
* @param line New text to set at the specified index
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}.
*/
@Deprecated
public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException;
// Paper end
/**
* Gets all the lines of text currently on the {@link Side#FRONT} of this sign.
*
* @return Array of Strings containing each line of text
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#getLines()}.
* @deprecated A sign may have multiple writable sides now. Use {@link Sign#getSide(Side)} and {@link SignSide#lines()}.
*/
@Deprecated(since = "1.20")
@NotNull
@ -31,7 +70,7 @@ public interface Sign extends TileState, Colorable {
* @param index Line number to get the text from, starting at 0
* @return Text on the given line
* @throws IndexOutOfBoundsException Thrown when the line does not exist
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#getLine(int)}.
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int)}.
*/
@Deprecated(since = "1.20")
@NotNull
@ -46,7 +85,7 @@ public interface Sign extends TileState, Colorable {
* @param index Line number to set the text at, starting from 0
* @param line New text to set at the specified index
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#setLine(int, String)}.
* @deprecated A sign may have multiple writable sides now. Use {@link #getSide(Side)} and {@link SignSide#line(int, net.kyori.adventure.text.Component)}.
*/
@Deprecated(since = "1.20")
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;

View File

@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull;
* Represents a side of a sign.
*/
public interface SignSide extends Colorable {
// Paper start
/**
* Gets all the lines of text currently on the sign.
*
* @return List of components containing each line of text
*/
@NotNull
public java.util.List<net.kyori.adventure.text.Component> lines();
/**
* Gets the line of text at the specified index.
* <p>
* For example, getLine(0) will return the first line of text.
*
* @param index Line number to get the text from, starting at 0
* @throws IndexOutOfBoundsException Thrown when the line does not exist
* @return Text on the given line
*/
@NotNull
public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException;
/**
* Sets the line of text at the specified index.
* <p>
* For example, setLine(0, "Line One") will set the first line of text to
* "Line One".
*
* @param index Line number to set the text at, starting from 0
* @param line New text to set at the specified index
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
*/
public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException;
// Paper end
/**
* Gets all the lines of text currently on this side of the sign.
*
* @return Array of Strings containing each line of text
* @deprecated in favour of {@link #lines()}
*/
@NotNull
@Deprecated // Paper
public String[] getLines();
/**
@ -24,8 +59,10 @@ public interface SignSide extends Colorable {
* @param index Line number to get the text from, starting at 0
* @return Text on the given line
* @throws IndexOutOfBoundsException Thrown when the line does not exist
* @deprecated in favour of {@link #line(int)}
*/
@NotNull
@Deprecated // Paper
public String getLine(int index) throws IndexOutOfBoundsException;
/**
@ -37,7 +74,9 @@ public interface SignSide extends Colorable {
* @param index Line number to set the text at, starting from 0
* @param line New text to set at the specified index
* @throws IndexOutOfBoundsException If the index is out of the range 0..3
* @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException;
/**

View File

@ -32,7 +32,7 @@ public abstract class Command {
protected String description;
protected String usageMessage;
private String permission;
private String permissionMessage;
private net.kyori.adventure.text.Component permissionMessage; // Paper
public org.spigotmc.CustomTimingsHandler timings; // Spigot
protected Command(@NotNull String name) {
@ -186,10 +186,10 @@ public abstract class Command {
if (permissionMessage == null) {
target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is a mistake.");
} else if (permissionMessage.length() != 0) {
for (String line : permissionMessage.replace("<permission>", permission).split("\n")) {
target.sendMessage(line);
}
// Paper start - use components for permissionMessage
} else if (!permissionMessage.equals(net.kyori.adventure.text.Component.empty())) {
target.sendMessage(permissionMessage.replaceText(net.kyori.adventure.text.TextReplacementConfig.builder().matchLiteral("<permission>").replacement(permission).build()));
// Paper end
}
return false;
@ -327,7 +327,7 @@ public abstract class Command {
@Deprecated(since = "1.20.4")
@Nullable
public String getPermissionMessage() {
return permissionMessage;
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serializeOrNull(permissionMessage); // Paper
}
/**
@ -398,7 +398,7 @@ public abstract class Command {
@Deprecated(since = "1.20.4")
@NotNull
public Command setPermissionMessage(@Nullable String permissionMessage) {
this.permissionMessage = permissionMessage;
this.permissionMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(permissionMessage); // Paper
return this;
}
@ -413,13 +413,61 @@ public abstract class Command {
this.usageMessage = (usage == null) ? "" : usage;
return this;
}
// Paper start
/**
* Gets the permission message.
*
* @return the permission message
* @deprecated permission messages have not worked for player-executed
* commands since 1.13 as clients without permission to execute a command
* are unaware of its existence and therefore will not send an unknown
* command execution to the server. This message will only ever be shown to
* consoles or when this command is executed with
* {@link Bukkit#dispatchCommand(CommandSender, String)}.
*/
@Deprecated
public net.kyori.adventure.text.@Nullable Component permissionMessage() {
return this.permissionMessage;
}
/**
* Sets the permission message.
*
* @param permissionMessage the permission message
* @deprecated permission messages have not worked for player-executed
* commands since 1.13 as clients without permission to execute a command
* are unaware of its existence and therefore will not send an unknown
* command execution to the server. This message will only ever be shown to
* consoles or when this command is executed with
* {@link Bukkit#dispatchCommand(CommandSender, String)}.
*/
@Deprecated
public void permissionMessage(net.kyori.adventure.text.@Nullable Component permissionMessage) {
this.permissionMessage = permissionMessage;
}
// Paper end
public static void broadcastCommandMessage(@NotNull CommandSender source, @NotNull String message) {
broadcastCommandMessage(source, message, true);
}
public static void broadcastCommandMessage(@NotNull CommandSender source, @NotNull String message, boolean sendToSource) {
String result = source.getName() + ": " + message;
// Paper start
broadcastCommandMessage(source, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message), sendToSource);
}
public static void broadcastCommandMessage(@NotNull CommandSender source, net.kyori.adventure.text.@NotNull Component message) {
broadcastCommandMessage(source, message, true);
}
public static void broadcastCommandMessage(@NotNull CommandSender source, net.kyori.adventure.text.@NotNull Component message, boolean sendToSource) {
net.kyori.adventure.text.TextComponent.Builder result = net.kyori.adventure.text.Component.text()
.color(net.kyori.adventure.text.format.NamedTextColor.WHITE)
.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false)
.append(source.name())
.append(net.kyori.adventure.text.Component.text(": "))
.append(message);
// Paper end
if (source instanceof BlockCommandSender) {
BlockCommandSender blockCommandSender = (BlockCommandSender) source;
@ -438,7 +486,12 @@ public abstract class Command {
}
Set<Permissible> users = Bukkit.getPluginManager().getPermissionSubscriptions(Server.BROADCAST_CHANNEL_ADMINISTRATIVE);
String colored = ChatColor.GRAY + "" + ChatColor.ITALIC + "[" + result + ChatColor.GRAY + ChatColor.ITALIC + "]";
// Paper start
net.kyori.adventure.text.TextComponent.Builder colored = net.kyori.adventure.text.Component.text()
.color(net.kyori.adventure.text.format.NamedTextColor.GRAY)
.decorate(net.kyori.adventure.text.format.TextDecoration.ITALIC)
.append(net.kyori.adventure.text.Component.text("["), result, net.kyori.adventure.text.Component.text("]"));
// Paper end
if (sendToSource && !(source instanceof ConsoleCommandSender)) {
source.sendMessage(message);

View File

@ -6,20 +6,28 @@ import org.bukkit.permissions.Permissible;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface CommandSender extends Permissible {
public interface CommandSender extends net.kyori.adventure.audience.Audience, Permissible { // Paper
/**
* Sends this sender a message
*
* @param message Message to be displayed
* @see #sendMessage(net.kyori.adventure.text.Component)
* @see #sendPlainMessage(String)
* @see #sendRichMessage(String)
*/
@org.jetbrains.annotations.ApiStatus.Obsolete // Paper
public void sendMessage(@NotNull String message);
/**
* Sends this sender multiple messages
*
* @param messages An array of messages to be displayed
* @see #sendMessage(net.kyori.adventure.text.Component)
* @see #sendPlainMessage(String)
* @see #sendRichMessage(String)
*/
@org.jetbrains.annotations.ApiStatus.Obsolete // Paper
public void sendMessage(@NotNull String... messages);
/**
@ -27,7 +35,10 @@ public interface CommandSender extends Permissible {
*
* @param message Message to be displayed
* @param sender The sender of this message
* @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component)
* @deprecated sender UUID is ignored
*/
@Deprecated // Paper
public void sendMessage(@Nullable UUID sender, @NotNull String message);
/**
@ -35,7 +46,10 @@ public interface CommandSender extends Permissible {
*
* @param messages An array of messages to be displayed
* @param sender The sender of this message
* @see #sendMessage(net.kyori.adventure.identity.Identified, net.kyori.adventure.text.Component)
* @deprecated sender UUID is ignored
*/
@Deprecated // Paper
public void sendMessage(@Nullable UUID sender, @NotNull String... messages);
/**
@ -61,7 +75,9 @@ public interface CommandSender extends Permissible {
* Sends this sender a chat component.
*
* @param component the components to send
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -70,7 +86,9 @@ public interface CommandSender extends Permissible {
* Sends an array of components as a single message to the sender.
*
* @param components the components to send
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -80,7 +98,9 @@ public interface CommandSender extends Permissible {
*
* @param component the components to send
* @param sender the sender of the message
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -90,7 +110,9 @@ public interface CommandSender extends Permissible {
*
* @param components the components to send
* @param sender the sender of the message
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@Nullable UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -99,4 +121,52 @@ public interface CommandSender extends Permissible {
@NotNull
Spigot spigot();
// Spigot end
// Paper start
/**
* Gets the name of this command sender
*
* @return Name of the sender
*/
public net.kyori.adventure.text.@NotNull Component name();
@Override
default void sendMessage(final net.kyori.adventure.identity.@NotNull Identity identity, final net.kyori.adventure.text.@NotNull Component message, final net.kyori.adventure.audience.@NotNull MessageType type) {
this.sendMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(message));
}
/**
* Sends a message with the MiniMessage format to the command sender.
* <p>
* See <a href="https://docs.advntr.dev/minimessage/">MiniMessage docs</a>
* for more information on the format.
*
* @param message MiniMessage content
*/
default void sendRichMessage(final @NotNull String message) {
this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message));
}
/**
* Sends a message with the MiniMessage format to the command sender.
* <p>
* See <a href="https://docs.advntr.dev/minimessage/">MiniMessage docs</a> and <a href="https://docs.advntr.dev/minimessage/dynamic-replacements">MiniMessage Placeholders docs</a>
* for more information on the format.
*
* @param message MiniMessage content
* @param resolvers resolvers to use
*/
default void sendRichMessage(final @NotNull String message, final net.kyori.adventure.text.minimessage.tag.resolver.@NotNull TagResolver... resolvers) {
this.sendMessage(net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(message, resolvers));
}
/**
* Sends a plain message to the command sender.
*
* @param message plain message
*/
default void sendPlainMessage(final @NotNull String message) {
this.sendMessage(net.kyori.adventure.text.Component.text(message));
}
// Paper end
}

View File

@ -67,7 +67,7 @@ public class PluginCommandYamlParser {
}
if (permissionMessage != null) {
newCmd.setPermissionMessage(permissionMessage.toString());
newCmd.permissionMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(permissionMessage.toString())); // Paper
}
pluginCmds.add(newCmd);

View File

@ -3,7 +3,7 @@ package org.bukkit.command;
import org.jetbrains.annotations.NotNull;
public interface ProxiedCommandSender extends CommandSender {
public interface ProxiedCommandSender extends CommandSender, net.kyori.adventure.audience.ForwardingAudience.Single { // Paper
/**
* Returns the CommandSender which triggered this proxied command
@ -21,4 +21,16 @@ public interface ProxiedCommandSender extends CommandSender {
@NotNull
CommandSender getCallee();
// Paper start
@Override
default void sendMessage(final net.kyori.adventure.identity.@NotNull Identity source, final net.kyori.adventure.text.@NotNull Component message, final net.kyori.adventure.audience.@NotNull MessageType type) {
net.kyori.adventure.audience.ForwardingAudience.Single.super.sendMessage(source, message, type);
}
@NotNull
@Override
default net.kyori.adventure.audience.Audience audience() {
return this.getCaller();
}
// Paper end
}

View File

@ -1058,4 +1058,98 @@ public interface ConfigurationSection {
* one line.
*/
public void setInlineComments(@NotNull String path, @Nullable List<String> comments);
// Paper start - add rich message component support to configuration
/**
* Gets the requested MiniMessage formatted String as Component by path.
* <p>
* If the Component does not exist but a default value has been specified,
* this will return the default value. If the Component does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the Component to get.
* @return Requested Component.
*/
default net.kyori.adventure.text.@Nullable Component getRichMessage(final @NotNull String path) {
return this.getRichMessage(path, null);
}
/**
* Gets the requested MiniMessage formatted String as Component by path.
* <p>
* If the Component does not exist but a default value has been specified,
* this will return the default value. If the Component does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the Component to get.
* @param fallback component that will be used as fallback
* @return Requested Component.
*/
@Contract("_, !null -> !null")
default net.kyori.adventure.text.@Nullable Component getRichMessage(final @NotNull String path, final net.kyori.adventure.text.@Nullable Component fallback) {
return this.getComponent(path, net.kyori.adventure.text.minimessage.MiniMessage.miniMessage(), fallback);
}
/**
* Sets the specified path to the given value.
* <p>
* If value is null, the entry will be removed. Any existing entry will be
* replaced, regardless of what the new value is.
*
* @param path Path of the object to set.
* @param value New value to set the path to.
*/
default void setRichMessage(final @NotNull String path, final net.kyori.adventure.text.@Nullable Component value) {
this.setComponent(path, net.kyori.adventure.text.minimessage.MiniMessage.miniMessage(), value);
}
/**
* Gets the requested formatted String as Component by path deserialized by the ComponentDecoder.
* <p>
* If the Component does not exist but a default value has been specified,
* this will return the default value. If the Component does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the Component to get.
* @param decoder ComponentDecoder instance used for deserialization
* @return Requested Component.
*/
default <C extends net.kyori.adventure.text.Component> @Nullable C getComponent(final @NotNull String path, final net.kyori.adventure.text.serializer.@NotNull ComponentDecoder<? super String, C> decoder) {
return this.getComponent(path, decoder, null);
}
/**
* Gets the requested formatted String as Component by path deserialized by the ComponentDecoder.
* <p>
* If the Component does not exist but a default value has been specified,
* this will return the default value. If the Component does not exist and no
* default value was specified, this will return null.
*
* @param path Path of the Component to get.
* @param decoder ComponentDecoder instance used for deserialization
* @param fallback component that will be used as fallback
* @return Requested Component.
*/
@Contract("_, _, !null -> !null")
default <C extends net.kyori.adventure.text.Component> @Nullable C getComponent(final @NotNull String path, final net.kyori.adventure.text.serializer.@NotNull ComponentDecoder<? super String, C> decoder, final @Nullable C fallback) {
java.util.Objects.requireNonNull(decoder, "decoder");
final String value = this.getString(path);
return decoder.deserializeOr(value, fallback);
}
/**
* Sets the specified path to the given value.
* <p>
* If value is null, the entry will be removed. Any existing entry will be
* replaced, regardless of what the new value is.
*
* @param path Path of the object to set.
* @param encoder the encoder used to transform the value
* @param value New value to set the path to.
*/
default <C extends net.kyori.adventure.text.Component> void setComponent(final @NotNull String path, final net.kyori.adventure.text.serializer.@NotNull ComponentEncoder<C, String> encoder, final @Nullable C value) {
java.util.Objects.requireNonNull(encoder, "encoder");
this.set(path, encoder.serializeOrNull(value));
}
// Paper end - add rich message component support to configuration
}

View File

@ -55,6 +55,7 @@ public interface Conversable {
*
* @param message Message to be displayed
*/
@org.jetbrains.annotations.ApiStatus.Obsolete // Paper
public void sendRawMessage(@NotNull String message);
/**
@ -62,6 +63,8 @@ public interface Conversable {
*
* @param message Message to be displayed
* @param sender The sender of this message
* @deprecated sender UUID is ignored
*/
@Deprecated // Paper
public void sendRawMessage(@Nullable UUID sender, @NotNull String message);
}

View File

@ -310,6 +310,19 @@ public abstract class Enchantment implements Keyed, Translatable {
* @return True if the enchantment may be applied, otherwise False
*/
public abstract boolean canEnchantItem(@NotNull ItemStack item);
// Paper start
/**
* Get the name of the enchantment with its applied level.
* <p>
* If the given {@code level} is either less than the {@link #getStartLevel()} or greater than the {@link #getMaxLevel()},
* the level may not be shown in the numeral format one may otherwise expect.
* </p>
*
* @param level the level of the enchantment to show
* @return the name of the enchantment with {@code level} applied
*/
public abstract net.kyori.adventure.text.@NotNull Component displayName(int level);
// Paper end
/**
* Gets the Enchantment at the specified key

View File

@ -20,4 +20,11 @@ public abstract class EnchantmentWrapper extends Enchantment {
public Enchantment getEnchantment() {
return this;
}
// Paper start
@NotNull
@Override
public net.kyori.adventure.text.Component displayName(int level) {
return getEnchantment().displayName(level);
}
// Paper end
}

View File

@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable;
* Not all methods are guaranteed to work/may have side effects when
* {@link #isInWorld()} is false.
*/
public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder {
public interface Entity extends Metadatable, CommandSender, Nameable, PersistentDataHolder, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowEntity>, net.kyori.adventure.sound.Sound.Emitter { // Paper
/**
* Gets the entity's current position
@ -776,4 +776,20 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
@Override
Spigot spigot();
// Spigot end
// Paper start
/**
* Gets the entity's display name formatted with their team prefix/suffix and
* the entity's default hover/click events.
*
* @return the team display name
*/
net.kyori.adventure.text.@NotNull Component teamDisplayName();
@NotNull
@Override
default net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowEntity> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowEntity> op) {
return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.customName())));
}
// Paper end
}

View File

@ -58,7 +58,41 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents a player, connected or not
*/
public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient {
public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginMessageRecipient, net.kyori.adventure.identity.Identified, net.kyori.adventure.bossbar.BossBarViewer { // Paper
// Paper start
@Override
default net.kyori.adventure.identity.@NotNull Identity identity() {
return net.kyori.adventure.identity.Identity.identity(this.getUniqueId());
}
/**
* Gets an unmodifiable view of all known currently active bossbars.
* <p>
* <b>This currently only returns bossbars shown to the player via
* {@link #showBossBar(net.kyori.adventure.bossbar.BossBar)} and does not contain bukkit
* {@link org.bukkit.boss.BossBar} instances shown to the player.</b>
*
* @return an unmodifiable view of all known currently active bossbars
* @since 4.14.0
*/
@Override
@org.jetbrains.annotations.UnmodifiableView @NotNull Iterable<? extends net.kyori.adventure.bossbar.BossBar> activeBossBars();
/**
* Gets the "friendly" name to display of this player.
*
* @return the display name
*/
net.kyori.adventure.text.@NotNull Component displayName();
/**
* Sets the "friendly" name to display of this player.
*
* @param displayName the display name to set
*/
void displayName(final net.kyori.adventure.text.@Nullable Component displayName);
// Paper end
/**
* {@inheritDoc}
@ -75,7 +109,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* places defined by plugins.
*
* @return the friendly name
* @deprecated in favour of {@link #displayName()}
*/
@Deprecated // Paper
@NotNull
public String getDisplayName();
@ -87,15 +123,50 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* places defined by plugins.
*
* @param name The new display name.
* @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setDisplayName(@Nullable String name);
// Paper start
/**
* Sets the name that is shown on the in-game player list.
* <p>
* If the value is null, the name will be identical to {@link #getName()}.
*
* @param name new player list name
*/
void playerListName(net.kyori.adventure.text.@Nullable Component name);
/**
* Gets the name that is shown on the in-game player list.
*
* @return the player list name
*/
net.kyori.adventure.text.@NotNull Component playerListName();
/**
* Gets the currently displayed player list header for this player.
*
* @return player list header or null
*/
net.kyori.adventure.text.@Nullable Component playerListHeader();
/**
* Gets the currently displayed player list footer for this player.
*
* @return player list footer or null
*/
net.kyori.adventure.text.@Nullable Component playerListFooter();
// Paper end
/**
* Gets the name that is shown on the player list.
*
* @return the player list name
* @deprecated in favour of {@link #playerListName()}
*/
@NotNull
@Deprecated // Paper
public String getPlayerListName();
/**
@ -104,7 +175,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* If the value is null, the name will be identical to {@link #getName()}.
*
* @param name new player list name
* @deprecated in favour of {@link #playerListName(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setPlayerListName(@Nullable String name);
/**
@ -126,7 +199,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Gets the currently displayed player list header for this player.
*
* @return player list header or null
* @deprecated in favour of {@link #playerListHeader()}
*/
@Deprecated // Paper
@Nullable
public String getPlayerListHeader();
@ -134,7 +209,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Gets the currently displayed player list footer for this player.
*
* @return player list header or null
* @deprecated in favour of {@link #playerListFooter()}
*/
@Deprecated // Paper
@Nullable
public String getPlayerListFooter();
@ -142,14 +219,18 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Sets the currently displayed player list header for this player.
*
* @param header player list header, null for empty
* @deprecated in favour of {@link #sendPlayerListHeader(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setPlayerListHeader(@Nullable String header);
/**
* Sets the currently displayed player list footer for this player.
*
* @param footer player list footer, null for empty
* @deprecated in favour of {@link #sendPlayerListFooter(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setPlayerListFooter(@Nullable String footer);
/**
@ -158,7 +239,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*
* @param header player list header, null for empty
* @param footer player list footer, null for empty
* @deprecated in favour of {@link #sendPlayerListHeaderAndFooter(net.kyori.adventure.text.Component, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setPlayerListHeaderFooter(@Nullable String header, @Nullable String footer);
/**
@ -235,9 +318,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Kicks player with custom kick message.
*
* @param message kick message
* @deprecated in favour of {@link #kick(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void kickPlayer(@Nullable String message);
// Paper start
/**
* Kicks the player with the default kick message.
* @see #kick(net.kyori.adventure.text.Component)
*/
void kick();
/**
* Kicks player with custom kick message.
*
* @param message kick message
*/
void kick(final net.kyori.adventure.text.@Nullable Component message);
// Paper end
/**
* Adds this user to the {@link ProfileBanList}. If a previous ban exists, this will
* update the entry.
@ -924,6 +1023,106 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/
public void sendEquipmentChange(@NotNull LivingEntity entity, @NotNull Map<EquipmentSlot, ItemStack> items);
// Paper start
/**
* Send a sign change. This fakes a sign change packet for a user at
* a certain location. This will not actually change the world in any way.
* This method will use a sign at the location's block or a faked sign
* sent via
* {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}.
* <p>
* If the client does not have a sign at the given location it will
* display an error message to the user.
*
* @param loc the location of the sign
* @param lines the new text on the sign or null to clear it
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated
default void sendSignChange(@NotNull Location loc, @Nullable java.util.List<? extends net.kyori.adventure.text.Component> lines) throws IllegalArgumentException {
this.sendSignChange(loc, lines, DyeColor.BLACK);
}
/**
* Send a sign change. This fakes a sign change packet for a user at
* a certain location. This will not actually change the world in any way.
* This method will use a sign at the location's block or a faked sign
* sent via
* {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}.
* <p>
* If the client does not have a sign at the given location it will
* display an error message to the user.
*
* @param loc the location of the sign
* @param lines the new text on the sign or null to clear it
* @param dyeColor the color of the sign
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if dyeColor is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated
default void sendSignChange(@NotNull Location loc, @Nullable java.util.List<? extends net.kyori.adventure.text.Component> lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException {
this.sendSignChange(loc, lines, dyeColor, false);
}
/**
* Send a sign change. This fakes a sign change packet for a user at
* a certain location. This will not actually change the world in any way.
* This method will use a sign at the location's block or a faked sign
* sent via
* {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}.
* <p>
* If the client does not have a sign at the given location it will
* display an error message to the user.
*
* @param loc the location of the sign
* @param lines the new text on the sign or null to clear it
* @param hasGlowingText whether the text of the sign should glow as if dyed with a glowing ink sac
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if dyeColor is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated
default void sendSignChange(@NotNull Location loc, @Nullable java.util.List<? extends net.kyori.adventure.text.Component> lines, boolean hasGlowingText) throws IllegalArgumentException {
this.sendSignChange(loc, lines, DyeColor.BLACK, hasGlowingText);
}
/**
* Send a sign change. This fakes a sign change packet for a user at
* a certain location. This will not actually change the world in any way.
* This method will use a sign at the location's block or a faked sign
* sent via
* {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}.
* <p>
* If the client does not have a sign at the given location it will
* display an error message to the user.
*
* @param loc the location of the sign
* @param lines the new text on the sign or null to clear it
* @param dyeColor the color of the sign
* @param hasGlowingText whether the text of the sign should glow as if dyed with a glowing ink sac
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if dyeColor is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated
void sendSignChange(@NotNull Location loc, @Nullable java.util.List<? extends net.kyori.adventure.text.Component> lines, @NotNull DyeColor dyeColor, boolean hasGlowingText)
throws IllegalArgumentException;
// Paper end
/**
* Send a sign change. This fakes a sign change packet for a user at
* a certain location. This will not actually change the world in any way.
@ -941,7 +1140,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @param lines the new text on the sign or null to clear it
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated // Paper
public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException;
/**
@ -963,7 +1166,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if dyeColor is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated // Paper
public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException;
/**
@ -986,7 +1193,11 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @throws IllegalArgumentException if location is null
* @throws IllegalArgumentException if dyeColor is null
* @throws IllegalArgumentException if lines is non-null and has a length less than 4
* @deprecated Use {@link #sendBlockUpdate(Location, TileState)} by creating a new virtual
* {@link org.bukkit.block.Sign} block state via {@link BlockData#createBlockState()}
* (constructed e.g. via {@link Material#createBlockData()})
*/
@Deprecated // Paper
public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor, boolean hasGlowingText) throws IllegalArgumentException;
/**
@ -1461,7 +1672,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @throws IllegalArgumentException Thrown if the URL is null.
* @throws IllegalArgumentException Thrown if the URL is too long.
* @deprecated Minecraft no longer uses textures packs. Instead you
* should use {@link #setResourcePack(String)}.
* should use {@link #setResourcePack(UUID, String, byte[], net.kyori.adventure.text.Component, boolean)}.
*/
@Deprecated(since = "1.7.2")
public void setTexturePack(@NotNull String url);
@ -1497,7 +1708,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @throws IllegalArgumentException Thrown if the URL is null.
* @throws IllegalArgumentException Thrown if the URL is too long. The
* length restriction is an implementation specific arbitrary value.
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/
@Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url);
/**
@ -1529,6 +1742,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* pack correctly.
* </ul>
*
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
* @param url The URL from which the client will download the resource
* pack. The string must contain only US-ASCII characters and should
* be encoded as per RFC 1738.
@ -1541,6 +1755,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
*/
@Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url, @Nullable byte[] hash);
/**
@ -1565,7 +1780,53 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}.
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
* </ul>
*
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
* @param url The URL from which the client will download the resource
* pack. The string must contain only US-ASCII characters and should
* be encoded as per RFC 1738.
* @param hash The sha1 hash sum of the resource pack file which is used
* to apply a cached version of the pack directly without downloading
* if it is available. Hast to be 20 bytes long!
* @param prompt The optional custom prompt message to be shown to client.
* @throws IllegalArgumentException Thrown if the URL is null.
* @throws IllegalArgumentException Thrown if the URL is too long. The
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
*/
@Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt);
// Paper start
/**
* Request that the player's client download and switch resource packs.
* <p>
* The player's client will download the new resource pack asynchronously
* in the background, and will automatically switch to it once the
* download is complete. If the client has downloaded and cached a
* resource pack with the same hash in the past it will not download but
* directly apply the cached pack. If the hash is null and the client has
* downloaded and cached the same resource pack in the past, it will
* perform a file size check against the response content to determine if
* the resource pack has changed and needs to be downloaded again. When
* this request is sent for the very first time from a given server, the
* client will first display a confirmation GUI to the player before
* proceeding with the download.
* <p>
* Notes:
* <ul>
* <li>Players can disable server resources on their client, in which
* case this method will have no affect on them. Use the
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
@ -1583,8 +1844,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
* @see #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)
*/
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt);
default void setResourcePack(final @NotNull String url, final byte @Nullable [] hash, final net.kyori.adventure.text.@Nullable Component prompt) {
this.setResourcePack(url, hash, prompt, false);
}
// Paper end
/**
* Request that the player's client download and switch resource packs.
@ -1608,7 +1873,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}.
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
@ -1627,7 +1892,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/
@Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, boolean force);
/**
@ -1652,7 +1919,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}.
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
@ -1672,9 +1939,61 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/
@Deprecated // Paper
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt, boolean force);
// Paper start
/**
* Request that the player's client download and switch resource packs.
* <p>
* The player's client will download the new resource pack asynchronously
* in the background, and will automatically switch to it once the
* download is complete. If the client has downloaded and cached a
* resource pack with the same hash in the past it will not download but
* directly apply the cached pack. If the hash is null and the client has
* downloaded and cached the same resource pack in the past, it will
* perform a file size check against the response content to determine if
* the resource pack has changed and needs to be downloaded again. When
* this request is sent for the very first time from a given server, the
* client will first display a confirmation GUI with a custom prompt
* to the player before proceeding with the download.
* <p>
* Notes:
* <ul>
* <li>Players can disable server resources on their client, in which
* case this method will have no affect on them. Use the
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
* </ul>
*
* @param url The URL from which the client will download the resource
* pack. The string must contain only US-ASCII characters and should
* be encoded as per RFC 1738.
* @param hash The sha1 hash sum of the resource pack file which is used
* to apply a cached version of the pack directly without downloading
* if it is available. Hast to be 20 bytes long!
* @param prompt The optional custom prompt message to be shown to client.
* @param force If true, the client will be disconnected from the server
* when it declines to use the resource pack.
* @throws IllegalArgumentException Thrown if the URL is null.
* @throws IllegalArgumentException Thrown if the URL is too long. The
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
* @see #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)
*/
default void setResourcePack(final @NotNull String url, final byte @Nullable [] hash, final net.kyori.adventure.text.@Nullable Component prompt, final boolean force) {
this.setResourcePack(UUID.nameUUIDFromBytes(url.getBytes(java.nio.charset.StandardCharsets.UTF_8)), url, hash, prompt, force);
}
// Paper end
/**
* Request that the player's client download and switch resource packs.
* <p>
@ -1697,7 +2016,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePack(UUID)} or {@link #removeResourcePacks()}.
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
@ -1718,9 +2037,60 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/
@Deprecated // Paper - adventure
public void setResourcePack(@NotNull UUID id, @NotNull String url, @Nullable byte[] hash, @Nullable String prompt, boolean force);
// Paper start
/**
* Request that the player's client download and switch resource packs.
* <p>
* The player's client will download the new resource pack asynchronously
* in the background, and will automatically switch to it once the
* download is complete. If the client has downloaded and cached a
* resource pack with the same hash in the past it will not download but
* directly apply the cached pack. If the hash is null and the client has
* downloaded and cached the same resource pack in the past, it will
* perform a file size check against the response content to determine if
* the resource pack has changed and needs to be downloaded again. When
* this request is sent for the very first time from a given server, the
* client will first display a confirmation GUI to the player before
* proceeding with the download.
* <p>
* Notes:
* <ul>
* <li>Players can disable server resources on their client, in which
* case this method will have no affect on them. Use the
* {@link PlayerResourcePackStatusEvent} to figure out whether or not
* the player loaded the pack!
* <li>To remove a resource pack you can use
* {@link #removeResourcePacks(UUID, UUID...)} or {@link #clearResourcePacks()}.
* <li>The request is sent with empty string as the hash when the hash is
* not provided. This might result in newer versions not loading the
* pack correctly.
* </ul>
*
* @param uuid Unique resource pack ID.
* @param url The URL from which the client will download the resource
* pack. The string must contain only US-ASCII characters and should
* be encoded as per RFC 1738.
* @param hash The sha1 hash sum of the resource pack file which is used
* to apply a cached version of the pack directly without downloading
* if it is available. Hast to be 20 bytes long!
* @param prompt The optional custom prompt message to be shown to client.
* @param force If true, the client will be disconnected from the server
* when it declines to use the resource pack.
* @throws IllegalArgumentException Thrown if the URL is null.
* @throws IllegalArgumentException Thrown if the URL is too long. The
* length restriction is an implementation specific arbitrary value.
* @throws IllegalArgumentException Thrown if the hash is not 20 bytes
* long.
* @see #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)
*/
void setResourcePack(@NotNull UUID uuid, @NotNull String url, byte @Nullable [] hash, net.kyori.adventure.text.@Nullable Component prompt, boolean force);
// Paper end
/**
* Request that the player's client download and include another resource pack.
* <p>
@ -1773,12 +2143,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*
* @param id the id of the resource pack.
* @throws IllegalArgumentException If the ID is null.
* @see #removeResourcePacks(UUID, UUID...)
*/
public void removeResourcePack(@NotNull UUID id);
/**
* Request that the player's client remove all loaded resource pack sent by
* the server.
* @see #clearResourcePacks()
*/
public void removeResourcePacks();
@ -1916,7 +2288,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*
* @param title Title text
* @param subtitle Subtitle text
* @deprecated API behavior subject to change
* @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
*/
@Deprecated(since = "1.8.7")
public void sendTitle(@Nullable String title, @Nullable String subtitle);
@ -1935,7 +2307,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @param fadeIn time in ticks for titles to fade in. Defaults to 10.
* @param stay time in ticks for titles to stay. Defaults to 70.
* @param fadeOut time in ticks for titles to fade out. Defaults to 20.
* @deprecated Use {@link #showTitle(net.kyori.adventure.title.Title)} or {@link #sendTitlePart(net.kyori.adventure.title.TitlePart, Object)}
*/
@Deprecated // Paper - Adventure
public void sendTitle(@Nullable String title, @Nullable String subtitle, int fadeIn, int stay, int fadeOut);
/**
@ -2210,6 +2584,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/
public int getClientViewDistance();
// Paper start
/**
* Gets the player's current locale.
*
* @return the player's locale
*/
@NotNull java.util.Locale locale();
// Paper end
/**
* Gets the player's estimated ping in milliseconds.
*
@ -2235,8 +2617,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* they wish.
*
* @return the player's locale
* @deprecated in favour of {@link #locale()}
*/
@NotNull
@Deprecated // Paper
public String getLocale();
/**
@ -2288,6 +2672,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*/
public boolean isAllowingServerListings();
// Paper start
@NotNull
@Override
default net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowEntity> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowEntity> op) {
return net.kyori.adventure.text.event.HoverEvent.showEntity(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowEntity.of(this.getType().getKey(), this.getUniqueId(), this.displayName())));
}
// Paper end
// Spigot start
public class Spigot extends Entity.Spigot {
@ -2319,11 +2711,13 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
throw new UnsupportedOperationException("Not supported yet.");
}
@Deprecated // Paper
@Override
public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent component) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Deprecated // Paper
@Override
public void sendMessage(@NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
throw new UnsupportedOperationException("Not supported yet.");
@ -2334,7 +2728,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*
* @param position the screen position
* @param component the components to send
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent component) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -2344,7 +2740,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
*
* @param position the screen position
* @param components the components to send
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -2355,7 +2753,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @param position the screen position
* @param sender the sender of the message
* @param component the components to send
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable java.util.UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent component) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -2366,7 +2766,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @param position the screen position
* @param sender the sender of the message
* @param components the components to send
* @deprecated use {@code sendMessage} methods that accept {@link net.kyori.adventure.text.Component}
*/
@Deprecated // Paper
public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable java.util.UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) {
throw new UnsupportedOperationException("Not supported yet.");
}

View File

@ -13,17 +13,37 @@ public interface TextDisplay extends Display {
* Gets the displayed text.
*
* @return the displayed text.
* @deprecated in favour of {@link #text()}
*/
@Nullable
@Deprecated // Paper
String getText();
/**
* Sets the displayed text.
*
* @param text the new text
* @deprecated in favour of {@link #text(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setText(@Nullable String text);
// Paper start
/**
* Gets the displayed text.
*
* @return the displayed text
*/
net.kyori.adventure.text.@NotNull Component text();
/**
* Sets the displayed text.
*
* @param text the new text
*/
void text(net.kyori.adventure.text.@Nullable Component text);
// Paper end
/**
* Gets the maximum line width before wrapping.
*

View File

@ -32,7 +32,9 @@ public interface CommandMinecart extends Minecart {
* same as setting it to "@".
*
* @param name New name for this CommandMinecart.
* @deprecated in favour of {@link #customName(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setName(@Nullable String name);
}

View File

@ -17,18 +17,38 @@ public class SignChangeEvent extends BlockEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;
private final Player player;
private final String[] lines;
private final java.util.List<net.kyori.adventure.text.Component> adventure$lines; // Paper
private final Side side;
// Paper start
public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List<net.kyori.adventure.text.Component> adventure$lines, @NotNull Side side) {
super(theBlock);
this.player = player;
this.adventure$lines = adventure$lines;
this.side = side;
}
@Deprecated
public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player player, @NotNull final java.util.List<net.kyori.adventure.text.Component> adventure$lines) {
this(theBlock, player, adventure$lines, Side.FRONT);
}
// Paper end
@Deprecated(since = "1.19.4")
public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines) {
this(theBlock, thePlayer, theLines, Side.FRONT);
}
@Deprecated // Paper
public SignChangeEvent(@NotNull final Block theBlock, @NotNull final Player thePlayer, @NotNull final String[] theLines, @NotNull Side side) {
super(theBlock);
this.player = thePlayer;
this.lines = theLines;
// Paper start
this.adventure$lines = new java.util.ArrayList<>();
for (String theLine : theLines) {
this.adventure$lines.add(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(theLine));
}
// Paper end
this.side = side;
}
@ -42,14 +62,14 @@ public class SignChangeEvent extends BlockEvent implements Cancellable {
return player;
}
// Paper start
/**
* Gets all of the lines of text from the sign involved in this event.
*
* @return the String array for the sign's lines new text
*/
@NotNull
public String[] getLines() {
return lines;
public @NotNull java.util.List<net.kyori.adventure.text.Component> lines() {
return this.adventure$lines;
}
/**
@ -61,9 +81,8 @@ public class SignChangeEvent extends BlockEvent implements Cancellable {
* @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3
* or < 0}
*/
@Nullable
public String getLine(int index) throws IndexOutOfBoundsException {
return lines[index];
public net.kyori.adventure.text.@Nullable Component line(int index) throws IndexOutOfBoundsException {
return this.adventure$lines.get(index);
}
/**
@ -74,8 +93,51 @@ public class SignChangeEvent extends BlockEvent implements Cancellable {
* @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3
* or < 0}
*/
public void line(int index, net.kyori.adventure.text.@Nullable Component line) throws IndexOutOfBoundsException {
this.adventure$lines.set(index, line);
}
// Paper end
/**
* Gets all of the lines of text from the sign involved in this event.
*
* @return the String array for the sign's lines new text
* @deprecated in favour of {@link #lines()}
*/
@NotNull
@Deprecated // Paper
public String[] getLines() {
return adventure$lines.stream().map(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()::serialize).toArray(String[]::new); // Paper
}
/**
* Gets a single line of text from the sign involved in this event.
*
* @param index index of the line to get
* @return the String containing the line of text associated with the
* provided index
* @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3
* or < 0}
* @deprecated in favour of {@link #line(int)}
*/
@Nullable
@Deprecated // Paper
public String getLine(int index) throws IndexOutOfBoundsException {
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.adventure$lines.get(index)); // Paper
}
/**
* Sets a single line for the sign involved in this event
*
* @param index index of the line to set
* @param line text to set
* @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3
* or < 0}
* @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException {
lines[index] = line;
adventure$lines.set(index, line != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(line) : null); // Paper
}
/**

View File

@ -12,27 +12,50 @@ import org.jetbrains.annotations.Nullable;
*/
public class PlayerDeathEvent extends EntityDeathEvent {
private int newExp = 0;
private String deathMessage = "";
private net.kyori.adventure.text.Component deathMessage; // Paper - adventure
private int newLevel = 0;
private int newTotalExp = 0;
private boolean keepLevel = false;
private boolean keepInventory = false;
public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, @Nullable final String deathMessage) {
// Paper start - adventure
@org.jetbrains.annotations.ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final @Nullable net.kyori.adventure.text.Component deathMessage) {
this(player, damageSource, drops, droppedExp, 0, deathMessage);
}
public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, final int newExp, @Nullable final String deathMessage) {
@org.jetbrains.annotations.ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final @Nullable net.kyori.adventure.text.Component deathMessage) {
this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage);
}
public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) {
@org.jetbrains.annotations.ApiStatus.Internal
public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable net.kyori.adventure.text.Component deathMessage) {
super(player, damageSource, drops, droppedExp);
this.newExp = newExp;
this.newTotalExp = newTotalExp;
this.newLevel = newLevel;
this.deathMessage = deathMessage;
}
// Paper end - adventure
@Deprecated // Paper
public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, @Nullable final String deathMessage) {
this(player, damageSource, drops, droppedExp, 0, deathMessage);
}
@Deprecated // Paper
public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, final int newExp, @Nullable final String deathMessage) {
this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage);
}
@Deprecated // Paper
public PlayerDeathEvent(@NotNull final Player player, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final String deathMessage) {
super(player, damageSource, drops, droppedExp);
this.newExp = newExp;
this.newTotalExp = newTotalExp;
this.newLevel = newLevel;
this.deathMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); // Paper
}
@NotNull
@Override
@ -40,25 +63,49 @@ public class PlayerDeathEvent extends EntityDeathEvent {
return (Player) entity;
}
// Paper start - adventure
/**
* Set the death message that will appear to everyone on the server.
*
* @param deathMessage Message to appear to other players on the server.
* @param deathMessage Component message to appear to other players on the server.
*/
public void setDeathMessage(@Nullable String deathMessage) {
public void deathMessage(final net.kyori.adventure.text.@Nullable Component deathMessage) {
this.deathMessage = deathMessage;
}
/**
* Get the death message that will appear to everyone on the server.
*
* @return Message to appear to other players on the server.
* @return Component message to appear to other players on the server.
*/
@Nullable
public String getDeathMessage() {
return deathMessage;
public net.kyori.adventure.text.@Nullable Component deathMessage() {
return this.deathMessage;
}
// Paper end - adventure
/**
* Set the death message that will appear to everyone on the server.
*
* @param deathMessage Message to appear to other players on the server.
* @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setDeathMessage(@Nullable String deathMessage) {
this.deathMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); // Paper
}
/**
* Get the death message that will appear to everyone on the server.
*
* @return Message to appear to other players on the server.
* @deprecated in favour of {@link #deathMessage()}
*/
@Nullable
@Deprecated // Paper
public String getDeathMessage() {
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serializeOrNull(this.deathMessage); // Paper
}
// Paper end
/**
* Gets how much EXP the Player should have at respawn.
* <p>

View File

@ -163,7 +163,18 @@ public enum InventoryType {
private final String title;
private final MenuType menuType;
private final boolean isCreatable;
// Paper start
private final net.kyori.adventure.text.Component defaultTitleComponent;
/**
* Gets the inventory's default title.
*
* @return the inventory's default title
*/
public net.kyori.adventure.text.@NotNull Component defaultTitle() {
return defaultTitleComponent;
}
// Paper end
private InventoryType(int defaultSize, /*@NotNull*/ String defaultTitle, @Nullable MenuType type) {
this(defaultSize, defaultTitle, type, true);
}
@ -173,6 +184,7 @@ public enum InventoryType {
title = defaultTitle;
this.menuType = type;
this.isCreatable = isCreatable;
this.defaultTitleComponent = net.kyori.adventure.text.Component.text(defaultTitle); // Paper - Adventure
}
public int getDefaultSize() {
@ -180,6 +192,7 @@ public enum InventoryType {
}
@NotNull
@Deprecated // Paper
public String getDefaultTitle() {
return title;
}

View File

@ -22,7 +22,11 @@ import org.jetbrains.annotations.NotNull;
* <p>
* Care should be taken to check {@link #isAsynchronous()} and treat the event
* appropriately.
*
* @deprecated use {@link io.papermc.paper.event.player.AsyncChatEvent} instead
*/
@Deprecated // Paper
@org.bukkit.Warning(value = false, reason = "Don't nag on old event yet") // Paper
public class AsyncPlayerChatEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;

View File

@ -10,11 +10,18 @@ import org.jetbrains.annotations.NotNull;
* Stores details for players attempting to log in.
* <p>
* This event is asynchronous, and not run using main thread.
* <p>
* When this event is fired, the player's locale is not
* available. Therefore, any translatable component will be
* rendered with the default locale, {@link java.util.Locale#US}.
* <p>
* Consider rendering any translatable yourself with {@link net.kyori.adventure.translation.GlobalTranslator#render}
* if the client's language is known.
*/
public class AsyncPlayerPreLoginEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private Result result;
private String message;
private net.kyori.adventure.text.Component message; // Paper
private final String name;
private final InetAddress ipAddress;
private final UUID uniqueId;
@ -33,7 +40,7 @@ public class AsyncPlayerPreLoginEvent extends Event {
public AsyncPlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId, boolean transferred) {
super(true);
this.result = Result.ALLOWED;
this.message = "";
this.message = net.kyori.adventure.text.Component.empty(); // Paper
this.name = name;
this.ipAddress = ipAddress;
this.uniqueId = uniqueId;
@ -86,6 +93,7 @@ public class AsyncPlayerPreLoginEvent extends Event {
this.result = result == null ? null : Result.valueOf(result.name());
}
// Paper start
/**
* Gets the current kick message that will be used if getResult() !=
* Result.ALLOWED
@ -93,7 +101,7 @@ public class AsyncPlayerPreLoginEvent extends Event {
* @return Current kick message
*/
@NotNull
public String getKickMessage() {
public net.kyori.adventure.text.Component kickMessage() {
return message;
}
@ -102,29 +110,81 @@ public class AsyncPlayerPreLoginEvent extends Event {
*
* @param message New kick message
*/
public void setKickMessage(@NotNull final String message) {
public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) {
this.message = message;
}
/**
* Allows the player to log in
*/
public void allow() {
result = Result.ALLOWED;
message = "";
}
/**
* Disallows the player from logging in, with the given reason
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
*/
public void disallow(@NotNull final Result result, @NotNull final String message) {
public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) {
this.result = result;
this.message = message;
}
/**
* Disallows the player from logging in, with the given reason
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
* @deprecated This method uses a deprecated enum from {@link
* PlayerPreLoginEvent}
* @see #disallow(Result, String)
*/
@Deprecated
public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final net.kyori.adventure.text.Component message) {
this.result = result == null ? null : Result.valueOf(result.name());
this.message = message;
}
// Paper end
/**
* Gets the current kick message that will be used if getResult() !=
* Result.ALLOWED
*
* @return Current kick message
* @deprecated in favour of {@link #kickMessage()}
*/
@NotNull
@Deprecated // Paper
public String getKickMessage() {
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper
}
/**
* Sets the kick message to display if getResult() != Result.ALLOWED
*
* @param message New kick message
* @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setKickMessage(@NotNull final String message) {
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**
* Allows the player to log in
*/
public void allow() {
result = Result.ALLOWED;
message = net.kyori.adventure.text.Component.empty(); // Paper
}
/**
* Disallows the player from logging in, with the given reason
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
* @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void disallow(@NotNull final Result result, @NotNull final String message) {
this.result = result;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**
* Disallows the player from logging in, with the given reason
*
@ -137,7 +197,7 @@ public class AsyncPlayerPreLoginEvent extends Event {
@Deprecated(since = "1.3.2")
public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final String message) {
this.result = result == null ? null : Result.valueOf(result.name());
this.message = message;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**

View File

@ -12,12 +12,7 @@ import org.jetbrains.annotations.NotNull;
/**
* Holds information for player chat and commands
*
* @deprecated This event will fire from the main thread and allows the use of
* all of the Bukkit API, unlike the {@link AsyncPlayerChatEvent}.
* <p>
* Listening to this event forces chat to wait for the main thread which
* causes delays for chat. {@link AsyncPlayerChatEvent} is the encouraged
* alternative for thread safe implementations.
* @deprecated Listening to this event forces chat to wait for the main thread, delaying chat messages. It is recommended to use {@link io.papermc.paper.event.player.AsyncChatEvent} instead, wherever possible.
*/
@Deprecated(since = "1.3.1")
@Warning(reason = "Listening to this event forces chat to wait for the main thread, delaying chat messages.")

View File

@ -14,7 +14,7 @@ public abstract class PlayerEvent extends Event {
player = who;
}
PlayerEvent(@NotNull final Player who, boolean async) {
public PlayerEvent(@NotNull final Player who, boolean async) { // Paper - public
super(async);
player = who;

View File

@ -10,21 +10,27 @@ import org.jetbrains.annotations.Nullable;
*/
public class PlayerJoinEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private String joinMessage;
public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) {
// Paper start
private net.kyori.adventure.text.Component joinMessage;
public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final net.kyori.adventure.text.Component joinMessage) {
super(playerJoined);
this.joinMessage = joinMessage;
}
@Deprecated // Paper end
public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) {
super(playerJoined);
this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper end
}
// Paper start
/**
* Gets the join message to send to all online players
*
* @return string join message. Can be null
*/
@Nullable
public String getJoinMessage() {
return joinMessage;
public net.kyori.adventure.text.@Nullable Component joinMessage() {
return this.joinMessage;
}
/**
@ -32,9 +38,33 @@ public class PlayerJoinEvent extends PlayerEvent {
*
* @param joinMessage join message. If null, no message will be sent
*/
public void setJoinMessage(@Nullable String joinMessage) {
public void joinMessage(net.kyori.adventure.text.@Nullable Component joinMessage) {
this.joinMessage = joinMessage;
}
// Paper end
/**
* Gets the join message to send to all online players
*
* @return string join message. Can be null
* @deprecated in favour of {@link #joinMessage()}
*/
@Nullable
@Deprecated // Paper
public String getJoinMessage() {
return this.joinMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.joinMessage); // Paper
}
/**
* Sets the join message to send to all online players
*
* @param joinMessage join message. If null, no message will be sent
* @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setJoinMessage(@Nullable String joinMessage) {
this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper
}
@NotNull
@Override

View File

@ -10,35 +10,84 @@ import org.jetbrains.annotations.NotNull;
*/
public class PlayerKickEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private String leaveMessage;
private String kickReason;
private net.kyori.adventure.text.Component leaveMessage; // Paper
private net.kyori.adventure.text.Component kickReason; // Paper
private boolean cancel;
@Deprecated // Paper
public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final String kickReason, @NotNull final String leaveMessage) {
super(playerKicked);
this.kickReason = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(kickReason); // Paper
this.leaveMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(leaveMessage); // Paper
this.cancel = false;
}
// Paper start
public PlayerKickEvent(@NotNull final Player playerKicked, @NotNull final net.kyori.adventure.text.Component kickReason, @NotNull final net.kyori.adventure.text.Component leaveMessage) {
super(playerKicked);
this.kickReason = kickReason;
this.leaveMessage = leaveMessage;
this.cancel = false;
}
/**
* Gets the leave message send to all online players
*
* @return string kick reason
*/
public net.kyori.adventure.text.@NotNull Component leaveMessage() {
return this.leaveMessage;
}
/**
* Sets the leave message send to all online players
*
* @param leaveMessage leave message
*/
public void leaveMessage(net.kyori.adventure.text.@NotNull Component leaveMessage) {
this.leaveMessage = leaveMessage;
}
/**
* Gets the reason why the player is getting kicked
*
* @return string kick reason
*/
public net.kyori.adventure.text.@NotNull Component reason() {
return this.kickReason;
}
/**
* Sets the reason why the player is getting kicked
*
* @param kickReason kick reason
*/
public void reason(net.kyori.adventure.text.@NotNull Component kickReason) {
this.kickReason = kickReason;
}
// Paper end
/**
* Gets the reason why the player is getting kicked
*
* @return string kick reason
* @deprecated in favour of {@link #reason()}
*/
@NotNull
@Deprecated // Paper
public String getReason() {
return kickReason;
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.kickReason); // Paper
}
/**
* Gets the leave message send to all online players
*
* @return string kick reason
* @deprecated in favour of {@link #leaveMessage()}
*/
@NotNull
@Deprecated // Paper
public String getLeaveMessage() {
return leaveMessage;
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.leaveMessage); // Paper
}
@Override
@ -55,18 +104,22 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable {
* Sets the reason why the player is getting kicked
*
* @param kickReason kick reason
* @deprecated in favour of {@link #reason(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setReason(@NotNull String kickReason) {
this.kickReason = kickReason;
this.kickReason = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(kickReason); // Paper
}
/**
* Sets the leave message send to all online players
*
* @param leaveMessage leave message
* @deprecated in favour of {@link #leaveMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setLeaveMessage(@NotNull String leaveMessage) {
this.leaveMessage = leaveMessage;
this.leaveMessage = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(leaveMessage); // Paper
}
@NotNull

View File

@ -12,17 +12,31 @@ public class PlayerLocaleChangeEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
//
private final String locale;
// Paper start
private final java.util.Locale adventure$locale;
/**
* @see Player#locale()
*
* @return the player's new locale
*/
public @NotNull java.util.Locale locale() {
return this.adventure$locale;
}
// Paper end
public PlayerLocaleChangeEvent(@NotNull Player who, @NotNull String locale) {
super(who);
this.locale = locale;
this.adventure$locale = java.util.Objects.requireNonNullElse(net.kyori.adventure.translation.Translator.parseLocale(locale), java.util.Locale.US); // Paper start
}
/**
* @return the player's new locale
* @see Player#getLocale()
* @deprecated in favour of {@link #locale()}
*/
@NotNull
@Deprecated // Paper
public String getLocale() {
return locale;
}

View File

@ -18,7 +18,7 @@ public class PlayerLoginEvent extends PlayerEvent {
private final InetAddress realAddress;
private final String hostname;
private Result result = Result.ALLOWED;
private String message = "";
private net.kyori.adventure.text.Component message = net.kyori.adventure.text.Component.empty();
/**
* This constructor defaults message to an empty string, and result to
@ -60,13 +60,53 @@ public class PlayerLoginEvent extends PlayerEvent {
* @param result The result status for this event
* @param message The message to be displayed if result denies login
* @param realAddress the actual, unspoofed connecting address
* @deprecated in favour of {@link #PlayerLoginEvent(Player, String, InetAddress, Result, net.kyori.adventure.text.Component, InetAddress)}
*/
@Deprecated // Paper
public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final String message, @NotNull final InetAddress realAddress) {
this(player, hostname, address, realAddress);
this.result = result;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
// Paper start
/**
* This constructor pre-configures the event with a result and message
*
* @param player The {@link Player} for this event
* @param hostname The hostname that was used to connect to the server
* @param address The address the player used to connect, provided for
* timing issues
* @param result The result status for this event
* @param message The message to be displayed if result denies login
* @param realAddress the actual, unspoofed connecting address
*/
public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message, @NotNull final InetAddress realAddress) {
this(player, hostname, address, realAddress); // Spigot
this.result = result;
this.message = message;
}
/**
* Gets the current kick message that will be used if getResult() !=
* Result.ALLOWED
*
* @return Current kick message
*/
public net.kyori.adventure.text.@NotNull Component kickMessage() {
return this.message;
}
/**
* Sets the kick message to display if getResult() != Result.ALLOWED
*
* @param message New kick message
*/
public void kickMessage(net.kyori.adventure.text.@NotNull Component message) {
this.message = message;
}
// Paper end
/**
* Gets the current result of the login, as an enum
*
@ -91,19 +131,23 @@ public class PlayerLoginEvent extends PlayerEvent {
* Result.ALLOWED
*
* @return Current kick message
* @deprecated in favour of {@link #kickMessage()}
*/
@NotNull
@Deprecated // Paper
public String getKickMessage() {
return message;
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper
}
/**
* Sets the kick message to display if getResult() != Result.ALLOWED
*
* @param message New kick message
* @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setKickMessage(@NotNull final String message) {
this.message = message;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**
@ -122,7 +166,7 @@ public class PlayerLoginEvent extends PlayerEvent {
*/
public void allow() {
result = Result.ALLOWED;
message = "";
message = net.kyori.adventure.text.Component.empty(); // Paper
}
/**
@ -130,8 +174,21 @@ public class PlayerLoginEvent extends PlayerEvent {
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
* @deprecated in favour of {@link #disallow(Result, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper start
public void disallow(@NotNull final Result result, @NotNull final String message) {
this.result = result;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message);
}
/**
* Disallows the player from logging in, with the given reason
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
*/
public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) {
// Paper end
this.result = result;
this.message = message;
}

View File

@ -9,6 +9,13 @@ import org.jetbrains.annotations.NotNull;
/**
* Stores details for players attempting to log in
* <p>
* When this event is fired, the player's locale is not
* available. Therefore, any translatable component will be
* rendered with the default locale, {@link java.util.Locale#US}.
* <p>
* Consider rendering any translatable yourself with {@link net.kyori.adventure.translation.GlobalTranslator#render}
* if the client's language is known.
*
* @deprecated This event causes synchronization from the login thread; {@link
* AsyncPlayerPreLoginEvent} is preferred to keep the secondary threads
@ -19,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
public class PlayerPreLoginEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private Result result;
private String message;
private net.kyori.adventure.text.Component message; // Paper
private final String name;
private final InetAddress ipAddress;
private final UUID uniqueId;
@ -31,7 +38,7 @@ public class PlayerPreLoginEvent extends Event {
public PlayerPreLoginEvent(@NotNull final String name, @NotNull final InetAddress ipAddress, @NotNull final UUID uniqueId) {
this.result = Result.ALLOWED;
this.message = "";
this.message = net.kyori.adventure.text.Component.empty(); // Paper
this.name = name;
this.ipAddress = ipAddress;
this.uniqueId = uniqueId;
@ -56,6 +63,7 @@ public class PlayerPreLoginEvent extends Event {
this.result = result;
}
// Paper start
/**
* Gets the current kick message that will be used if getResult() !=
* Result.ALLOWED
@ -63,7 +71,7 @@ public class PlayerPreLoginEvent extends Event {
* @return Current kick message
*/
@NotNull
public String getKickMessage() {
public net.kyori.adventure.text.Component kickMessage() {
return message;
}
@ -72,28 +80,65 @@ public class PlayerPreLoginEvent extends Event {
*
* @param message New kick message
*/
public void setKickMessage(@NotNull final String message) {
public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) {
this.message = message;
}
/**
* Allows the player to log in
*/
public void allow() {
result = Result.ALLOWED;
message = "";
}
/**
* Disallows the player from logging in, with the given reason
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
*/
public void disallow(@NotNull final Result result, @NotNull final String message) {
public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) {
this.result = result;
this.message = message;
}
// Paper end
/**
* Gets the current kick message that will be used if getResult() !=
* Result.ALLOWED
*
* @return Current kick message
* @deprecated in favour of {@link #kickMessage()}
*/
@Deprecated // Paper
@NotNull
public String getKickMessage() {
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper
}
/**
* Sets the kick message to display if getResult() != Result.ALLOWED
*
* @param message New kick message
* @deprecated in favour of {@link #kickMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setKickMessage(@NotNull final String message) {
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**
* Allows the player to log in
*/
public void allow() {
result = Result.ALLOWED;
message = net.kyori.adventure.text.Component.empty(); // Paper
}
/**
* Disallows the player from logging in, with the given reason
*
* @param result New result for disallowing the player
* @param message Kick message to display to the user
* @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void disallow(@NotNull final Result result, @NotNull final String message) {
this.result = result;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**
* Gets the player's name.

View File

@ -10,9 +10,15 @@ import org.jetbrains.annotations.Nullable;
*/
public class PlayerQuitEvent extends PlayerEvent {
private static final HandlerList handlers = new HandlerList();
private String quitMessage;
private net.kyori.adventure.text.Component quitMessage; // Paper
@Deprecated // Paper
public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) {
super(who);
this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper
}
// Paper start
public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) {
super(who);
this.quitMessage = quitMessage;
}
@ -22,8 +28,7 @@ public class PlayerQuitEvent extends PlayerEvent {
*
* @return string quit message
*/
@Nullable
public String getQuitMessage() {
public net.kyori.adventure.text.@Nullable Component quitMessage() {
return quitMessage;
}
@ -32,9 +37,33 @@ public class PlayerQuitEvent extends PlayerEvent {
*
* @param quitMessage quit message
*/
public void setQuitMessage(@Nullable String quitMessage) {
public void quitMessage(net.kyori.adventure.text.@Nullable Component quitMessage) {
this.quitMessage = quitMessage;
}
// Paper end
/**
* Gets the quit message to send to all online players
*
* @return string quit message
* @deprecated in favour of {@link #quitMessage()}
*/
@Nullable
@Deprecated // Paper
public String getQuitMessage() {
return this.quitMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.quitMessage); // Paper
}
/**
* Sets the quit message to send to all online players
*
* @param quitMessage quit message
* @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setQuitMessage(@Nullable String quitMessage) {
this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper
}
@NotNull
@Override

View File

@ -9,16 +9,16 @@ import org.jetbrains.annotations.NotNull;
/**
* Event triggered for server broadcast messages such as from
* {@link org.bukkit.Server#broadcast(String, String)}.
* {@link org.bukkit.Server#broadcast(net.kyori.adventure.text.Component)} (String, String)}.
*
* <b>This event behaves similarly to {@link AsyncPlayerChatEvent} in that it
* <b>This event behaves similarly to {@link io.papermc.paper.event.player.AsyncChatEvent} in that it
* should be async if fired from an async thread. Please see that event for
* further information.</b>
*/
public class BroadcastMessageEvent extends ServerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private String message;
private net.kyori.adventure.text.Component message; // Paper
private final Set<CommandSender> recipients;
private boolean cancelled = false;
@ -27,29 +27,66 @@ public class BroadcastMessageEvent extends ServerEvent implements Cancellable {
this(false, message, recipients);
}
@Deprecated // Paper
public BroadcastMessageEvent(boolean isAsync, @NotNull String message, @NotNull Set<CommandSender> recipients) {
// Paper start
super(isAsync);
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message);
this.recipients = recipients;
}
@Deprecated
public BroadcastMessageEvent(net.kyori.adventure.text.@NotNull Component message, @NotNull Set<CommandSender> recipients) {
this(false, message, recipients);
}
public BroadcastMessageEvent(boolean isAsync, net.kyori.adventure.text.@NotNull Component message, @NotNull Set<CommandSender> recipients) {
// Paper end
super(isAsync);
this.message = message;
this.recipients = recipients;
}
// Paper start
/**
* Get the broadcast message.
*
* @return Message to broadcast
*/
public net.kyori.adventure.text.@NotNull Component message() {
return this.message;
}
/**
* Set the broadcast message.
*
* @param message New message to broadcast
*/
public void message(net.kyori.adventure.text.@NotNull Component message) {
this.message = message;
}
// Paper end
/**
* Get the message to broadcast.
*
* @return Message to broadcast
* @deprecated in favour of {@link #message()}
*/
@NotNull
@Deprecated // Paper
public String getMessage() {
return message;
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.message); // Paper
}
/**
* Set the message to broadcast.
*
* @param message New message to broadcast
* @deprecated in favour of {@link #message(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setMessage(@NotNull String message) {
this.message = message;
this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper
}
/**

View File

@ -22,7 +22,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable<Player>
private static final HandlerList handlers = new HandlerList();
private final String hostname;
private final InetAddress address;
private String motd;
private net.kyori.adventure.text.Component motd; // Paper
private final int numPlayers;
private int maxPlayers;
@ -31,7 +31,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable<Player>
Preconditions.checkArgument(numPlayers >= 0, "Cannot have negative number of players online", numPlayers);
this.hostname = hostname;
this.address = address;
this.motd = motd;
this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper
this.numPlayers = numPlayers;
this.maxPlayers = maxPlayers;
}
@ -45,15 +45,80 @@ public class ServerListPingEvent extends ServerEvent implements Iterable<Player>
* @param address the address of the pinger
* @param motd the message of the day
* @param maxPlayers the max number of players
* @deprecated in favour of {@link #ServerListPingEvent(String, java.net.InetAddress, net.kyori.adventure.text.Component, int)}
*/
@Deprecated // Paper
protected ServerListPingEvent(@NotNull final String hostname, @NotNull final InetAddress address, @NotNull final String motd, final int maxPlayers) {
super(true);
this.numPlayers = MAGIC_PLAYER_COUNT;
this.hostname = hostname;
this.address = address;
this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper
this.maxPlayers = maxPlayers;
}
// Paper start
@Deprecated
public ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) {
this("", address, motd, numPlayers, maxPlayers);
}
public ServerListPingEvent(@NotNull final String hostname, @NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int numPlayers, final int maxPlayers) {
super(true);
Preconditions.checkArgument(numPlayers >= 0, "Cannot have negative number of players online (%s)", numPlayers);
this.hostname = hostname;
this.address = address;
this.motd = motd;
this.numPlayers = numPlayers;
this.maxPlayers = maxPlayers;
}
/**
* This constructor is intended for implementations that provide the
* {@link #iterator()} method, thus provided the {@link #getNumPlayers()}
* count.
*
* @param address the address of the pinger
* @param motd the message of the day
* @param maxPlayers the max number of players
* @deprecated in favour of {@link #ServerListPingEvent(String, java.net.InetAddress, net.kyori.adventure.text.Component, int)}
*/
@Deprecated
protected ServerListPingEvent(@NotNull final InetAddress address, @NotNull final net.kyori.adventure.text.Component motd, final int maxPlayers) {
this("", address, motd, maxPlayers);
}
/**
* This constructor is intended for implementations that provide the
* {@link #iterator()} method, thus provided the {@link #getNumPlayers()}
* count.
*
* @param hostname The hostname that was used to connect to the server
* @param address the address of the pinger
* @param motd the message of the day
* @param maxPlayers the max number of players
*/
protected ServerListPingEvent(final @NotNull String hostname, final @NotNull InetAddress address, final net.kyori.adventure.text.@NotNull Component motd, final int maxPlayers) {
this.numPlayers = MAGIC_PLAYER_COUNT;
this.hostname = hostname;
this.address = address;
this.motd = motd;
this.maxPlayers = maxPlayers;
}
/**
* Get the message of the day message.
*
* @return the message of the day
*/
public net.kyori.adventure.text.@NotNull Component motd() {
return motd;
}
/**
* Change the message of the day message.
*
* @param motd the message of the day
*/
public void motd(net.kyori.adventure.text.@NotNull Component motd) {
this.motd = motd;
}
// Paper end
/**
* Gets the hostname that the player used to connect to the server, or
@ -80,19 +145,23 @@ public class ServerListPingEvent extends ServerEvent implements Iterable<Player>
* Get the message of the day message.
*
* @return the message of the day
* @deprecated in favour of {@link #motd()}
*/
@NotNull
@Deprecated // Paper
public String getMotd() {
return motd;
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.motd); // Paper
}
/**
* Change the message of the day message.
*
* @param motd the message of the day
* @deprecated in favour of {@link #motd(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setMotd(@NotNull String motd) {
this.motd = motd;
this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper
}
/**

View File

@ -269,12 +269,26 @@ public interface InventoryView {
*/
public boolean setProperty(@NotNull Property prop, int value);
// Paper start
/**
* Get the title of this inventory window.
*
* @return The title.
*/
@NotNull
default net.kyori.adventure.text.Component title() {
return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(this.getTitle());
}
// Paper end
/**
* Get the title of this inventory window.
*
* @return The title.
* @deprecated in favour of {@link #title()}
*/
@Deprecated // Paper
@NotNull
public String getTitle();
/**

View File

@ -200,4 +200,24 @@ public interface ItemFactory {
*/
@NotNull
ItemStack enchantItem(@NotNull final ItemStack item, final int level, final boolean allowTreasures);
// Paper start - Adventure
/**
* Creates a hover event for the given item.
*
* @param item The item
* @return A hover event
*/
@NotNull
net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op);
/**
* Get the formatted display name of the {@link ItemStack}.
*
* @param itemStack the {@link ItemStack}
* @return display name of the {@link ItemStack}
*/
@NotNull
net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack);
// Paper end - Adventure
}

View File

@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable;
* use this class to encapsulate Materials for which {@link Material#isItem()}
* returns false.</b>
*/
public class ItemStack implements Cloneable, ConfigurationSerializable, Translatable {
public class ItemStack implements Cloneable, ConfigurationSerializable, Translatable, net.kyori.adventure.text.event.HoverEventSource<net.kyori.adventure.text.event.HoverEvent.ShowItem> { // Paper
private Material type = Material.AIR;
private int amount = 0;
private MaterialData data = null;
@ -626,4 +626,21 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
public String getTranslationKey() {
return Bukkit.getUnsafe().getTranslationKey(this);
}
// Paper start
@NotNull
@Override
public net.kyori.adventure.text.event.HoverEvent<net.kyori.adventure.text.event.HoverEvent.ShowItem> asHoverEvent(final @NotNull java.util.function.UnaryOperator<net.kyori.adventure.text.event.HoverEvent.ShowItem> op) {
return org.bukkit.Bukkit.getServer().getItemFactory().asHoverEvent(this, op);
}
/**
* Get the formatted display name of the {@link ItemStack}.
*
* @return display name of the {@link ItemStack}
*/
public net.kyori.adventure.text.@NotNull Component displayName() {
return Bukkit.getServer().getItemFactory().displayName(this);
}
// Paper end
}

View File

@ -145,11 +145,45 @@ public interface MenuType extends Keyed {
* @param player the player the view belongs to
* @param title the title of the view
* @return the created {@link InventoryView}
* @deprecated Use {@link #create(HumanEntity, net.kyori.adventure.text.Component)} instead.
*/
@NotNull
@Deprecated(since = "1.21") // Paper - adventure
V create(@NotNull HumanEntity player, @NotNull String title);
// Paper start - adventure
/**
* Creates a view of the specified menu type.
* <p>
* The player provided to create this view must be the player the view
* is opened for. See {@link HumanEntity#openInventory(InventoryView)}
* for more information.
*
* @param player the player the view belongs to
* @param title the title of the view
* @return the created {@link InventoryView}
*/
@NotNull
V create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title);
// Paper end - adventure
}
// Paper start - adventure
/**
* Creates a view of the specified menu type.
* <p>
* The player provided to create this view must be the player the view
* is opened for. See {@link HumanEntity#openInventory(InventoryView)}
* for more information.
*
* @param player the player the view belongs to
* @param title the title of the view
* @return the created {@link InventoryView}
*/
@NotNull
InventoryView create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title);
// Paper end - adventure
/**
* Yields this MenuType as a typed version of itself with a plain
* {@link InventoryView} representing it.

View File

@ -7,10 +7,15 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a {@link Material#WRITTEN_BOOK}) that can have a title, an author,
* Represents a {@link Material#WRITTEN_BOOK} that can have a title, an author,
* and pages.
* <p>
* Before using this type, make sure to check the itemstack's material with
* {@link org.bukkit.inventory.ItemStack#getType()}. {@code instanceof} on
* the meta instance is not sufficient due to unusual inheritance
* with relation to {@link WritableBookMeta}.
*/
public interface BookMeta extends WritableBookMeta {
public interface BookMeta extends WritableBookMeta, net.kyori.adventure.inventory.Book { // Paper - adventure
/**
* Represents the generation (or level of copying) of a written book
@ -116,6 +121,153 @@ public interface BookMeta extends WritableBookMeta {
@NotNull
BookMeta clone();
// Paper start - adventure
//<editor-fold desc="deprecations" defaultstate="collapsed">
/**
* @deprecated use {@link #page(int)}
*/
@Deprecated
@Override
@NotNull String getPage(int page);
/**
* @deprecated use {@link #page(int, net.kyori.adventure.text.Component)}
*/
@Deprecated
@Override
void setPage(int page, @NotNull String data);
/**
* @deprecated use {@link #pages()}
*/
@Deprecated
@Override
@NotNull List<String> getPages();
/**
* @deprecated use {@link #pages(List)}
*/
@Deprecated
@Override
void setPages(@NotNull List<String> pages);
/**
* @deprecated use {@link #pages(net.kyori.adventure.text.Component...)}
*/
@Deprecated
@Override
void setPages(@NotNull String... pages);
/**
* @deprecated use {@link #addPages(net.kyori.adventure.text.Component...)}
*/
@Deprecated
@Override
void addPage(@NotNull String... pages);
//</editor-fold>
/**
* Gets the title of the book.
* <p>
* Plugins should check that hasTitle() returns true before calling this
* method.
*
* @return the title of the book
*/
@Override
net.kyori.adventure.text.@Nullable Component title();
/**
* Sets the title of the book.
* <p>
* Limited to 32 characters. Removes title when given null.
*
* @param title the title to set
* @return the same {@link BookMeta} instance
*/
@org.jetbrains.annotations.Contract(value = "_ -> this", pure = false)
@Override
@NotNull BookMeta title(net.kyori.adventure.text.@Nullable Component title);
/**
* Gets the author of the book.
* <p>
* Plugins should check that hasAuthor() returns true before calling this
* method.
*
* @return the author of the book
*/
@Override
net.kyori.adventure.text.@Nullable Component author();
/**
* Sets the author of the book. Removes author when given null.
*
* @param author the author to set
* @return the same {@link BookMeta} instance
*/
@org.jetbrains.annotations.Contract(value = "_ -> this", pure = false)
@Override
@NotNull BookMeta author(net.kyori.adventure.text.@Nullable Component author);
/**
* Gets the specified page in the book. The page must exist.
* <p>
* Pages are 1-indexed.
*
* @param page the page number to get, in range [1, getPageCount()]
* @return the page from the book
*/
net.kyori.adventure.text.@NotNull Component page(int page);
/**
* Sets the specified page in the book. Pages of the book must be
* contiguous.
* <p>
* The data can be up to 1024 characters in length, additional characters
* are truncated.
* <p>
* Pages are 1-indexed.
*
* @param page the page number to set, in range [1, getPageCount()]
* @param data the data to set for that page
*/
void page(int page, net.kyori.adventure.text.@NotNull Component data);
/**
* Adds new pages to the end of the book. Up to a maximum of 100 pages with
* 1024 characters per page.
*
* @param pages A list of strings, each being a page
*/
void addPages(net.kyori.adventure.text.@NotNull Component @NotNull ... pages);
interface BookMetaBuilder extends net.kyori.adventure.inventory.Book.Builder {
@Override
@NotNull BookMetaBuilder title(net.kyori.adventure.text.@Nullable Component title);
@Override
@NotNull BookMetaBuilder author(net.kyori.adventure.text.@Nullable Component author);
@Override
@NotNull BookMetaBuilder addPage(net.kyori.adventure.text.@NotNull Component page);
@Override
@NotNull BookMetaBuilder pages(net.kyori.adventure.text.@NotNull Component @NotNull ... pages);
@Override
@NotNull BookMetaBuilder pages(java.util.@NotNull Collection<net.kyori.adventure.text.Component> pages);
@Override
@NotNull BookMeta build();
}
@Override
@NotNull BookMetaBuilder toBuilder();
// Paper end
// Spigot start
public class Spigot {
@ -124,8 +276,10 @@ public interface BookMeta extends WritableBookMeta {
*
* @param page the page number to get
* @return the page from the book
* @deprecated in favour of {@link #page(int)}
*/
@NotNull
@Deprecated // Paper
public BaseComponent[] getPage(int page) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -139,7 +293,9 @@ public interface BookMeta extends WritableBookMeta {
*
* @param page the page number to set
* @param data the data to set for that page
* @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setPage(int page, @Nullable BaseComponent... data) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -148,8 +304,10 @@ public interface BookMeta extends WritableBookMeta {
* Gets all the pages in the book.
*
* @return list of all the pages in the book
* @deprecated in favour of {@link #pages()}
*/
@NotNull
@Deprecated // Paper
public List<BaseComponent[]> getPages() {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -159,7 +317,9 @@ public interface BookMeta extends WritableBookMeta {
* pages. Maximum 50 pages with 256 characters per page.
*
* @param pages A list of pages to set the book to use
* @deprecated in favour of {@link #pages(java.util.List)}
*/
@Deprecated // Paper
public void setPages(@NotNull List<BaseComponent[]> pages) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -169,7 +329,9 @@ public interface BookMeta extends WritableBookMeta {
* pages. Maximum 50 pages with 256 characters per page.
*
* @param pages A list of component arrays, each being a page
* @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)}
*/
@Deprecated // Paper
public void setPages(@NotNull BaseComponent[]... pages) {
throw new UnsupportedOperationException("Not supported yet.");
}
@ -179,7 +341,9 @@ public interface BookMeta extends WritableBookMeta {
* with 256 characters per page.
*
* @param pages A list of component arrays, each being a page
* @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)}
*/
@Deprecated // Paper
public void addPage(@NotNull BaseComponent[]... pages) {
throw new UnsupportedOperationException("Not supported yet.");
}

View File

@ -38,12 +38,65 @@ import org.jetbrains.annotations.Nullable;
*/
public interface ItemMeta extends Cloneable, ConfigurationSerializable, PersistentDataHolder {
// Paper start
/**
* Checks for existence of a custom name.
*
* @return true if this has a custom name
*/
boolean hasCustomName();
/**
* Gets the custom name.
*
* <p>Plugins should check that {@link #hasCustomName()} returns {@code true} before calling this method.</p>
*
* @return the custom name
*/
net.kyori.adventure.text.@Nullable Component customName();
/**
* Sets the custom name.
*
* @param customName the custom name to set
*/
void customName(final net.kyori.adventure.text.@Nullable Component customName);
/**
* Checks for existence of a display name.
*
* @apiNote This method is obsolete, use {@link #hasCustomName()} instead.
* @return true if this has a display name
*/
boolean hasDisplayName();
@ApiStatus.Obsolete(since = "1.21.4")
default boolean hasDisplayName() {
return this.hasCustomName();
}
/**
* Gets the display name.
*
* <p>Plugins should check that {@link #hasDisplayName()} returns <code>true</code> before calling this method.</p>
*
* @apiNote This method is obsolete, use {@link #customName()} instead.
* @return the display name
*/
@ApiStatus.Obsolete(since = "1.21.4")
default net.kyori.adventure.text.@Nullable Component displayName() {
return this.customName();
}
/**
* Sets the display name.
*
* @param displayName the display name to set
* @apiNote This method is obsolete, use {@link #customName(Component)} instead.
*/
@ApiStatus.Obsolete(since = "1.21.4")
default void displayName(final net.kyori.adventure.text.@Nullable Component displayName) {
this.customName(displayName);
}
// Paper end
/**
* Gets the display name that is set.
@ -52,7 +105,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* before calling this method.
*
* @return the display name that is set
* @deprecated in favour of {@link #displayName()}
*/
@Deprecated // Paper
@NotNull
String getDisplayName();
@ -60,7 +115,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Sets the display name.
*
* @param name the name to set
* @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setDisplayName(@Nullable String name);
/**
@ -73,6 +130,32 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
*/
boolean hasItemName();
// Paper start
/**
* Gets the item name component that is set.
* <br>
* Item name differs from display name in that it is cannot be edited by an
* anvil, is not styled with italics, and does not show labels.
* <p>
* Plugins should check that {@link #hasItemName()} returns <code>true</code> before
* calling this method.
*
* @return the item name that is set
* @see #hasItemName()
*/
@org.jetbrains.annotations.NotNull
Component itemName();
/**
* Sets the item name.
* <br>
* Item name differs from display name in that it is cannot be edited by an
* anvil, is not styled with italics, and does not show labels.
*
* @param name the name to set, null to remove it
*/
void itemName(@Nullable final Component name);
// Paper end
/**
* Gets the item name that is set.
* <br>
@ -83,7 +166,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* calling this method.
*
* @return the item name that is set
* @deprecated in favour of {@link #itemName()}
*/
@Deprecated // Paper
@NotNull
String getItemName();
@ -94,7 +179,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* anvil, is not styled with italics, and does not show labels.
*
* @param name the name to set
* @deprecated in favour of {@link #itemName(Component)}
*/
@Deprecated // Paper
void setItemName(@Nullable String name);
/**
@ -135,6 +222,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
*/
boolean hasLore();
// Paper start
/**
* Gets the lore.
*
* <p>Plugins should check that {@link #hasLore()} returns <code>true</code> before calling this method.</p>
*
* @return the lore
*/
@Nullable List<net.kyori.adventure.text.Component> lore();
/**
* Sets the lore.
*
* @param lore the lore to set
*/
void lore(final @Nullable List<? extends net.kyori.adventure.text.Component> lore);
// Paper end
/**
* Gets the lore that is set.
* <p>
@ -142,7 +247,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* calling this method.
*
* @return a list of lore that is set
* @deprecated in favour of {@link #lore()}
*/
@Deprecated // Paper
@Nullable
List<String> getLore();
@ -151,7 +258,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste
* Removes lore when given null.
*
* @param lore the lore that will be set
* @deprecated in favour of {@link #lore(List)}
*/
@Deprecated // Paper
void setLore(@Nullable List<String> lore);
/**

View File

@ -149,27 +149,64 @@ public interface PotionMeta extends ItemMeta {
/**
* Checks for existence of a custom potion name translation suffix.
*
* @deprecated conflicting name, use {@link #hasCustomPotionName()}
* @return true if this has a custom potion name
*/
boolean hasCustomName();
@Deprecated(forRemoval = true, since = "1.21.4")
default boolean hasCustomName() {
return this.hasCustomPotionName();
}
/**
* Gets the potion name translation suffix that is set.
* <p>
* Plugins should check that hasCustomName() returns <code>true</code>
* Plugins should check that {@link #hasCustomPotionName()} returns {@code true}
* before calling this method.
*
* @deprecated conflicting name, use {@link #getCustomPotionName()}
* @return the potion name that is set
*/
@Deprecated(forRemoval = true, since = "1.21.4")
@Nullable
default String getCustomName() {
return this.getCustomPotionName();
}
/**
* Sets the potion name translation suffix.
*
* @deprecated conflicting name, use {@link #setCustomPotionName(String)}
* @param name the name to set
*/
@Deprecated(forRemoval = true, since = "1.21.4")
default void setCustomName(@Nullable String name) {
this.setCustomPotionName(name);
}
/**
* Checks for existence of a custom potion name translation suffix.
*
* @return true if this has a custom potion name
*/
boolean hasCustomPotionName();
/**
* Gets the potion name translation suffix that is set.
* <p>
* Plugins should check that {@link #hasCustomPotionName()} returns {@code true}
* before calling this method.
*
* @return the potion name that is set
*/
@Nullable
String getCustomName();
String getCustomPotionName();
/**
* Sets the potion name translation suffix.
*
* @param name the name to set
*/
void setCustomName(@Nullable String name);
void setCustomPotionName(@Nullable String name);
@Override
PotionMeta clone();

View File

@ -5,8 +5,14 @@ import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
/**
* Represents a book ({@link Material#WRITABLE_BOOK} or {@link
* Material#WRITTEN_BOOK}) that can have pages.
* Represents a book ({@link Material#WRITABLE_BOOK}) that can have pages.
* <p>
* For {@link Material#WRITTEN_BOOK}, use {@link BookMeta}.
* <p>
* Before using this type, make sure to check the itemstack's material with
* {@link org.bukkit.inventory.ItemStack#getType()}. {@code instanceof} on
* the meta instance is not sufficient due to unusual inheritance
* with relation to {@link BookMeta}.
*/
public interface WritableBookMeta extends ItemMeta {

View File

@ -61,4 +61,21 @@ public interface TrimMaterial extends Keyed, Translatable {
private static TrimMaterial getTrimMaterial(@NotNull String key) {
return Registry.TRIM_MATERIAL.getOrThrow(NamespacedKey.minecraft(key));
}
// Paper start - adventure
/**
* Get the description of this {@link TrimMaterial}.
*
* @return the description
*/
net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component description();
/**
* @deprecated this method assumes that {@link #description()} will
* always be a translatable component which is not guaranteed.
*/
@Override
@Deprecated(forRemoval = true)
@org.jetbrains.annotations.NotNull String getTranslationKey();
// Paper end - adventure
}

View File

@ -89,4 +89,21 @@ public interface TrimPattern extends Keyed, Translatable {
private static TrimPattern getTrimPattern(@NotNull String key) {
return Registry.TRIM_PATTERN.getOrThrow(NamespacedKey.minecraft(key));
}
// Paper start - adventure
/**
* Get the description of this {@link TrimPattern}.
*
* @return the description
*/
net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component description();
/**
* @deprecated this method assumes that {@link #description()} will
* always be a translatable component which is not guaranteed.
*/
@Override
@Deprecated(forRemoval = true)
@org.jetbrains.annotations.NotNull String getTranslationKey();
// Paper end - adventure
}

View File

@ -17,7 +17,7 @@ public final class MapCursor {
private byte x, y;
private byte direction;
private boolean visible;
private String caption;
private net.kyori.adventure.text.Component caption; // Paper
private Type type;
/**
@ -32,7 +32,7 @@ public final class MapCursor {
*/
@Deprecated(since = "1.6.2")
public MapCursor(byte x, byte y, byte direction, byte type, boolean visible) {
this(x, y, direction, type, visible, null);
this(x, y, direction, type, visible, (String) null); // Paper
}
/**
@ -45,7 +45,7 @@ public final class MapCursor {
* @param visible Whether the cursor is visible by default.
*/
public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible) {
this(x, y, direction, type, visible, null);
this(x, y, direction, type, visible, (String) null); // Paper
}
/**
@ -57,7 +57,7 @@ public final class MapCursor {
* @param type The type (color/style) of the map cursor.
* @param visible Whether the cursor is visible by default.
* @param caption cursor caption
* @deprecated Magic value, use {@link #MapCursor(byte, byte, byte, Type, boolean, String)}
* @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, Type, boolean, net.kyori.adventure.text.Component)}
*/
@Deprecated(since = "1.13")
public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) {
@ -66,8 +66,42 @@ public final class MapCursor {
setDirection(direction);
setRawType(type);
this.visible = visible;
this.caption = caption;
this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper
}
// Paper start
/**
* Initialize the map cursor.
*
* @param x The x coordinate, from -128 to 127.
* @param y The y coordinate, from -128 to 127.
* @param direction The facing of the cursor, from 0 to 15.
* @param type The type (color/style) of the map cursor.
* @param visible Whether the cursor is visible by default.
* @param caption cursor caption
* @deprecated Magic value
*/
@Deprecated
public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) {
this.x = x; this.y = y; this.visible = visible; this.caption = caption;
setDirection(direction);
setRawType(type);
}
/**
* Initialize the map cursor.
*
* @param x The x coordinate, from -128 to 127.
* @param y The y coordinate, from -128 to 127.
* @param direction The facing of the cursor, from 0 to 15.
* @param type The type (color/style) of the map cursor.
* @param visible Whether the cursor is visible by default.
* @param caption cursor caption
*/
public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) {
this.x = x; this.y = y; this.visible = visible; this.caption = caption;
setDirection(direction);
setType(type);
}
// Paper end
/**
* Initialize the map cursor.
@ -85,7 +119,7 @@ public final class MapCursor {
setDirection(direction);
this.type = type;
this.visible = visible;
this.caption = caption;
this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper
}
/**
@ -204,23 +238,45 @@ public final class MapCursor {
this.visible = visible;
}
// Paper start
/**
* Gets the caption on this cursor.
*
* @return caption
*/
public net.kyori.adventure.text.@Nullable Component caption() {
return this.caption;
}
/**
* Sets the caption on this cursor.
*
* @param caption new caption
*/
public void caption(net.kyori.adventure.text.@Nullable Component caption) {
this.caption = caption;
}
// Paper end
/**
* Gets the caption on this cursor.
*
* @return caption
* @deprecated in favour of {@link #caption()}
*/
@Nullable
@Deprecated // Paper
public String getCaption() {
return caption;
return this.caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.caption); // Paper
}
/**
* Sets the caption on this cursor.
*
* @param caption new caption
* @deprecated in favour of {@link #caption(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
public void setCaption(@Nullable String caption) {
this.caption = caption;
this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper
}
/**

View File

@ -117,4 +117,22 @@ public final class MapCursorCollection {
public MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable String caption) {
return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption));
}
// Paper start
/**
* Add a cursor to the collection.
*
* @param x The x coordinate, from -128 to 127.
* @param y The y coordinate, from -128 to 127.
* @param direction The facing of the cursor, from 0 to 15.
* @param type The type (color/style) of the map cursor.
* @param visible Whether the cursor is visible.
* @param caption banner caption
* @return The newly added MapCursor.
* @deprecated Magic value
*/
@Deprecated
public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) {
return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption));
}
// Paper end
}

View File

@ -126,4 +126,34 @@ public interface Permissible extends ServerOperator {
*/
@NotNull
public Set<PermissionAttachmentInfo> getEffectivePermissions();
// Paper start - add TriState permission checks
/**
* Checks if this object has a permission set and, if it is set, the value of the permission.
*
* @param permission the permission to check
* @return a tri-state of if the permission is set and, if it is set, it's value
*/
default net.kyori.adventure.util.@NotNull TriState permissionValue(final @NotNull Permission permission) {
if (this.isPermissionSet(permission)) {
return net.kyori.adventure.util.TriState.byBoolean(this.hasPermission(permission));
} else {
return net.kyori.adventure.util.TriState.NOT_SET;
}
}
/**
* Checks if this object has a permission set and, if it is set, the value of the permission.
*
* @param permission the permission to check
* @return a tri-state of if the permission is set and, if it is set, it's value
*/
default net.kyori.adventure.util.@NotNull TriState permissionValue(final @NotNull String permission) {
if (this.isPermissionSet(permission)) {
return net.kyori.adventure.util.TriState.byBoolean(this.hasPermission(permission));
} else {
return net.kyori.adventure.util.TriState.NOT_SET;
}
}
// Paper end
}

View File

@ -179,6 +179,13 @@ public interface Plugin extends TabExecutor {
@NotNull
public Logger getLogger();
// Paper start - Adventure component logger
@NotNull
default net.kyori.adventure.text.logger.slf4j.ComponentLogger getComponentLogger() {
return net.kyori.adventure.text.logger.slf4j.ComponentLogger.logger(getLogger().getName());
}
// Paper end
/**
* Returns the name of the plugin.
* <p>

View File

@ -20,13 +20,35 @@ public interface Objective {
@NotNull
String getName();
// Paper start - Adventure
/**
* Gets the display name for this objective
*
* @return this objective's display name
* @throws IllegalStateException if this objective has been unregistered
*/
net.kyori.adventure.text.@NotNull Component displayName();
/**
* Sets the name displayed to players for this objective.
*
* @param displayName Display name to set
* @throws IllegalStateException if this objective has been unregistered
* @throws IllegalArgumentException if displayName is null
* @throws IllegalArgumentException if displayName is longer than 128
* characters.
*/
void displayName(net.kyori.adventure.text.@Nullable Component displayName);
// Paper end - Adventure
/**
* Gets the name displayed to players for this objective
*
* @return this objective's display name
* @throws IllegalStateException if this objective has been unregistered
* @deprecated in favour of {@link #displayName()}
*/
@NotNull
@Deprecated // Paper
String getDisplayName();
/**
@ -34,7 +56,9 @@ public interface Objective {
*
* @param displayName Display name to set
* @throws IllegalStateException if this objective has been unregistered
* @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setDisplayName(@NotNull String displayName);
/**

View File

@ -26,6 +26,40 @@ public interface Scoreboard {
@NotNull
Objective registerNewObjective(@NotNull String name, @NotNull String criteria);
// Paper start - Adventure
/**
* Registers an Objective on this Scoreboard
*
* @param name Name of the Objective
* @param criteria Criteria for the Objective
* @param displayName display name for the Objective.
* @return The registered Objective
* @throws IllegalArgumentException if name is longer than 32767
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)}
*/
@NotNull
@Deprecated
Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName);
/**
* Registers an Objective on this Scoreboard
*
* @param name Name of the Objective
* @param criteria Criteria for the Objective
* @param displayName Name displayed to players for the Objective.
* @param renderType Manner of rendering the Objective
* @return The registered Objective
* @throws IllegalArgumentException if name is longer than 32767
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)}
*/
@NotNull
@Deprecated
Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException;
/**
* Registers an Objective on this Scoreboard
*
@ -37,7 +71,38 @@ public interface Scoreboard {
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated use {@link #registerNewObjective(String, Criteria, String)}
*/
@NotNull
Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName) throws IllegalArgumentException;
/**
* Registers an Objective on this Scoreboard
*
* @param name Name of the Objective
* @param criteria Criteria for the Objective
* @param displayName Name displayed to players for the Objective.
* @param renderType Manner of rendering the Objective
* @return The registered Objective
* @throws IllegalArgumentException if name is longer than 32767
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
*/
@NotNull
Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException;
// Paper end - Adventure
/**
* Registers an Objective on this Scoreboard
*
* @param name Name of the Objective
* @param criteria Criteria for the Objective
* @param displayName Name displayed to players for the Objective.
* @return The registered Objective
* @throws IllegalArgumentException if name is longer than 32767
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)}
*/
@Deprecated(since = "1.20.5")
@NotNull
@ -55,7 +120,7 @@ public interface Scoreboard {
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated use {@link #registerNewObjective(String, Criteria, String, RenderType)}
* @deprecated use {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)}
*/
@Deprecated(since = "1.20.5")
@NotNull
@ -72,8 +137,10 @@ public interface Scoreboard {
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated in favour of {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component)}
*/
@NotNull
@Deprecated // Paper
Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName);
/**
@ -88,8 +155,10 @@ public interface Scoreboard {
* characters.
* @throws IllegalArgumentException if an objective by that name already
* exists
* @deprecated in favour of {@link #registerNewObjective(String, Criteria, net.kyori.adventure.text.Component, RenderType)}
*/
@NotNull
@Deprecated // Paper
Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @NotNull String displayName, @NotNull RenderType renderType);
/**

View File

@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable;
* properties. This team is only relevant to the display of the associated
* {@link #getScoreboard() scoreboard}.
*/
public interface Team {
public interface Team extends net.kyori.adventure.audience.ForwardingAudience { // Paper - Make Team extend ForwardingAudience
/**
* Gets the name of this Team
@ -23,14 +23,14 @@ public interface Team {
@NotNull
String getName();
// Paper start - Adventure
/**
* Gets the name displayed to entries for this team
* Gets the display name for this team
*
* @return Team display name
* @throws IllegalStateException if this team has been unregistered
*/
@NotNull
String getDisplayName();
net.kyori.adventure.text.@NotNull Component displayName();
/**
* Sets the name displayed to entries for this team
@ -38,7 +38,7 @@ public interface Team {
* @param displayName New display name
* @throws IllegalStateException if this team has been unregistered
*/
void setDisplayName(@NotNull String displayName);
void displayName(net.kyori.adventure.text.@Nullable Component displayName);
/**
* Gets the prefix prepended to the display of entries on this team.
@ -46,8 +46,7 @@ public interface Team {
* @return Team prefix
* @throws IllegalStateException if this team has been unregistered
*/
@NotNull
String getPrefix();
net.kyori.adventure.text.@NotNull Component prefix();
/**
* Sets the prefix prepended to the display of entries on this team.
@ -55,7 +54,7 @@ public interface Team {
* @param prefix New prefix
* @throws IllegalStateException if this team has been unregistered
*/
void setPrefix(@NotNull String prefix);
void prefix(net.kyori.adventure.text.@Nullable Component prefix);
/**
* Gets the suffix appended to the display of entries on this team.
@ -63,8 +62,7 @@ public interface Team {
* @return the team's current suffix
* @throws IllegalStateException if this team has been unregistered
*/
@NotNull
String getSuffix();
net.kyori.adventure.text.@NotNull Component suffix();
/**
* Sets the suffix appended to the display of entries on this team.
@ -72,6 +70,101 @@ public interface Team {
* @param suffix the new suffix for this team.
* @throws IllegalStateException if this team has been unregistered
*/
void suffix(net.kyori.adventure.text.@Nullable Component suffix);
/**
* Checks if the team has a color specified
*
* @return true if it has a <b>color</b>
* @throws IllegalStateException if this team has been unregistered
*/
boolean hasColor();
/**
* Gets the color of the team.
* <br>
* This only sets the team outline, other occurrences of colors such as in
* names are handled by prefixes / suffixes.
*
* @return team color
* @throws IllegalStateException if this team has been unregistered
* @throws IllegalStateException if the team doesn't have a color
* @see #hasColor()
*/
net.kyori.adventure.text.format.@NotNull TextColor color();
/**
* Sets the color of the team.
* <br>
* This only sets the team outline, other occurrences of colors such as in
* names are handled by prefixes / suffixes.
*
* @param color new color, null for no color
*/
void color(net.kyori.adventure.text.format.@Nullable NamedTextColor color);
// Paper end - Adventure
/**
* Gets the name displayed to entries for this team
*
* @return Team display name
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #displayName()}
*/
@NotNull
@Deprecated // Paper
String getDisplayName();
/**
* Sets the name displayed to entries for this team
*
* @param displayName New display name
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #displayName(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setDisplayName(@NotNull String displayName);
/**
* Gets the prefix prepended to the display of entries on this team.
*
* @return Team prefix
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #prefix()}
*/
@NotNull
@Deprecated // Paper
String getPrefix();
/**
* Sets the prefix prepended to the display of entries on this team.
*
* @param prefix New prefix
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #prefix(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setPrefix(@NotNull String prefix);
/**
* Gets the suffix appended to the display of entries on this team.
*
* @return the team's current suffix
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #suffix()}
*/
@NotNull
@Deprecated // Paper
String getSuffix();
/**
* Sets the suffix appended to the display of entries on this team.
*
* @param suffix the new suffix for this team.
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #suffix(net.kyori.adventure.text.Component)}
*/
@Deprecated // Paper
void setSuffix(@NotNull String suffix);
/**
@ -82,8 +175,10 @@ public interface Team {
*
* @return team color, defaults to {@link ChatColor#RESET}
* @throws IllegalStateException if this team has been unregistered
* @deprecated in favour of {@link #color()}
*/
@NotNull
@Deprecated // Paper
ChatColor getColor();
/**
@ -94,7 +189,9 @@ public interface Team {
*
* @param color new color, must be non-null. Use {@link ChatColor#RESET} for
* no color
* @deprecated in favour of {@link #color(net.kyori.adventure.text.format.NamedTextColor)}
*/
@Deprecated // Paper
void setColor(@NotNull ChatColor color);
/**

View File

@ -0,0 +1,31 @@
package io.papermc.paper.adventure;
import java.util.HashSet;
import java.util.Set;
import net.kyori.adventure.key.Key;
import org.bukkit.NamespacedKey;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class KeyTest {
@Test
public void equalsTest() {
Key key = new NamespacedKey("test", "key");
Key key1 = Key.key("test", "key");
assertEquals(key, key1);
assertEquals(key1, key);
}
@Test
public void setTest() {
Key key = new NamespacedKey("test", "key");
Key key1 = Key.key("test", "key");
Set<Key> set = new HashSet<>(Set.of(key));
Set<Key> set1 = new HashSet<>(Set.of(key1));
assertTrue(set.contains(key1));
assertTrue(set1.contains(key));
}
}