Add various missing jd, bump remaining deps (#1718)

This commit is contained in:
R00tB33rMan
2026-01-29 08:31:50 -05:00
committed by GitHub
parent 5320aae5d9
commit 7d0c002f89
185 changed files with 2990 additions and 502 deletions

View File

@@ -24,7 +24,7 @@ dependencies {
api(libs.guava) api(libs.guava)
// DEPRECATED: Will be removed in Velocity Polymer // DEPRECATED: Will be removed in Velocity Polymer
api("com.moandjiezana.toml:toml4j:0.7.2") api("io.hotmoka:toml4j:0.7.3")
api(platform(libs.adventure.bom)) api(platform(libs.adventure.bom))
api("net.kyori:adventure-api") api("net.kyori:adventure-api")
@@ -55,8 +55,6 @@ tasks {
} }
} }
withType<Javadoc> { withType<Javadoc> {
exclude("com/velocitypowered/api/plugin/ap/**")
val o = options as StandardJavadocDocletOptions val o = options as StandardJavadocDocletOptions
o.encoding = "UTF-8" o.encoding = "UTF-8"
o.source = "21" o.source = "21"
@@ -66,7 +64,7 @@ tasks {
"https://www.javadocs.dev/org.slf4j/slf4j-api/${libs.slf4j.get().version}/", "https://www.javadocs.dev/org.slf4j/slf4j-api/${libs.slf4j.get().version}/",
"https://guava.dev/releases/${libs.guava.get().version}/api/docs/", "https://guava.dev/releases/${libs.guava.get().version}/api/docs/",
"https://google.github.io/guice/api-docs/${libs.guice.get().version}/javadoc/", "https://google.github.io/guice/api-docs/${libs.guice.get().version}/javadoc/",
"https://docs.oracle.com/en/java/javase/17/docs/api/", "https://docs.oracle.com/en/java/javase/21/docs/api/",
"https://jd.advntr.dev/api/${libs.adventure.bom.get().version}/", "https://jd.advntr.dev/api/${libs.adventure.bom.get().version}/",
"https://jd.advntr.dev/text-minimessage/${libs.adventure.bom.get().version}/", "https://jd.advntr.dev/text-minimessage/${libs.adventure.bom.get().version}/",
"https://jd.advntr.dev/key/${libs.adventure.bom.get().version}/", "https://jd.advntr.dev/key/${libs.adventure.bom.get().version}/",
@@ -79,8 +77,5 @@ tasks {
"implNote:a:Implementation Note:", "implNote:a:Implementation Note:",
"sinceMinecraft:a:Since Minecraft:" "sinceMinecraft:a:Since Minecraft:"
) )
// Disable the crazy super-strict doclint tool in Java 8
o.addStringOption("Xdoclint:none", "-quiet")
} }
} }

View File

@@ -36,6 +36,15 @@ import javax.tools.StandardLocation;
@SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"}) @SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"})
public class PluginAnnotationProcessor extends AbstractProcessor { public class PluginAnnotationProcessor extends AbstractProcessor {
/**
* Creates a new {@code PluginAnnotationProcessor}.
*
* <p>The processor is instantiated by the Java compiler and initialized via
* {@link #init(ProcessingEnvironment)}.</p>
*/
public PluginAnnotationProcessor() {
}
private ProcessingEnvironment environment; private ProcessingEnvironment environment;
private String pluginClassFound; private String pluginClassFound;
private boolean warnedAboutMultiplePlugins; private boolean warnedAboutMultiplePlugins;

View File

@@ -24,7 +24,19 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/ */
public final class SerializedPluginDescription { public final class SerializedPluginDescription {
/**
* The string pattern used to validate plugin IDs.
*
* <p>Plugin IDs must start with a lowercase letter and may contain lowercase letters,
* digits, hyphens, and underscores. The total length must not exceed 64 characters.</p>
*/
public static final String ID_PATTERN_STRING = "[a-z][a-z0-9-_]{0,63}"; public static final String ID_PATTERN_STRING = "[a-z][a-z0-9-_]{0,63}";
/**
* The compiled pattern used to validate plugin IDs.
*
* <p>Plugin IDs must start with a lowercase letter and may contain lowercase letters,
* digits, hyphens, and underscores. The total length must not exceed 64 characters.</p>
*/
public static final Pattern ID_PATTERN = Pattern.compile(ID_PATTERN_STRING); public static final Pattern ID_PATTERN = Pattern.compile(ID_PATTERN_STRING);
// @Nullable is used here to make GSON skip these in the serialized file // @Nullable is used here to make GSON skip these in the serialized file
@@ -64,34 +76,78 @@ public final class SerializedPluginDescription {
.collect(Collectors.toList()), dependencies, qualifiedName); .collect(Collectors.toList()), dependencies, qualifiedName);
} }
/**
* Gets the ID of the plugin this dependency refers to.
*
* @return the plugin ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* Gets the human-readable name of the plugin.
*
* @return the plugin's name, or {@code null} if not specified
*/
public @Nullable String getName() { public @Nullable String getName() {
return name; return name;
} }
/**
* Gets the version string of the plugin.
*
* @return the plugin version, or {@code null} if not specified
*/
public @Nullable String getVersion() { public @Nullable String getVersion() {
return version; return version;
} }
/**
* Gets the plugin's description, typically a short summary of its functionality.
*
* @return the description, or {@code null} if not specified
*/
public @Nullable String getDescription() { public @Nullable String getDescription() {
return description; return description;
} }
/**
* Gets the website URL for the plugin.
*
* <p>This is often used to link to documentation, support, or the plugin's homepage.</p>
*
* @return the plugin URL, or {@code null} if not specified
*/
public @Nullable String getUrl() { public @Nullable String getUrl() {
return url; return url;
} }
/**
* Gets the list of authors who contributed to the plugin.
*
* @return an immutable list of authors; empty if none were specified
*/
public List<String> getAuthors() { public List<String> getAuthors() {
return authors == null ? ImmutableList.of() : authors; return authors == null ? ImmutableList.of() : authors;
} }
/**
* Gets the list of declared dependencies for the plugin.
*
* <p>Dependencies may be required or optional and describe other plugins, this one depends.</p>
*
* @return an immutable list of plugin dependencies
*/
public List<Dependency> getDependencies() { public List<Dependency> getDependencies() {
return dependencies == null ? ImmutableList.of() : dependencies; return dependencies == null ? ImmutableList.of() : dependencies;
} }
/**
* Gets the fully qualified name of the plugin's main class.
*
* @return the main class name
*/
public String getMain() { public String getMain() {
return main; return main;
} }
@@ -142,15 +198,33 @@ public final class SerializedPluginDescription {
private final String id; private final String id;
private final boolean optional; private final boolean optional;
/**
* Constructs a new dependency class.
*
* @param id the ID of the dependent plugin
* @param optional whether the dependency is optional
*/
public Dependency(String id, boolean optional) { public Dependency(String id, boolean optional) {
this.id = id; this.id = id;
this.optional = optional; this.optional = optional;
} }
/**
* Gets the ID of the plugin this dependency refers to.
*
* @return the plugin ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* Indicates whether this dependency is optional.
*
* <p>Optional dependencies are not required for the plugin to load.</p>
*
* @return {@code true} if the dependency is optional; {@code false} otherwise
*/
public boolean isOptional() { public boolean isOptional() {
return optional; return optional;
} }

View File

@@ -25,20 +25,20 @@ public interface CommandSource extends Audience, PermissionSubject {
* @param message MiniMessage content * @param message MiniMessage content
* @see <a href="https://docs.advntr.dev/minimessage/format.html">MiniMessage docs</a> * @see <a href="https://docs.advntr.dev/minimessage/format.html">MiniMessage docs</a>
* for more information on the format. * for more information on the format.
**/ */
default void sendRichMessage(final @NotNull String message) { default void sendRichMessage(final @NotNull String message) {
this.sendMessage(MiniMessage.miniMessage().deserialize(message, this)); this.sendMessage(MiniMessage.miniMessage().deserialize(message, this));
} }
/** /**
* Sends a message with the MiniMessage format to this source. * Sends a message with the MiniMessage format to this source.
* *
* @param message MiniMessage content * @param message MiniMessage content
* @param resolvers resolvers to use * @param resolvers resolvers to use
* @see <a href="https://docs.advntr.dev/minimessage/">MiniMessage docs</a> * @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> * and <a href="https://docs.advntr.dev/minimessage/dynamic-replacements">MiniMessage Placeholders docs</a>
* for more information on the format. * for more information on the format.
**/ */
default void sendRichMessage( default void sendRichMessage(
final @NotNull String message, final @NotNull String message,
final @NotNull TagResolver @NotNull... resolvers final @NotNull TagResolver @NotNull... resolvers
@@ -47,13 +47,13 @@ public interface CommandSource extends Audience, PermissionSubject {
} }
/** /**
* Sends a plain message to this source. * Sends a plain message to this source.
* *
* @param message plain message * @param message plain message
* @apiNote This method will not apply any form of parse to the text provided, * @apiNote This method will not apply any form of parse to the text provided,
* however, it is recommended not to use legacy color codes as this is a deprecated format * however, it is recommended not to use legacy color codes as this is a deprecated format
* and not recommended. * and not recommended.
*/ */
default void sendPlainMessage(final @NotNull String message) { default void sendPlainMessage(final @NotNull String message) {
this.sendMessage(Component.text(message)); this.sendMessage(Component.text(message));
} }

View File

@@ -20,6 +20,12 @@ import org.jetbrains.annotations.NotNull;
*/ */
public final class VelocityBrigadierMessage implements Message, ComponentLike { public final class VelocityBrigadierMessage implements Message, ComponentLike {
/**
* Creates a new {@link VelocityBrigadierMessage} using the given {@link Component} as the message.
*
* @param message the component to use as the tooltip message
* @return a new instance of {@link VelocityBrigadierMessage}
*/
public static VelocityBrigadierMessage tooltip(Component message) { public static VelocityBrigadierMessage tooltip(Component message) {
return new VelocityBrigadierMessage(message); return new VelocityBrigadierMessage(message);
} }

View File

@@ -20,6 +20,8 @@ public interface Continuation {
/** /**
* Resumes the continuation after the executed task failed. * Resumes the continuation after the executed task failed.
*
* @param exception the {@link Throwable} that caused the failure
*/ */
void resumeWithException(Throwable exception); void resumeWithException(Throwable exception);
} }

View File

@@ -13,12 +13,28 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* Represents an interface to perform direct dispatch of an event. This makes integration easier to * Represents an interface to perform direct dispatch of an event. This makes integration easier to
* achieve with platforms such as RxJava. While this interface can be used to implement an awaiting * achieve with platforms such as RxJava. While this interface can be used to implement an awaiting
* event handler, {@link AwaitingEventExecutor} provides a more idiomatic means to doing so. * event handler, {@link AwaitingEventExecutor} provides a more idiomatic means to doing so.
*
* @param <E> the event type this handler accepts
*/ */
@FunctionalInterface @FunctionalInterface
public interface EventHandler<E> { public interface EventHandler<E> {
/**
* Executes this handler synchronously with the given event.
*
* @param event the event to handle
*/
void execute(E event); void execute(E event);
/**
* Executes this handler asynchronously with the given event.
*
* <p>If asynchronous handling is not implemented, the event is executed synchronously
* and this method returns {@code null}.</p>
*
* @param event the event to handle
* @return an {@link EventTask} representing the async task, or {@code null} if not async
*/
default @Nullable EventTask executeAsync(E event) { default @Nullable EventTask executeAsync(E event) {
execute(event); execute(event);
return null; return null;

View File

@@ -73,6 +73,7 @@ public interface EventManager {
* servicing connections while a plugin handles a potentially long-running operation such as a * servicing connections while a plugin handles a potentially long-running operation such as a
* database query. * database query.
* *
* @param <E> the event type
* @param event the event to fire * @param event the event to fire
* @return a {@link CompletableFuture} representing the posted event * @return a {@link CompletableFuture} representing the posted event
*/ */

View File

@@ -12,7 +12,34 @@ package com.velocitypowered.api.event;
*/ */
public enum PostOrder { public enum PostOrder {
FIRST, EARLY, NORMAL, LATE, LAST, /**
* Indicates the listener should be invoked first, before any other listener.
* This order is suitable for listeners that must handle the event before others.
*/
FIRST,
/**
* Indicates the listener should be invoked early, but after listeners with {@link #FIRST}.
* This order is suitable for handling the event before most other listeners.
*/
EARLY,
/**
* Indicates the listener should be invoked in the normal order of execution.
* This is the default and most commonly used order.
*/
NORMAL,
/**
* Indicates the listener should be invoked later in the execution order,
* after listeners with {@link #NORMAL}.
* This order is suitable for listeners that should observe the results of
* earlier listeners.
*/
LATE,
/**
* Indicates the listener should be invoked last, after all other listeners.
* This order is suitable for listeners that should run only after all others
* have completed handling the event.
*/
LAST,
/** /**
* Previously used to specify that {@link Subscribe#priority()} should be used. * Previously used to specify that {@link Subscribe#priority()} should be used.

View File

@@ -15,6 +15,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Indicates an event that has a result attached to it. * Indicates an event that has a result attached to it.
*
* @param <R> the type of result associated with the event
*/ */
public interface ResultedEvent<R extends ResultedEvent.Result> { public interface ResultedEvent<R extends ResultedEvent.Result> {
@@ -70,10 +72,20 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
return status ? "allowed" : "denied"; return status ? "allowed" : "denied";
} }
/**
* Returns a result indicating the event is allowed to proceed.
*
* @return an allowed {@link GenericResult}
*/
public static GenericResult allowed() { public static GenericResult allowed() {
return ALLOWED; return ALLOWED;
} }
/**
* Returns a result indicating the event is denied.
*
* @return a denied {@link GenericResult}
*/
public static GenericResult denied() { public static GenericResult denied() {
return DENIED; return DENIED;
} }
@@ -89,6 +101,12 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
private final boolean status; private final boolean status;
private final @Nullable Component reason; private final @Nullable Component reason;
/**
* Represents an allowed or denied result that may include a denial reason.
*
* @param status whether the result is allowed
* @param reason the component explaining why the result was denied, or {@code null}
*/
protected ComponentResult(boolean status, @Nullable Component reason) { protected ComponentResult(boolean status, @Nullable Component reason) {
this.status = status; this.status = status;
this.reason = reason; this.reason = reason;
@@ -99,6 +117,11 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
return status; return status;
} }
/**
* Returns the denial reason component, if present.
*
* @return an {@link Optional} containing the reason component if the result is denied
*/
public Optional<Component> getReasonComponent() { public Optional<Component> getReasonComponent() {
return Optional.ofNullable(reason); return Optional.ofNullable(reason);
} }
@@ -114,10 +137,22 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
return "denied"; return "denied";
} }
/**
* Returns a result indicating the event is allowed to proceed.
*
* @return an allowed {@link ComponentResult}
*/
public static ComponentResult allowed() { public static ComponentResult allowed() {
return ALLOWED; return ALLOWED;
} }
/**
* Returns a result indicating the event is denied, with the given reason component.
*
* @param reason the denial reason to show
* @return a denied {@link ComponentResult}
* @throws NullPointerException if the reason is null
*/
public static ComponentResult denied(Component reason) { public static ComponentResult denied(Component reason) {
Preconditions.checkNotNull(reason, "reason"); Preconditions.checkNotNull(reason, "reason");
return new ComponentResult(false, reason); return new ComponentResult(false, reason);

View File

@@ -106,6 +106,8 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/** /**
* Represents information about a command invocation, including its signed state and source. * Represents information about a command invocation, including its signed state and source.
* *
* @param signedState the signed state of the command
* @param source the source of the command invocation
* @since 3.4.0 * @since 3.4.0
*/ */
public record InvocationInfo(SignedState signedState, Source source) { public record InvocationInfo(SignedState signedState, Source source) {
@@ -191,10 +193,22 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
this.command = command; this.command = command;
} }
/**
* Returns the command to be executed, if it was overridden.
*
* @return an {@link Optional} containing the new command string (without leading slash),
* or empty if no override is present
*/
public Optional<String> getCommand() { public Optional<String> getCommand() {
return Optional.ofNullable(command); return Optional.ofNullable(command);
} }
/**
* Indicates whether this command should be forwarded directly to the backend server
* instead of being processed by the proxy.
*
* @return {@code true} if the command should be forwarded to the server, {@code false} otherwise
*/
public boolean isForwardToServer() { public boolean isForwardToServer() {
return forward; return forward;
} }

View File

@@ -37,10 +37,20 @@ public class PlayerAvailableCommandsEvent {
this.rootNode = checkNotNull(rootNode, "rootNode"); this.rootNode = checkNotNull(rootNode, "rootNode");
} }
/**
* Gets the player that the available commands are being sent to.
*
* @return the targeted player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Gets the root command node that represents the available commands.
*
* @return the Brigadier root command node
*/
public RootCommandNode<?> getRootNode() { public RootCommandNode<?> getRootNode() {
return rootNode; return rootNode;
} }

View File

@@ -21,6 +21,12 @@ public final class ConnectionHandshakeEvent {
private final InboundConnection connection; private final InboundConnection connection;
private final HandshakeIntent intent; private final HandshakeIntent intent;
/**
* Constructs a new {@link ConnectionHandshakeEvent}.
*
* @param connection the inbound connection from the client
* @param intent the intent of the handshake (e.g., login or status)
*/
public ConnectionHandshakeEvent(InboundConnection connection, HandshakeIntent intent) { public ConnectionHandshakeEvent(InboundConnection connection, HandshakeIntent intent) {
this.connection = Preconditions.checkNotNull(connection, "connection"); this.connection = Preconditions.checkNotNull(connection, "connection");
this.intent = Preconditions.checkNotNull(intent, "intent"); this.intent = Preconditions.checkNotNull(intent, "intent");
@@ -39,10 +45,20 @@ public final class ConnectionHandshakeEvent {
this.intent = HandshakeIntent.LOGIN; this.intent = HandshakeIntent.LOGIN;
} }
/**
* Returns the inbound connection associated with this handshake.
*
* @return the connection
*/
public InboundConnection getConnection() { public InboundConnection getConnection() {
return connection; return connection;
} }
/**
* Returns the {@link HandshakeIntent} associated with this connection handshake.
*
* @return the intent of the handshake
*/
public HandshakeIntent getIntent() { public HandshakeIntent getIntent() {
return this.intent; return this.intent;
} }

View File

@@ -17,12 +17,10 @@ import com.velocitypowered.api.proxy.Player;
* Operations on the provided player, aside from basic data retrieval operations, may behave in * Operations on the provided player, aside from basic data retrieval operations, may behave in
* undefined ways. * undefined ways.
* *
* <p> * <p>Velocity typically fires this event asynchronously and does not wait for a response. However,
* Velocity typically fires this event asynchronously and does not wait for a response. However, * it will wait for all {@link DisconnectEvent}s for every player on the proxy to fire
* it will wait for all {@link DisconnectEvent}s for every player on the proxy to fire * successfully before the proxy shuts down. This event is the sole exception to the
* successfully before the proxy shuts down. This event is the sole exception to the * {@link AwaitingEvent} contract.</p>
* {@link AwaitingEvent} contract.
* </p>
*/ */
@AwaitingEvent @AwaitingEvent
public final class DisconnectEvent { public final class DisconnectEvent {
@@ -30,15 +28,31 @@ public final class DisconnectEvent {
private final Player player; private final Player player;
private final LoginStatus loginStatus; private final LoginStatus loginStatus;
/**
* Creates a new {@link DisconnectEvent}.
*
* @param player the player who disconnected
* @param loginStatus the status of the player's login at the time of disconnection
*/
public DisconnectEvent(Player player, LoginStatus loginStatus) { public DisconnectEvent(Player player, LoginStatus loginStatus) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
this.loginStatus = Preconditions.checkNotNull(loginStatus, "loginStatus"); this.loginStatus = Preconditions.checkNotNull(loginStatus, "loginStatus");
} }
/**
* Returns the player who disconnected.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the login status of the player at the time of disconnection.
*
* @return the login status
*/
public LoginStatus getLoginStatus() { public LoginStatus getLoginStatus() {
return loginStatus; return loginStatus;
} }
@@ -56,11 +70,29 @@ public final class DisconnectEvent {
*/ */
public enum LoginStatus { public enum LoginStatus {
/**
* The player completed a successful login to the proxy.
*/
SUCCESSFUL_LOGIN, SUCCESSFUL_LOGIN,
/**
* The player was disconnected because another login with the same UUID occurred.
*/
CONFLICTING_LOGIN, CONFLICTING_LOGIN,
/**
* The player voluntarily disconnected before completing the login.
*/
CANCELLED_BY_USER, CANCELLED_BY_USER,
/**
* The proxy disconnected the player before login completed.
*/
CANCELLED_BY_PROXY, CANCELLED_BY_PROXY,
/**
* The player disconnected on their own, but only after starting the login and before completing it.
*/
CANCELLED_BY_USER_BEFORE_COMPLETE, CANCELLED_BY_USER_BEFORE_COMPLETE,
/**
* The player disconnected before joining the initial backend server.
*/
PRE_SERVER_JOIN PRE_SERVER_JOIN
} }
} }

View File

@@ -24,11 +24,21 @@ public final class LoginEvent implements ResultedEvent<ResultedEvent.ComponentRe
private final Player player; private final Player player;
private ComponentResult result; private ComponentResult result;
/**
* Constructs a new {@link LoginEvent}.
*
* @param player the player who has completed authentication
*/
public LoginEvent(Player player) { public LoginEvent(Player player) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
this.result = ComponentResult.allowed(); this.result = ComponentResult.allowed();
} }
/**
* Returns the player who has completed authentication.
*
* @return the authenticated player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }

View File

@@ -61,26 +61,56 @@ public final class PluginMessageEvent implements ResultedEvent<PluginMessageEven
this.result = Preconditions.checkNotNull(result, "result"); this.result = Preconditions.checkNotNull(result, "result");
} }
/**
* Gets the source that sent this plugin message (a {@link Player} or {@link ServerConnection}).
*
* @return the message source
*/
public ChannelMessageSource getSource() { public ChannelMessageSource getSource() {
return source; return source;
} }
/**
* Gets the target recipient of this plugin message.
*
* @return the message sink
*/
public ChannelMessageSink getTarget() { public ChannelMessageSink getTarget() {
return target; return target;
} }
/**
* Gets the channel identifier this message was sent on.
*
* @return the plugin message identifier
*/
public ChannelIdentifier getIdentifier() { public ChannelIdentifier getIdentifier() {
return identifier; return identifier;
} }
/**
* Gets the raw payload of the plugin message.
*
* @return a copy of the message data
*/
public byte[] getData() { public byte[] getData() {
return Arrays.copyOf(data, data.length); return Arrays.copyOf(data, data.length);
} }
/**
* Returns the plugin message payload as a {@link ByteArrayInputStream}.
*
* @return the input stream wrapping the data
*/
public ByteArrayInputStream dataAsInputStream() { public ByteArrayInputStream dataAsInputStream() {
return new ByteArrayInputStream(data); return new ByteArrayInputStream(data);
} }
/**
* Returns the plugin message payload as a {@link ByteArrayDataInput}.
*
* @return the data input stream for reading structured data
*/
public ByteArrayDataInput dataAsDataStream() { public ByteArrayDataInput dataAsDataStream() {
return ByteStreams.newDataInput(data); return ByteStreams.newDataInput(data);
} }
@@ -120,10 +150,21 @@ public final class PluginMessageEvent implements ResultedEvent<PluginMessageEven
return status ? "forward to sink" : "handled message at proxy"; return status ? "forward to sink" : "handled message at proxy";
} }
/**
* Returns a result that forwards the plugin message to the target.
*
* @return the forward result
*/
public static ForwardResult forward() { public static ForwardResult forward() {
return ALLOWED; return ALLOWED;
} }
/**
* Returns a result that marks the plugin message as handled at the proxy.
* This prevents it from being forwarded.
*
* @return the handled result
*/
public static ForwardResult handled() { public static ForwardResult handled() {
return DENIED; return DENIED;
} }

View File

@@ -23,10 +23,20 @@ public final class PostLoginEvent {
private final Player player; private final Player player;
/**
* Constructs a new PostLoginEvent.
*
* @param player the player who has logged in
*/
public PostLoginEvent(Player player) { public PostLoginEvent(Player player) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
} }
/**
* Gets the player who has logged in and is about to connect to their first server.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }

View File

@@ -63,16 +63,27 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
this.result = PreLoginComponentResult.allowed(); this.result = PreLoginComponentResult.allowed();
} }
/**
* Gets the inbound connection associated with this login attempt.
*
* @return the inbound connection
*/
public InboundConnection getConnection() { public InboundConnection getConnection() {
return connection; return connection;
} }
/**
* Gets the username of the player attempting to connect.
*
* @return the player's username
*/
public String getUsername() { public String getUsername() {
return username; return username;
} }
/** /**
* Returns the UUID of the connecting player. * Returns the UUID of the connecting player.
*
* <p>This value is {@code null} on 1.19.2 and lower, * <p>This value is {@code null} on 1.19.2 and lower,
* up to 1.20.1 it is optional and from 1.20.2 it will always be available.</p> * up to 1.20.1 it is optional and from 1.20.2 it will always be available.</p>
* *
@@ -129,14 +140,29 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
return result != Result.DISALLOWED; return result != Result.DISALLOWED;
} }
/**
* Gets the reason component shown to the player if the connection is denied.
*
* @return the reason as a {@link net.kyori.adventure.text.Component}, or empty if not denied
*/
public Optional<net.kyori.adventure.text.Component> getReasonComponent() { public Optional<net.kyori.adventure.text.Component> getReasonComponent() {
return Optional.ofNullable(reason); return Optional.ofNullable(reason);
} }
/**
* Checks if this result explicitly forces online mode for the connection.
*
* @return true if online mode is forced
*/
public boolean isOnlineModeAllowed() { public boolean isOnlineModeAllowed() {
return result == Result.FORCE_ONLINE; return result == Result.FORCE_ONLINE;
} }
/**
* Checks if this result explicitly forces offline mode for the connection.
*
* @return true if offline mode is forced
*/
public boolean isForceOfflineMode() { public boolean isForceOfflineMode() {
return result == Result.FORCE_OFFLINE; return result == Result.FORCE_OFFLINE;
} }

View File

@@ -28,15 +28,31 @@ public final class PreTransferEvent implements ResultedEvent<PreTransferEvent.Tr
private final Player player; private final Player player;
private TransferResult result = TransferResult.ALLOWED; private TransferResult result = TransferResult.ALLOWED;
/**
* Constructs a new PreTransferEvent.
*
* @param player the player being transferred
* @param address the destination address
*/
public PreTransferEvent(final Player player, final InetSocketAddress address) { public PreTransferEvent(final Player player, final InetSocketAddress address) {
this.player = requireNonNull(player); this.player = requireNonNull(player);
this.originalAddress = requireNonNull(address); this.originalAddress = requireNonNull(address);
} }
/**
* Returns the player attempting to transfer.
*
* @return the player
*/
public Player player() { public Player player() {
return this.player; return this.player;
} }
/**
* Returns the original target address the player is attempting to connect to.
*
* @return the original address
*/
public InetSocketAddress originalAddress() { public InetSocketAddress originalAddress() {
return this.originalAddress; return this.originalAddress;
} }
@@ -56,7 +72,13 @@ public final class PreTransferEvent implements ResultedEvent<PreTransferEvent.Tr
* Transfer Result of a player to another host. * Transfer Result of a player to another host.
*/ */
public static class TransferResult implements ResultedEvent.Result { public static class TransferResult implements ResultedEvent.Result {
/**
* A result allowing the transfer to proceed without modifying the destination.
*/
private static final TransferResult ALLOWED = new TransferResult(true, null); private static final TransferResult ALLOWED = new TransferResult(true, null);
/**
* A result denying the transfer entirely.
*/
private static final TransferResult DENIED = new TransferResult(false, null); private static final TransferResult DENIED = new TransferResult(false, null);
private final InetSocketAddress address; private final InetSocketAddress address;
@@ -67,10 +89,20 @@ public final class PreTransferEvent implements ResultedEvent<PreTransferEvent.Tr
this.allowed = allowed; this.allowed = allowed;
} }
/**
* Allows the transfer to proceed to the originally specified address.
*
* @return an allowed result
*/
public static TransferResult allowed() { public static TransferResult allowed() {
return ALLOWED; return ALLOWED;
} }
/**
* Denies the transfer attempt.
*
* @return a denied result
*/
public static TransferResult denied() { public static TransferResult denied() {
return DENIED; return DENIED;
} }
@@ -92,6 +124,11 @@ public final class PreTransferEvent implements ResultedEvent<PreTransferEvent.Tr
return this.allowed; return this.allowed;
} }
/**
* Returns the destination address for the transfer, if overridden.
*
* @return the overridden address or null if not specified
*/
@Nullable @Nullable
public InetSocketAddress address() { public InetSocketAddress address() {
return this.address; return this.address;

View File

@@ -34,11 +34,22 @@ public final class PermissionsSetupEvent {
private final PermissionProvider defaultProvider; private final PermissionProvider defaultProvider;
private PermissionProvider provider; private PermissionProvider provider;
/**
* Constructs a new {@link PermissionsSetupEvent}.
*
* @param subject the subject (e.g., player or console) whose permissions are being initialized
* @param provider the default permission provider used for the subject
*/
public PermissionsSetupEvent(PermissionSubject subject, PermissionProvider provider) { public PermissionsSetupEvent(PermissionSubject subject, PermissionProvider provider) {
this.subject = Preconditions.checkNotNull(subject, "subject"); this.subject = Preconditions.checkNotNull(subject, "subject");
this.provider = this.defaultProvider = Preconditions.checkNotNull(provider, "provider"); this.provider = this.defaultProvider = Preconditions.checkNotNull(provider, "provider");
} }
/**
* Gets the subject whose permissions are being initialized.
*
* @return the permission subject
*/
public PermissionSubject getSubject() { public PermissionSubject getSubject() {
return this.subject; return this.subject;
} }
@@ -53,6 +64,11 @@ public final class PermissionsSetupEvent {
return this.provider.createFunction(subject); return this.provider.createFunction(subject);
} }
/**
* Gets the current {@link PermissionProvider} in use for this subject.
*
* @return the permission provider
*/
public PermissionProvider getProvider() { public PermissionProvider getProvider() {
return this.provider; return this.provider;
} }

View File

@@ -53,14 +53,29 @@ public final class CookieReceiveEvent implements ResultedEvent<CookieReceiveEven
this.result = Preconditions.checkNotNull(result, "result"); this.result = Preconditions.checkNotNull(result, "result");
} }
/**
* Returns the player who sent the cookie response.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the original cookie identifier received from the client.
*
* @return the original cookie key
*/
public Key getOriginalKey() { public Key getOriginalKey() {
return originalKey; return originalKey;
} }
/**
* Returns the original cookie data received from the client, if present.
*
* @return the original cookie data, or {@code null} if not present
*/
public byte @Nullable [] getOriginalData() { public byte @Nullable [] getOriginalData() {
return originalData; return originalData;
} }
@@ -97,10 +112,20 @@ public final class CookieReceiveEvent implements ResultedEvent<CookieReceiveEven
return status; return status;
} }
/**
* Returns the replacement key to forward, if any.
*
* @return the key to forward, or {@code null} if unchanged
*/
public Key getKey() { public Key getKey() {
return key; return key;
} }
/**
* Returns the replacement data to forward, if any.
*
* @return the data to forward, or {@code null} if unchanged
*/
public byte[] getData() { public byte[] getData() {
return data; return data;
} }

View File

@@ -47,10 +47,20 @@ public final class CookieRequestEvent implements ResultedEvent<CookieRequestEven
this.result = Preconditions.checkNotNull(result, "result"); this.result = Preconditions.checkNotNull(result, "result");
} }
/**
* Returns the player from whom the cookie is being requested.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the original identifier of the cookie being requested.
*
* @return the original cookie key
*/
public Key getOriginalKey() { public Key getOriginalKey() {
return originalKey; return originalKey;
} }
@@ -84,6 +94,11 @@ public final class CookieRequestEvent implements ResultedEvent<CookieRequestEven
return status; return status;
} }
/**
* Returns the replacement key to use for the cookie request, if one was provided.
*
* @return the new key, or {@code null} if unchanged
*/
public Key getKey() { public Key getKey() {
return key; return key;
} }

View File

@@ -52,14 +52,29 @@ public final class CookieStoreEvent implements ResultedEvent<CookieStoreEvent.Fo
this.result = Preconditions.checkNotNull(result, "result"); this.result = Preconditions.checkNotNull(result, "result");
} }
/**
* Returns the player who should store the cookie.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the original key identifying the cookie to be stored.
*
* @return the cookie key
*/
public Key getOriginalKey() { public Key getOriginalKey() {
return originalKey; return originalKey;
} }
/**
* Returns the original data of the cookie to be stored.
*
* @return the cookie data
*/
public byte[] getOriginalData() { public byte[] getOriginalData() {
return originalData; return originalData;
} }
@@ -96,10 +111,22 @@ public final class CookieStoreEvent implements ResultedEvent<CookieStoreEvent.Fo
return status; return status;
} }
/**
* Returns the replacement key to use when forwarding the cookie,
* or {@code null} if the original key should be used.
*
* @return the new cookie key, or {@code null} if unchanged
*/
public Key getKey() { public Key getKey() {
return key; return key;
} }
/**
* Returns the replacement data to use when forwarding the cookie,
* or {@code null} if the original data should be used.
*
* @return the new cookie data, or {@code null} if unchanged
*/
public byte[] getData() { public byte[] getData() {
return data; return data;
} }

View File

@@ -48,18 +48,38 @@ public final class GameProfileRequestEvent {
this.onlineMode = onlineMode; this.onlineMode = onlineMode;
} }
/**
* Returns the inbound connection from the player attempting to log in.
*
* @return the inbound connection
*/
public InboundConnection getConnection() { public InboundConnection getConnection() {
return connection; return connection;
} }
/**
* Returns the username associated with the original game profile.
*
* @return the username
*/
public String getUsername() { public String getUsername() {
return username; return username;
} }
/**
* Returns the original game profile before any plugin customization.
*
* @return the original {@link GameProfile}
*/
public GameProfile getOriginalProfile() { public GameProfile getOriginalProfile() {
return originalProfile; return originalProfile;
} }
/**
* Returns whether the player is connecting in online mode.
*
* @return {@code true} if the connection is in online mode, otherwise {@code false}
*/
public boolean isOnlineMode() { public boolean isOnlineMode() {
return onlineMode; return onlineMode;
} }
@@ -92,5 +112,4 @@ public final class GameProfileRequestEvent {
+ "}"; + "}";
} }
} }

View File

@@ -134,6 +134,11 @@ public final class KickedFromServerEvent implements
return true; return true;
} }
/**
* Returns the reason shown to the player upon disconnection.
*
* @return the reason component
*/
public Component getReasonComponent() { public Component getReasonComponent() {
return component; return component;
} }
@@ -173,10 +178,21 @@ public final class KickedFromServerEvent implements
return false; return false;
} }
/**
* Returns the target server to which the player should be redirected.
*
* @return the server to redirect to
*/
public @NonNull RegisteredServer getServer() { public @NonNull RegisteredServer getServer() {
return server; return server;
} }
/**
* Returns the message that will be sent to the player after redirection.
* This may be {@code null} if the kick reason should be reused or nothing should be sent.
*
* @return the message component, or {@code null}
*/
public @Nullable Component getMessageComponent() { public @Nullable Component getMessageComponent() {
return message; return message;
} }
@@ -230,6 +246,12 @@ public final class KickedFromServerEvent implements
return false; return false;
} }
/**
* Returns the message that will be sent to the player after redirection.
* This may be {@code null} if the kick reason should be reused or nothing should be sent.
*
* @return the message component, or {@code null}
*/
public Component getMessageComponent() { public Component getMessageComponent() {
return message; return message;
} }

View File

@@ -21,15 +21,31 @@ public final class PlayerChannelRegisterEvent {
private final Player player; private final Player player;
private final List<ChannelIdentifier> channels; private final List<ChannelIdentifier> channels;
/**
* Constructs a new PlayerChannelRegisterEvent.
*
* @param player the player who sent the plugin message
* @param channels the list of channels the player is registering
*/
public PlayerChannelRegisterEvent(Player player, List<ChannelIdentifier> channels) { public PlayerChannelRegisterEvent(Player player, List<ChannelIdentifier> channels) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
this.channels = Preconditions.checkNotNull(channels, "channels"); this.channels = Preconditions.checkNotNull(channels, "channels");
} }
/**
* Gets the player who sent the plugin message to register channels.
*
* @return the player involved in this event
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Gets the list of {@link ChannelIdentifier}s that the player registered.
*
* @return the list of registered channels
*/
public List<ChannelIdentifier> getChannels() { public List<ChannelIdentifier> getChannels() {
return channels; return channels;
} }

View File

@@ -21,15 +21,35 @@ public final class PlayerChannelUnregisterEvent {
private final Player player; private final Player player;
private final List<ChannelIdentifier> channels; private final List<ChannelIdentifier> channels;
/**
* Constructs a new {@link PlayerChannelUnregisterEvent}.
*
* @param player the player that sent the unregister message
* @param channels the list of {@link ChannelIdentifier}s being unregistered
* @throws NullPointerException if {@code player} or {@code channels} is {@code null}
*/
public PlayerChannelUnregisterEvent(Player player, List<ChannelIdentifier> channels) { public PlayerChannelUnregisterEvent(Player player, List<ChannelIdentifier> channels) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
this.channels = Preconditions.checkNotNull(channels, "channels"); this.channels = Preconditions.checkNotNull(channels, "channels");
} }
/**
* Gets the {@link Player} who sent the unregister message.
*
* @return the player involved in this event
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Gets the list of {@link ChannelIdentifier}s that the player has unregistered.
*
* <p>These identifiers correspond to the plugin message channels that the client has
* indicated it will no longer use.</p>
*
* @return the list of unregistered channels
*/
public List<ChannelIdentifier> getChannels() { public List<ChannelIdentifier> getChannels() {
return channels; return channels;
} }

View File

@@ -38,10 +38,20 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
this.result = ChatResult.allowed(); this.result = ChatResult.allowed();
} }
/**
* Gets the player who sent the chat message.
*
* @return the player who sent the message
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Gets the (possibly modified) chat message to be sent.
*
* @return an {@link Optional} containing the message, or empty if none
*/
public String getMessage() { public String getMessage() {
return message; return message;
} }
@@ -88,6 +98,11 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
this.message = message; this.message = message;
} }
/**
* Gets the (possibly modified) chat message to be sent.
*
* @return an {@link Optional} containing the message, or empty if none
*/
public Optional<String> getMessage() { public Optional<String> getMessage() {
return Optional.ofNullable(message); return Optional.ofNullable(message);
} }

View File

@@ -37,10 +37,20 @@ public class PlayerChooseInitialServerEvent {
this.initialServer = initialServer; this.initialServer = initialServer;
} }
/**
* Gets the player who is choosing the initial server.
*
* @return the connected player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Gets the initial server the player will connect to.
*
* @return an {@link Optional} containing the selected server, or empty if none was set
*/
public Optional<RegisteredServer> getInitialServer() { public Optional<RegisteredServer> getInitialServer() {
return Optional.ofNullable(initialServer); return Optional.ofNullable(initialServer);
} }

View File

@@ -29,10 +29,20 @@ public final class PlayerClientBrandEvent {
this.brand = Preconditions.checkNotNull(brand); this.brand = Preconditions.checkNotNull(brand);
} }
/**
* Gets the player who sent the client brand.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Gets the brand string sent by the client.
*
* @return the client brand
*/
public String getBrand() { public String getBrand() {
return brand; return brand;
} }
@@ -40,9 +50,9 @@ public final class PlayerClientBrandEvent {
@Override @Override
public String toString() { public String toString() {
return "PlayerClientBrandEvent{" return "PlayerClientBrandEvent{"
+ "player=" + player + "player=" + player
+ ", brand='" + brand + '\'' + ", brand='" + brand + '\''
+ '}'; + '}';
} }
} }

View File

@@ -21,15 +21,31 @@ public final class PlayerModInfoEvent {
private final Player player; private final Player player;
private final ModInfo modInfo; private final ModInfo modInfo;
/**
* Constructs a new {@code PlayerModInfoEvent}.
*
* @param player the player sending their mod list
* @param modInfo the mod list information
*/
public PlayerModInfoEvent(Player player, ModInfo modInfo) { public PlayerModInfoEvent(Player player, ModInfo modInfo) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
this.modInfo = Preconditions.checkNotNull(modInfo, "modInfo"); this.modInfo = Preconditions.checkNotNull(modInfo, "modInfo");
} }
/**
* Returns the player who sent their mod list.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the mod information sent by the player.
*
* @return the mod information
*/
public ModInfo getModInfo() { public ModInfo getModInfo() {
return modInfo; return modInfo;
} }

View File

@@ -33,6 +33,8 @@ public class PlayerResourcePackStatusEvent {
/** /**
* Instantiates this event. * Instantiates this event.
* *
* @param player the player affected by the status update
* @param status the status of the resource pack
* @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent * @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent
* (Player, UUID, Status, ResourcePackInfo)} instead. * (Player, UUID, Status, ResourcePackInfo)} instead.
*/ */
@@ -44,6 +46,9 @@ public class PlayerResourcePackStatusEvent {
/** /**
* Instantiates this event. * Instantiates this event.
* *
* @param player the player affected by the status update
* @param status the status of the resource pack
* @param packInfo the resource pack metadata
* @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent * @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent
* (Player, UUID, Status, ResourcePackInfo)} instead. * (Player, UUID, Status, ResourcePackInfo)} instead.
*/ */
@@ -54,6 +59,11 @@ public class PlayerResourcePackStatusEvent {
/** /**
* Instantiates this event. * Instantiates this event.
*
* @param player the player affected by the status update
* @param packId the unique ID of the resource pack
* @param status the status of the resource pack
* @param packInfo the resource pack metadata
*/ */
public PlayerResourcePackStatusEvent( public PlayerResourcePackStatusEvent(
Player player, UUID packId, Status status, ResourcePackInfo packInfo) { Player player, UUID packId, Status status, ResourcePackInfo packInfo) {

View File

@@ -22,15 +22,31 @@ public final class PlayerSettingsChangedEvent {
private final Player player; private final Player player;
private final PlayerSettings playerSettings; private final PlayerSettings playerSettings;
/**
* Constructs a new PlayerSettingsChangedEvent.
*
* @param player the player who changed settings
* @param playerSettings the new settings sent by the client
*/
public PlayerSettingsChangedEvent(Player player, PlayerSettings playerSettings) { public PlayerSettingsChangedEvent(Player player, PlayerSettings playerSettings) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");
this.playerSettings = Preconditions.checkNotNull(playerSettings, "playerSettings"); this.playerSettings = Preconditions.checkNotNull(playerSettings, "playerSettings");
} }
/**
* Returns the player whose settings changed.
*
* @return the player
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the new client settings sent by the player.
*
* @return the updated player settings
*/
public PlayerSettings getPlayerSettings() { public PlayerSettings getPlayerSettings() {
return playerSettings; return playerSettings;
} }

View File

@@ -45,14 +45,29 @@ public final class ServerConnectedEvent {
this.previousServer = previousServer; this.previousServer = previousServer;
} }
/**
* Returns the player involved in this event.
*
* @return the {@link Player} who connected
*/
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
/**
* Returns the server the player successfully connected to.
*
* @return the {@link RegisteredServer} the player connected to
*/
public RegisteredServer getServer() { public RegisteredServer getServer() {
return server; return server;
} }
/**
* Returns the server the player was previously connected to, if any.
*
* @return an {@link Optional} of the previous {@link RegisteredServer}, or empty if none
*/
public Optional<RegisteredServer> getPreviousServer() { public Optional<RegisteredServer> getPreviousServer() {
return Optional.ofNullable(previousServer); return Optional.ofNullable(previousServer);
} }

View File

@@ -63,10 +63,20 @@ public class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
this.result = checkNotNull(result, "result"); this.result = checkNotNull(result, "result");
} }
/**
* Gets the connection from which the login plugin message was received.
*
* @return the server connection
*/
public ServerConnection getConnection() { public ServerConnection getConnection() {
return connection; return connection;
} }
/**
* Gets the identifier of the channel this login plugin message was sent on.
*
* @return the channel identifier
*/
public ChannelIdentifier getIdentifier() { public ChannelIdentifier getIdentifier() {
return identifier; return identifier;
} }
@@ -100,6 +110,11 @@ public class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
return ByteStreams.newDataInput(contents); return ByteStreams.newDataInput(contents);
} }
/**
* Gets the sequence ID of the plugin message sent by the server.
*
* @return the sequence ID
*/
public int getSequenceId() { public int getSequenceId() {
return sequenceId; return sequenceId;
} }
@@ -146,10 +161,21 @@ public class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
return response.clone(); return response.clone();
} }
/**
* Returns a result indicating that this login plugin message was not handled by the proxy.
*
* @return the unknown response result
*/
public static ResponseResult unknown() { public static ResponseResult unknown() {
return UNKNOWN; return UNKNOWN;
} }
/**
* Returns a result with a reply to the server's login plugin message.
*
* @param response the response bytes to send
* @return a response result containing the response data
*/
public static ResponseResult reply(byte[] response) { public static ResponseResult reply(byte[] response) {
checkNotNull(response, "response"); checkNotNull(response, "response");
return new ResponseResult(response); return new ResponseResult(response);

View File

@@ -21,6 +21,13 @@ public class ServerPostConnectEvent {
private final Player player; private final Player player;
private final RegisteredServer previousServer; private final RegisteredServer previousServer;
/**
* Constructs a new {@link ServerPostConnectEvent}.
*
* @param player the player that connected to the server
* @param previousServer the server the player was previously connected to, or {@code null}
* if the player had not been connected to a server before
*/
public ServerPostConnectEvent(Player player, public ServerPostConnectEvent(Player player,
@Nullable RegisteredServer previousServer) { @Nullable RegisteredServer previousServer) {
this.player = Preconditions.checkNotNull(player, "player"); this.player = Preconditions.checkNotNull(player, "player");

View File

@@ -126,6 +126,11 @@ public final class ServerPreConnectEvent implements
return server != null; return server != null;
} }
/**
* Returns the server the player will be connected to if the result is allowed.
*
* @return the server to connect to, or an empty Optional if the connection is denied
*/
public Optional<RegisteredServer> getServer() { public Optional<RegisteredServer> getServer() {
return Optional.ofNullable(server); return Optional.ofNullable(server);
} }

View File

@@ -29,6 +29,9 @@ public class ServerResourcePackRemoveEvent implements ResultedEvent<ResultedEven
/** /**
* Instantiates this event. * Instantiates this event.
*
* @param packId the UUID of the resource pack to remove, or {@code null} to clear all
* @param serverConnection the server attempting to remove the resource pack
*/ */
public ServerResourcePackRemoveEvent(UUID packId, ServerConnection serverConnection) { public ServerResourcePackRemoveEvent(UUID packId, ServerConnection serverConnection) {
this.result = ResultedEvent.GenericResult.allowed(); this.result = ResultedEvent.GenericResult.allowed();

View File

@@ -42,18 +42,39 @@ public class ServerResourcePackSendEvent implements ResultedEvent<ResultedEvent.
this.providedResourcePack = receivedResourcePack; this.providedResourcePack = receivedResourcePack;
} }
/**
* Gets the server connection that attempted to send the resource pack.
*
* @return the server connection
*/
public ServerConnection getServerConnection() { public ServerConnection getServerConnection() {
return serverConnection; return serverConnection;
} }
/**
* Gets the original resource pack provided by the server.
*
* @return the resource pack sent by the server
*/
public ResourcePackInfo getReceivedResourcePack() { public ResourcePackInfo getReceivedResourcePack() {
return receivedResourcePack; return receivedResourcePack;
} }
/**
* Gets the resource pack that will be forwarded to the player.
* This can be different from the one received from the server.
*
* @return the resource pack to send to the player
*/
public ResourcePackInfo getProvidedResourcePack() { public ResourcePackInfo getProvidedResourcePack() {
return providedResourcePack; return providedResourcePack;
} }
/**
* Sets the resource pack that should be forwarded to the player.
*
* @param providedResourcePack the resource pack to send to the player
*/
public void setProvidedResourcePack(ResourcePackInfo providedResourcePack) { public void setProvidedResourcePack(ResourcePackInfo providedResourcePack) {
this.providedResourcePack = providedResourcePack; this.providedResourcePack = providedResourcePack;
} }

View File

@@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
/** /**
* This event is executed when a player entered the configuration state and can be configured by Velocity. * This event is executed when a player entered the configuration state and can be configured by Velocity.
*
* <p>Velocity will wait for this event before continuing/ending the configuration state.</p> * <p>Velocity will wait for this event before continuing/ending the configuration state.</p>
* *
* @param player The player who can be configured. * @param player The player who can be configured.

View File

@@ -15,8 +15,9 @@ import org.jetbrains.annotations.NotNull;
/** /**
* This event is executed when a player is about to enter the configuration state. * This event is executed when a player is about to enter the configuration state.
* It is <b>not</b> called for the initial configuration of a player after login. * It is <b>not</b> called for the initial configuration of a player after login.
*
* <p>Velocity will wait for this event before asking the client to enter configuration state. * <p>Velocity will wait for this event before asking the client to enter configuration state.
* However due to backend server being unable to keep the connection alive during state changes, * However, due to backend server being unable to keep the connection alive during state changes,
* Velocity will only wait for a maximum of 5 seconds.</p> * Velocity will only wait for a maximum of 5 seconds.</p>
* *
* @param player The player who is about to enter configuration state. * @param player The player who is about to enter configuration state.

View File

@@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
/** /**
* This event is executed when a player has entered the configuration state. * This event is executed when a player has entered the configuration state.
*
* <p>From this moment on, until the {@link PlayerFinishedConfigurationEvent} is executed, * <p>From this moment on, until the {@link PlayerFinishedConfigurationEvent} is executed,
* the {@linkplain Player#getProtocolState()} method is guaranteed * the {@linkplain Player#getProtocolState()} method is guaranteed
* to return {@link ProtocolState#CONFIGURATION}.</p> * to return {@link ProtocolState#CONFIGURATION}.</p>

View File

@@ -14,8 +14,9 @@ import org.jetbrains.annotations.NotNull;
/** /**
* This event is executed when a player is about to finish the configuration state. * This event is executed when a player is about to finish the configuration state.
*
* <p>Velocity will wait for this event before asking the client to finish the configuration state. * <p>Velocity will wait for this event before asking the client to finish the configuration state.
* However due to backend server being unable to keep the connection alive during state changes, * However, due to backend server being unable to keep the connection alive during state changes,
* Velocity will only wait for a maximum of 5 seconds. If you need to hold a player in configuration * Velocity will only wait for a maximum of 5 seconds. If you need to hold a player in configuration
* state, use the {@link PlayerConfigurationEvent}.</p> * state, use the {@link PlayerConfigurationEvent}.</p>
* *

View File

@@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull;
/** /**
* This event is executed when a player has finished the configuration state. * This event is executed when a player has finished the configuration state.
*
* <p>From this moment on, the {@link Player#getProtocolState()} method * <p>From this moment on, the {@link Player#getProtocolState()} method
* will return {@link ProtocolState#PLAY}.</p> * will return {@link ProtocolState#PLAY}.</p>
* *

View File

@@ -19,15 +19,31 @@ public final class ListenerBoundEvent {
private final InetSocketAddress address; private final InetSocketAddress address;
private final ListenerType listenerType; private final ListenerType listenerType;
/**
* Constructs a new {@link ListenerBoundEvent}.
*
* @param address the socket address the listener is bound to
* @param listenerType the type of listener that was bound
*/
public ListenerBoundEvent(InetSocketAddress address, ListenerType listenerType) { public ListenerBoundEvent(InetSocketAddress address, ListenerType listenerType) {
this.address = Preconditions.checkNotNull(address, "address"); this.address = Preconditions.checkNotNull(address, "address");
this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType"); this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType");
} }
/**
* Returns the socket address the listener is bound to.
*
* @return the bound socket address
*/
public InetSocketAddress getAddress() { public InetSocketAddress getAddress() {
return address; return address;
} }
/**
* Returns the type of listener that was bound.
*
* @return the listener type
*/
public ListenerType getListenerType() { public ListenerType getListenerType() {
return listenerType; return listenerType;
} }

View File

@@ -19,15 +19,31 @@ public final class ListenerCloseEvent {
private final InetSocketAddress address; private final InetSocketAddress address;
private final ListenerType listenerType; private final ListenerType listenerType;
/**
* Constructs a new {@link ListenerCloseEvent}.
*
* @param address the socket address the listener was bound to
* @param listenerType the type of listener being closed
*/
public ListenerCloseEvent(InetSocketAddress address, ListenerType listenerType) { public ListenerCloseEvent(InetSocketAddress address, ListenerType listenerType) {
this.address = Preconditions.checkNotNull(address, "address"); this.address = Preconditions.checkNotNull(address, "address");
this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType"); this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType");
} }
/**
* Returns the socket address the listener was bound to.
*
* @return the bound socket address
*/
public InetSocketAddress getAddress() { public InetSocketAddress getAddress() {
return address; return address;
} }
/**
* Returns the type of listener being closed.
*
* @return the listener type
*/
public ListenerType getListenerType() { public ListenerType getListenerType() {
return listenerType; return listenerType;
} }

View File

@@ -17,6 +17,12 @@ import com.velocitypowered.api.event.annotation.AwaitingEvent;
@AwaitingEvent @AwaitingEvent
public final class ProxyInitializeEvent { public final class ProxyInitializeEvent {
/**
* Creates a new {@code ProxyInitializeEvent}.
*/
public ProxyInitializeEvent() {
}
@Override @Override
public String toString() { public String toString() {
return "ProxyInitializeEvent"; return "ProxyInitializeEvent";

View File

@@ -28,6 +28,12 @@ public final class ProxyPingEvent implements ResultedEvent<ResultedEvent.Generic
private ServerPing ping; private ServerPing ping;
private GenericResult result = GenericResult.allowed(); private GenericResult result = GenericResult.allowed();
/**
* Constructs a new {@code ProxyPingEvent}.
*
* @param connection the incoming connection requesting server info
* @param ping the server ping response to send
*/
public ProxyPingEvent(final InboundConnection connection, final ServerPing ping) { public ProxyPingEvent(final InboundConnection connection, final ServerPing ping) {
this.connection = Preconditions.checkNotNull(connection, "connection"); this.connection = Preconditions.checkNotNull(connection, "connection");
this.ping = Preconditions.checkNotNull(ping, "ping"); this.ping = Preconditions.checkNotNull(ping, "ping");

View File

@@ -26,6 +26,12 @@ import com.velocitypowered.api.event.annotation.AwaitingEvent;
@AwaitingEvent @AwaitingEvent
public final class ProxyPreShutdownEvent { public final class ProxyPreShutdownEvent {
/**
* Creates a new {@code ProxyPreShutdownEvent}.
*/
public ProxyPreShutdownEvent() {
}
@Override @Override
public String toString() { public String toString() {
return "ProxyPreShutdownEvent"; return "ProxyPreShutdownEvent";

View File

@@ -12,6 +12,12 @@ package com.velocitypowered.api.event.proxy;
*/ */
public class ProxyReloadEvent { public class ProxyReloadEvent {
/**
* Creates a new {@code ProxyReloadEvent}.
*/
public ProxyReloadEvent() {
}
@Override @Override
public String toString() { public String toString() {
return "ProxyReloadEvent"; return "ProxyReloadEvent";

View File

@@ -16,6 +16,12 @@ import com.velocitypowered.api.event.annotation.AwaitingEvent;
@AwaitingEvent @AwaitingEvent
public final class ProxyShutdownEvent { public final class ProxyShutdownEvent {
/**
* Creates a new {@code ProxyShutdownEvent}.
*/
public ProxyShutdownEvent() {
}
@Override @Override
public String toString() { public String toString() {
return "ProxyShutdownEvent"; return "ProxyShutdownEvent";

View File

@@ -23,6 +23,12 @@ import org.jetbrains.annotations.NotNull;
* @since 3.3.0 * @since 3.3.0
*/ */
public record ServerRegisteredEvent(@NotNull RegisteredServer registeredServer) { public record ServerRegisteredEvent(@NotNull RegisteredServer registeredServer) {
/**
* Constructs a new {@link ServerRegisteredEvent}.
*
* @param registeredServer the server that was registered
*/
public ServerRegisteredEvent { public ServerRegisteredEvent {
Preconditions.checkNotNull(registeredServer, "registeredServer"); Preconditions.checkNotNull(registeredServer, "registeredServer");
} }

View File

@@ -23,6 +23,12 @@ import org.jetbrains.annotations.NotNull;
* @since 3.3.0 * @since 3.3.0
*/ */
public record ServerUnregisteredEvent(@NotNull RegisteredServer unregisteredServer) { public record ServerUnregisteredEvent(@NotNull RegisteredServer unregisteredServer) {
/**
* Constructs a {@link ServerUnregisteredEvent}.
*
* @param unregisteredServer the server that was unregistered
*/
public ServerUnregisteredEvent { public ServerUnregisteredEvent {
Preconditions.checkNotNull(unregisteredServer, "unregisteredServer"); Preconditions.checkNotNull(unregisteredServer, "unregisteredServer");
} }

View File

@@ -11,16 +11,33 @@ package com.velocitypowered.api.network;
* Represents the ClientIntent of a client in the Handshake state. * Represents the ClientIntent of a client in the Handshake state.
*/ */
public enum HandshakeIntent { public enum HandshakeIntent {
/**
* Indicates that the client is performing a status request (e.g., server list ping).
*/
STATUS(1), STATUS(1),
/**
* Indicates that the client intends to log in to the server.
*/
LOGIN(2), LOGIN(2),
/**
* Indicates that the client is initiating a transfer (e.g., Velocity-native forwarding).
*/
TRANSFER(3); TRANSFER(3);
/**
* The numeric ID associated with this handshake intent.
*/
private final int id; private final int id;
HandshakeIntent(int id) { HandshakeIntent(int id) {
this.id = id; this.id = id;
} }
/**
* Returns the numeric ID associated with this handshake intent.
*
* @return the handshake intent ID
*/
public int id() { public int id() {
return this.id; return this.id;
} }

View File

@@ -11,7 +11,13 @@ package com.velocitypowered.api.network;
* Represents each listener type. * Represents each listener type.
*/ */
public enum ListenerType { public enum ListenerType {
/**
* A standard Minecraft listener for player connections.
*/
MINECRAFT("Minecraft"), MINECRAFT("Minecraft"),
/**
* A listener for the legacy server list ping protocol (Query).
*/
QUERY("Query"); QUERY("Query");
final String name; final String name;

View File

@@ -16,6 +16,7 @@ package com.velocitypowered.api.network;
public enum ProtocolState { public enum ProtocolState {
/** /**
* Initial connection State. * Initial connection State.
*
* <p>This status can be caused by a {@link HandshakeIntent#STATUS}, * <p>This status can be caused by a {@link HandshakeIntent#STATUS},
* {@link HandshakeIntent#LOGIN} or {@link HandshakeIntent#TRANSFER} intent.</p> * {@link HandshakeIntent#LOGIN} or {@link HandshakeIntent#TRANSFER} intent.</p>
* If the intent is LOGIN or TRANSFER, the next state will be {@link #LOGIN}, * If the intent is LOGIN or TRANSFER, the next state will be {@link #LOGIN},
@@ -24,6 +25,7 @@ public enum ProtocolState {
HANDSHAKE, HANDSHAKE,
/** /**
* Ping State of a connection. * Ping State of a connection.
*
* <p>Connections with the {@link HandshakeIntent#STATUS} intent will pass through this state * <p>Connections with the {@link HandshakeIntent#STATUS} intent will pass through this state
* and be disconnected after it requests the ping from the server * and be disconnected after it requests the ping from the server
* and the server responds with the respective ping.</p> * and the server responds with the respective ping.</p>
@@ -31,11 +33,13 @@ public enum ProtocolState {
STATUS, STATUS,
/** /**
* Authentication State of a connection. * Authentication State of a connection.
*
* <p>At this moment the player is authenticating with the authentication servers.</p> * <p>At this moment the player is authenticating with the authentication servers.</p>
*/ */
LOGIN, LOGIN,
/** /**
* Configuration State of a connection. * Configuration State of a connection.
*
* <p>At this point the player allows the server to send information * <p>At this point the player allows the server to send information
* such as resource packs and plugin messages, at the same time the player * such as resource packs and plugin messages, at the same time the player
* will send his client brand and the respective plugin messages * will send his client brand and the respective plugin messages
@@ -46,6 +50,7 @@ public enum ProtocolState {
CONFIGURATION, CONFIGURATION,
/** /**
* Game State of a connection. * Game State of a connection.
*
* <p>In this state is where the whole game runs, the server is able to change * <p>In this state is where the whole game runs, the server is able to change
* the player's state to {@link #CONFIGURATION} as needed in versions 1.20.2 and higher.</p> * the player's state to {@link #CONFIGURATION} as needed in versions 1.20.2 and higher.</p>
*/ */

View File

@@ -21,6 +21,9 @@ import java.util.Set;
* Represents each Minecraft protocol version. * Represents each Minecraft protocol version.
*/ */
public enum ProtocolVersion implements Ordered<ProtocolVersion> { public enum ProtocolVersion implements Ordered<ProtocolVersion> {
/**
* Represents an unknown protocol version.
*/
UNKNOWN(-1, "Unknown") { UNKNOWN(-1, "Unknown") {
@Override @Override
public boolean isUnknown() { public boolean isUnknown() {
@@ -32,6 +35,9 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
return false; return false;
} }
}, },
/**
* Represents legacy protocol versions before 1.7.
*/
LEGACY(-2, "Legacy") { LEGACY(-2, "Legacy") {
@Override @Override
public boolean isLegacy() { public boolean isLegacy() {
@@ -43,57 +49,201 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
return false; return false;
} }
}, },
MINECRAFT_1_7_2(4, /**
"1.7.2", "1.7.3", "1.7.4", "1.7.5"), * Minecraft 1.7.2 to 1.7.5.
MINECRAFT_1_7_6(5, */
"1.7.6", "1.7.7", "1.7.8", "1.7.9", "1.7.10"), MINECRAFT_1_7_2(4, "1.7.2", "1.7.3", "1.7.4", "1.7.5"),
MINECRAFT_1_8(47, /**
"1.8", "1.8.1", "1.8.2", "1.8.3", "1.8.4", "1.8.5", "1.8.6", "1.8.7", "1.8.8", "1.8.9"), * Minecraft 1.7.6 to 1.7.10.
*/
MINECRAFT_1_7_6(5, "1.7.6", "1.7.7", "1.7.8", "1.7.9", "1.7.10"),
/**
* Minecraft 1.8 to 1.8.9.
*/
MINECRAFT_1_8(47, "1.8", "1.8.1", "1.8.2", "1.8.3", "1.8.4", "1.8.5", "1.8.6", "1.8.7", "1.8.8", "1.8.9"),
/**
* Minecraft 1.9.
*/
MINECRAFT_1_9(107, "1.9"), MINECRAFT_1_9(107, "1.9"),
/**
* Minecraft 1.9.1.
*/
MINECRAFT_1_9_1(108, "1.9.1"), MINECRAFT_1_9_1(108, "1.9.1"),
/**
* Minecraft 1.9.2.
*/
MINECRAFT_1_9_2(109, "1.9.2"), MINECRAFT_1_9_2(109, "1.9.2"),
/**
* Minecraft 1.9.3 to 1.9.4.
*/
MINECRAFT_1_9_4(110, "1.9.3", "1.9.4"), MINECRAFT_1_9_4(110, "1.9.3", "1.9.4"),
/**
* Minecraft 1.10 to 1.10.2.
*/
MINECRAFT_1_10(210, "1.10", "1.10.1", "1.10.2"), MINECRAFT_1_10(210, "1.10", "1.10.1", "1.10.2"),
/**
* Minecraft 1.11.
*/
MINECRAFT_1_11(315, "1.11"), MINECRAFT_1_11(315, "1.11"),
/**
* Minecraft 1.11.1 to 1.11.2.
*/
MINECRAFT_1_11_1(316, "1.11.1", "1.11.2"), MINECRAFT_1_11_1(316, "1.11.1", "1.11.2"),
/**
* Minecraft 1.12.
*/
MINECRAFT_1_12(335, "1.12"), MINECRAFT_1_12(335, "1.12"),
/**
* Minecraft 1.12.1.
*/
MINECRAFT_1_12_1(338, "1.12.1"), MINECRAFT_1_12_1(338, "1.12.1"),
/**
* Minecraft 1.12.2.
*/
MINECRAFT_1_12_2(340, "1.12.2"), MINECRAFT_1_12_2(340, "1.12.2"),
/**
* Minecraft 1.13.
*/
MINECRAFT_1_13(393, "1.13"), MINECRAFT_1_13(393, "1.13"),
/**
* Minecraft 1.13.1.
*/
MINECRAFT_1_13_1(401, "1.13.1"), MINECRAFT_1_13_1(401, "1.13.1"),
/**
* Minecraft 1.13.2.
*/
MINECRAFT_1_13_2(404, "1.13.2"), MINECRAFT_1_13_2(404, "1.13.2"),
/**
* Minecraft 1.14.
*/
MINECRAFT_1_14(477, "1.14"), MINECRAFT_1_14(477, "1.14"),
/**
* Minecraft 1.14.1.
*/
MINECRAFT_1_14_1(480, "1.14.1"), MINECRAFT_1_14_1(480, "1.14.1"),
/**
* Minecraft 1.14.2.
*/
MINECRAFT_1_14_2(485, "1.14.2"), MINECRAFT_1_14_2(485, "1.14.2"),
/**
* Minecraft 1.14.3.
*/
MINECRAFT_1_14_3(490, "1.14.3"), MINECRAFT_1_14_3(490, "1.14.3"),
/**
* Minecraft 1.14.4.
*/
MINECRAFT_1_14_4(498, "1.14.4"), MINECRAFT_1_14_4(498, "1.14.4"),
/**
* Minecraft 1.15.
*/
MINECRAFT_1_15(573, "1.15"), MINECRAFT_1_15(573, "1.15"),
/**
* Minecraft 1.15.1.
*/
MINECRAFT_1_15_1(575, "1.15.1"), MINECRAFT_1_15_1(575, "1.15.1"),
/**
* Minecraft 1.15.2.
*/
MINECRAFT_1_15_2(578, "1.15.2"), MINECRAFT_1_15_2(578, "1.15.2"),
/**
* Minecraft 1.16.
*/
MINECRAFT_1_16(735, "1.16"), MINECRAFT_1_16(735, "1.16"),
/**
* Minecraft 1.16.1.
*/
MINECRAFT_1_16_1(736, "1.16.1"), MINECRAFT_1_16_1(736, "1.16.1"),
/**
* Minecraft 1.16.2.
*/
MINECRAFT_1_16_2(751, "1.16.2"), MINECRAFT_1_16_2(751, "1.16.2"),
/**
* Minecraft 1.16.3.
*/
MINECRAFT_1_16_3(753, "1.16.3"), MINECRAFT_1_16_3(753, "1.16.3"),
/**
* Minecraft 1.16.4 to 1.16.5.
*/
MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"), MINECRAFT_1_16_4(754, "1.16.4", "1.16.5"),
/**
* Minecraft 1.17.
*/
MINECRAFT_1_17(755, "1.17"), MINECRAFT_1_17(755, "1.17"),
/**
* Minecraft 1.17.1.
*/
MINECRAFT_1_17_1(756, "1.17.1"), MINECRAFT_1_17_1(756, "1.17.1"),
/**
* Minecraft 1.18 to 1.18.1.
*/
MINECRAFT_1_18(757, "1.18", "1.18.1"), MINECRAFT_1_18(757, "1.18", "1.18.1"),
/**
* Minecraft 1.18.2.
*/
MINECRAFT_1_18_2(758, "1.18.2"), MINECRAFT_1_18_2(758, "1.18.2"),
/**
* Minecraft 1.19.
*/
MINECRAFT_1_19(759, "1.19"), MINECRAFT_1_19(759, "1.19"),
/**
* Minecraft 1.19.1 to 1.19.2.
*/
MINECRAFT_1_19_1(760, "1.19.1", "1.19.2"), MINECRAFT_1_19_1(760, "1.19.1", "1.19.2"),
/**
* Minecraft 1.19.3.
*/
MINECRAFT_1_19_3(761, "1.19.3"), MINECRAFT_1_19_3(761, "1.19.3"),
/**
* Minecraft 1.19.4.
*/
MINECRAFT_1_19_4(762, "1.19.4"), MINECRAFT_1_19_4(762, "1.19.4"),
/**
* Minecraft 1.20 to 1.20.1.
*/
MINECRAFT_1_20(763, "1.20", "1.20.1"), MINECRAFT_1_20(763, "1.20", "1.20.1"),
/**
* Minecraft 1.20.2.
*/
MINECRAFT_1_20_2(764, "1.20.2"), MINECRAFT_1_20_2(764, "1.20.2"),
/**
* Minecraft 1.20.3 to 1.20.4.
*/
MINECRAFT_1_20_3(765, "1.20.3", "1.20.4"), MINECRAFT_1_20_3(765, "1.20.3", "1.20.4"),
/**
* Minecraft 1.20.5 to 1.20.6.
*/
MINECRAFT_1_20_5(766, "1.20.5", "1.20.6"), MINECRAFT_1_20_5(766, "1.20.5", "1.20.6"),
/**
* Minecraft 1.21 to 1.21.1.
*/
MINECRAFT_1_21(767, "1.21", "1.21.1"), MINECRAFT_1_21(767, "1.21", "1.21.1"),
/**
* Minecraft 1.21.2 to 1.21.3.
*/
MINECRAFT_1_21_2(768, "1.21.2", "1.21.3"), MINECRAFT_1_21_2(768, "1.21.2", "1.21.3"),
/**
* Minecraft 1.21.4.
*/
MINECRAFT_1_21_4(769, "1.21.4"), MINECRAFT_1_21_4(769, "1.21.4"),
/**
* Minecraft 1.21.5.
*/
MINECRAFT_1_21_5(770, "1.21.5"), MINECRAFT_1_21_5(770, "1.21.5"),
/**
* Minecraft 1.21.6.
*/
MINECRAFT_1_21_6(771, "1.21.6"), MINECRAFT_1_21_6(771, "1.21.6"),
/**
* Minecraft 1.21.7 to 1.21.8.
*/
MINECRAFT_1_21_7(772, "1.21.7", "1.21.8"), MINECRAFT_1_21_7(772, "1.21.7", "1.21.8"),
/**
* Minecraft 1.21.9 to 1.21.10.
*/
MINECRAFT_1_21_9(773, "1.21.9", "1.21.10"), MINECRAFT_1_21_9(773, "1.21.9", "1.21.10"),
/**
* Minecraft 1.21.11.
*/
MINECRAFT_1_21_11(774, "1.21.11"); MINECRAFT_1_21_11(774, "1.21.11");
private static final int SNAPSHOT_BIT = 30; private static final int SNAPSHOT_BIT = 30;

View File

@@ -15,7 +15,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* Represents three different states of a setting. * Represents three different states of a setting.
* *
* <p>Possible values:</p> * <p>Possible values:</p>
* <p></p> *
* <ul> * <ul>
* <li>{@link #TRUE} - a positive setting</li> * <li>{@link #TRUE} - a positive setting</li>
* <li>{@link #FALSE} - a negative (negated) setting</li> * <li>{@link #FALSE} - a negative (negated) setting</li>

View File

@@ -12,18 +12,37 @@ package com.velocitypowered.api.plugin;
*/ */
public class InvalidPluginException extends Exception { public class InvalidPluginException extends Exception {
/**
* Creates a new exception with no detail message.
*/
public InvalidPluginException() { public InvalidPluginException() {
super(); super();
} }
/**
* Creates a new exception with the specified detail message.
*
* @param message the detail message
*/
public InvalidPluginException(String message) { public InvalidPluginException(String message) {
super(message); super(message);
} }
/**
* Creates a new exception with the specified detail message and cause.
*
* @param message the detail message
* @param cause the cause of the exception
*/
public InvalidPluginException(String message, Throwable cause) { public InvalidPluginException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
/**
* Creates a new exception with the specified cause.
*
* @param cause the cause of the exception
*/
public InvalidPluginException(Throwable cause) { public InvalidPluginException(Throwable cause) {
super(cause); super(cause);
} }

View File

@@ -96,6 +96,12 @@ public interface PluginDescription {
return ImmutableSet.of(); return ImmutableSet.of();
} }
/**
* Gets a specific dependency of the {@link Plugin} by its ID.
*
* @param id the ID of the dependency to look up
* @return an {@link Optional} containing the matching {@link PluginDependency}, or empty if not found
*/
default Optional<PluginDependency> getDependency(String id) { default Optional<PluginDependency> getDependency(String id) {
return Optional.empty(); return Optional.empty();
} }

View File

@@ -150,6 +150,8 @@ public interface Player extends
/** /**
* Returns the player's game profile. * Returns the player's game profile.
*
* @return the player's profile
*/ */
GameProfile getGameProfile(); GameProfile getGameProfile();
@@ -242,10 +244,10 @@ public interface Player extends
* Gets the {@link ResourcePackInfo} of the currently applied * Gets the {@link ResourcePackInfo} of the currently applied
* resource-pack or null if none. * resource-pack or null if none.
* *
* <p> Note that since 1.20.3 it is no longer recommended to use * <p>Note that since 1.20.3 it is no longer recommended to use
* this method as it will only return the last applied * this method as it will only return the last applied
* resource pack. To get all applied resource packs, use * resource pack. To get all applied resource packs, use
* {@link #getAppliedResourcePacks()} instead. </p> * {@link #getAppliedResourcePacks()} instead.</p>
* *
* @return the applied resource pack or null if none. * @return the applied resource pack or null if none.
*/ */
@@ -258,10 +260,10 @@ public interface Player extends
* the user is currently downloading or is currently * the user is currently downloading or is currently
* prompted to install or null if none. * prompted to install or null if none.
* *
* <p> Note that since 1.20.3 it is no longer recommended to use * <p>Note that since 1.20.3 it is no longer recommended to use
* this method as it will only return the last pending * this method as it will only return the last pending
* resource pack. To get all pending resource packs, use * resource pack. To get all pending resource packs, use
* {@link #getPendingResourcePacks()} instead. </p> * {@link #getPendingResourcePacks()} instead.</p>
* *
* @return the pending resource pack or null if none * @return the pending resource pack or null if none
*/ */
@@ -313,6 +315,7 @@ public interface Player extends
/** /**
* {@inheritDoc} * {@inheritDoc}
*
* <p><strong>Note that this method does not send a plugin message to the server the player * <p><strong>Note that this method does not send a plugin message to the server the player
* is connected to.</strong> You should only use this method if you are trying to communicate * is connected to.</strong> You should only use this method if you are trying to communicate
* with a mod that is installed on the player's client.</p> * with a mod that is installed on the player's client.</p>
@@ -336,7 +339,6 @@ public interface Player extends
Component.text(getUsername())))); Component.text(getUsername()))));
} }
/** /**
* Gets the player's client brand. * Gets the player's client brand.
* *
@@ -384,12 +386,11 @@ public interface Player extends
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
*
* @apiNote <b>This method is not currently implemented in Velocity * @apiNote <b>This method is not currently implemented in Velocity
* and will not perform any actions.</b> * and will not perform any actions.</b>
* @see #playSound(Sound, Sound.Emitter) * @see #playSound(Sound, Sound.Emitter)
* @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported"> * @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported">
* Unsupported Adventure Operations</a> * Unsupported Adventure Operations</a>
*/ */
@Override @Override
default void playSound(@NotNull Sound sound) { default void playSound(@NotNull Sound sound) {
@@ -402,7 +403,7 @@ public interface Player extends
* and will not perform any actions.</b> * and will not perform any actions.</b>
* @see #playSound(Sound, Sound.Emitter) * @see #playSound(Sound, Sound.Emitter)
* @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported"> * @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported">
* Unsupported Adventure Operations</a> * Unsupported Adventure Operations</a>
*/ */
@Override @Override
default void playSound(@NotNull Sound sound, double x, double y, double z) { default void playSound(@NotNull Sound sound, double x, double y, double z) {
@@ -445,7 +446,7 @@ public interface Player extends
* and will not perform any actions.</b> * and will not perform any actions.</b>
* *
* @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported"> * @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported">
* Unsupported Adventure Operations</a> * Unsupported Adventure Operations</a>
*/ */
@Override @Override
default void openBook(@NotNull Book book) { default void openBook(@NotNull Book book) {
@@ -458,7 +459,7 @@ public interface Player extends
* and will not perform any actions.</b> * and will not perform any actions.</b>
* *
* @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported"> * @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported">
* Unsupported Adventure Operations</a> * Unsupported Adventure Operations</a>
*/ */
@Override @Override
default void showDialog(@NotNull DialogLike dialog) { default void showDialog(@NotNull DialogLike dialog) {
@@ -471,7 +472,7 @@ public interface Player extends
* and will not perform any actions.</b> * and will not perform any actions.</b>
* *
* @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported"> * @see <a href="https://docs.papermc.io/velocity/dev/pitfalls/#audience-operations-are-not-fully-supported">
* Unsupported Adventure Operations</a> * Unsupported Adventure Operations</a>
*/ */
@Override @Override
default void closeDialog() { default void closeDialog() {
@@ -521,4 +522,4 @@ public interface Player extends
* @sinceMinecraft 1.21 * @sinceMinecraft 1.21
*/ */
void setServerLinks(@NotNull List<ServerLink> links); void setServerLinks(@NotNull List<ServerLink> links);
} }

View File

@@ -28,7 +28,6 @@ public interface IdentifiedKey extends KeySigned {
*/ */
PublicKey getSignedPublicKey(); PublicKey getSignedPublicKey();
/** /**
* Validates a signature against this public key. * Validates a signature against this public key.
* *
@@ -59,7 +58,15 @@ public interface IdentifiedKey extends KeySigned {
* The different versions of player keys, per Minecraft version. * The different versions of player keys, per Minecraft version.
*/ */
enum Revision implements Ordered<Revision> { enum Revision implements Ordered<Revision> {
/**
* Represents the original key revision introduced in Minecraft 1.19.
* Keys are not tied to a specific player identity.
*/
GENERIC_V1(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19)), GENERIC_V1(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19)),
/**
* Represents the key revision introduced in Minecraft 1.19.1.
* Keys are cryptographically linked to player identities.
*/
LINKED_V2(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19_1)); LINKED_V2(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19_1));
final Set<Revision> backwardsCompatibleTo; final Set<Revision> backwardsCompatibleTo;
@@ -69,11 +76,21 @@ public interface IdentifiedKey extends KeySigned {
this.backwardsCompatibleTo = backwardsCompatibleTo; this.backwardsCompatibleTo = backwardsCompatibleTo;
this.applicableTo = applicableTo; this.applicableTo = applicableTo;
} }
/**
* Returns the set of revisions that this revision is backwards-compatible with.
*
* @return a set of compatible earlier revisions
*/
public Set<Revision> getBackwardsCompatibleTo() { public Set<Revision> getBackwardsCompatibleTo() {
return backwardsCompatibleTo; return backwardsCompatibleTo;
} }
/**
* Returns the set of Minecraft protocol versions this revision applies to.
*
* @return a set of applicable protocol versions
*/
public Set<ProtocolVersion> getApplicableTo() { public Set<ProtocolVersion> getApplicableTo() {
return applicableTo; return applicableTo;
} }

View File

@@ -34,7 +34,6 @@ public interface KeySigned {
*/ */
Instant getExpiryTemporal(); Instant getExpiryTemporal();
/** /**
* Check if the signature has expired. * Check if the signature has expired.
* *
@@ -56,6 +55,7 @@ public interface KeySigned {
* Validates the signature, expiry temporal and key against the * Validates the signature, expiry temporal and key against the
* signer public key. Note: This will **not** check for * signer public key. Note: This will **not** check for
* expiry. You can check for expiry with {@link KeySigned#hasExpired()}. * expiry. You can check for expiry with {@link KeySigned#hasExpired()}.
*
* <p>DOES NOT WORK YET FOR MESSAGES AND COMMANDS!</p> * <p>DOES NOT WORK YET FOR MESSAGES AND COMMANDS!</p>
* Addendum: Does not work for 1.19.1 until the user has authenticated. * Addendum: Does not work for 1.19.1 until the user has authenticated.
* *

View File

@@ -31,6 +31,11 @@ public final class LegacyChannelIdentifier implements ChannelIdentifier {
this.name = name; this.name = name;
} }
/**
* Returns the name of this legacy plugin message channel.
*
* @return the channel name
*/
public String getName() { public String getName() {
return name; return name;
} }

View File

@@ -84,14 +84,29 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
return create(key.namespace(), key.value()); return create(key.namespace(), key.value());
} }
/**
* Returns the namespace of this channel identifier.
*
* @return the namespace string (e.g., {@code minecraft})
*/
public String getNamespace() { public String getNamespace() {
return namespace; return namespace;
} }
/**
* Returns the name of the channel within its namespace.
*
* @return the channel name string
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Converts this channel identifier to a {@link Key} object.
*
* @return a {@link Key} representing this identifier
*/
public Key asKey() { public Key asKey() {
return Key.key(namespace, name); return Key.key(namespace, name);
} }

View File

@@ -86,8 +86,17 @@ public interface PlayerSettings {
* The client's current chat display mode. * The client's current chat display mode.
*/ */
enum ChatMode { enum ChatMode {
/**
* Chat is fully visible.
*/
SHOWN, SHOWN,
/**
* Only command messages are shown.
*/
COMMANDS_ONLY, COMMANDS_ONLY,
/**
* Chat is completely hidden.
*/
HIDDEN HIDDEN
} }
@@ -95,7 +104,13 @@ public interface PlayerSettings {
* The player's selected dominant hand. * The player's selected dominant hand.
*/ */
enum MainHand { enum MainHand {
/**
* This scope defines the left hand.
*/
LEFT, LEFT,
/**
* This scope defines the right hand.
*/
RIGHT RIGHT
} }
@@ -103,8 +118,17 @@ public interface PlayerSettings {
* The client's current "Particles" option state. * The client's current "Particles" option state.
*/ */
enum ParticleStatus { enum ParticleStatus {
/**
* All particles are shown.
*/
ALL, ALL,
/**
* A reduced number of particles are shown.
*/
DECREASED, DECREASED,
/**
* Minimal particle effects are shown.
*/
MINIMAL MINIMAL
} }
} }

View File

@@ -87,7 +87,6 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
/** /**
* Returns a copy of this {@link ResourcePackInfo} instance as a builder, using the new URL. * Returns a copy of this {@link ResourcePackInfo} instance as a builder, using the new URL.
* <p/>
* It is <b>not</b> guaranteed that * It is <b>not</b> guaranteed that
* {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)} * {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)}
* is true, because the {@link ResourcePackInfo#getOrigin()} and * is true, because the {@link ResourcePackInfo#getOrigin()} and
@@ -108,6 +107,7 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* Sets the id of the resource pack. * Sets the id of the resource pack.
* *
* @param id the id the resource-pack * @param id the id the resource-pack
* @return this builder instance
*/ */
Builder setId(UUID id); Builder setId(UUID id);
@@ -128,6 +128,7 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* the player will be disconnected from the network * the player will be disconnected from the network
* *
* @param shouldForce whether or not to force the client to accept the resource pack * @param shouldForce whether or not to force the client to accept the resource pack
* @return this builder instance
*/ */
Builder setShouldForce(boolean shouldForce); Builder setShouldForce(boolean shouldForce);
@@ -140,6 +141,7 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* before downloading. * before downloading.
* *
* @param hash the SHA-1 hash of the resource-pack * @param hash the SHA-1 hash of the resource-pack
* @return this builder instance
*/ */
Builder setHash(@Nullable byte[] hash); Builder setHash(@Nullable byte[] hash);
@@ -148,6 +150,7 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* This will only display if the client version is 1.17 or newer. * This will only display if the client version is 1.17 or newer.
* *
* @param prompt the component to display * @param prompt the component to display
* @return this builder instance
*/ */
Builder setPrompt(@Nullable Component prompt); Builder setPrompt(@Nullable Component prompt);
@@ -174,4 +177,4 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
*/ */
PLUGIN_ON_PROXY PLUGIN_ON_PROXY
} }
} }

View File

@@ -17,34 +17,74 @@ public final class SkinParts {
private final byte bitmask; private final byte bitmask;
/**
* Constructs a new SkinParts object with the provided bitmask.
*
* @param skinBitmask the bitmask representing which skin parts are enabled
*/
public SkinParts(byte skinBitmask) { public SkinParts(byte skinBitmask) {
this.bitmask = skinBitmask; this.bitmask = skinBitmask;
} }
/**
* Returns whether the player has a cape enabled.
*
* @return true if the cape is enabled, false otherwise
*/
public boolean hasCape() { public boolean hasCape() {
return (bitmask & 1) == 1; return (bitmask & 1) == 1;
} }
/**
* Returns whether the player has a jacket enabled.
*
* @return true if the jacket is enabled, false otherwise
*/
public boolean hasJacket() { public boolean hasJacket() {
return ((bitmask >> 1) & 1) == 1; return ((bitmask >> 1) & 1) == 1;
} }
/**
* Returns whether the player has a left sleeve enabled.
*
* @return true if the left sleeve is enabled, false otherwise
*/
public boolean hasLeftSleeve() { public boolean hasLeftSleeve() {
return ((bitmask >> 2) & 1) == 1; return ((bitmask >> 2) & 1) == 1;
} }
/**
* Returns whether the player has a right sleeve enabled.
*
* @return true if the right sleeve is enabled, false otherwise
*/
public boolean hasRightSleeve() { public boolean hasRightSleeve() {
return ((bitmask >> 3) & 1) == 1; return ((bitmask >> 3) & 1) == 1;
} }
/**
* Returns whether the player has their left pants enabled.
*
* @return true if the left pants are enabled, false otherwise
*/
public boolean hasLeftPants() { public boolean hasLeftPants() {
return ((bitmask >> 4) & 1) == 1; return ((bitmask >> 4) & 1) == 1;
} }
/**
* Returns whether the player has their right pants enabled.
*
* @return true if the right pants are enabled, false otherwise
*/
public boolean hasRightPants() { public boolean hasRightPants() {
return ((bitmask >> 5) & 1) == 1; return ((bitmask >> 5) & 1) == 1;
} }
/**
* Returns whether the player has a hat enabled.
*
* @return true if the hat is enabled, false otherwise
*/
public boolean hasHat() { public boolean hasHat() {
return ((bitmask >> 6) & 1) == 1; return ((bitmask >> 6) & 1) == 1;
} }

View File

@@ -237,8 +237,11 @@ public interface TabListEntry extends KeyIdentifiable {
/** /**
* Sets the {@link IdentifiedKey} of the {@link TabListEntry}. * Sets the {@link IdentifiedKey} of the {@link TabListEntry}.
*
* <p>This only works for players currently <b>not</b> connected to this proxy.</p> * <p>This only works for players currently <b>not</b> connected to this proxy.</p>
*
* <p>For any player currently connected to this proxy this will be filled automatically.</p> * <p>For any player currently connected to this proxy this will be filled automatically.</p>
*
* <p>Will ignore mismatching key revisions data.</p> * <p>Will ignore mismatching key revisions data.</p>
* *
* @param chatSession session to set * @param chatSession session to set

View File

@@ -147,7 +147,6 @@ public final class QueryResponse {
return plugins; return plugins;
} }
/** /**
* Creates a new {@link Builder} instance from data represented by this response, so that you * Creates a new {@link Builder} instance from data represented by this response, so that you
* may create a new {@link QueryResponse} with new data. It is guaranteed that * may create a new {@link QueryResponse} with new data. It is guaranteed that
@@ -434,14 +433,31 @@ public final class QueryResponse {
this.version = version; this.version = version;
} }
/**
* Gets the name of the plugin.
*
* @return the plugin name
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Gets the version of the plugin, if available.
*
* @return an {@link Optional} containing the version if present
*/
public Optional<String> getVersion() { public Optional<String> getVersion() {
return Optional.ofNullable(version); return Optional.ofNullable(version);
} }
/**
* Creates a new {@link PluginInformation} instance with the given name and version.
*
* @param name the name of the plugin
* @param version the version of the plugin (nullable)
* @return a new {@link PluginInformation} instance
*/
public static PluginInformation of(String name, @Nullable String version) { public static PluginInformation of(String name, @Nullable String version) {
return new PluginInformation(name, version); return new PluginInformation(name, version);
} }

View File

@@ -32,11 +32,21 @@ public final class ServerInfo implements Comparable<ServerInfo> {
this.address = Preconditions.checkNotNull(address, "address"); this.address = Preconditions.checkNotNull(address, "address");
} }
public final String getName() { /**
* Gets the name of the server.
*
* @return the name of the server
*/
public String getName() {
return name; return name;
} }
public final InetSocketAddress getAddress() { /**
* Gets the network address of the server.
*
* @return the {@link InetSocketAddress} of the server
*/
public InetSocketAddress getAddress() {
return address; return address;
} }
@@ -49,7 +59,7 @@ public final class ServerInfo implements Comparable<ServerInfo> {
} }
@Override @Override
public final boolean equals(@Nullable Object o) { public boolean equals(@Nullable Object o) {
if (this == o) { if (this == o) {
return true; return true;
} }
@@ -62,7 +72,7 @@ public final class ServerInfo implements Comparable<ServerInfo> {
} }
@Override @Override
public final int hashCode() { public int hashCode() {
return Objects.hash(name, address); return Objects.hash(name, address);
} }

View File

@@ -22,7 +22,6 @@ import java.util.UUID;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* Represents a 1.7 and above server list ping response. This class is immutable. * Represents a 1.7 and above server list ping response. This class is immutable.
*/ */
@@ -34,6 +33,14 @@ public final class ServerPing {
private final @Nullable Favicon favicon; private final @Nullable Favicon favicon;
private final @Nullable ModInfo modinfo; private final @Nullable ModInfo modinfo;
/**
* Constructs an initial ServerPing instance.
*
* @param version the version of the server
* @param players the players on the server, or {@code null} if not shown
* @param description the MOTD for the server
* @param favicon the server's favicon, or {@code null} if not set
*/
public ServerPing(Version version, @Nullable Players players, public ServerPing(Version version, @Nullable Players players,
net.kyori.adventure.text.Component description, @Nullable Favicon favicon) { net.kyori.adventure.text.Component description, @Nullable Favicon favicon) {
this(version, players, description, favicon, ModInfo.DEFAULT); this(version, players, description, favicon, ModInfo.DEFAULT);
@@ -58,23 +65,48 @@ public final class ServerPing {
this.modinfo = modinfo; this.modinfo = modinfo;
} }
/**
* Gets the version shown to the client during the ping.
*
* @return the version
*/
public Version getVersion() { public Version getVersion() {
return version; return version;
} }
/**
* Gets the player information shown to the client.
*
* @return the player information, or empty if not shown
*/
public Optional<Players> getPlayers() { public Optional<Players> getPlayers() {
return Optional.ofNullable(players); return Optional.ofNullable(players);
} }
/**
* Gets the description (MOTD) component shown in the ping response.
*
* @return the description component
*/
@Nullable @Nullable
public Component getDescriptionComponent() { public Component getDescriptionComponent() {
return description; return description;
} }
/**
* Gets the favicon sent to the client.
*
* @return the favicon, or empty if not present
*/
public Optional<Favicon> getFavicon() { public Optional<Favicon> getFavicon() {
return Optional.ofNullable(favicon); return Optional.ofNullable(favicon);
} }
/**
* Gets the mod info sent to the client.
*
* @return the mod info, or empty if not present
*/
public Optional<ModInfo> getModinfo() { public Optional<ModInfo> getModinfo() {
return Optional.ofNullable(modinfo); return Optional.ofNullable(modinfo);
} }
@@ -139,6 +171,11 @@ public final class ServerPing {
return builder; return builder;
} }
/**
* Creates a new {@link Builder} for constructing a {@link ServerPing}.
*
* @return a new ServerPing builder
*/
public static Builder builder() { public static Builder builder() {
return new Builder(); return new Builder();
} }
@@ -346,34 +383,74 @@ public final class ServerPing {
description, favicon, nullOutModinfo ? null : new ModInfo(modType, mods)); description, favicon, nullOutModinfo ? null : new ModInfo(modType, mods));
} }
/**
* Gets the version currently set in the builder.
*
* @return the version
*/
public Version getVersion() { public Version getVersion() {
return version; return version;
} }
/**
* Gets the number of players online.
*
* @return the online player count
*/
public int getOnlinePlayers() { public int getOnlinePlayers() {
return onlinePlayers; return onlinePlayers;
} }
/**
* Gets the maximum player capacity.
*
* @return the max player count
*/
public int getMaximumPlayers() { public int getMaximumPlayers() {
return maximumPlayers; return maximumPlayers;
} }
/**
* Gets the sample players shown in the ping.
*
* @return the sample player list
*/
public List<SamplePlayer> getSamplePlayers() { public List<SamplePlayer> getSamplePlayers() {
return samplePlayers; return samplePlayers;
} }
/**
* Gets the description component currently set in the builder.
*
* @return the server description, or empty if unset
*/
public Optional<Component> getDescriptionComponent() { public Optional<Component> getDescriptionComponent() {
return Optional.ofNullable(description); return Optional.ofNullable(description);
} }
/**
* Gets the favicon currently set in the builder.
*
* @return the favicon, or empty if none
*/
public Optional<Favicon> getFavicon() { public Optional<Favicon> getFavicon() {
return Optional.ofNullable(favicon); return Optional.ofNullable(favicon);
} }
/**
* Gets the type of mod loader (e.g., "FML").
*
* @return the mod type string
*/
public String getModType() { public String getModType() {
return modType; return modType;
} }
/**
* Gets the list of mods reported in the ping.
*
* @return the mod list
*/
public List<ModInfo.Mod> getMods() { public List<ModInfo.Mod> getMods() {
return mods; return mods;
} }
@@ -417,10 +494,20 @@ public final class ServerPing {
this.name = Preconditions.checkNotNull(name, "name"); this.name = Preconditions.checkNotNull(name, "name");
} }
/**
* Gets the protocol number associated with the server version.
*
* @return the protocol version number
*/
public int getProtocol() { public int getProtocol() {
return protocol; return protocol;
} }
/**
* Gets the user-facing name of the server version.
*
* @return the version name
*/
public String getName() { public String getName() {
return name; return name;
} }
@@ -474,14 +561,29 @@ public final class ServerPing {
this.sample = ImmutableList.copyOf(sample); this.sample = ImmutableList.copyOf(sample);
} }
/**
* Gets the number of online players.
*
* @return the number of online players
*/
public int getOnline() { public int getOnline() {
return online; return online;
} }
/**
* Gets the maximum number of players the server claims it can hold.
*
* @return the maximum number of players
*/
public int getMax() { public int getMax() {
return max; return max;
} }
/**
* Gets a sample list of online players.
*
* @return the sample players
*/
public List<SamplePlayer> getSample() { public List<SamplePlayer> getSample() {
return sample == null ? ImmutableList.of() : sample; return sample == null ? ImmutableList.of() : sample;
} }
@@ -519,22 +621,47 @@ public final class ServerPing {
*/ */
public static final class SamplePlayer { public static final class SamplePlayer {
/**
* A constant representing an anonymous sample player with a null UUID and generic name.
*/
public static final SamplePlayer ANONYMOUS = new SamplePlayer( public static final SamplePlayer ANONYMOUS = new SamplePlayer(
"Anonymous Player", "Anonymous Player",
new UUID(0L, 0L) new UUID(0L, 0L)
); );
/**
* The legacy string name of the player.
*/
private final String name; private final String name;
/**
* The unique identifier (UUID) of the player.
*/
private final UUID id; private final UUID id;
/**
* Constructs a SamplePlayer with the given name and UUID.
*
* @param name the name of the player
* @param id the UUID of the player
*/
public SamplePlayer(String name, UUID id) { public SamplePlayer(String name, UUID id) {
this.name = name; this.name = name;
this.id = id; this.id = id;
} }
/**
* Gets the legacy string name of the sample player.
*
* @return the player name
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Gets the UUID of the sample player.
*
* @return the player UUID
*/
public UUID getId() { public UUID getId() {
return id; return id;
} }

View File

@@ -200,14 +200,29 @@ public final class GameProfile {
this.signature = Preconditions.checkNotNull(signature, "signature"); this.signature = Preconditions.checkNotNull(signature, "signature");
} }
/**
* Returns the name of this property.
*
* @return the property name
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Returns the value of this property.
*
* @return the property value
*/
public String getValue() { public String getValue() {
return value; return value;
} }
/**
* Returns the Mojang-provided signature for this property.
*
* @return the property signature
*/
public String getSignature() { public String getSignature() {
return signature; return signature;
} }

View File

@@ -18,6 +18,10 @@ import java.util.Objects;
*/ */
public final class ModInfo { public final class ModInfo {
/**
* The default mod info used when no mods are present.
* Typically used for Forge-compatible connections that require a placeholder.
*/
public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of()); public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of());
private final String type; private final String type;
@@ -34,10 +38,20 @@ public final class ModInfo {
this.modList = ImmutableList.copyOf(modList); this.modList = ImmutableList.copyOf(modList);
} }
/**
* Returns the Forge mod list type (e.g., "FML").
*
* @return the mod list type
*/
public String getType() { public String getType() {
return type; return type;
} }
/**
* Returns an immutable list of all mods in this mod list.
*
* @return the list of mods
*/
public List<Mod> getMods() { public List<Mod> getMods() {
return modList; return modList;
} }
@@ -89,10 +103,20 @@ public final class ModInfo {
Preconditions.checkArgument(version.length() < 128, "mod version is too long"); Preconditions.checkArgument(version.length() < 128, "mod version is too long");
} }
/**
* Returns the mod ID (identifier string).
*
* @return the mod ID
*/
public String getId() { public String getId() {
return id; return id;
} }
/**
* Returns the mod version string.
*
* @return the mod version
*/
public String getVersion() { public String getVersion() {
return version; return version;
} }

View File

@@ -33,14 +33,29 @@ public final class ProxyVersion {
this.version = Preconditions.checkNotNull(version, "version"); this.version = Preconditions.checkNotNull(version, "version");
} }
/**
* Gets the name of the proxy implementation.
*
* @return the name of the proxy
*/
public String getName() { public String getName() {
return name; return name;
} }
/**
* Gets the vendor of the proxy implementation.
*
* @return the vendor of the proxy
*/
public String getVendor() { public String getVendor() {
return vendor; return vendor;
} }
/**
* Gets the version of the proxy implementation.
*
* @return the version of the proxy
*/
public String getVersion() { public String getVersion() {
return version; return version;
} }

View File

@@ -38,6 +38,7 @@ public final class ServerLink {
* *
* @param label a custom component label to display * @param label a custom component label to display
* @param link the URL to open when clicked * @param link the URL to open when clicked
* @return a {@link ServerLink} instance with the given label and URL
*/ */
public static ServerLink serverLink(Component label, String link) { public static ServerLink serverLink(Component label, String link) {
return new ServerLink(label, link); return new ServerLink(label, link);
@@ -48,6 +49,7 @@ public final class ServerLink {
* *
* @param type the {@link Type built-in type} of link * @param type the {@link Type built-in type} of link
* @param link the URL to open when clicked * @param link the URL to open when clicked
* @return a {@link ServerLink} instance with the given type and URL
*/ */
public static ServerLink serverLink(Type type, String link) { public static ServerLink serverLink(Type type, String link) {
return new ServerLink(type, link); return new ServerLink(type, link);
@@ -86,15 +88,45 @@ public final class ServerLink {
* @apiNote {@link Type#BUG_REPORT} links are shown on the connection error screen * @apiNote {@link Type#BUG_REPORT} links are shown on the connection error screen
*/ */
public enum Type { public enum Type {
/**
* A link to report bugs related to the server or gameplay.
*/
BUG_REPORT, BUG_REPORT,
/**
* A link to the server's community guidelines or rules.
*/
COMMUNITY_GUIDELINES, COMMUNITY_GUIDELINES,
/**
* A link to the servers support or help desk.
*/
SUPPORT, SUPPORT,
/**
* A link showing the current server or service status.
*/
STATUS, STATUS,
/**
* A link to provide feedback to the server staff or developers.
*/
FEEDBACK, FEEDBACK,
/**
* A link to the servers community hub or Discord.
*/
COMMUNITY, COMMUNITY,
/**
* A link to the server's main website.
*/
WEBSITE, WEBSITE,
/**
* A link to the server's forums.
*/
FORUMS, FORUMS,
/**
* A link to server or game-related news.
*/
NEWS, NEWS,
/**
* A link to announcements from the server team.
*/
ANNOUNCEMENTS ANNOUNCEMENTS
} }

View File

@@ -3,12 +3,12 @@ configurate3 = "3.7.3"
configurate4 = "4.2.0" configurate4 = "4.2.0"
flare = "2.0.1" flare = "2.0.1"
log4j = "2.25.3" log4j = "2.25.3"
netty = "4.2.7.Final" netty = "4.2.9.Final"
[plugins] [plugins]
fill = "io.papermc.fill.gradle:1.0.10" fill = "io.papermc.fill.gradle:1.0.10"
shadow = "com.gradleup.shadow:9.3.1" shadow = "com.gradleup.shadow:9.3.1"
spotless = "com.diffplug.spotless:8.2.0" spotless = "com.diffplug.spotless:8.2.1"
[libraries] [libraries]
adventure-bom = "net.kyori:adventure-bom:4.26.1" adventure-bom = "net.kyori:adventure-bom:4.26.1"
@@ -21,7 +21,7 @@ brigadier = "com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT"
bstats = "org.bstats:bstats-base:3.1.0" bstats = "org.bstats:bstats-base:3.1.0"
caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3"
checker-qual = "org.checkerframework:checker-qual:3.53.0" checker-qual = "org.checkerframework:checker-qual:3.53.0"
checkstyle = "com.puppycrawl.tools:checkstyle:10.9.3" checkstyle = "com.puppycrawl.tools:checkstyle:13.0.0"
completablefutures = "com.spotify:completable-futures:0.3.6" completablefutures = "com.spotify:completable-futures:0.3.6"
configurate3-hocon = { module = "org.spongepowered:configurate-hocon", version.ref = "configurate3" } configurate3-hocon = { module = "org.spongepowered:configurate-hocon", version.ref = "configurate3" }
configurate3-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate3" } configurate3-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate3" }
@@ -30,12 +30,12 @@ configurate4-hocon = { module = "org.spongepowered:configurate-hocon", version.r
configurate4-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate4" } configurate4-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate4" }
configurate4-gson = { module = "org.spongepowered:configurate-gson", version.ref = "configurate4" } configurate4-gson = { module = "org.spongepowered:configurate-gson", version.ref = "configurate4" }
disruptor = "com.lmax:disruptor:4.0.0" disruptor = "com.lmax:disruptor:4.0.0"
fastutil = "it.unimi.dsi:fastutil:8.5.15" fastutil = "it.unimi.dsi:fastutil:8.5.18"
flare-core = { module = "space.vectrix.flare:flare", version.ref = "flare" } flare-core = { module = "space.vectrix.flare:flare", version.ref = "flare" }
flare-fastutil = { module = "space.vectrix.flare:flare-fastutil", version.ref = "flare" } flare-fastutil = { module = "space.vectrix.flare:flare-fastutil", version.ref = "flare" }
jline = "org.jline:jline-terminal-jansi:3.30.6" jline = "org.jline:jline-terminal-jansi:3.30.6"
jopt = "net.sf.jopt-simple:jopt-simple:5.0.4" jopt = "net.sf.jopt-simple:jopt-simple:5.0.4"
junit = "org.junit.jupiter:junit-jupiter:5.14.2" junit = "org.junit.jupiter:junit-jupiter:6.0.2"
jspecify = "org.jspecify:jspecify:1.0.0" jspecify = "org.jspecify:jspecify:1.0.0"
kyori-ansi = "net.kyori:ansi:1.1.1" kyori-ansi = "net.kyori:ansi:1.1.1"
guava = "com.google.guava:guava:33.5.0-jre" guava = "com.google.guava:guava:33.5.0-jre"

View File

@@ -54,8 +54,8 @@ public class MoreByteBufUtils {
BufferPreference preferred = nativeStuff.preferredBufferType(); BufferPreference preferred = nativeStuff.preferredBufferType();
return switch (preferred) { return switch (preferred) {
case DIRECT_PREFERRED, HEAP_PREFERRED -> case DIRECT_PREFERRED, HEAP_PREFERRED ->
// The native prefers this type, but doesn't strictly require we provide it. // The native prefers this type, but doesn't strictly require we provide it.
true; true;
case DIRECT_REQUIRED -> buf.hasMemoryAddress(); case DIRECT_REQUIRED -> buf.hasMemoryAddress();
case HEAP_REQUIRED -> buf.hasArray(); case HEAP_REQUIRED -> buf.hasArray();
}; };

View File

@@ -14,10 +14,6 @@ application {
} }
tasks { tasks {
withType<Checkstyle> {
exclude("**/com/velocitypowered/proxy/protocol/packet/**")
}
jar { jar {
manifest { manifest {
attributes["Implementation-Title"] = "Velocity" attributes["Implementation-Title"] = "Velocity"
@@ -33,7 +29,7 @@ tasks {
transform(Log4j2PluginsCacheFileTransformer::class.java) transform(Log4j2PluginsCacheFileTransformer::class.java)
// Exclude all the collection types we don"t intend to use // Exclude all the collection types we don't intend to use
exclude("it/unimi/dsi/fastutil/booleans/**") exclude("it/unimi/dsi/fastutil/booleans/**")
exclude("it/unimi/dsi/fastutil/bytes/**") exclude("it/unimi/dsi/fastutil/bytes/**")
exclude("it/unimi/dsi/fastutil/chars/**") exclude("it/unimi/dsi/fastutil/chars/**")
@@ -42,7 +38,7 @@ tasks {
exclude("it/unimi/dsi/fastutil/longs/**") exclude("it/unimi/dsi/fastutil/longs/**")
exclude("it/unimi/dsi/fastutil/shorts/**") exclude("it/unimi/dsi/fastutil/shorts/**")
// Exclude the fastutil IO utilities - we don"t use them. // Exclude the fastutil IO utilities - we don't use them.
exclude("it/unimi/dsi/fastutil/io/**") exclude("it/unimi/dsi/fastutil/io/**")
// Exclude most of the int types - Object2IntMap have a values() method that returns an // Exclude most of the int types - Object2IntMap have a values() method that returns an

View File

@@ -650,7 +650,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
} }
/** /**
* Calls {@link #shutdown(boolean, Component)} with the default reason "Proxy shutting down." * Calls {@link #shutdown(boolean, Component)} with the default reason "Proxy shutting down.".
* *
* @param explicitExit whether the user explicitly shut down the proxy * @param explicitExit whether the user explicitly shut down the proxy
*/ */

View File

@@ -37,7 +37,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
* Modern (Minecraft 1.20.3+) ResourcePackHandler * Modern (Minecraft 1.20.3+) ResourcePackHandler.
*/ */
public final class ModernResourcePackHandler extends ResourcePackHandler { public final class ModernResourcePackHandler extends ResourcePackHandler {
private final ListMultimap<UUID, ResourcePackInfo> outstandingResourcePacks = private final ListMultimap<UUID, ResourcePackInfo> outstandingResourcePacks =

View File

@@ -118,6 +118,7 @@ public abstract sealed class ResourcePackHandler
/** /**
* Processes a client response to a sent resource-pack. * Processes a client response to a sent resource-pack.
*
* <p>Cases in which no action will be taken:</p> * <p>Cases in which no action will be taken:</p>
* <ul> * <ul>
* *

View File

@@ -545,6 +545,36 @@ public class VelocityEventManager implements EventManager {
} }
} }
private <E> void fire(final @Nullable CompletableFuture<E> future, final E event,
final int offset, final boolean currentlyAsync, final HandlerRegistration[] registrations) {
for (int i = offset; i < registrations.length; i++) {
final HandlerRegistration registration = registrations[i];
try {
final EventTask eventTask = registration.handler.executeAsync(event);
if (eventTask == null) {
continue;
}
final ContinuationTask<E> continuationTask = new ContinuationTask<>(eventTask,
registrations, future, event, i, currentlyAsync);
if (currentlyAsync || !eventTask.requiresAsync()) {
if (continuationTask.execute()) {
continue;
}
} else {
registration.plugin.getExecutorService().execute(continuationTask);
}
// fire will continue in another thread once the async task is
// executed and the continuation is resumed
return;
} catch (final Throwable t) {
logHandlerException(registration, t);
}
}
if (future != null) {
future.complete(event);
}
}
private static final int TASK_STATE_DEFAULT = 0; private static final int TASK_STATE_DEFAULT = 0;
private static final int TASK_STATE_EXECUTING = 1; private static final int TASK_STATE_EXECUTING = 1;
private static final int TASK_STATE_CONTINUE_IMMEDIATELY = 2; private static final int TASK_STATE_CONTINUE_IMMEDIATELY = 2;
@@ -669,40 +699,10 @@ public class VelocityEventManager implements EventManager {
} }
} }
private <E> void fire(final @Nullable CompletableFuture<E> future, final E event,
final int offset, final boolean currentlyAsync, final HandlerRegistration[] registrations) {
for (int i = offset; i < registrations.length; i++) {
final HandlerRegistration registration = registrations[i];
try {
final EventTask eventTask = registration.handler.executeAsync(event);
if (eventTask == null) {
continue;
}
final ContinuationTask<E> continuationTask = new ContinuationTask<>(eventTask,
registrations, future, event, i, currentlyAsync);
if (currentlyAsync || !eventTask.requiresAsync()) {
if (continuationTask.execute()) {
continue;
}
} else {
registration.plugin.getExecutorService().execute(continuationTask);
}
// fire will continue in another thread once the async task is
// executed and the continuation is resumed
return;
} catch (final Throwable t) {
logHandlerException(registration, t);
}
}
if (future != null) {
future.complete(event);
}
}
private static void logHandlerException( private static void logHandlerException(
final HandlerRegistration registration, final Throwable t) { final HandlerRegistration registration, final Throwable t) {
final PluginDescription pluginDescription = registration.plugin.getDescription(); final PluginDescription pluginDescription = registration.plugin.getDescription();
logger.error("Couldn't pass {} to {} {}", registration.eventType.getSimpleName(), logger.error("Couldn't pass {} to {} {}", registration.eventType.getSimpleName(),
pluginDescription.getId(), pluginDescription.getVersion().orElse(""), t); pluginDescription.getId(), pluginDescription.getVersion().orElse(""), t);
} }
} }

View File

@@ -633,7 +633,7 @@ public enum ProtocolUtils {
private static final int FORGE_MAX_ARRAY_LENGTH = Integer.MAX_VALUE & 0x1FFF9A; private static final int FORGE_MAX_ARRAY_LENGTH = Integer.MAX_VALUE & 0x1FFF9A;
/** /**
* Reads an byte array for legacy version 1.7 from the specified {@code buf} * Reads an byte array for legacy version 1.7 from the specified {@code buf}.
* *
* @param buf the buffer to read from * @param buf the buffer to read from
* @return the read byte array * @return the read byte array
@@ -671,7 +671,7 @@ public enum ProtocolUtils {
} }
/** /**
* Writes an byte array for legacy version 1.7 to the specified {@code buf} * Writes an byte array for legacy version 1.7 to the specified {@code buf}.
* *
* @param b array * @param b array
* @param buf buf * @param buf buf
@@ -695,7 +695,7 @@ public enum ProtocolUtils {
} }
/** /**
* Writes an {@link ByteBuf} for legacy version 1.7 to the specified {@code buf} * Writes an {@link ByteBuf} for legacy version 1.7 to the specified {@code buf}.
* *
* @param b array * @param b array
* @param buf buf * @param buf buf

View File

@@ -53,6 +53,13 @@ import java.util.function.Predicate;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a packet that contains the list of available commands, implementing {@link MinecraftPacket}.
*
* <p>The {@code AvailableCommandsPacket} is responsible for transmitting the set of commands
* that a player can execute. It provides the necessary information about available commands
* within the current session or game state.</p>
*/
public class AvailableCommandsPacket implements MinecraftPacket { public class AvailableCommandsPacket implements MinecraftPacket {
private static final Command<CommandSource> PLACEHOLDER_COMMAND = source -> 0; private static final Command<CommandSource> PLACEHOLDER_COMMAND = source -> 0;

View File

@@ -29,6 +29,10 @@ import java.util.UUID;
import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.bossbar.BossBar;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a packet used to manage boss bars.
* This packet can add, remove, or update a boss bar.
*/
public class BossBarPacket implements MinecraftPacket { public class BossBarPacket implements MinecraftPacket {
private static final Enum2IntMap<BossBar.Color> COLORS_TO_PROTOCOL = private static final Enum2IntMap<BossBar.Color> COLORS_TO_PROTOCOL =
@@ -70,6 +74,14 @@ public class BossBarPacket implements MinecraftPacket {
private int overlay; private int overlay;
private short flags; private short flags;
/**
* Creates a packet to add a new boss bar.
*
* @param id the UUID of the boss bar
* @param bar the {@link BossBar} instance
* @param name the {@link ComponentHolder} containing the boss bar's name
* @return a {@link BossBarPacket} to add a boss bar
*/
public static BossBarPacket createAddPacket( public static BossBarPacket createAddPacket(
final UUID id, final UUID id,
final BossBar bar, final BossBar bar,
@@ -86,6 +98,13 @@ public class BossBarPacket implements MinecraftPacket {
return packet; return packet;
} }
/**
* Creates a packet to remove an existing boss bar.
*
* @param id the UUID of the boss bar to remove
* @param bar the {@link BossBar} instance
* @return a {@link BossBarPacket} to remove a boss bar
*/
public static BossBarPacket createRemovePacket(final UUID id, final BossBar bar) { public static BossBarPacket createRemovePacket(final UUID id, final BossBar bar) {
final BossBarPacket packet = new BossBarPacket(); final BossBarPacket packet = new BossBarPacket();
packet.setUuid(id); packet.setUuid(id);
@@ -93,6 +112,13 @@ public class BossBarPacket implements MinecraftPacket {
return packet; return packet;
} }
/**
* Creates a packet to update the progress (percentage) of the boss bar.
*
* @param id the UUID of the boss bar
* @param bar the {@link BossBar} instance
* @return a {@link BossBarPacket} to update the boss bar's progress
*/
public static BossBarPacket createUpdateProgressPacket(final UUID id, final BossBar bar) { public static BossBarPacket createUpdateProgressPacket(final UUID id, final BossBar bar) {
final BossBarPacket packet = new BossBarPacket(); final BossBarPacket packet = new BossBarPacket();
packet.setUuid(id); packet.setUuid(id);
@@ -101,6 +127,14 @@ public class BossBarPacket implements MinecraftPacket {
return packet; return packet;
} }
/**
* Creates a packet to update the name of the boss bar.
*
* @param id the UUID of the boss bar
* @param bar the {@link BossBar} instance
* @param name the {@link ComponentHolder} containing the boss bar's new name
* @return a {@link BossBarPacket} to update the boss bar's name
*/
public static BossBarPacket createUpdateNamePacket( public static BossBarPacket createUpdateNamePacket(
final UUID id, final UUID id,
final BossBar bar, final BossBar bar,
@@ -113,6 +147,13 @@ public class BossBarPacket implements MinecraftPacket {
return packet; return packet;
} }
/**
* Creates a packet to update the style (color and overlay) of the boss bar.
*
* @param id the UUID of the boss bar
* @param bar the {@link BossBar} instance
* @return a {@link BossBarPacket} to update the boss bar's style
*/
public static BossBarPacket createUpdateStylePacket(final UUID id, final BossBar bar) { public static BossBarPacket createUpdateStylePacket(final UUID id, final BossBar bar) {
final BossBarPacket packet = new BossBarPacket(); final BossBarPacket packet = new BossBarPacket();
packet.setUuid(id); packet.setUuid(id);
@@ -122,6 +163,13 @@ public class BossBarPacket implements MinecraftPacket {
return packet; return packet;
} }
/**
* Creates a packet to update the properties of the boss bar.
*
* @param id the UUID of the boss bar
* @param bar the {@link BossBar} instance
* @return a {@link BossBarPacket} to update the boss bar's properties
*/
public static BossBarPacket createUpdatePropertiesPacket(final UUID id, final BossBar bar) { public static BossBarPacket createUpdatePropertiesPacket(final UUID id, final BossBar bar) {
final BossBarPacket packet = new BossBarPacket(); final BossBarPacket packet = new BossBarPacket();
packet.setUuid(id); packet.setUuid(id);
@@ -130,6 +178,12 @@ public class BossBarPacket implements MinecraftPacket {
return packet; return packet;
} }
/**
* Retrieves the UUID of the boss bar.
*
* @return the UUID of the boss bar
* @throws IllegalStateException if the UUID has not been set
*/
public UUID getUuid() { public UUID getUuid() {
if (uuid == null) { if (uuid == null) {
throw new IllegalStateException("No boss bar UUID specified"); throw new IllegalStateException("No boss bar UUID specified");
@@ -214,7 +268,8 @@ public class BossBarPacket implements MinecraftPacket {
this.overlay = ProtocolUtils.readVarInt(buf); this.overlay = ProtocolUtils.readVarInt(buf);
this.flags = buf.readUnsignedByte(); this.flags = buf.readUnsignedByte();
} }
case REMOVE -> {} case REMOVE -> {
}
case UPDATE_PERCENT -> this.percent = buf.readFloat(); case UPDATE_PERCENT -> this.percent = buf.readFloat();
case UPDATE_NAME -> this.name = ComponentHolder.read(buf, version); case UPDATE_NAME -> this.name = ComponentHolder.read(buf, version);
case UPDATE_STYLE -> { case UPDATE_STYLE -> {
@@ -235,22 +290,23 @@ public class BossBarPacket implements MinecraftPacket {
ProtocolUtils.writeVarInt(buf, action); ProtocolUtils.writeVarInt(buf, action);
switch (action) { switch (action) {
case ADD -> { case ADD -> {
if (name == null) { if (name == null) {
throw new IllegalStateException("No name specified!"); throw new IllegalStateException("No name specified!");
} }
name.write(buf); name.write(buf);
buf.writeFloat(percent); buf.writeFloat(percent);
ProtocolUtils.writeVarInt(buf, color); ProtocolUtils.writeVarInt(buf, color);
ProtocolUtils.writeVarInt(buf, overlay); ProtocolUtils.writeVarInt(buf, overlay);
buf.writeByte(flags); buf.writeByte(flags);
}
case REMOVE -> {
} }
case REMOVE -> {}
case UPDATE_PERCENT -> buf.writeFloat(percent); case UPDATE_PERCENT -> buf.writeFloat(percent);
case UPDATE_NAME -> { case UPDATE_NAME -> {
if (name == null) { if (name == null) {
throw new IllegalStateException("No name specified!"); throw new IllegalStateException("No name specified!");
} }
name.write(buf); name.write(buf);
} }
case UPDATE_STYLE -> { case UPDATE_STYLE -> {
ProtocolUtils.writeVarInt(buf, color); ProtocolUtils.writeVarInt(buf, color);
@@ -264,7 +320,7 @@ public class BossBarPacket implements MinecraftPacket {
private static byte serializeFlags(Set<BossBar.Flag> flags) { private static byte serializeFlags(Set<BossBar.Flag> flags) {
byte val = 0x0; byte val = 0x0;
for (BossBar.Flag flag : flags) { for (BossBar.Flag flag : flags) {
val |= FLAG_BITS_TO_PROTOCOL.get(flag); val |= (byte) FLAG_BITS_TO_PROTOCOL.get(flag);
} }
return val; return val;
} }
@@ -273,4 +329,4 @@ public class BossBarPacket implements MinecraftPacket {
public boolean handle(MinecraftSessionHandler handler) { public boolean handle(MinecraftSessionHandler handler) {
return handler.handle(this); return handler.handle(this);
} }
} }

View File

@@ -23,6 +23,14 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/**
* Represents a packet used as a delimiter for bundling multiple packets together.
* The {@code BundleDelimiterPacket} marks the beginning or end of a packet bundle,
* allowing the server and client to process groups of packets as a single logical unit.
*
* <p>This packet is typically used to signal the start or end of a packet sequence that
* are sent together, enabling efficient transmission and processing of related data.</p>
*/
public final class BundleDelimiterPacket implements MinecraftPacket { public final class BundleDelimiterPacket implements MinecraftPacket {
public static final BundleDelimiterPacket INSTANCE = new BundleDelimiterPacket(); public static final BundleDelimiterPacket INSTANCE = new BundleDelimiterPacket();

View File

@@ -23,9 +23,13 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.Objects; import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the client settings packet in Minecraft, which is sent by the client
* to the server to communicate its settings such as locale, view distance, chat preferences,
* skin customization, and other client-side configurations.
*/
public class ClientSettingsPacket implements MinecraftPacket { public class ClientSettingsPacket implements MinecraftPacket {
private @Nullable String locale; private @Nullable String locale;
private byte viewDistance; private byte viewDistance;
@@ -41,6 +45,19 @@ public class ClientSettingsPacket implements MinecraftPacket {
public ClientSettingsPacket() { public ClientSettingsPacket() {
} }
/**
* Constructs a new {@code ClientSettingsPacket} with the specified settings.
*
* @param locale the client's locale setting
* @param viewDistance the view distance
* @param chatVisibility the client's chat visibility setting
* @param chatColors whether chat colors are enabled
* @param skinParts the customization for skin parts
* @param mainHand the client's main hand preference
* @param textFilteringEnabled whether text filtering is enabled
* @param clientListingAllowed whether the client allows listing
* @param particleStatus whether particles are enabled
*/
public ClientSettingsPacket(String locale, byte viewDistance, int chatVisibility, boolean chatColors, public ClientSettingsPacket(String locale, byte viewDistance, int chatVisibility, boolean chatColors,
short skinParts, int mainHand, boolean textFilteringEnabled, boolean clientListingAllowed, short skinParts, int mainHand, boolean textFilteringEnabled, boolean clientListingAllowed,
int particleStatus) { int particleStatus) {
@@ -55,6 +72,12 @@ public class ClientSettingsPacket implements MinecraftPacket {
this.particleStatus = particleStatus; this.particleStatus = particleStatus;
} }
/**
* Gets the client's locale.
*
* @return the locale
* @throws IllegalStateException if no locale is specified
*/
public String getLocale() { public String getLocale() {
if (locale == null) { if (locale == null) {
throw new IllegalStateException("No locale specified"); throw new IllegalStateException("No locale specified");
@@ -132,10 +155,10 @@ public class ClientSettingsPacket implements MinecraftPacket {
@Override @Override
public String toString() { public String toString() {
return "ClientSettings{" + "locale='" + locale + '\'' + ", viewDistance=" + viewDistance + return "ClientSettings{" + "locale='" + locale + '\'' + ", viewDistance=" + viewDistance
", chatVisibility=" + chatVisibility + ", chatColors=" + chatColors + ", skinParts=" + + ", chatVisibility=" + chatVisibility + ", chatColors=" + chatColors + ", skinParts="
skinParts + ", mainHand=" + mainHand + ", chatFilteringEnabled=" + textFilteringEnabled + + skinParts + ", mainHand=" + mainHand + ", chatFilteringEnabled=" + textFilteringEnabled
", clientListingAllowed=" + clientListingAllowed + ", particleStatus=" + particleStatus + '}'; + ", clientListingAllowed=" + clientListingAllowed + ", particleStatus=" + particleStatus + '}';
} }
@Override @Override

View File

@@ -25,6 +25,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
/**
* Represents a packet sent from the server to the client to request cookies.
* This packet can be used to initiate a request for cookie-related data from the client,
* typically for authentication or tracking purposes.
*/
public class ClientboundCookieRequestPacket implements MinecraftPacket { public class ClientboundCookieRequestPacket implements MinecraftPacket {
private Key key; private Key key;

View File

@@ -22,11 +22,16 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.Random;
import net.kyori.adventure.sound.Sound; import net.kyori.adventure.sound.Sound;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Random; /**
* A clientbound packet that instructs the client to play a sound tied to an entity.
*
* <p>This is sent by the server when a sound should be played at the location of a
* specific entity, with optional fixed range and seed.</p>
*/
public class ClientboundSoundEntityPacket implements MinecraftPacket { public class ClientboundSoundEntityPacket implements MinecraftPacket {
private static final Random SEEDS_RANDOM = new Random(); private static final Random SEEDS_RANDOM = new Random();
@@ -35,8 +40,16 @@ public class ClientboundSoundEntityPacket implements MinecraftPacket {
private @Nullable Float fixedRange; private @Nullable Float fixedRange;
private int emitterEntityId; private int emitterEntityId;
public ClientboundSoundEntityPacket() {} public ClientboundSoundEntityPacket() {
}
/**
* Constructs a new sound entity packet.
*
* @param sound the sound to play
* @param fixedRange the fixed attenuation range, or {@code null} to use the default
* @param emitterEntityId the entity ID of the sound emitter
*/
public ClientboundSoundEntityPacket(Sound sound, @Nullable Float fixedRange, int emitterEntityId) { public ClientboundSoundEntityPacket(Sound sound, @Nullable Float fixedRange, int emitterEntityId) {
this.sound = sound; this.sound = sound;
this.fixedRange = fixedRange; this.fixedRange = fixedRange;
@@ -55,8 +68,9 @@ public class ClientboundSoundEntityPacket implements MinecraftPacket {
ProtocolUtils.writeMinimalKey(buf, sound.name()); ProtocolUtils.writeMinimalKey(buf, sound.name());
buf.writeBoolean(fixedRange != null); buf.writeBoolean(fixedRange != null);
if (fixedRange != null) if (fixedRange != null) {
buf.writeFloat(fixedRange); buf.writeFloat(fixedRange);
}
ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source()); ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source());

View File

@@ -22,18 +22,24 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import javax.annotation.Nullable;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
import net.kyori.adventure.sound.Sound; import net.kyori.adventure.sound.Sound;
import net.kyori.adventure.sound.SoundStop; import net.kyori.adventure.sound.SoundStop;
import javax.annotation.Nullable; /**
* A clientbound packet instructing the client to stop one or more sounds.
*
* <p>This packet supports specifying a {@link Sound.Source}, a {@link Key} sound identifier,
* or both together. If neither is specified, the client will stop all currently playing sounds.</p>
*/
public class ClientboundStopSoundPacket implements MinecraftPacket { public class ClientboundStopSoundPacket implements MinecraftPacket {
private @Nullable Sound.Source source; private @Nullable Sound.Source source;
private @Nullable Key soundName; private @Nullable Key soundName;
public ClientboundStopSoundPacket() {} public ClientboundStopSoundPacket() {
}
public ClientboundStopSoundPacket(SoundStop soundStop) { public ClientboundStopSoundPacket(SoundStop soundStop) {
this(soundStop.source(), soundStop.sound()); this(soundStop.source(), soundStop.sound());

View File

@@ -25,6 +25,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
/**
* Represents a packet sent from the server to the client to store a cookie.
* This packet can be used to send cookie-related data from the server to be stored or processed
* by the client.
*/
public class ClientboundStoreCookiePacket implements MinecraftPacket { public class ClientboundStoreCookiePacket implements MinecraftPacket {
private Key key; private Key key;

View File

@@ -23,6 +23,13 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/**
* Represents the packet sent by the server to the client to clear any
* currently displayed configuration dialog.
*
* <p>This packet is used during the configuration phase (1.21.6+) to
* instruct the client to dismiss an active dialog window.</p>
*/
public class DialogClearPacket implements MinecraftPacket { public class DialogClearPacket implements MinecraftPacket {
public static final DialogClearPacket INSTANCE = new DialogClearPacket(); public static final DialogClearPacket INSTANCE = new DialogClearPacket();

View File

@@ -27,6 +27,13 @@ import io.netty.buffer.ByteBuf;
import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.BinaryTag;
import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.BinaryTagIO;
/**
* Represents the packet sent by the server to the client to display a configuration dialog
* during the configuration phase in Minecraft 1.21.6+.
*
* <p>This packet is only relevant in the CONFIG and PLAY states. If the ID is {@code 0},
* a dialog is to be shown and the accompanying {@link BinaryTag} contains its data.</p>
*/
public class DialogShowPacket implements MinecraftPacket { public class DialogShowPacket implements MinecraftPacket {
private final StateRegistry state; private final StateRegistry state;

View File

@@ -28,6 +28,12 @@ import io.netty.buffer.ByteBuf;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a packet sent by the server to disconnect the client. This packet contains
* a reason for the disconnection, which is sent to the client and displayed to the player.
* The packet can be sent in different states (e.g., login, play), which affects how the
* reason is processed.
*/
public class DisconnectPacket implements MinecraftPacket { public class DisconnectPacket implements MinecraftPacket {
private @Nullable ComponentHolder reason; private @Nullable ComponentHolder reason;
@@ -42,6 +48,12 @@ public class DisconnectPacket implements MinecraftPacket {
this.reason = Preconditions.checkNotNull(reason, "reason"); this.reason = Preconditions.checkNotNull(reason, "reason");
} }
/**
* Retrieves the reason for the disconnection, which will be sent to the client.
*
* @return the reason for the disconnection as a {@link ComponentHolder}
* @throws IllegalStateException if no reason is specified
*/
public ComponentHolder getReason() { public ComponentHolder getReason() {
if (reason == null) { if (reason == null) {
throw new IllegalStateException("No reason specified"); throw new IllegalStateException("No reason specified");
@@ -62,8 +74,8 @@ public class DisconnectPacket implements MinecraftPacket {
@Override @Override
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
reason = ComponentHolder.read(buf, state == StateRegistry.LOGIN reason = ComponentHolder.read(buf, state == StateRegistry.LOGIN
? ProtocolVersion.MINECRAFT_1_20_2 : version); ? ProtocolVersion.MINECRAFT_1_20_2 : version);
} }
@Override @Override
@@ -76,9 +88,17 @@ public class DisconnectPacket implements MinecraftPacket {
return handler.handle(this); return handler.handle(this);
} }
/**
* Creates a new {@code DisconnectPacket} with the specified reason and version.
*
* @param component the component explaining the disconnection reason
* @param version the protocol version in use
* @param state the state in which the disconnection occurs
* @return the created {@code DisconnectPacket}
*/
public static DisconnectPacket create(Component component, ProtocolVersion version, StateRegistry state) { public static DisconnectPacket create(Component component, ProtocolVersion version, StateRegistry state) {
Preconditions.checkNotNull(component, "component"); Preconditions.checkNotNull(component, "component");
return new DisconnectPacket(state, new ComponentHolder(state == StateRegistry.LOGIN return new DisconnectPacket(state, new ComponentHolder(state == StateRegistry.LOGIN
? ProtocolVersion.MINECRAFT_1_20_2 : version, component)); ? ProtocolVersion.MINECRAFT_1_20_2 : version, component));
} }
} }

View File

@@ -26,6 +26,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.Arrays; import java.util.Arrays;
/**
* Represents the encryption request packet in Minecraft, which is sent by the server
* during the encryption handshake process. This packet is used to initiate secure
* communication by providing the client with the server's public key and a verified token.
* The client must respond with the encrypted shared secret and verify token.
*/
public class EncryptionRequestPacket implements MinecraftPacket { public class EncryptionRequestPacket implements MinecraftPacket {
private String serverId = ""; private String serverId = "";

View File

@@ -26,10 +26,18 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import com.velocitypowered.proxy.util.except.QuietDecoderException; import com.velocitypowered.proxy.util.except.QuietDecoderException;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.Arrays;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Arrays; /**
* Represents the encryption response packet in Minecraft, which is sent by the client
* during the encryption handshake process. This packet contains the shared secret
* and verifies the token used to establish secure communication between the client
* and the server.
*
* <p>The packet structure varies depending on the Minecraft protocol version, with additional
* fields such as a salt being present in versions 1.19 and above.</p>
*/
public class EncryptionResponsePacket implements MinecraftPacket { public class EncryptionResponsePacket implements MinecraftPacket {
private static final QuietDecoderException NO_SALT = new QuietDecoderException( private static final QuietDecoderException NO_SALT = new QuietDecoderException(
@@ -47,6 +55,13 @@ public class EncryptionResponsePacket implements MinecraftPacket {
return verifyToken.clone(); return verifyToken.clone();
} }
/**
* Retrieves the salt used in the encryption response. The salt is introduced in
* Minecraft version 1.19 and is optional in certain protocol versions.
*
* @return the salt used in the encryption response
* @throws QuietDecoderException if the salt is not present
*/
public long getSalt() { public long getSalt() {
if (salt == null) { if (salt == null) {
throw NO_SALT; throw NO_SALT;

View File

@@ -27,6 +27,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/**
* Represents a handshake packet in Minecraft, which is used during the initial connection process.
* This packet contains information such as the protocol version, server address, port, and the intent
* of the handshake (e.g., login or status request). This packet is crucial for establishing a connection
* between the client and the server.
*/
public class HandshakePacket implements MinecraftPacket { public class HandshakePacket implements MinecraftPacket {
// This size was chosen to ensure Forge clients can still connect even with very long hostnames. // This size was chosen to ensure Forge clients can still connect even with very long hostnames.
@@ -110,13 +116,13 @@ public class HandshakePacket implements MinecraftPacket {
@Override @Override
public int decodeExpectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction, public int decodeExpectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion version) { ProtocolVersion version) {
return 7; return 7;
} }
@Override @Override
public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction,
ProtocolVersion version) { ProtocolVersion version) {
return 9 + (MAXIMUM_HOSTNAME_LENGTH * 3); return 9 + (MAXIMUM_HOSTNAME_LENGTH * 3);
} }

View File

@@ -26,6 +26,10 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
/**
* Represents a packet that contains both the header and footer for the player list screen (tab list) in Minecraft.
* This packet allows the server to set or update the header and footer text that is displayed on the client's tab list.
*/
public class HeaderAndFooterPacket implements MinecraftPacket { public class HeaderAndFooterPacket implements MinecraftPacket {
private final ComponentHolder header; private final ComponentHolder header;
@@ -67,11 +71,11 @@ public class HeaderAndFooterPacket implements MinecraftPacket {
public static HeaderAndFooterPacket create(Component header, public static HeaderAndFooterPacket create(Component header,
Component footer, ProtocolVersion protocolVersion) { Component footer, ProtocolVersion protocolVersion) {
return new HeaderAndFooterPacket(new ComponentHolder(protocolVersion, header), return new HeaderAndFooterPacket(new ComponentHolder(protocolVersion, header),
new ComponentHolder(protocolVersion, footer)); new ComponentHolder(protocolVersion, footer));
} }
public static HeaderAndFooterPacket reset(ProtocolVersion version) { public static HeaderAndFooterPacket reset(ProtocolVersion version) {
ComponentHolder empty = new ComponentHolder(version, Component.empty()); ComponentHolder empty = new ComponentHolder(version, Component.empty());
return new HeaderAndFooterPacket(empty, empty); return new HeaderAndFooterPacket(empty, empty);
} }
} }

View File

@@ -21,13 +21,19 @@ import com.google.common.collect.ImmutableSet;
import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.connection.registry.DimensionInfo;
import com.velocitypowered.proxy.protocol.*; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.BinaryTagIO;
import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a packet sent to the client when they successfully join a game in Minecraft.
* This packet contains all the necessary information to initialize the client state,
* including the player's entity ID, game mode, dimension, world settings, and more.
*/
public class JoinGamePacket implements MinecraftPacket { public class JoinGamePacket implements MinecraftPacket {
private static final BinaryTagIO.Reader JOINGAME_READER = BinaryTagIO.reader(4 * 1024 * 1024); private static final BinaryTagIO.Reader JOINGAME_READER = BinaryTagIO.reader(4 * 1024 * 1024);
@@ -204,17 +210,17 @@ public class JoinGamePacket implements MinecraftPacket {
@Override @Override
public String toString() { public String toString() {
return "JoinGame{" + "entityId=" + entityId + ", gamemode=" + gamemode + ", dimension=" + return "JoinGame{" + "entityId=" + entityId + ", gamemode=" + gamemode + ", dimension="
dimension + ", partialHashedSeed=" + partialHashedSeed + ", difficulty=" + difficulty + + dimension + ", partialHashedSeed=" + partialHashedSeed + ", difficulty=" + difficulty
", isHardcore=" + isHardcore + ", maxPlayers=" + maxPlayers + ", levelType='" + levelType + + ", isHardcore=" + isHardcore + ", maxPlayers=" + maxPlayers + ", levelType='" + levelType
'\'' + ", viewDistance=" + viewDistance + ", reducedDebugInfo=" + reducedDebugInfo + + '\'' + ", viewDistance=" + viewDistance + ", reducedDebugInfo=" + reducedDebugInfo
", showRespawnScreen=" + showRespawnScreen + ", doLimitedCrafting=" + doLimitedCrafting + + ", showRespawnScreen=" + showRespawnScreen + ", doLimitedCrafting=" + doLimitedCrafting
", levelNames=" + levelNames + ", registry='" + registry + '\'' + ", dimensionInfo='" + + ", levelNames=" + levelNames + ", registry='" + registry + '\'' + ", dimensionInfo='"
dimensionInfo + '\'' + ", currentDimensionData='" + currentDimensionData + '\'' + + dimensionInfo + '\'' + ", currentDimensionData='" + currentDimensionData + '\''
", previousGamemode=" + previousGamemode + ", simulationDistance=" + simulationDistance + + ", previousGamemode=" + previousGamemode + ", simulationDistance=" + simulationDistance
", lastDeathPosition='" + lastDeathPosition + '\'' + ", portalCooldown=" + portalCooldown + + ", lastDeathPosition='" + lastDeathPosition + '\'' + ", portalCooldown=" + portalCooldown
", seaLevel=" + seaLevel + + ", seaLevel=" + seaLevel
'}'; + '}';
} }
@Override @Override

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