From 7cede708754fc7fbe86bdc379203be27847ab709 Mon Sep 17 00:00:00 2001 From: RootBeer Date: Mon, 26 Jan 2026 00:17:01 -0500 Subject: [PATCH 1/7] Bump various dependencies, including requirements for checkstyle --- api/build.gradle.kts | 9 +- .../plugin/ap/PluginAnnotationProcessor.java | 9 + .../ap/SerializedPluginDescription.java | 74 ++++++++ .../api/command/CommandSource.java | 30 ++-- .../api/command/VelocityBrigadierMessage.java | 6 + .../api/event/Continuation.java | 4 +- .../api/event/EventHandler.java | 16 ++ .../api/event/EventManager.java | 1 + .../velocitypowered/api/event/PostOrder.java | 29 +++- .../api/event/ResultedEvent.java | 35 ++++ .../event/command/CommandExecuteEvent.java | 14 ++ .../command/PlayerAvailableCommandsEvent.java | 10 ++ .../connection/ConnectionHandshakeEvent.java | 16 ++ .../api/event/connection/DisconnectEvent.java | 44 ++++- .../api/event/connection/LoginEvent.java | 10 ++ .../event/connection/PluginMessageEvent.java | 41 +++++ .../api/event/connection/PostLoginEvent.java | 10 ++ .../api/event/connection/PreLoginEvent.java | 26 +++ .../event/connection/PreTransferEvent.java | 37 ++++ .../permission/PermissionsSetupEvent.java | 16 ++ .../api/event/player/CookieReceiveEvent.java | 25 +++ .../api/event/player/CookieRequestEvent.java | 15 ++ .../api/event/player/CookieStoreEvent.java | 27 +++ .../event/player/GameProfileRequestEvent.java | 21 ++- .../event/player/KickedFromServerEvent.java | 22 +++ .../player/PlayerChannelRegisterEvent.java | 16 ++ .../player/PlayerChannelUnregisterEvent.java | 20 +++ .../api/event/player/PlayerChatEvent.java | 15 ++ .../PlayerChooseInitialServerEvent.java | 10 ++ .../event/player/PlayerClientBrandEvent.java | 16 +- .../api/event/player/PlayerModInfoEvent.java | 16 ++ .../player/PlayerResourcePackStatusEvent.java | 10 ++ .../player/PlayerSettingsChangedEvent.java | 16 ++ .../event/player/ServerConnectedEvent.java | 15 ++ .../player/ServerLoginPluginMessageEvent.java | 26 +++ .../event/player/ServerPostConnectEvent.java | 7 + .../event/player/ServerPreConnectEvent.java | 5 + .../player/ServerResourcePackRemoveEvent.java | 3 + .../player/ServerResourcePackSendEvent.java | 21 +++ .../PlayerConfigurationEvent.java | 1 + .../PlayerEnterConfigurationEvent.java | 3 +- .../PlayerEnteredConfigurationEvent.java | 1 + .../PlayerFinishConfigurationEvent.java | 3 +- .../PlayerFinishedConfigurationEvent.java | 1 + .../api/event/proxy/ListenerBoundEvent.java | 16 ++ .../api/event/proxy/ListenerCloseEvent.java | 16 ++ .../api/event/proxy/ProxyInitializeEvent.java | 6 + .../api/event/proxy/ProxyPingEvent.java | 6 + .../event/proxy/ProxyPreShutdownEvent.java | 6 + .../api/event/proxy/ProxyReloadEvent.java | 6 + .../api/event/proxy/ProxyShutdownEvent.java | 6 + .../proxy/server/ServerRegisteredEvent.java | 6 + .../proxy/server/ServerUnregisteredEvent.java | 6 + .../api/network/HandshakeIntent.java | 17 ++ .../api/network/ListenerType.java | 6 + .../api/network/ProtocolState.java | 5 + .../api/network/ProtocolVersion.java | 162 +++++++++++++++++- .../api/permission/Tristate.java | 2 +- .../api/plugin/InvalidPluginException.java | 19 ++ .../api/plugin/PluginDescription.java | 6 + .../com/velocitypowered/api/proxy/Player.java | 25 +-- .../api/proxy/crypto/IdentifiedKey.java | 23 ++- .../api/proxy/crypto/KeySigned.java | 2 +- .../messages/LegacyChannelIdentifier.java | 5 + .../messages/MinecraftChannelIdentifier.java | 15 ++ .../api/proxy/player/PlayerSettings.java | 24 +++ .../api/proxy/player/ResourcePackInfo.java | 7 +- .../api/proxy/player/SkinParts.java | 40 +++++ .../api/proxy/player/TabListEntry.java | 3 + .../api/proxy/server/QueryResponse.java | 18 +- .../api/proxy/server/ServerInfo.java | 18 +- .../api/proxy/server/ServerPing.java | 129 +++++++++++++- .../velocitypowered/api/util/GameProfile.java | 15 ++ .../com/velocitypowered/api/util/ModInfo.java | 24 +++ .../api/util/ProxyVersion.java | 15 ++ .../velocitypowered/api/util/ServerLink.java | 32 ++++ gradle/libs.versions.toml | 8 +- .../natives/util/MoreByteBufUtils.java | 4 +- .../velocitypowered/proxy/VelocityServer.java | 2 +- .../handler/ModernResourcePackHandler.java | 2 +- .../handler/ResourcePackHandler.java | 1 + .../proxy/event/VelocityEventManager.java | 62 +++---- .../proxy/protocol/ProtocolUtils.java | 6 +- .../src/main/resources/default-velocity.toml | 2 +- 84 files changed, 1415 insertions(+), 110 deletions(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 268a8197ba..5e503f6a84 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { api(libs.guava) // 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("net.kyori:adventure-api") @@ -55,8 +55,6 @@ tasks { } } withType { - exclude("com/velocitypowered/api/plugin/ap/**") - val o = options as StandardJavadocDocletOptions o.encoding = "UTF-8" o.source = "21" @@ -66,7 +64,7 @@ tasks { "https://www.javadocs.dev/org.slf4j/slf4j-api/${libs.slf4j.get().version}/", "https://guava.dev/releases/${libs.guava.get().version}/api/docs/", "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/text-minimessage/${libs.adventure.bom.get().version}/", "https://jd.advntr.dev/key/${libs.adventure.bom.get().version}/", @@ -79,8 +77,5 @@ tasks { "implNote:a:Implementation Note:", "sinceMinecraft:a:Since Minecraft:" ) - - // Disable the crazy super-strict doclint tool in Java 8 - o.addStringOption("Xdoclint:none", "-quiet") } } diff --git a/api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java b/api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java index b44f284787..6424d34e01 100644 --- a/api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java +++ b/api/src/ap/java/com/velocitypowered/api/plugin/ap/PluginAnnotationProcessor.java @@ -36,6 +36,15 @@ @SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"}) public class PluginAnnotationProcessor extends AbstractProcessor { + /** + * Creates a new {@code PluginAnnotationProcessor}. + * + *

The processor is instantiated by the Java compiler and initialized via + * {@link #init(ProcessingEnvironment)}.

+ */ + public PluginAnnotationProcessor() { + } + private ProcessingEnvironment environment; private String pluginClassFound; private boolean warnedAboutMultiplePlugins; diff --git a/api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java b/api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java index b712d8967d..b8a35ec95e 100644 --- a/api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java +++ b/api/src/ap/java/com/velocitypowered/api/plugin/ap/SerializedPluginDescription.java @@ -24,7 +24,19 @@ */ public final class SerializedPluginDescription { + /** + * The string pattern used to validate plugin IDs. + * + *

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.

+ */ public static final String ID_PATTERN_STRING = "[a-z][a-z0-9-_]{0,63}"; + /** + * The compiled pattern used to validate plugin IDs. + * + *

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.

+ */ public static final Pattern ID_PATTERN = Pattern.compile(ID_PATTERN_STRING); // @Nullable is used here to make GSON skip these in the serialized file @@ -64,34 +76,78 @@ static SerializedPluginDescription from(Plugin plugin, String qualifiedName) { .collect(Collectors.toList()), dependencies, qualifiedName); } + /** + * Gets the ID of the plugin this dependency refers to. + * + * @return the plugin ID + */ public String getId() { 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() { return name; } + /** + * Gets the version string of the plugin. + * + * @return the plugin version, or {@code null} if not specified + */ public @Nullable String getVersion() { 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() { return description; } + /** + * Gets the website URL for the plugin. + * + *

This is often used to link to documentation, support, or the plugin's homepage.

+ * + * @return the plugin URL, or {@code null} if not specified + */ public @Nullable String getUrl() { 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 getAuthors() { return authors == null ? ImmutableList.of() : authors; } + /** + * Gets the list of declared dependencies for the plugin. + * + *

Dependencies may be required or optional and describe other plugins, this one depends.

+ * + * @return an immutable list of plugin dependencies + */ public List getDependencies() { 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() { return main; } @@ -142,15 +198,33 @@ public static final class Dependency { private final String id; 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) { this.id = id; this.optional = optional; } + /** + * Gets the ID of the plugin this dependency refers to. + * + * @return the plugin ID + */ public String getId() { return id; } + /** + * Indicates whether this dependency is optional. + * + *

Optional dependencies are not required for the plugin to load.

+ * + * @return {@code true} if the dependency is optional; {@code false} otherwise + */ public boolean isOptional() { return optional; } diff --git a/api/src/main/java/com/velocitypowered/api/command/CommandSource.java b/api/src/main/java/com/velocitypowered/api/command/CommandSource.java index 3cc0392515..24d5272dab 100644 --- a/api/src/main/java/com/velocitypowered/api/command/CommandSource.java +++ b/api/src/main/java/com/velocitypowered/api/command/CommandSource.java @@ -25,20 +25,20 @@ public interface CommandSource extends Audience, PermissionSubject { * @param message MiniMessage content * @see MiniMessage docs * for more information on the format. - **/ + */ default void sendRichMessage(final @NotNull String message) { this.sendMessage(MiniMessage.miniMessage().deserialize(message, this)); } /** - * Sends a message with the MiniMessage format to this source. - * - * @param message MiniMessage content - * @param resolvers resolvers to use - * @see MiniMessage docs - * and MiniMessage Placeholders docs - * for more information on the format. - **/ + * Sends a message with the MiniMessage format to this source. + * + * @param message MiniMessage content + * @param resolvers resolvers to use + * @see MiniMessage docs + * and MiniMessage Placeholders docs + * for more information on the format. + */ default void sendRichMessage( final @NotNull String message, final @NotNull TagResolver @NotNull... resolvers @@ -47,13 +47,13 @@ default void sendRichMessage( } /** - * Sends a plain message to this source. - * - * @param message plain message - * @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 + * Sends a plain message to this source. + * + * @param message plain message + * @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 * and not recommended. - */ + */ default void sendPlainMessage(final @NotNull String message) { this.sendMessage(Component.text(message)); } diff --git a/api/src/main/java/com/velocitypowered/api/command/VelocityBrigadierMessage.java b/api/src/main/java/com/velocitypowered/api/command/VelocityBrigadierMessage.java index 0ae69591ef..bd6415c30d 100644 --- a/api/src/main/java/com/velocitypowered/api/command/VelocityBrigadierMessage.java +++ b/api/src/main/java/com/velocitypowered/api/command/VelocityBrigadierMessage.java @@ -20,6 +20,12 @@ */ 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) { return new VelocityBrigadierMessage(message); } diff --git a/api/src/main/java/com/velocitypowered/api/event/Continuation.java b/api/src/main/java/com/velocitypowered/api/event/Continuation.java index 30672ef606..5c17bf7b5f 100644 --- a/api/src/main/java/com/velocitypowered/api/event/Continuation.java +++ b/api/src/main/java/com/velocitypowered/api/event/Continuation.java @@ -20,6 +20,8 @@ public interface Continuation { /** * Resumes the continuation after the executed task failed. + * + * @param exception the {@link Throwable} that caused the failure */ void resumeWithException(Throwable exception); -} \ No newline at end of file +} diff --git a/api/src/main/java/com/velocitypowered/api/event/EventHandler.java b/api/src/main/java/com/velocitypowered/api/event/EventHandler.java index 3f0a1aa0c3..ca8b164b32 100644 --- a/api/src/main/java/com/velocitypowered/api/event/EventHandler.java +++ b/api/src/main/java/com/velocitypowered/api/event/EventHandler.java @@ -13,12 +13,28 @@ * 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 * event handler, {@link AwaitingEventExecutor} provides a more idiomatic means to doing so. + * + * @param the event type this handler accepts */ @FunctionalInterface public interface EventHandler { + /** + * Executes this handler synchronously with the given event. + * + * @param event the event to handle + */ void execute(E event); + /** + * Executes this handler asynchronously with the given event. + * + *

If asynchronous handling is not implemented, the event is executed synchronously + * and this method returns {@code null}.

+ * + * @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) { execute(event); return null; diff --git a/api/src/main/java/com/velocitypowered/api/event/EventManager.java b/api/src/main/java/com/velocitypowered/api/event/EventManager.java index ed11986c17..b8d604cf8e 100644 --- a/api/src/main/java/com/velocitypowered/api/event/EventManager.java +++ b/api/src/main/java/com/velocitypowered/api/event/EventManager.java @@ -73,6 +73,7 @@ void register(Object plugin, Class eventClass, short postOrder, * servicing connections while a plugin handles a potentially long-running operation such as a * database query. * + * @param the event type * @param event the event to fire * @return a {@link CompletableFuture} representing the posted event */ diff --git a/api/src/main/java/com/velocitypowered/api/event/PostOrder.java b/api/src/main/java/com/velocitypowered/api/event/PostOrder.java index 98fa2e86f5..21b418cb56 100644 --- a/api/src/main/java/com/velocitypowered/api/event/PostOrder.java +++ b/api/src/main/java/com/velocitypowered/api/event/PostOrder.java @@ -12,7 +12,34 @@ */ 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. diff --git a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java index 0aafd05831..d2a338601f 100644 --- a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java @@ -15,6 +15,8 @@ /** * Indicates an event that has a result attached to it. + * + * @param the type of result associated with the event */ public interface ResultedEvent { @@ -70,10 +72,20 @@ public String toString() { return status ? "allowed" : "denied"; } + /** + * Returns a result indicating the event is allowed to proceed. + * + * @return an allowed {@link GenericResult} + */ public static GenericResult allowed() { return ALLOWED; } + /** + * Returns a result indicating the event is denied. + * + * @return a denied {@link GenericResult} + */ public static GenericResult denied() { return DENIED; } @@ -89,6 +101,12 @@ final class ComponentResult implements Result { private final boolean status; 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) { this.status = status; this.reason = reason; @@ -99,6 +117,11 @@ public boolean isAllowed() { return status; } + /** + * Returns the denial reason component, if present. + * + * @return an {@link Optional} containing the reason component if the result is denied + */ public Optional getReasonComponent() { return Optional.ofNullable(reason); } @@ -114,10 +137,22 @@ public String toString() { return "denied"; } + /** + * Returns a result indicating the event is allowed to proceed. + * + * @return an allowed {@link ComponentResult} + */ public static ComponentResult 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) { Preconditions.checkNotNull(reason, "reason"); return new ComponentResult(false, reason); diff --git a/api/src/main/java/com/velocitypowered/api/event/command/CommandExecuteEvent.java b/api/src/main/java/com/velocitypowered/api/event/command/CommandExecuteEvent.java index 7ed704fc0a..6daa62a825 100644 --- a/api/src/main/java/com/velocitypowered/api/event/command/CommandExecuteEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/command/CommandExecuteEvent.java @@ -106,6 +106,8 @@ public String toString() { /** * 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 */ public record InvocationInfo(SignedState signedState, Source source) { @@ -191,10 +193,22 @@ private CommandResult(final boolean status, final boolean forward, final @Nullab 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 getCommand() { 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() { return forward; } diff --git a/api/src/main/java/com/velocitypowered/api/event/command/PlayerAvailableCommandsEvent.java b/api/src/main/java/com/velocitypowered/api/event/command/PlayerAvailableCommandsEvent.java index d00cffac67..265fbdda90 100644 --- a/api/src/main/java/com/velocitypowered/api/event/command/PlayerAvailableCommandsEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/command/PlayerAvailableCommandsEvent.java @@ -37,10 +37,20 @@ public PlayerAvailableCommandsEvent(Player player, this.rootNode = checkNotNull(rootNode, "rootNode"); } + /** + * Gets the player that the available commands are being sent to. + * + * @return the targeted player + */ public Player getPlayer() { return player; } + /** + * Gets the root command node that represents the available commands. + * + * @return the Brigadier root command node + */ public RootCommandNode getRootNode() { return rootNode; } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java index e344b6c504..d3ddc0e37c 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/ConnectionHandshakeEvent.java @@ -21,6 +21,12 @@ public final class ConnectionHandshakeEvent { private final InboundConnection connection; 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) { this.connection = Preconditions.checkNotNull(connection, "connection"); this.intent = Preconditions.checkNotNull(intent, "intent"); @@ -39,10 +45,20 @@ public ConnectionHandshakeEvent(InboundConnection connection) { this.intent = HandshakeIntent.LOGIN; } + /** + * Returns the inbound connection associated with this handshake. + * + * @return the connection + */ public InboundConnection getConnection() { return connection; } + /** + * Returns the {@link HandshakeIntent} associated with this connection handshake. + * + * @return the intent of the handshake + */ public HandshakeIntent getIntent() { return this.intent; } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java index bec7b74562..4a2dba4fd3 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java @@ -17,12 +17,10 @@ * Operations on the provided player, aside from basic data retrieval operations, may behave in * undefined ways. * - *

- * 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 - * successfully before the proxy shuts down. This event is the sole exception to the - * {@link AwaitingEvent} contract. - *

+ *

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 + * successfully before the proxy shuts down. This event is the sole exception to the + * {@link AwaitingEvent} contract.

*/ @AwaitingEvent public final class DisconnectEvent { @@ -30,15 +28,31 @@ public final class DisconnectEvent { private final Player player; 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) { this.player = Preconditions.checkNotNull(player, "player"); this.loginStatus = Preconditions.checkNotNull(loginStatus, "loginStatus"); } + /** + * Returns the player who disconnected. + * + * @return the player + */ public Player getPlayer() { return player; } + /** + * Returns the login status of the player at the time of disconnection. + * + * @return the login status + */ public LoginStatus getLoginStatus() { return loginStatus; } @@ -56,11 +70,29 @@ public String toString() { */ public enum LoginStatus { + /** + * The player completed a successful login to the proxy. + */ SUCCESSFUL_LOGIN, + /** + * The player was disconnected because another login with the same UUID occurred. + */ CONFLICTING_LOGIN, + /** + * The player voluntarily disconnected before completing the login. + */ CANCELLED_BY_USER, + /** + * The proxy disconnected the player before login completed. + */ CANCELLED_BY_PROXY, + /** + * The player disconnected on their own, but only after starting the login and before completing it. + */ CANCELLED_BY_USER_BEFORE_COMPLETE, + /** + * The player disconnected before joining the initial backend server. + */ PRE_SERVER_JOIN } } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/LoginEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/LoginEvent.java index 494088972c..3ec0126497 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/LoginEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/LoginEvent.java @@ -24,11 +24,21 @@ public final class LoginEvent implements ResultedEventThis 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.

* @@ -129,14 +140,29 @@ public boolean isAllowed() { 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 getReasonComponent() { 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() { 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() { return result == Result.FORCE_OFFLINE; } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java index 584ab0052d..37e96a7d1a 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/PreTransferEvent.java @@ -28,15 +28,31 @@ public final class PreTransferEvent implements ResultedEvent 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 channels) { this.player = Preconditions.checkNotNull(player, "player"); 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() { return player; } + /** + * Gets the list of {@link ChannelIdentifier}s that the player registered. + * + * @return the list of registered channels + */ public List getChannels() { return channels; } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChannelUnregisterEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChannelUnregisterEvent.java index 86eeb2bc91..69e59da07c 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChannelUnregisterEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChannelUnregisterEvent.java @@ -21,15 +21,35 @@ public final class PlayerChannelUnregisterEvent { private final Player player; private final List 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 channels) { this.player = Preconditions.checkNotNull(player, "player"); 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() { return player; } + /** + * Gets the list of {@link ChannelIdentifier}s that the player has unregistered. + * + *

These identifiers correspond to the plugin message channels that the client has + * indicated it will no longer use.

+ * + * @return the list of unregistered channels + */ public List getChannels() { return channels; } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java index dd1fae29b4..6548cf6027 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChatEvent.java @@ -38,10 +38,20 @@ public PlayerChatEvent(Player player, String message) { this.result = ChatResult.allowed(); } + /** + * Gets the player who sent the chat message. + * + * @return the player who sent the message + */ public Player getPlayer() { 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() { return message; } @@ -88,6 +98,11 @@ private ChatResult(boolean status, @Nullable String 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 getMessage() { return Optional.ofNullable(message); } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java index 73d41ecdcd..587d374a01 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java @@ -37,10 +37,20 @@ public PlayerChooseInitialServerEvent(Player player, @Nullable RegisteredServer this.initialServer = initialServer; } + /** + * Gets the player who is choosing the initial server. + * + * @return the connected player + */ public Player getPlayer() { 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 getInitialServer() { return Optional.ofNullable(initialServer); } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerClientBrandEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerClientBrandEvent.java index 268d5b6a19..0a45093fc9 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerClientBrandEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerClientBrandEvent.java @@ -29,10 +29,20 @@ public PlayerClientBrandEvent(Player player, String brand) { this.brand = Preconditions.checkNotNull(brand); } + /** + * Gets the player who sent the client brand. + * + * @return the player + */ public Player getPlayer() { return player; } + /** + * Gets the brand string sent by the client. + * + * @return the client brand + */ public String getBrand() { return brand; } @@ -40,9 +50,9 @@ public String getBrand() { @Override public String toString() { return "PlayerClientBrandEvent{" - + "player=" + player - + ", brand='" + brand + '\'' - + '}'; + + "player=" + player + + ", brand='" + brand + '\'' + + '}'; } } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerModInfoEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerModInfoEvent.java index eb0b413363..377b8b452a 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerModInfoEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerModInfoEvent.java @@ -21,15 +21,31 @@ public final class PlayerModInfoEvent { private final Player player; 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) { this.player = Preconditions.checkNotNull(player, "player"); this.modInfo = Preconditions.checkNotNull(modInfo, "modInfo"); } + /** + * Returns the player who sent their mod list. + * + * @return the player + */ public Player getPlayer() { return player; } + /** + * Returns the mod information sent by the player. + * + * @return the mod information + */ public ModInfo getModInfo() { return modInfo; } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java index d212666b71..9e3f59f292 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerResourcePackStatusEvent.java @@ -33,6 +33,8 @@ public class PlayerResourcePackStatusEvent { /** * 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 * (Player, UUID, Status, ResourcePackInfo)} instead. */ @@ -44,6 +46,9 @@ public PlayerResourcePackStatusEvent(Player player, Status status) { /** * 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 * (Player, UUID, Status, ResourcePackInfo)} instead. */ @@ -54,6 +59,11 @@ public PlayerResourcePackStatusEvent(Player player, Status status, ResourcePackI /** * 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( Player player, UUID packId, Status status, ResourcePackInfo packInfo) { diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerSettingsChangedEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerSettingsChangedEvent.java index cd1bd01c22..542633c72b 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerSettingsChangedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerSettingsChangedEvent.java @@ -22,15 +22,31 @@ public final class PlayerSettingsChangedEvent { private final Player player; 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) { this.player = Preconditions.checkNotNull(player, "player"); this.playerSettings = Preconditions.checkNotNull(playerSettings, "playerSettings"); } + /** + * Returns the player whose settings changed. + * + * @return the player + */ public Player getPlayer() { return player; } + /** + * Returns the new client settings sent by the player. + * + * @return the updated player settings + */ public PlayerSettings getPlayerSettings() { return playerSettings; } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerConnectedEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerConnectedEvent.java index ac4452a0a8..48e9858733 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerConnectedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerConnectedEvent.java @@ -45,14 +45,29 @@ public ServerConnectedEvent(Player player, RegisteredServer server, this.previousServer = previousServer; } + /** + * Returns the player involved in this event. + * + * @return the {@link Player} who connected + */ public Player getPlayer() { return player; } + /** + * Returns the server the player successfully connected to. + * + * @return the {@link RegisteredServer} the player connected to + */ public RegisteredServer getServer() { 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 getPreviousServer() { return Optional.ofNullable(previousServer); } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerLoginPluginMessageEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerLoginPluginMessageEvent.java index 9597e02afa..d790d97548 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerLoginPluginMessageEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerLoginPluginMessageEvent.java @@ -63,10 +63,20 @@ public void setResult(ResponseResult result) { this.result = checkNotNull(result, "result"); } + /** + * Gets the connection from which the login plugin message was received. + * + * @return the server connection + */ public ServerConnection getConnection() { return connection; } + /** + * Gets the identifier of the channel this login plugin message was sent on. + * + * @return the channel identifier + */ public ChannelIdentifier getIdentifier() { return identifier; } @@ -100,6 +110,11 @@ public ByteArrayDataInput contentsAsDataStream() { return ByteStreams.newDataInput(contents); } + /** + * Gets the sequence ID of the plugin message sent by the server. + * + * @return the sequence ID + */ public int getSequenceId() { return sequenceId; } @@ -146,10 +161,21 @@ public byte[] getResponse() { 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() { 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) { checkNotNull(response, "response"); return new ResponseResult(response); diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEvent.java index 95e70a49f3..cb751dd71a 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerPostConnectEvent.java @@ -21,6 +21,13 @@ public class ServerPostConnectEvent { private final Player player; 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, @Nullable RegisteredServer previousServer) { this.player = Preconditions.checkNotNull(player, "player"); diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java index 98bcb60d3a..593a824e5b 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerPreConnectEvent.java @@ -126,6 +126,11 @@ public boolean isAllowed() { 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 getServer() { return Optional.ofNullable(server); } diff --git a/api/src/main/java/com/velocitypowered/api/event/player/ServerResourcePackRemoveEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/ServerResourcePackRemoveEvent.java index 96d1bb8e52..52901cf4bb 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/ServerResourcePackRemoveEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/ServerResourcePackRemoveEvent.java @@ -29,6 +29,9 @@ public class ServerResourcePackRemoveEvent implements ResultedEventVelocity will wait for this event before continuing/ending the configuration state.

* * @param player The player who can be configured. diff --git a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnterConfigurationEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnterConfigurationEvent.java index 05d6c2af02..97a2ded0e0 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnterConfigurationEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnterConfigurationEvent.java @@ -15,8 +15,9 @@ /** * This event is executed when a player is about to enter the configuration state. * It is not called for the initial configuration of a player after login. + * *

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.

* * @param player The player who is about to enter configuration state. diff --git a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnteredConfigurationEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnteredConfigurationEvent.java index c16777066c..6560f7bc43 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnteredConfigurationEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerEnteredConfigurationEvent.java @@ -14,6 +14,7 @@ /** * This event is executed when a player has entered the configuration state. + * *

From this moment on, until the {@link PlayerFinishedConfigurationEvent} is executed, * the {@linkplain Player#getProtocolState()} method is guaranteed * to return {@link ProtocolState#CONFIGURATION}.

diff --git a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishConfigurationEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishConfigurationEvent.java index 50df5a8abe..1cd3f2833c 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishConfigurationEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishConfigurationEvent.java @@ -14,8 +14,9 @@ /** * This event is executed when a player is about to finish the configuration state. + * *

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 * state, use the {@link PlayerConfigurationEvent}.

* diff --git a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishedConfigurationEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishedConfigurationEvent.java index 517f119cfe..994a1d4111 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishedConfigurationEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/configuration/PlayerFinishedConfigurationEvent.java @@ -14,6 +14,7 @@ /** * This event is executed when a player has finished the configuration state. + * *

From this moment on, the {@link Player#getProtocolState()} method * will return {@link ProtocolState#PLAY}.

* diff --git a/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerBoundEvent.java b/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerBoundEvent.java index 662e403db7..1824a69c8d 100644 --- a/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerBoundEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerBoundEvent.java @@ -19,15 +19,31 @@ public final class ListenerBoundEvent { private final InetSocketAddress address; 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) { this.address = Preconditions.checkNotNull(address, "address"); this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType"); } + /** + * Returns the socket address the listener is bound to. + * + * @return the bound socket address + */ public InetSocketAddress getAddress() { return address; } + /** + * Returns the type of listener that was bound. + * + * @return the listener type + */ public ListenerType getListenerType() { return listenerType; } diff --git a/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerCloseEvent.java b/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerCloseEvent.java index c2551a3598..da8c61d624 100644 --- a/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerCloseEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/proxy/ListenerCloseEvent.java @@ -19,15 +19,31 @@ public final class ListenerCloseEvent { private final InetSocketAddress address; 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) { this.address = Preconditions.checkNotNull(address, "address"); this.listenerType = Preconditions.checkNotNull(listenerType, "listenerType"); } + /** + * Returns the socket address the listener was bound to. + * + * @return the bound socket address + */ public InetSocketAddress getAddress() { return address; } + /** + * Returns the type of listener being closed. + * + * @return the listener type + */ public ListenerType getListenerType() { return listenerType; } diff --git a/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyInitializeEvent.java b/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyInitializeEvent.java index d01ce190d5..7e19f0e1a5 100644 --- a/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyInitializeEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyInitializeEvent.java @@ -17,6 +17,12 @@ @AwaitingEvent public final class ProxyInitializeEvent { + /** + * Creates a new {@code ProxyInitializeEvent}. + */ + public ProxyInitializeEvent() { + } + @Override public String toString() { return "ProxyInitializeEvent"; diff --git a/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyPingEvent.java b/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyPingEvent.java index 635554366b..14d4088498 100644 --- a/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyPingEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/proxy/ProxyPingEvent.java @@ -28,6 +28,12 @@ public final class ProxyPingEvent implements ResultedEventThis status can be caused by a {@link HandshakeIntent#STATUS}, * {@link HandshakeIntent#LOGIN} or {@link HandshakeIntent#TRANSFER} intent.

* If the intent is LOGIN or TRANSFER, the next state will be {@link #LOGIN}, @@ -24,6 +25,7 @@ public enum ProtocolState { HANDSHAKE, /** * Ping State of a connection. + * *

Connections with the {@link HandshakeIntent#STATUS} intent will pass through this state * and be disconnected after it requests the ping from the server * and the server responds with the respective ping.

@@ -31,11 +33,13 @@ public enum ProtocolState { STATUS, /** * Authentication State of a connection. + * *

At this moment the player is authenticating with the authentication servers.

*/ LOGIN, /** * Configuration State of a connection. + * *

At this point the player allows the server to send information * such as resource packs and plugin messages, at the same time the player * will send his client brand and the respective plugin messages @@ -46,6 +50,7 @@ public enum ProtocolState { CONFIGURATION, /** * Game State of a connection. + * *

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.

*/ diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index e803c30240..c3eba7657e 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -21,6 +21,9 @@ * Represents each Minecraft protocol version. */ public enum ProtocolVersion implements Ordered { + /** + * Represents an unknown protocol version. + */ UNKNOWN(-1, "Unknown") { @Override public boolean isUnknown() { @@ -32,6 +35,9 @@ public boolean isSupported() { return false; } }, + /** + * Represents legacy protocol versions before 1.7. + */ LEGACY(-2, "Legacy") { @Override public boolean isLegacy() { @@ -43,57 +49,201 @@ public boolean isSupported() { return false; } }, - MINECRAFT_1_7_2(4, - "1.7.2", "1.7.3", "1.7.4", "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_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.2 to 1.7.5. + */ + MINECRAFT_1_7_2(4, "1.7.2", "1.7.3", "1.7.4", "1.7.5"), + /** + * 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.1. + */ MINECRAFT_1_9_1(108, "1.9.1"), + /** + * Minecraft 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.10 to 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.1 to 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.1. + */ MINECRAFT_1_12_1(338, "1.12.1"), + /** + * Minecraft 1.12.2. + */ MINECRAFT_1_12_2(340, "1.12.2"), + /** + * Minecraft 1.13. + */ MINECRAFT_1_13(393, "1.13"), + /** + * Minecraft 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.14. + */ MINECRAFT_1_14(477, "1.14"), + /** + * Minecraft 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.3. + */ MINECRAFT_1_14_3(490, "1.14.3"), + /** + * Minecraft 1.14.4. + */ MINECRAFT_1_14_4(498, "1.14.4"), + /** + * Minecraft 1.15. + */ MINECRAFT_1_15(573, "1.15"), + /** + * Minecraft 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.16. + */ MINECRAFT_1_16(735, "1.16"), + /** + * Minecraft 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.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.17. + */ MINECRAFT_1_17(755, "1.17"), + /** + * Minecraft 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.2. + */ MINECRAFT_1_18_2(758, "1.18.2"), + /** + * Minecraft 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.3. + */ MINECRAFT_1_19_3(761, "1.19.3"), + /** + * Minecraft 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.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.5 to 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.2 to 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.5. + */ MINECRAFT_1_21_5(770, "1.21.5"), + /** + * Minecraft 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.9 to 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"); private static final int SNAPSHOT_BIT = 30; diff --git a/api/src/main/java/com/velocitypowered/api/permission/Tristate.java b/api/src/main/java/com/velocitypowered/api/permission/Tristate.java index ddbe26a866..02f6924b78 100644 --- a/api/src/main/java/com/velocitypowered/api/permission/Tristate.java +++ b/api/src/main/java/com/velocitypowered/api/permission/Tristate.java @@ -15,7 +15,7 @@ * Represents three different states of a setting. * *

Possible values:

- *

+ * *
    *
  • {@link #TRUE} - a positive setting
  • *
  • {@link #FALSE} - a negative (negated) setting
  • diff --git a/api/src/main/java/com/velocitypowered/api/plugin/InvalidPluginException.java b/api/src/main/java/com/velocitypowered/api/plugin/InvalidPluginException.java index 1882d26404..bee2a26d5e 100644 --- a/api/src/main/java/com/velocitypowered/api/plugin/InvalidPluginException.java +++ b/api/src/main/java/com/velocitypowered/api/plugin/InvalidPluginException.java @@ -12,18 +12,37 @@ */ public class InvalidPluginException extends Exception { + /** + * Creates a new exception with no detail message. + */ public InvalidPluginException() { super(); } + /** + * Creates a new exception with the specified detail message. + * + * @param message the detail message + */ public InvalidPluginException(String 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) { super(message, cause); } + /** + * Creates a new exception with the specified cause. + * + * @param cause the cause of the exception + */ public InvalidPluginException(Throwable cause) { super(cause); } diff --git a/api/src/main/java/com/velocitypowered/api/plugin/PluginDescription.java b/api/src/main/java/com/velocitypowered/api/plugin/PluginDescription.java index 540b54ea5e..cbf9b48700 100644 --- a/api/src/main/java/com/velocitypowered/api/plugin/PluginDescription.java +++ b/api/src/main/java/com/velocitypowered/api/plugin/PluginDescription.java @@ -96,6 +96,12 @@ default Collection getDependencies() { 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 getDependency(String id) { return Optional.empty(); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index efe21cd746..456f654170 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -150,6 +150,8 @@ public interface Player extends /** * Returns the player's game profile. + * + * @return the player's profile */ GameProfile getGameProfile(); @@ -242,10 +244,10 @@ default void clearHeaderAndFooter() { * Gets the {@link ResourcePackInfo} of the currently applied * resource-pack or null if none. * - *

    Note that since 1.20.3 it is no longer recommended to use + *

    Note that since 1.20.3 it is no longer recommended to use * this method as it will only return the last applied * resource pack. To get all applied resource packs, use - * {@link #getAppliedResourcePacks()} instead.

    + * {@link #getAppliedResourcePacks()} instead.

    * * @return the applied resource pack or null if none. */ @@ -258,10 +260,10 @@ default void clearHeaderAndFooter() { * the user is currently downloading or is currently * prompted to install or null if none. * - *

    Note that since 1.20.3 it is no longer recommended to use + *

    Note that since 1.20.3 it is no longer recommended to use * this method as it will only return the last pending * resource pack. To get all pending resource packs, use - * {@link #getPendingResourcePacks()} instead.

    + * {@link #getPendingResourcePacks()} instead.

    * * @return the pending resource pack or null if none */ @@ -313,6 +315,7 @@ default void clearHeaderAndFooter() { /** * {@inheritDoc} + * *

    Note that this method does not send a plugin message to the server the player * is connected to. You should only use this method if you are trying to communicate * with a mod that is installed on the player's client.

    @@ -336,7 +339,6 @@ default void clearHeaderAndFooter() { Component.text(getUsername())))); } - /** * Gets the player's client brand. * @@ -384,12 +386,11 @@ default void clearHeaderAndFooter() { /** * {@inheritDoc} * - * * @apiNote This method is not currently implemented in Velocity * and will not perform any actions. * @see #playSound(Sound, Sound.Emitter) * @see - * Unsupported Adventure Operations + * Unsupported Adventure Operations */ @Override default void playSound(@NotNull Sound sound) { @@ -402,7 +403,7 @@ default void playSound(@NotNull Sound sound) { * and will not perform any actions. * @see #playSound(Sound, Sound.Emitter) * @see - * Unsupported Adventure Operations + * Unsupported Adventure Operations */ @Override default void playSound(@NotNull Sound sound, double x, double y, double z) { @@ -445,7 +446,7 @@ default void stopSound(@NotNull SoundStop stop) { * and will not perform any actions. * * @see - * Unsupported Adventure Operations + * Unsupported Adventure Operations */ @Override default void openBook(@NotNull Book book) { @@ -458,7 +459,7 @@ default void openBook(@NotNull Book book) { * and will not perform any actions. * * @see - * Unsupported Adventure Operations + * Unsupported Adventure Operations */ @Override default void showDialog(@NotNull DialogLike dialog) { @@ -471,7 +472,7 @@ default void showDialog(@NotNull DialogLike dialog) { * and will not perform any actions. * * @see - * Unsupported Adventure Operations + * Unsupported Adventure Operations */ @Override default void closeDialog() { @@ -521,4 +522,4 @@ default void closeDialog() { * @sinceMinecraft 1.21 */ void setServerLinks(@NotNull List links); -} \ No newline at end of file +} diff --git a/api/src/main/java/com/velocitypowered/api/proxy/crypto/IdentifiedKey.java b/api/src/main/java/com/velocitypowered/api/proxy/crypto/IdentifiedKey.java index d2a6cc94e3..b6c0112127 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/crypto/IdentifiedKey.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/crypto/IdentifiedKey.java @@ -28,7 +28,6 @@ public interface IdentifiedKey extends KeySigned { */ PublicKey getSignedPublicKey(); - /** * 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. */ enum Revision implements Ordered { + /** + * 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)), + /** + * 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)); final Set backwardsCompatibleTo; @@ -69,11 +76,21 @@ enum Revision implements Ordered { this.backwardsCompatibleTo = backwardsCompatibleTo; this.applicableTo = applicableTo; } - + + /** + * Returns the set of revisions that this revision is backwards-compatible with. + * + * @return a set of compatible earlier revisions + */ public Set getBackwardsCompatibleTo() { return backwardsCompatibleTo; } - + + /** + * Returns the set of Minecraft protocol versions this revision applies to. + * + * @return a set of applicable protocol versions + */ public Set getApplicableTo() { return applicableTo; } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/crypto/KeySigned.java b/api/src/main/java/com/velocitypowered/api/proxy/crypto/KeySigned.java index 8ad64c1811..83fd402f5f 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/crypto/KeySigned.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/crypto/KeySigned.java @@ -34,7 +34,6 @@ public interface KeySigned { */ Instant getExpiryTemporal(); - /** * Check if the signature has expired. * @@ -56,6 +55,7 @@ default boolean hasExpired() { * Validates the signature, expiry temporal and key against the * signer public key. Note: This will **not** check for * expiry. You can check for expiry with {@link KeySigned#hasExpired()}. + * *

    DOES NOT WORK YET FOR MESSAGES AND COMMANDS!

    * Addendum: Does not work for 1.19.1 until the user has authenticated. * diff --git a/api/src/main/java/com/velocitypowered/api/proxy/messages/LegacyChannelIdentifier.java b/api/src/main/java/com/velocitypowered/api/proxy/messages/LegacyChannelIdentifier.java index 9da9a7b4aa..eafb484f4f 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/messages/LegacyChannelIdentifier.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/messages/LegacyChannelIdentifier.java @@ -31,6 +31,11 @@ public LegacyChannelIdentifier(String name) { this.name = name; } + /** + * Returns the name of this legacy plugin message channel. + * + * @return the channel name + */ public String getName() { return name; } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/messages/MinecraftChannelIdentifier.java b/api/src/main/java/com/velocitypowered/api/proxy/messages/MinecraftChannelIdentifier.java index a271a414d4..92f8ef9fee 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/messages/MinecraftChannelIdentifier.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/messages/MinecraftChannelIdentifier.java @@ -84,14 +84,29 @@ public static MinecraftChannelIdentifier from(Key key) { return create(key.namespace(), key.value()); } + /** + * Returns the namespace of this channel identifier. + * + * @return the namespace string (e.g., {@code minecraft}) + */ public String getNamespace() { return namespace; } + /** + * Returns the name of the channel within its namespace. + * + * @return the channel name string + */ public String getName() { return name; } + /** + * Converts this channel identifier to a {@link Key} object. + * + * @return a {@link Key} representing this identifier + */ public Key asKey() { return Key.key(namespace, name); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java b/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java index 416cbf154e..91cca964f2 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/PlayerSettings.java @@ -86,8 +86,17 @@ public interface PlayerSettings { * The client's current chat display mode. */ enum ChatMode { + /** + * Chat is fully visible. + */ SHOWN, + /** + * Only command messages are shown. + */ COMMANDS_ONLY, + /** + * Chat is completely hidden. + */ HIDDEN } @@ -95,7 +104,13 @@ enum ChatMode { * The player's selected dominant hand. */ enum MainHand { + /** + * This scope defines the left hand. + */ LEFT, + /** + * This scope defines the right hand. + */ RIGHT } @@ -103,8 +118,17 @@ enum MainHand { * The client's current "Particles" option state. */ enum ParticleStatus { + /** + * All particles are shown. + */ ALL, + /** + * A reduced number of particles are shown. + */ DECREASED, + /** + * Minimal particle effects are shown. + */ MINIMAL } } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java b/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java index 82937685ab..7e620185a0 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/ResourcePackInfo.java @@ -87,7 +87,6 @@ public interface ResourcePackInfo extends ResourcePackRequestLike { /** * Returns a copy of this {@link ResourcePackInfo} instance as a builder, using the new URL. - *

    * It is not guaranteed that * {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)} * is true, because the {@link ResourcePackInfo#getOrigin()} and @@ -108,6 +107,7 @@ interface Builder { * Sets the id of the resource pack. * * @param id the id the resource-pack + * @return this builder instance */ Builder setId(UUID id); @@ -128,6 +128,7 @@ interface Builder { * the player will be disconnected from the network * * @param shouldForce whether or not to force the client to accept the resource pack + * @return this builder instance */ Builder setShouldForce(boolean shouldForce); @@ -140,6 +141,7 @@ interface Builder { * before downloading. * * @param hash the SHA-1 hash of the resource-pack + * @return this builder instance */ Builder setHash(@Nullable byte[] hash); @@ -148,6 +150,7 @@ interface Builder { * This will only display if the client version is 1.17 or newer. * * @param prompt the component to display + * @return this builder instance */ Builder setPrompt(@Nullable Component prompt); @@ -174,4 +177,4 @@ enum Origin { */ PLUGIN_ON_PROXY } -} \ No newline at end of file +} diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/SkinParts.java b/api/src/main/java/com/velocitypowered/api/proxy/player/SkinParts.java index 1a5030feb6..893553417a 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/SkinParts.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/SkinParts.java @@ -17,34 +17,74 @@ public final class SkinParts { 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) { this.bitmask = skinBitmask; } + /** + * Returns whether the player has a cape enabled. + * + * @return true if the cape is enabled, false otherwise + */ public boolean hasCape() { return (bitmask & 1) == 1; } + /** + * Returns whether the player has a jacket enabled. + * + * @return true if the jacket is enabled, false otherwise + */ public boolean hasJacket() { 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() { 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() { 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() { 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() { 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() { return ((bitmask >> 6) & 1) == 1; } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java b/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java index aea45287fc..57a42392d3 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java @@ -237,8 +237,11 @@ public Builder profile(GameProfile profile) { /** * Sets the {@link IdentifiedKey} of the {@link TabListEntry}. + * *

    This only works for players currently not connected to this proxy.

    + * *

    For any player currently connected to this proxy this will be filled automatically.

    + * *

    Will ignore mismatching key revisions data.

    * * @param chatSession session to set diff --git a/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java b/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java index 6c794bf4c4..c51765f805 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/server/QueryResponse.java @@ -147,7 +147,6 @@ public Collection getPlugins() { return plugins; } - /** * 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 @@ -434,14 +433,31 @@ public static final class PluginInformation { this.version = version; } + /** + * Gets the name of the plugin. + * + * @return the plugin name + */ public String getName() { return name; } + /** + * Gets the version of the plugin, if available. + * + * @return an {@link Optional} containing the version if present + */ public Optional getVersion() { 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) { return new PluginInformation(name, version); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerInfo.java b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerInfo.java index fd686297ee..9546a66200 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerInfo.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerInfo.java @@ -32,11 +32,21 @@ public ServerInfo(String name, InetSocketAddress 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; } - public final InetSocketAddress getAddress() { + /** + * Gets the network address of the server. + * + * @return the {@link InetSocketAddress} of the server + */ + public InetSocketAddress getAddress() { return address; } @@ -49,7 +59,7 @@ public String toString() { } @Override - public final boolean equals(@Nullable Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } @@ -62,7 +72,7 @@ public final boolean equals(@Nullable Object o) { } @Override - public final int hashCode() { + public int hashCode() { return Objects.hash(name, address); } diff --git a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java index eb86f93ea1..4743d05e98 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java @@ -22,7 +22,6 @@ import net.kyori.adventure.text.Component; import org.jspecify.annotations.Nullable; - /** * 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 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, net.kyori.adventure.text.Component description, @Nullable Favicon favicon) { this(version, players, description, favicon, ModInfo.DEFAULT); @@ -58,23 +65,48 @@ public ServerPing(Version version, @Nullable Players players, this.modinfo = modinfo; } + /** + * Gets the version shown to the client during the ping. + * + * @return the version + */ public Version getVersion() { return version; } + /** + * Gets the player information shown to the client. + * + * @return the player information, or empty if not shown + */ public Optional getPlayers() { return Optional.ofNullable(players); } + /** + * Gets the description (MOTD) component shown in the ping response. + * + * @return the description component + */ @Nullable public Component getDescriptionComponent() { return description; } + /** + * Gets the favicon sent to the client. + * + * @return the favicon, or empty if not present + */ public Optional getFavicon() { return Optional.ofNullable(favicon); } + /** + * Gets the mod info sent to the client. + * + * @return the mod info, or empty if not present + */ public Optional getModinfo() { return Optional.ofNullable(modinfo); } @@ -139,6 +171,11 @@ public Builder asBuilder() { return builder; } + /** + * Creates a new {@link Builder} for constructing a {@link ServerPing}. + * + * @return a new ServerPing builder + */ public static Builder builder() { return new Builder(); } @@ -346,34 +383,74 @@ public ServerPing build() { description, favicon, nullOutModinfo ? null : new ModInfo(modType, mods)); } + /** + * Gets the version currently set in the builder. + * + * @return the version + */ public Version getVersion() { return version; } + /** + * Gets the number of players online. + * + * @return the online player count + */ public int getOnlinePlayers() { return onlinePlayers; } + /** + * Gets the maximum player capacity. + * + * @return the max player count + */ public int getMaximumPlayers() { return maximumPlayers; } + /** + * Gets the sample players shown in the ping. + * + * @return the sample player list + */ public List getSamplePlayers() { return samplePlayers; } + /** + * Gets the description component currently set in the builder. + * + * @return the server description, or empty if unset + */ public Optional getDescriptionComponent() { return Optional.ofNullable(description); } + /** + * Gets the favicon currently set in the builder. + * + * @return the favicon, or empty if none + */ public Optional getFavicon() { return Optional.ofNullable(favicon); } + /** + * Gets the type of mod loader (e.g., "FML"). + * + * @return the mod type string + */ public String getModType() { return modType; } + /** + * Gets the list of mods reported in the ping. + * + * @return the mod list + */ public List getMods() { return mods; } @@ -417,10 +494,20 @@ public Version(int protocol, String name) { this.name = Preconditions.checkNotNull(name, "name"); } + /** + * Gets the protocol number associated with the server version. + * + * @return the protocol version number + */ public int getProtocol() { return protocol; } + /** + * Gets the legacy string name of the sample player. + * + * @return the player name + */ public String getName() { return name; } @@ -474,14 +561,29 @@ public Players(int online, int max, List sample) { this.sample = ImmutableList.copyOf(sample); } + /** + * Gets the number of online players. + * + * @return the number of online players + */ public int getOnline() { return online; } + /** + * Gets the maximum number of players the server claims it can hold. + * + * @return the maximum number of players + */ public int getMax() { return max; } + /** + * Gets a sample list of online players. + * + * @return the sample players + */ public List getSample() { return sample == null ? ImmutableList.of() : sample; } @@ -519,22 +621,47 @@ public int hashCode() { */ 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( "Anonymous Player", new UUID(0L, 0L) ); + /** + * The legacy string name of the player. + */ private final String name; + /** + * The unique identifier (UUID) of the player. + */ private final UUID id; + /** + * Constructs a SamplePlayer from a {@link Component}-based name. + * + * @param name the name of the player as a {@link Component} + * @param id the UUID of the player + */ public SamplePlayer(String name, UUID id) { this.name = name; this.id = id; } + /** + * Gets the legacy string name of the sample player. + * + * @return the player name + */ public String getName() { return name; } + /** + * Gets the UUID of the sample player. + * + * @return the player UUID + */ public UUID getId() { return id; } diff --git a/api/src/main/java/com/velocitypowered/api/util/GameProfile.java b/api/src/main/java/com/velocitypowered/api/util/GameProfile.java index 27c4213802..e918c8e9e5 100644 --- a/api/src/main/java/com/velocitypowered/api/util/GameProfile.java +++ b/api/src/main/java/com/velocitypowered/api/util/GameProfile.java @@ -200,14 +200,29 @@ public Property(String name, String value, String signature) { this.signature = Preconditions.checkNotNull(signature, "signature"); } + /** + * Returns the name of this property. + * + * @return the property name + */ public String getName() { return name; } + /** + * Returns the value of this property. + * + * @return the property value + */ public String getValue() { return value; } + /** + * Returns the Mojang-provided signature for this property. + * + * @return the property signature + */ public String getSignature() { return signature; } diff --git a/api/src/main/java/com/velocitypowered/api/util/ModInfo.java b/api/src/main/java/com/velocitypowered/api/util/ModInfo.java index cfc522891a..d5e252fa44 100644 --- a/api/src/main/java/com/velocitypowered/api/util/ModInfo.java +++ b/api/src/main/java/com/velocitypowered/api/util/ModInfo.java @@ -18,6 +18,10 @@ */ 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()); private final String type; @@ -34,10 +38,20 @@ public ModInfo(String type, List modList) { this.modList = ImmutableList.copyOf(modList); } + /** + * Returns the Forge mod list type (e.g., "FML"). + * + * @return the mod list type + */ public String getType() { return type; } + /** + * Returns an immutable list of all mods in this mod list. + * + * @return the list of mods + */ public List getMods() { return modList; } @@ -89,10 +103,20 @@ public Mod(String id, String version) { Preconditions.checkArgument(version.length() < 128, "mod version is too long"); } + /** + * Returns the mod ID (identifier string). + * + * @return the mod ID + */ public String getId() { return id; } + /** + * Returns the mod version string. + * + * @return the mod version + */ public String getVersion() { return version; } diff --git a/api/src/main/java/com/velocitypowered/api/util/ProxyVersion.java b/api/src/main/java/com/velocitypowered/api/util/ProxyVersion.java index abc3a14aad..303fbd0f85 100644 --- a/api/src/main/java/com/velocitypowered/api/util/ProxyVersion.java +++ b/api/src/main/java/com/velocitypowered/api/util/ProxyVersion.java @@ -33,14 +33,29 @@ public ProxyVersion(String name, String vendor, String version) { this.version = Preconditions.checkNotNull(version, "version"); } + /** + * Gets the name of the proxy implementation. + * + * @return the name of the proxy + */ public String getName() { return name; } + /** + * Gets the vendor of the proxy implementation. + * + * @return the vendor of the proxy + */ public String getVendor() { return vendor; } + /** + * Gets the version of the proxy implementation. + * + * @return the version of the proxy + */ public String getVersion() { return version; } diff --git a/api/src/main/java/com/velocitypowered/api/util/ServerLink.java b/api/src/main/java/com/velocitypowered/api/util/ServerLink.java index 9eb04a9801..484833fe81 100644 --- a/api/src/main/java/com/velocitypowered/api/util/ServerLink.java +++ b/api/src/main/java/com/velocitypowered/api/util/ServerLink.java @@ -38,6 +38,7 @@ private ServerLink(Type type, String url) { * * @param label a custom component label to display * @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) { return new ServerLink(label, link); @@ -48,6 +49,7 @@ public static ServerLink serverLink(Component label, String link) { * * @param type the {@link Type built-in type} of link * @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) { return new ServerLink(type, link); @@ -86,15 +88,45 @@ public URI getUrl() { * @apiNote {@link Type#BUG_REPORT} links are shown on the connection error screen */ public enum Type { + /** + * A link to report bugs related to the server or gameplay. + */ BUG_REPORT, + /** + * A link to the server's community guidelines or rules. + */ COMMUNITY_GUIDELINES, + /** + * A link to the server’s support or help desk. + */ SUPPORT, + /** + * A link showing the current server or service status. + */ STATUS, + /** + * A link to provide feedback to the server staff or developers. + */ FEEDBACK, + /** + * A link to the server’s community hub or Discord. + */ COMMUNITY, + /** + * A link to the server's main website. + */ WEBSITE, + /** + * A link to the server's forums. + */ FORUMS, + /** + * A link to server or game-related news. + */ NEWS, + /** + * A link to announcements from the server team. + */ ANNOUNCEMENTS } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7be8d4698e..b8a22e770b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ configurate3 = "3.7.3" configurate4 = "4.2.0" flare = "2.0.1" log4j = "2.25.3" -netty = "4.2.7.Final" +netty = "4.2.9.Final" [plugins] fill = "io.papermc.fill.gradle:1.0.10" @@ -21,7 +21,7 @@ brigadier = "com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT" bstats = "org.bstats:bstats-base:3.1.0" caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" 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" configurate3-hocon = { module = "org.spongepowered:configurate-hocon", 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-gson = { module = "org.spongepowered:configurate-gson", version.ref = "configurate4" } 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-fastutil = { module = "space.vectrix.flare:flare-fastutil", version.ref = "flare" } jline = "org.jline:jline-terminal-jansi:3.30.6" 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" kyori-ansi = "net.kyori:ansi:1.1.1" guava = "com.google.guava:guava:33.5.0-jre" diff --git a/native/src/main/java/com/velocitypowered/natives/util/MoreByteBufUtils.java b/native/src/main/java/com/velocitypowered/natives/util/MoreByteBufUtils.java index 13f4f0c570..886f20818b 100644 --- a/native/src/main/java/com/velocitypowered/natives/util/MoreByteBufUtils.java +++ b/native/src/main/java/com/velocitypowered/natives/util/MoreByteBufUtils.java @@ -54,8 +54,8 @@ private static boolean isCompatible(Native nativeStuff, ByteBuf buf) { BufferPreference preferred = nativeStuff.preferredBufferType(); return switch (preferred) { case DIRECT_PREFERRED, HEAP_PREFERRED -> - // The native prefers this type, but doesn't strictly require we provide it. - true; + // The native prefers this type, but doesn't strictly require we provide it. + true; case DIRECT_REQUIRED -> buf.hasMemoryAddress(); case HEAP_REQUIRED -> buf.hasArray(); }; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 95f10bcbb0..f44cb99e60 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -650,7 +650,7 @@ public void shutdown(boolean explicitExit, Component reason) { } /** - * 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 */ diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ModernResourcePackHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ModernResourcePackHandler.java index f0fd5e084c..3bef8a4ba2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ModernResourcePackHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ModernResourcePackHandler.java @@ -37,7 +37,7 @@ import org.jetbrains.annotations.Nullable; /** - * Modern (Minecraft 1.20.3+) ResourcePackHandler + * Modern (Minecraft 1.20.3+) ResourcePackHandler. */ public final class ModernResourcePackHandler extends ResourcePackHandler { private final ListMultimap outstandingResourcePacks = diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ResourcePackHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ResourcePackHandler.java index b384388534..dc04b912c2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ResourcePackHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/player/resourcepack/handler/ResourcePackHandler.java @@ -118,6 +118,7 @@ protected void sendResourcePackRequestPacket(final @NotNull ResourcePackInfo que /** * Processes a client response to a sent resource-pack. + * *

    Cases in which no action will be taken:

    *
      * diff --git a/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java b/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java index 9d54b2d073..7037ee2ae2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/event/VelocityEventManager.java @@ -545,6 +545,36 @@ private void fire(final @Nullable CompletableFuture future, } } + private void fire(final @Nullable CompletableFuture 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 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_EXECUTING = 1; private static final int TASK_STATE_CONTINUE_IMMEDIATELY = 2; @@ -669,40 +699,10 @@ public void resumeWithException(final Throwable exception) { } } - private void fire(final @Nullable CompletableFuture 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 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( final HandlerRegistration registration, final Throwable t) { final PluginDescription pluginDescription = registration.plugin.getDescription(); logger.error("Couldn't pass {} to {} {}", registration.eventType.getSimpleName(), pluginDescription.getId(), pluginDescription.getVersion().orElse(""), t); } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index efc0ed177b..093256d0c0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -633,7 +633,7 @@ public static List readProperties(ByteBuf buf) { 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 * @return the read byte array @@ -671,7 +671,7 @@ public static ByteBuf readRetainedByteBufSlice17(ByteBuf buf) { } /** - * 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 buf buf @@ -695,7 +695,7 @@ public static void writeByteArray17(byte[] b, ByteBuf buf, boolean allowExtended } /** - * 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 buf buf diff --git a/proxy/src/main/resources/default-velocity.toml b/proxy/src/main/resources/default-velocity.toml index 4d71e589b9..28de529782 100644 --- a/proxy/src/main/resources/default-velocity.toml +++ b/proxy/src/main/resources/default-velocity.toml @@ -42,7 +42,7 @@ forwarding-secret-file = "forwarding.secret" # Announce whether or not your server supports Forge. If you run a modded server, we # suggest turning this on. -# +# # If your network runs one modpack consistently, consider using ping-passthrough = "mods" # instead for a nicer display in the server list. announce-forge = false From 8050fdf09e4145cfbf6fc017045cd429d3fd8163 Mon Sep 17 00:00:00 2001 From: RootBeer Date: Mon, 26 Jan 2026 04:33:54 -0500 Subject: [PATCH 2/7] Make all packet-oriented classes require checkstyle for synchronization of maintenance --- proxy/build.gradle.kts | 17 ++- .../packet/AvailableCommandsPacket.java | 7 + .../proxy/protocol/packet/BossBarPacket.java | 88 +++++++++--- .../packet/BundleDelimiterPacket.java | 8 ++ .../protocol/packet/ClientSettingsPacket.java | 33 ++++- .../ClientboundCookieRequestPacket.java | 5 + .../packet/ClientboundSoundEntityPacket.java | 32 +++-- .../packet/ClientboundStopSoundPacket.java | 12 +- .../packet/ClientboundStoreCookiePacket.java | 5 + .../protocol/packet/DialogClearPacket.java | 7 + .../protocol/packet/DialogShowPacket.java | 7 + .../protocol/packet/DisconnectPacket.java | 26 +++- .../packet/EncryptionRequestPacket.java | 6 + .../packet/EncryptionResponsePacket.java | 19 ++- .../protocol/packet/HandshakePacket.java | 10 +- .../packet/HeaderAndFooterPacket.java | 8 +- .../proxy/protocol/packet/JoinGamePacket.java | 30 ++-- .../protocol/packet/KeepAlivePacket.java | 5 + .../protocol/packet/LegacyDisconnect.java | 20 ++- .../packet/LegacyHandshakePacket.java | 5 + .../protocol/packet/LegacyPingPacket.java | 5 + .../packet/LegacyPlayerListItemPacket.java | 48 +++++-- .../packet/LoginAcknowledgedPacket.java | 9 +- .../packet/LoginPluginMessagePacket.java | 17 +++ .../packet/LoginPluginResponsePacket.java | 11 ++ .../protocol/packet/PingIdentifyPacket.java | 3 + .../protocol/packet/PluginMessagePacket.java | 12 +- .../packet/RemovePlayerInfoPacket.java | 4 + .../packet/RemoveResourcePackPacket.java | 6 +- .../packet/ResourcePackRequestPacket.java | 26 ++-- .../packet/ResourcePackResponsePacket.java | 32 +++-- .../proxy/protocol/packet/RespawnPacket.java | 26 ++++ .../protocol/packet/ServerDataPacket.java | 15 +- .../protocol/packet/ServerLoginPacket.java | 31 ++++- .../packet/ServerLoginSuccessPacket.java | 16 +++ .../ServerboundCookieResponsePacket.java | 5 + .../ServerboundCustomClickActionPacket.java | 6 + .../protocol/packet/SetCompressionPacket.java | 4 + .../protocol/packet/StatusPingPacket.java | 4 + .../protocol/packet/StatusRequestPacket.java | 4 +- .../protocol/packet/StatusResponsePacket.java | 9 ++ .../packet/TabCompleteRequestPacket.java | 9 ++ .../packet/TabCompleteResponsePacket.java | 6 + .../proxy/protocol/packet/TransferPacket.java | 14 ++ .../packet/UpsertPlayerInfoPacket.java | 31 +++-- .../packet/brigadier/ArgumentIdentifier.java | 19 ++- .../brigadier/ArgumentPropertyRegistry.java | 16 ++- .../brigadier/ArgumentPropertySerializer.java | 10 ++ .../packet/brigadier/ModArgumentProperty.java | 11 ++ .../RegistryIdArgumentSerializer.java | 10 ++ .../packet/brigadier/RegistryKeyArgument.java | 9 ++ .../brigadier/RegistryKeyArgumentList.java | 29 ++++ .../RegistryKeyArgumentSerializer.java | 6 + .../brigadier/TimeArgumentSerializer.java | 6 + .../chat/ChatAcknowledgementPacket.java | 73 +++++----- .../protocol/packet/chat/ChatHandler.java | 16 +++ .../proxy/protocol/packet/chat/ChatQueue.java | 45 +++++- .../protocol/packet/chat/ChatTimeKeeper.java | 17 +++ .../proxy/protocol/packet/chat/ChatType.java | 8 +- .../protocol/packet/chat/CommandHandler.java | 66 +++++++-- .../protocol/packet/chat/ComponentHolder.java | 131 ++++++++++++++---- .../packet/chat/LastSeenMessages.java | 34 ++++- .../chat/PlayerChatCompletionPacket.java | 8 ++ .../chat/RateLimitedCommandHandler.java | 59 ++++---- .../packet/chat/RemoteChatSession.java | 5 + .../packet/chat/SystemChatPacket.java | 7 +- .../chat/builder/ChatBuilderFactory.java | 11 ++ .../packet/chat/builder/ChatBuilderV2.java | 7 + .../packet/chat/keyed/KeyedChatBuilder.java | 6 + .../packet/chat/keyed/KeyedChatHandler.java | 25 ++++ .../chat/keyed/KeyedCommandHandler.java | 16 ++- .../chat/keyed/KeyedPlayerChatPacket.java | 7 + .../chat/keyed/KeyedPlayerCommandPacket.java | 7 + .../packet/chat/legacy/LegacyChatBuilder.java | 7 + .../packet/chat/legacy/LegacyChatHandler.java | 7 + .../packet/chat/legacy/LegacyChatPacket.java | 7 + .../chat/legacy/LegacyCommandHandler.java | 17 ++- .../chat/session/SessionChatBuilder.java | 7 + .../chat/session/SessionChatHandler.java | 10 +- .../chat/session/SessionCommandHandler.java | 16 ++- .../chat/session/SessionPlayerChatPacket.java | 16 +++ .../session/SessionPlayerCommandPacket.java | 90 +++++++++--- .../session/UnsignedPlayerCommandPacket.java | 13 +- .../packet/config/ActiveFeaturesPacket.java | 7 + .../ClientboundCustomReportDetailsPacket.java | 60 ++++---- .../config/ClientboundServerLinksPacket.java | 103 ++++++++------ .../config/CodeOfConductAcceptPacket.java | 6 + .../packet/config/CodeOfConductPacket.java | 7 + .../packet/config/FinishedUpdatePacket.java | 9 +- .../packet/config/KnownPacksPacket.java | 93 ++++++++----- .../packet/config/RegistrySyncPacket.java | 12 ++ .../packet/config/StartUpdatePacket.java | 12 +- .../packet/config/TagsUpdatePacket.java | 10 +- .../LegacyMinecraftPingVersion.java | 10 ++ .../packet/title/GenericTitlePacket.java | 20 ++- .../packet/title/LegacyTitlePacket.java | 14 +- .../packet/title/TitleActionbarPacket.java | 10 ++ .../packet/title/TitleClearPacket.java | 9 ++ .../packet/title/TitleSubtitlePacket.java | 9 ++ .../packet/title/TitleTextPacket.java | 9 ++ .../packet/title/TitleTimesPacket.java | 9 ++ 101 files changed, 1578 insertions(+), 388 deletions(-) diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts index 599baba1ce..5929692c5e 100644 --- a/proxy/build.gradle.kts +++ b/proxy/build.gradle.kts @@ -14,10 +14,6 @@ application { } tasks { - withType { - exclude("**/com/velocitypowered/proxy/protocol/packet/**") - } - jar { manifest { attributes["Implementation-Title"] = "Velocity" @@ -33,7 +29,7 @@ tasks { 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/bytes/**") exclude("it/unimi/dsi/fastutil/chars/**") @@ -42,7 +38,7 @@ tasks { exclude("it/unimi/dsi/fastutil/longs/**") 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 most of the int types - Object2IntMap have a values() method that returns an @@ -112,6 +108,15 @@ tasks { workingDir = file("run").also(File::mkdirs) standardInput = System.`in` // Doesn't work? } + + withType().configureEach { + options.compilerArgs.addAll( + listOf( + "-Alog4j.graalvm.groupId=${project.group}", + "-Alog4j.graalvm.artifactId=${project.name}" + ) + ) + } } val projectVersion = version as String diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java index 2746b23f4e..23cebf6103 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommandsPacket.java @@ -53,6 +53,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a packet that contains the list of available commands, implementing {@link MinecraftPacket}. + * + *

      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.

      + */ public class AvailableCommandsPacket implements MinecraftPacket { private static final Command PLACEHOLDER_COMMAND = source -> 0; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java index d7748efffe..06cbd8619e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BossBarPacket.java @@ -29,6 +29,10 @@ import net.kyori.adventure.bossbar.BossBar; 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 { private static final Enum2IntMap COLORS_TO_PROTOCOL = @@ -70,6 +74,14 @@ public class BossBarPacket implements MinecraftPacket { private int overlay; 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( final UUID id, final BossBar bar, @@ -86,6 +98,13 @@ public static BossBarPacket createAddPacket( 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) { final BossBarPacket packet = new BossBarPacket(); packet.setUuid(id); @@ -93,6 +112,13 @@ public static BossBarPacket createRemovePacket(final UUID id, final BossBar bar) 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) { final BossBarPacket packet = new BossBarPacket(); packet.setUuid(id); @@ -101,6 +127,14 @@ public static BossBarPacket createUpdateProgressPacket(final UUID id, final Boss 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( final UUID id, final BossBar bar, @@ -113,6 +147,13 @@ public static BossBarPacket createUpdateNamePacket( 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) { final BossBarPacket packet = new BossBarPacket(); packet.setUuid(id); @@ -122,6 +163,13 @@ public static BossBarPacket createUpdateStylePacket(final UUID id, final BossBar 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) { final BossBarPacket packet = new BossBarPacket(); packet.setUuid(id); @@ -130,6 +178,12 @@ public static BossBarPacket createUpdatePropertiesPacket(final UUID id, final Bo 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() { if (uuid == null) { throw new IllegalStateException("No boss bar UUID specified"); @@ -214,7 +268,8 @@ public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi this.overlay = ProtocolUtils.readVarInt(buf); this.flags = buf.readUnsignedByte(); } - case REMOVE -> {} + case REMOVE -> { + } case UPDATE_PERCENT -> this.percent = buf.readFloat(); case UPDATE_NAME -> this.name = ComponentHolder.read(buf, version); case UPDATE_STYLE -> { @@ -235,22 +290,23 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi ProtocolUtils.writeVarInt(buf, action); switch (action) { case ADD -> { - if (name == null) { - throw new IllegalStateException("No name specified!"); - } - name.write(buf); - buf.writeFloat(percent); - ProtocolUtils.writeVarInt(buf, color); - ProtocolUtils.writeVarInt(buf, overlay); - buf.writeByte(flags); + if (name == null) { + throw new IllegalStateException("No name specified!"); + } + name.write(buf); + buf.writeFloat(percent); + ProtocolUtils.writeVarInt(buf, color); + ProtocolUtils.writeVarInt(buf, overlay); + buf.writeByte(flags); + } + case REMOVE -> { } - case REMOVE -> {} case UPDATE_PERCENT -> buf.writeFloat(percent); case UPDATE_NAME -> { - if (name == null) { - throw new IllegalStateException("No name specified!"); - } - name.write(buf); + if (name == null) { + throw new IllegalStateException("No name specified!"); + } + name.write(buf); } case UPDATE_STYLE -> { ProtocolUtils.writeVarInt(buf, color); @@ -264,7 +320,7 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi private static byte serializeFlags(Set flags) { byte val = 0x0; for (BossBar.Flag flag : flags) { - val |= FLAG_BITS_TO_PROTOCOL.get(flag); + val |= (byte) FLAG_BITS_TO_PROTOCOL.get(flag); } return val; } @@ -273,4 +329,4 @@ private static byte serializeFlags(Set flags) { public boolean handle(MinecraftSessionHandler handler) { return handler.handle(this); } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java index 4da691c763..5c6827f31a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/BundleDelimiterPacket.java @@ -23,6 +23,14 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; 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. + * + *

      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.

      + */ public final class BundleDelimiterPacket implements MinecraftPacket { public static final BundleDelimiterPacket INSTANCE = new BundleDelimiterPacket(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java index 39e6fde02c..743fb2bac9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettingsPacket.java @@ -23,9 +23,13 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; import java.util.Objects; - 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 { private @Nullable String locale; private byte viewDistance; @@ -41,6 +45,19 @@ public class ClientSettingsPacket implements MinecraftPacket { 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, short skinParts, int mainHand, boolean textFilteringEnabled, boolean clientListingAllowed, int particleStatus) { @@ -55,6 +72,12 @@ public ClientSettingsPacket(String locale, byte viewDistance, int chatVisibility this.particleStatus = particleStatus; } + /** + * Gets the client's locale. + * + * @return the locale + * @throws IllegalStateException if no locale is specified + */ public String getLocale() { if (locale == null) { throw new IllegalStateException("No locale specified"); @@ -132,10 +155,10 @@ public void setParticleStatus(int particleStatus) { @Override public String toString() { - return "ClientSettings{" + "locale='" + locale + '\'' + ", viewDistance=" + viewDistance + - ", chatVisibility=" + chatVisibility + ", chatColors=" + chatColors + ", skinParts=" + - skinParts + ", mainHand=" + mainHand + ", chatFilteringEnabled=" + textFilteringEnabled + - ", clientListingAllowed=" + clientListingAllowed + ", particleStatus=" + particleStatus + '}'; + return "ClientSettings{" + "locale='" + locale + '\'' + ", viewDistance=" + viewDistance + + ", chatVisibility=" + chatVisibility + ", chatColors=" + chatColors + ", skinParts=" + + skinParts + ", mainHand=" + mainHand + ", chatFilteringEnabled=" + textFilteringEnabled + + ", clientListingAllowed=" + clientListingAllowed + ", particleStatus=" + particleStatus + '}'; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java index fd558b29ca..0e7c2a7a00 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundCookieRequestPacket.java @@ -25,6 +25,11 @@ import io.netty.buffer.ByteBuf; 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 { private Key key; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java index 459f143010..be81201c96 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java @@ -22,11 +22,16 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +import java.util.Random; import net.kyori.adventure.sound.Sound; import org.jetbrains.annotations.Nullable; -import java.util.Random; - +/** + * A clientbound packet that instructs the client to play a sound tied to an entity. + * + *

      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.

      + */ public class ClientboundSoundEntityPacket implements MinecraftPacket { private static final Random SEEDS_RANDOM = new Random(); @@ -35,8 +40,16 @@ public class ClientboundSoundEntityPacket implements MinecraftPacket { private @Nullable Float fixedRange; 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) { this.sound = sound; this.fixedRange = fixedRange; @@ -55,18 +68,19 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi ProtocolUtils.writeMinimalKey(buf, sound.name()); buf.writeBoolean(fixedRange != null); - if (fixedRange != null) + if (fixedRange != null) { buf.writeFloat(fixedRange); - ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source()); + ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source()); - ProtocolUtils.writeVarInt(buf, emitterEntityId); + ProtocolUtils.writeVarInt(buf, emitterEntityId); - buf.writeFloat(sound.volume()); + buf.writeFloat(sound.volume()); - buf.writeFloat(sound.pitch()); + buf.writeFloat(sound.pitch()); - buf.writeLong(sound.seed().orElse(SEEDS_RANDOM.nextLong())); + buf.writeLong(sound.seed().orElse(SEEDS_RANDOM.nextLong())); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java index 3e085d38f7..ecf14c5aa2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStopSoundPacket.java @@ -22,18 +22,24 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +import javax.annotation.Nullable; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; import net.kyori.adventure.sound.SoundStop; -import javax.annotation.Nullable; - +/** + * A clientbound packet instructing the client to stop one or more sounds. + * + *

      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.

      + */ public class ClientboundStopSoundPacket implements MinecraftPacket { private @Nullable Sound.Source source; private @Nullable Key soundName; - public ClientboundStopSoundPacket() {} + public ClientboundStopSoundPacket() { + } public ClientboundStopSoundPacket(SoundStop soundStop) { this(soundStop.source(), soundStop.sound()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java index 7823b55841..e551473ac2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundStoreCookiePacket.java @@ -25,6 +25,11 @@ import io.netty.buffer.ByteBuf; 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 { private Key key; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java index 4188abfdb9..e64e1ada2d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogClearPacket.java @@ -23,6 +23,13 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; +/** + * Represents the packet sent by the server to the client to clear any + * currently displayed configuration dialog. + * + *

      This packet is used during the configuration phase (1.21.6+) to + * instruct the client to dismiss an active dialog window.

      + */ public class DialogClearPacket implements MinecraftPacket { public static final DialogClearPacket INSTANCE = new DialogClearPacket(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogShowPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogShowPacket.java index 67d4b8f82a..21a69cc216 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogShowPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DialogShowPacket.java @@ -27,6 +27,13 @@ import net.kyori.adventure.nbt.BinaryTag; 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+. + * + *

      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.

      + */ public class DialogShowPacket implements MinecraftPacket { private final StateRegistry state; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DisconnectPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DisconnectPacket.java index dd16cb61ed..7074e8fd25 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DisconnectPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/DisconnectPacket.java @@ -28,6 +28,12 @@ import net.kyori.adventure.text.Component; 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 { private @Nullable ComponentHolder reason; @@ -42,6 +48,12 @@ private DisconnectPacket(StateRegistry state, ComponentHolder 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() { if (reason == null) { throw new IllegalStateException("No reason specified"); @@ -62,8 +74,8 @@ public String toString() { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - reason = ComponentHolder.read(buf, state == StateRegistry.LOGIN - ? ProtocolVersion.MINECRAFT_1_20_2 : version); + reason = ComponentHolder.read(buf, state == StateRegistry.LOGIN + ? ProtocolVersion.MINECRAFT_1_20_2 : version); } @Override @@ -76,9 +88,17 @@ public boolean handle(MinecraftSessionHandler handler) { 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) { Preconditions.checkNotNull(component, "component"); return new DisconnectPacket(state, new ComponentHolder(state == StateRegistry.LOGIN ? ProtocolVersion.MINECRAFT_1_20_2 : version, component)); } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java index 422d5e117c..66af05e066 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequestPacket.java @@ -26,6 +26,12 @@ import io.netty.buffer.ByteBuf; 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 { private String serverId = ""; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java index fedb67a5e3..eed2ab1f4a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponsePacket.java @@ -26,10 +26,18 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import com.velocitypowered.proxy.util.except.QuietDecoderException; import io.netty.buffer.ByteBuf; -import org.checkerframework.checker.nullness.qual.Nullable; - import java.util.Arrays; +import org.checkerframework.checker.nullness.qual.Nullable; +/** + * 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. + * + *

      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.

      + */ public class EncryptionResponsePacket implements MinecraftPacket { private static final QuietDecoderException NO_SALT = new QuietDecoderException( @@ -47,6 +55,13 @@ public byte[] getVerifyToken() { 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() { if (salt == null) { throw NO_SALT; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java index 88cb3688bd..5deaf395fc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HandshakePacket.java @@ -27,6 +27,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; 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 { // This size was chosen to ensure Forge clients can still connect even with very long hostnames. @@ -110,13 +116,13 @@ public boolean handle(MinecraftSessionHandler handler) { @Override public int decodeExpectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion version) { + ProtocolVersion version) { return 7; } @Override public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion version) { + ProtocolVersion version) { return 9 + (MAXIMUM_HOSTNAME_LENGTH * 3); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java index 339d026f8f..55eb3ebce5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/HeaderAndFooterPacket.java @@ -26,6 +26,10 @@ import io.netty.buffer.ByteBuf; 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 { private final ComponentHolder header; @@ -67,11 +71,11 @@ public boolean handle(MinecraftSessionHandler handler) { public static HeaderAndFooterPacket create(Component header, Component footer, ProtocolVersion protocolVersion) { return new HeaderAndFooterPacket(new ComponentHolder(protocolVersion, header), - new ComponentHolder(protocolVersion, footer)); + new ComponentHolder(protocolVersion, footer)); } public static HeaderAndFooterPacket reset(ProtocolVersion version) { ComponentHolder empty = new ComponentHolder(version, Component.empty()); return new HeaderAndFooterPacket(empty, empty); } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java index 787d858ebf..81ac98aeb4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGamePacket.java @@ -21,13 +21,19 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; 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 it.unimi.dsi.fastutil.Pair; import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.CompoundBinaryTag; 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 { private static final BinaryTagIO.Reader JOINGAME_READER = BinaryTagIO.reader(4 * 1024 * 1024); @@ -204,17 +210,17 @@ public CompoundBinaryTag getRegistry() { @Override public String toString() { - return "JoinGame{" + "entityId=" + entityId + ", gamemode=" + gamemode + ", dimension=" + - dimension + ", partialHashedSeed=" + partialHashedSeed + ", difficulty=" + difficulty + - ", isHardcore=" + isHardcore + ", maxPlayers=" + maxPlayers + ", levelType='" + levelType + - '\'' + ", viewDistance=" + viewDistance + ", reducedDebugInfo=" + reducedDebugInfo + - ", showRespawnScreen=" + showRespawnScreen + ", doLimitedCrafting=" + doLimitedCrafting + - ", levelNames=" + levelNames + ", registry='" + registry + '\'' + ", dimensionInfo='" + - dimensionInfo + '\'' + ", currentDimensionData='" + currentDimensionData + '\'' + - ", previousGamemode=" + previousGamemode + ", simulationDistance=" + simulationDistance + - ", lastDeathPosition='" + lastDeathPosition + '\'' + ", portalCooldown=" + portalCooldown + - ", seaLevel=" + seaLevel + - '}'; + return "JoinGame{" + "entityId=" + entityId + ", gamemode=" + gamemode + ", dimension=" + + dimension + ", partialHashedSeed=" + partialHashedSeed + ", difficulty=" + difficulty + + ", isHardcore=" + isHardcore + ", maxPlayers=" + maxPlayers + ", levelType='" + levelType + + '\'' + ", viewDistance=" + viewDistance + ", reducedDebugInfo=" + reducedDebugInfo + + ", showRespawnScreen=" + showRespawnScreen + ", doLimitedCrafting=" + doLimitedCrafting + + ", levelNames=" + levelNames + ", registry='" + registry + '\'' + ", dimensionInfo='" + + dimensionInfo + '\'' + ", currentDimensionData='" + currentDimensionData + '\'' + + ", previousGamemode=" + previousGamemode + ", simulationDistance=" + simulationDistance + + ", lastDeathPosition='" + lastDeathPosition + '\'' + ", portalCooldown=" + portalCooldown + + ", seaLevel=" + seaLevel + + '}'; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java index a44e50eeaa..3ae2d89d30 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlivePacket.java @@ -23,6 +23,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a KeepAlive packet in Minecraft. This packet is used to ensure that the connection + * between the client and the server shall still be active by sending a randomly generated ID that + * the client must respond to. + */ public class KeepAlivePacket implements MinecraftPacket { private long randomId; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyDisconnect.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyDisconnect.java index e8f8deef29..952dfe28dc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyDisconnect.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyDisconnect.java @@ -25,7 +25,13 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -@SuppressWarnings("checkstyle:MissingJavadocType") +/** + * Represents a legacy disconnect packet that contains a reason for disconnection. + * This class is used to convert modern server ping responses into the legacy format, + * which is compatible with older Minecraft versions. + * + * @param reason the string reason for disconnection + */ public record LegacyDisconnect(String reason) { private static final ServerPing.Players FAKE_PLAYERS = new ServerPing.Players(0, 0, @@ -46,17 +52,17 @@ public static LegacyDisconnect fromServerPing(ServerPing response, return switch (version) { case MINECRAFT_1_3 -> - // Minecraft 1.3 and below use the section symbol as a delimiter. Accordingly, we must - // remove all section symbols, along with fetching just the first line of an (unformatted) - // MOTD. - new LegacyDisconnect(String.join(LEGACY_COLOR_CODE, + // Minecraft 1.3 and below use the section symbol as a delimiter. Accordingly, we must + // remove all section symbols, along with fetching just the first line of an (unformatted) + // MOTD. + new LegacyDisconnect(String.join(LEGACY_COLOR_CODE, cleanSectionSymbol(getFirstLine(PlainTextComponentSerializer.plainText().serialize( response.getDescriptionComponent()))), Integer.toString(players.getOnline()), Integer.toString(players.getMax()))); case MINECRAFT_1_4, MINECRAFT_1_6 -> - // Minecraft 1.4-1.6 provide support for more fields, and additionally support color codes. - new LegacyDisconnect(String.join("\0", + // Minecraft 1.4-1.6 provide support for more fields, and additionally support color codes. + new LegacyDisconnect(String.join("\0", LEGACY_COLOR_CODE + "1", Integer.toString(response.getVersion().getProtocol()), response.getVersion().getName(), diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java index 38483ed864..8a9aba2700 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyHandshakePacket.java @@ -23,6 +23,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a legacy handshake packet in Minecraft, which is typically used + * during the initial connection process for older versions of the Minecraft protocol. + * This class currently does not support decoding of the handshake packet. + */ public class LegacyHandshakePacket implements MinecraftPacket { @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java index 656d3222b2..c81c47221e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPingPacket.java @@ -26,6 +26,11 @@ import java.net.InetSocketAddress; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a legacy ping packet in Minecraft, commonly used in the server list ping process. + * This packet handles compatibility with older Minecraft versions and contains information + * such as the ping protocol version and optionally a virtual host address. + */ public class LegacyPingPacket implements MinecraftPacket { private final LegacyMinecraftPingVersion version; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java index 9dbe9cbcb8..cdffabccce 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LegacyPlayerListItemPacket.java @@ -33,6 +33,10 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a legacy player list item packet, which is used to modify the player list in a Minecraft client. + * The packet can add, remove, or update player entries (e.g., updating gamemode, latency, or display names). + */ public class LegacyPlayerListItemPacket implements MinecraftPacket { public static final int ADD_PLAYER = 0; @@ -76,16 +80,16 @@ public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi item.setLatency(ProtocolUtils.readVarInt(buf)); item.setDisplayName(readOptionalComponent(buf, version)); if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) { - if (buf.readBoolean()) { - item.setPlayerKey(ProtocolUtils.readPlayerKey(version, buf)); - } + if (buf.readBoolean()) { + item.setPlayerKey(ProtocolUtils.readPlayerKey(version, buf)); + } } } case UPDATE_GAMEMODE -> item.setGameMode(ProtocolUtils.readVarInt(buf)); case UPDATE_LATENCY -> item.setLatency(ProtocolUtils.readVarInt(buf)); case UPDATE_DISPLAY_NAME -> item.setDisplayName(readOptionalComponent(buf, version)); case REMOVE_PLAYER -> { - //Do nothing, all that is needed is the uuid + // Do nothing, all that is needed is the uuid } default -> throw new UnsupportedOperationException("Unknown action " + action); } @@ -107,6 +111,17 @@ public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi return null; } + /** + * Encodes this packet's contents into the given {@link ByteBuf}. + * + *

      This method serializes the packet data based on the current protocol version. + * Subclasses overriding this method should preserve compatibility with legacy + * and modern formats as needed.

      + * + * @param buf the buffer to write to + * @param direction the direction of the packet (clientbound or serverbound) + * @param version the Minecraft protocol version + */ @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_8)) { @@ -125,12 +140,12 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi ProtocolUtils.writeVarInt(buf, item.getLatency()); writeDisplayName(buf, item.getDisplayName(), version); if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19)) { - if (item.getPlayerKey() != null) { - buf.writeBoolean(true); - ProtocolUtils.writePlayerKey(buf, item.getPlayerKey()); - } else { - buf.writeBoolean(false); - } + if (item.getPlayerKey() != null) { + buf.writeBoolean(true); + ProtocolUtils.writePlayerKey(buf, item.getPlayerKey()); + } else { + buf.writeBoolean(false); + } } } case UPDATE_GAMEMODE -> ProtocolUtils.writeVarInt(buf, item.getGameMode()); @@ -172,6 +187,10 @@ private void writeDisplayName(ByteBuf buf, @Nullable Component displayName, } } + /** + * Represents an individual item in the player list, containing the player's details such as UUID, name, + * game mode, latency, and optionally a display name and player key. + */ public static class Item { private final UUID uuid; @@ -190,6 +209,15 @@ public Item(UUID uuid) { this.uuid = uuid; } + /** + * Creates an {@link Item} instance from a {@link TabListEntry}. + * This method extracts relevant data from the {@link TabListEntry} such as + * the player's profile ID, name, properties, latency, game mode, player key, + * and display name, and uses them to populate a new {@code Item}. + * + * @param entry the {@link TabListEntry} from which to extract data + * @return an {@link Item} populated with data from the {@link TabListEntry} + */ public static Item from(TabListEntry entry) { return new Item(entry.getProfile().getId()) .setName(entry.getProfile().getName()) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java index 16cf519b0b..15bbb2c343 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginAcknowledgedPacket.java @@ -23,6 +23,13 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a packet that acknowledges a successful login, implementing {@link MinecraftPacket}. + * + *

      The {@code LoginAcknowledgedPacket} is sent by the server to confirm that the player's login + * process has been successfully completed. It signals the transition from the login phase to the + * game or session phase.

      + */ public class LoginAcknowledgedPacket implements MinecraftPacket { @Override @@ -37,7 +44,7 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, @Override public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion version) { + ProtocolVersion version) { return 0; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java index 2fa82e922c..5833ea036a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginMessagePacket.java @@ -27,6 +27,10 @@ import io.netty.buffer.Unpooled; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a login plugin message packet sent during the login phase. This packet allows custom + * plugin messages to be sent from the server to the client before login is complete. + */ public class LoginPluginMessagePacket extends DeferredByteBufHolder implements MinecraftPacket { private int id; @@ -36,6 +40,13 @@ public LoginPluginMessagePacket() { super(null); } + /** + * Constructs a new {@code LoginPluginMessagePacket} with the specified ID, channel, and data buffer. + * + * @param id the plugin message ID + * @param channel the channel name, or {@code null} if not specified + * @param data the data buffer + */ public LoginPluginMessagePacket(int id, @Nullable String channel, ByteBuf data) { super(data); this.id = id; @@ -46,6 +57,12 @@ public int getId() { return id; } + /** + * Gets the plugin message channel. + * + * @return the channel name + * @throws IllegalStateException if the channel is not specified + */ public String getChannel() { if (channel == null) { throw new IllegalStateException("Channel is not specified!"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java index e7d9443dca..1a8c10664f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/LoginPluginResponsePacket.java @@ -27,6 +27,10 @@ import io.netty.buffer.Unpooled; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +/** + * Represents the response packet to a plugin message sent during the login phase. + * The packet contains the plugin message ID, a success flag, and any additional data. + */ public class LoginPluginResponsePacket extends DeferredByteBufHolder implements MinecraftPacket { private int id; @@ -36,6 +40,13 @@ public LoginPluginResponsePacket() { super(Unpooled.EMPTY_BUFFER); } + /** + * Constructs a new {@code LoginPluginResponsePacket} with the specified ID, success status, and data buffer. + * + * @param id the plugin message ID + * @param success {@code true} if the plugin message was successful, {@code false} otherwise + * @param buf the data buffer + */ public LoginPluginResponsePacket(int id, boolean success, @MonotonicNonNull ByteBuf buf) { super(buf); this.id = id; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java index 27c1351d5e..7d870dcf6f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PingIdentifyPacket.java @@ -23,6 +23,9 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a packet used for ping identification with a unique ID. + */ public class PingIdentifyPacket implements MinecraftPacket { private int id; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java index ecf2887fd9..bb8abf578d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessagePacket.java @@ -29,6 +29,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a plugin message packet, which allows for custom communication between + * a Minecraft server and a client via custom channels. + */ public class PluginMessagePacket extends DeferredByteBufHolder implements MinecraftPacket { private @Nullable String channel; @@ -43,6 +47,12 @@ public PluginMessagePacket(String channel, this.channel = channel; } + /** + * Gets the channel for this plugin message. + * + * @return the channel name + * @throws IllegalStateException if the channel is not set + */ public String getChannel() { if (channel == null) { throw new IllegalStateException("Channel is not specified."); @@ -73,7 +83,6 @@ public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi } else { this.replace(ProtocolUtils.readRetainedByteBufSlice17(buf)); } - } @Override @@ -97,7 +106,6 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi } else { ProtocolUtils.writeByteBuf17(content(), buf, true); // True for Forge support } - } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java index 90ab387178..255769d875 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemovePlayerInfoPacket.java @@ -27,6 +27,10 @@ import java.util.Collection; import java.util.UUID; +/** + * Represents a packet sent to remove player information from the player list. + * The packet contains a collection of {@link UUID}s representing the profiles to be removed. + */ public class RemovePlayerInfoPacket implements MinecraftPacket { private Collection profilesToRemove; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java index d003a0a951..8d6ef276c4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RemoveResourcePackPacket.java @@ -25,6 +25,10 @@ import io.netty.buffer.ByteBuf; import java.util.UUID; +/** + * Represents a packet sent to remove a previously applied resource pack from the client. + * The packet contains an optional UUID that identifies the resource pack to be removed. + */ public class RemoveResourcePackPacket implements MinecraftPacket { private UUID id; @@ -60,4 +64,4 @@ public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVer public boolean handle(MinecraftSessionHandler handler) { return handler.handle(this); } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java index a0f86aed11..b5e7e63fee 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackRequestPacket.java @@ -33,6 +33,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a resource pack request packet sent by the server to prompt the client to download a resource pack. + * The packet includes the resource pack URL, SHA1 hash, and optional prompt. + */ public class ResourcePackRequestPacket implements MinecraftPacket { private @MonotonicNonNull UUID id; // 1.20.3+ @@ -124,6 +128,12 @@ public void encode(ByteBuf buf, Direction direction, ProtocolVersion protocolVer } } + /** + * Converts this packet into a {@link VelocityResourcePackInfo} object, which contains the information + * about the resource pack being requested. + * + * @return a {@code VelocityResourcePackInfo} representing the resource pack information + */ public VelocityResourcePackInfo toServerPromptedPack() { final ResourcePackInfo.Builder builder = new VelocityResourcePackInfo.BuilderImpl(Preconditions.checkNotNull(url)) @@ -145,12 +155,12 @@ public boolean handle(MinecraftSessionHandler handler) { @Override public String toString() { - return "ResourcePackRequestPacket{" + - "id=" + id + - ", url='" + url + '\'' + - ", hash='" + hash + '\'' + - ", isRequired=" + isRequired + - ", prompt=" + prompt + - '}'; + return "ResourcePackRequestPacket{" + + "id=" + id + + ", url='" + url + '\'' + + ", hash='" + hash + '\'' + + ", isRequired=" + isRequired + + ", prompt=" + prompt + + '}'; } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java index 020c3530de..de5d08828e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ResourcePackResponsePacket.java @@ -24,10 +24,13 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; - import java.util.UUID; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +/** + * Represents the response packet sent by the client after receiving a resource pack request from the server. + * The packet contains information about the client's response, including the resource pack status. + */ public class ResourcePackResponsePacket implements MinecraftPacket { private UUID id; @@ -37,12 +40,25 @@ public class ResourcePackResponsePacket implements MinecraftPacket { public ResourcePackResponsePacket() { } + /** + * Constructs a new {@code ResourcePackResponsePacket} with the specified parameters. + * + * @param id the unique identifier for the response + * @param hash the hash of the resource pack + * @param status the status of the resource pack + */ public ResourcePackResponsePacket(UUID id, String hash, @MonotonicNonNull Status status) { this.id = id; this.hash = hash; this.status = status; } + /** + * Gets the status of the resource pack response. + * + * @return the status of the response + * @throws IllegalStateException if the packet has not been deserialized yet + */ public Status getStatus() { if (status == null) { throw new IllegalStateException("Packet not yet deserialized"); @@ -87,10 +103,10 @@ public boolean handle(MinecraftSessionHandler handler) { @Override public String toString() { - return "ResourcePackResponsePacket{" + - "id=" + id + - ", hash='" + hash + '\'' + - ", status=" + status + - '}'; + return "ResourcePackResponsePacket{" + + "id=" + id + + ", hash='" + hash + '\'' + + ", status=" + status + + '}'; } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java index fd9c8ca772..2e13fcad30 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/RespawnPacket.java @@ -28,6 +28,10 @@ import net.kyori.adventure.nbt.CompoundBinaryTag; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a respawn packet sent by the server when the player changes dimensions or respawns. + * The packet contains information about the new dimension, difficulty, gamemode, and more. + */ public class RespawnPacket implements MinecraftPacket { private int dimension; @@ -46,6 +50,22 @@ public class RespawnPacket implements MinecraftPacket { public RespawnPacket() { } + /** + * Constructs a new {@code RespawnPacket} with the specified parameters. + * + * @param dimension the dimension the player is respawning or teleporting to + * @param partialHashedSeed the partial hashed seed + * @param difficulty the difficulty of the server + * @param gamemode the player's current gamemode + * @param levelType the type of level (e.g., "default", "flat") + * @param dataToKeep a byte flag indicating whether certain data should be kept + * @param dimensionInfo additional information about the dimension (for 1.16-1.16.1) + * @param previousGamemode the player's previous gamemode + * @param currentDimensionData data about the current dimension (for 1.16.2+) + * @param lastDeathPosition optional last death position (for 1.19+) + * @param portalCooldown the cooldown for portal usage (for 1.20+) + * @param seaLevel a determinable spawn point for a user (for 1.21.2+) + */ public RespawnPacket(int dimension, long partialHashedSeed, short difficulty, short gamemode, String levelType, byte dataToKeep, DimensionInfo dimensionInfo, short previousGamemode, CompoundBinaryTag currentDimensionData, @@ -65,6 +85,12 @@ public RespawnPacket(int dimension, long partialHashedSeed, short difficulty, sh this.seaLevel = seaLevel; } + /** + * Creates a new {@code RespawnPacket} from a {@link JoinGamePacket}. + * + * @param joinGame the {@code JoinGamePacket} to use + * @return a new {@code RespawnPacket} based on the provided {@code JoinGamePacket} + */ public static RespawnPacket fromJoinGame(JoinGamePacket joinGame) { return new RespawnPacket(joinGame.getDimension(), joinGame.getPartialHashedSeed(), joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(), diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java index 325a3c9dfe..e1430aae3c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerDataPacket.java @@ -25,10 +25,14 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; import io.netty.buffer.ByteBuf; -import org.jetbrains.annotations.Nullable; import java.nio.charset.StandardCharsets; import java.util.Base64; +import org.jetbrains.annotations.Nullable; +/** + * Represents the server data packet sent from the server to the client, which contains information + * such as the server description, favicon, and secure chat enforcement status. + */ public class ServerDataPacket implements MinecraftPacket { private @Nullable ComponentHolder description; @@ -38,6 +42,13 @@ public class ServerDataPacket implements MinecraftPacket { public ServerDataPacket() { } + /** + * Constructs a new {@code ServerDataPacket} with the given server description, favicon, and secure chat enforcement status. + * + * @param description the server description (maybe null) + * @param favicon the server favicon (maybe null) + * @param secureChatEnforced whether secure chat is enforced (for versions 1.19.1 to 1.20.5) + */ public ServerDataPacket(@Nullable ComponentHolder description, @Nullable Favicon favicon, boolean secureChatEnforced) { this.description = description; @@ -127,4 +138,4 @@ public void setSecureChatEnforced(boolean secureChatEnforced) { public int encodeSizeHint(Direction direction, ProtocolVersion version) { return 8 * 1024; } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java index 65693cd815..8c8bec60b9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginPacket.java @@ -29,6 +29,11 @@ import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents the packet sent from the client to the server during the login phase. + * This packet contains the player's username, optionally a cryptographic key for + * authentication, and the holder UUID depending on the Minecraft protocol version. + */ public class ServerLoginPacket implements MinecraftPacket { private static final QuietDecoderException EMPTY_USERNAME = new QuietDecoderException( @@ -41,17 +46,35 @@ public class ServerLoginPacket implements MinecraftPacket { public ServerLoginPacket() { } + /** + * Constructs a {@code ServerLoginPacket} with a username and optional player key. + * + * @param username the player's username + * @param playerKey the player's cryptographic key, or {@code null} if not present + */ public ServerLoginPacket(String username, @Nullable IdentifiedKey playerKey) { this.username = Preconditions.checkNotNull(username, "username"); this.playerKey = playerKey; } + /** + * Constructs a new {@code ServerLoginPacket} with the specified username and holder UUID. + * + * @param username the player's username + * @param holderUuid the holder UUID (optional) + */ public ServerLoginPacket(String username, @Nullable UUID holderUuid) { this.username = Preconditions.checkNotNull(username, "username"); this.holderUuid = holderUuid; this.playerKey = null; } + /** + * Gets the player's username from the login packet. + * + * @return the player's username + * @throws IllegalStateException if the username is not specified + */ public String getUsername() { if (username == null) { throw new IllegalStateException("No username found!"); @@ -74,10 +97,10 @@ public void setPlayerKey(IdentifiedKey playerKey) { @Override public String toString() { return "ServerLogin{" - + "username='" + username + '\'' - + "playerKey='" + playerKey + '\'' - + "holderUUID='" + holderUuid + '\'' - + '}'; + + "username='" + username + '\'' + + "playerKey='" + playerKey + '\'' + + "holderUUID='" + holderUuid + '\'' + + '}'; } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java index 322cd9b195..86893cc088 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccessPacket.java @@ -30,6 +30,10 @@ import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents the packet sent from the server to the client to indicate successful login. + * This packet contains the player's UUID, username, and properties associated with their profile. + */ public class ServerLoginSuccessPacket implements MinecraftPacket { private @Nullable UUID uuid; @@ -38,6 +42,12 @@ public class ServerLoginSuccessPacket implements MinecraftPacket { private static final boolean strictErrorHandling = VelocityProperties .readBoolean("velocity.strictErrorHandling", true); + /** + * Gets the player's UUID from the login success packet. + * + * @return the player's UUID + * @throws IllegalStateException if the UUID is not specified + */ public UUID getUuid() { if (uuid == null) { throw new IllegalStateException("No UUID specified!"); @@ -49,6 +59,12 @@ public void setUuid(UUID uuid) { this.uuid = uuid; } + /** + * Gets the player's username from the login success packet. + * + * @return the player's username + * @throws IllegalStateException if the username is not specified + */ public String getUsername() { if (username == null) { throw new IllegalStateException("No username specified!"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java index bee12b8024..2191ae0935 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCookieResponsePacket.java @@ -26,6 +26,11 @@ import net.kyori.adventure.key.Key; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a server-bound packet sent by the client containing a key and an optional payload. + * This packet is typically used for exchanging metadata or other information between the client + * and server. + */ public class ServerboundCookieResponsePacket implements MinecraftPacket { private Key key; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java index 6b846c2343..9b5665fce0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerboundCustomClickActionPacket.java @@ -25,6 +25,12 @@ import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder; import io.netty.buffer.ByteBuf; +/** + * Represents a serverbound packet carrying an opaque custom click action payload. + * + *

      The payload is retained as-is and forwarded to the session handler without + * interpretation by the proxy.

      + */ public class ServerboundCustomClickActionPacket extends DeferredByteBufHolder implements MinecraftPacket { public ServerboundCustomClickActionPacket() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java index 6710bf85d8..7bba564571 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/SetCompressionPacket.java @@ -23,6 +23,10 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a packet that sets the compression threshold for network communication. + * When the size of a packet exceeds the threshold, the packet will be compressed. + */ public class SetCompressionPacket implements MinecraftPacket { private int threshold; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java index 302367044a..554e879389 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusPingPacket.java @@ -24,6 +24,10 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; +/** + * Represents a status ping packet sent by the client to the server, which is used to measure the latency + * between the client and server. + */ public class StatusPingPacket implements MinecraftPacket { private long randomId; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java index 870d99093f..cbf901cf39 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusRequestPacket.java @@ -24,12 +24,14 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; +/** + * Represents a status request packet sent by the client to the server to request the server's status. + */ public class StatusRequestPacket implements MinecraftPacket { public static final StatusRequestPacket INSTANCE = new StatusRequestPacket(); private StatusRequestPacket() { - } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java index 20fada4bc7..08dcb3dba6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/StatusResponsePacket.java @@ -25,6 +25,9 @@ import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a status response packet sent from the server to the client. + */ public class StatusResponsePacket implements MinecraftPacket { private @Nullable CharSequence status; @@ -36,6 +39,12 @@ public StatusResponsePacket(CharSequence status) { this.status = status; } + /** + * Gets the status message from the packet. + * + * @return the status message as a {@link String} + * @throws IllegalStateException if the status is not specified + */ public String getStatus() { if (status == null) { throw new IllegalStateException("Status is not specified"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java index dda4695bbc..5bdbcc6b16 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequestPacket.java @@ -29,6 +29,9 @@ import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a packet sent by the client when a tab-completion request is initiated. + */ public class TabCompleteRequestPacket implements MinecraftPacket { private static final int VANILLA_MAX_TAB_COMPLETE_LEN = 2048; @@ -39,6 +42,12 @@ public class TabCompleteRequestPacket implements MinecraftPacket { private boolean hasPosition; private long position; + /** + * Gets the command string to be completed. + * + * @return the command string + * @throws IllegalStateException if the command is not set + */ public String getCommand() { if (command == null) { throw new IllegalStateException("Command is not specified"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java index a22fff0bdb..dddad82fc9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteResponsePacket.java @@ -30,6 +30,9 @@ import java.util.List; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents the packet used to send tab-completion suggestions to the client. + */ public class TabCompleteResponsePacket implements MinecraftPacket { private int transactionId; @@ -122,6 +125,9 @@ public boolean handle(MinecraftSessionHandler handler) { return handler.handle(this); } + /** + * Represents an individual tab-completion suggestion (offer) sent to the client. + */ public static class Offer implements Comparable { private final String text; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java index b5a74e49f2..6f94c6c9f2 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TransferPacket.java @@ -25,6 +25,9 @@ import java.net.InetSocketAddress; import org.jetbrains.annotations.Nullable; +/** + * Represents a packet used to transfer a player to another server. + */ public class TransferPacket implements MinecraftPacket { private String host; private int port; @@ -32,11 +35,22 @@ public class TransferPacket implements MinecraftPacket { public TransferPacket() { } + /** + * Constructs a {@code TransferPacket} with the specified host and port. + * + * @param host the hostname of the destination server + * @param port the port of the destination server + */ public TransferPacket(final String host, final int port) { this.host = host; this.port = port; } + /** + * Gets the {@link InetSocketAddress} representing the transfer address. + * + * @return the {@code InetSocketAddress}, or {@code null} if the host is not set + */ @Nullable public InetSocketAddress address() { if (host == null) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java index 9ef40ef092..b86b8bd126 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/UpsertPlayerInfoPacket.java @@ -34,6 +34,9 @@ import java.util.UUID; import org.jetbrains.annotations.Nullable; +/** + * Represents the packet for updating or inserting player information. + */ public class UpsertPlayerInfoPacket implements MinecraftPacket { private static final Action[] ALL_ACTIONS = Action.class.getEnumConstants(); @@ -133,6 +136,9 @@ public boolean handle(MinecraftSessionHandler handler) { return handler.handle(this); } + /** + * Represents the possible actions in the player info packet. + */ public enum Action { ADD_PLAYER((ignored, buf, info) -> { // read info.profile = new GameProfile( @@ -213,6 +219,9 @@ private interface Write { } } + /** + * Represents an entry in the player info packet. + */ public static class Entry { private final UUID profileId; @@ -303,16 +312,16 @@ public void setChatSession(@Nullable RemoteChatSession chatSession) { @Override public String toString() { - return "Entry{" + - "profileId=" + profileId + - ", profile=" + profile + - ", listed=" + listed + - ", latency=" + latency + - ", gameMode=" + gameMode + - ", displayName=" + displayName + - ", listOrder=" + listOrder + - ", chatSession=" + chatSession + - '}'; + return "Entry{" + + "profileId=" + profileId + + ", profile=" + profile + + ", listed=" + listed + + ", latency=" + latency + + ", gameMode=" + gameMode + + ", displayName=" + displayName + + ", listOrder=" + listOrder + + ", chatSession=" + chatSession + + '}'; } } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentIdentifier.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentIdentifier.java index 6441f6f775..fe43f5d0c6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentIdentifier.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentIdentifier.java @@ -24,6 +24,14 @@ import java.util.Map; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents an identifier for a Brigadier command argument, mapping the argument to + * different protocol versions. + * + *

      The {@code ArgumentIdentifier} is responsible for holding an identifier string for + * an argument and a map that associates protocol versions with their respective IDs. + * It ensures that the protocol version is compatible with the Minecraft 1.19 protocol or later.

      + */ public class ArgumentIdentifier { private final String identifier; @@ -37,8 +45,8 @@ private ArgumentIdentifier(String identifier, VersionSet... versions) { Map temp = new HashMap<>(); ProtocolVersion previous = null; - for (int i = 0; i < versions.length; i++) { - VersionSet current = Preconditions.checkNotNull(versions[i]); + for (VersionSet version : versions) { + VersionSet current = Preconditions.checkNotNull(version); Preconditions.checkArgument( current.getVersion().noLessThan(ProtocolVersion.MINECRAFT_1_19), @@ -60,9 +68,9 @@ private ArgumentIdentifier(String identifier, VersionSet... versions) { @Override public String toString() { - return "ArgumentIdentifier{" + - "identifier='" + identifier + '\'' + - '}'; + return "ArgumentIdentifier{" + + "identifier='" + identifier + '\'' + + '}'; } public String getIdentifier() { @@ -101,7 +109,6 @@ public int getId() { public ProtocolVersion getVersion() { return version; } - } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java index 203ab375cf..ba7ab86b3b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java @@ -45,11 +45,18 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; -import org.jetbrains.annotations.NotNull; - import java.util.HashMap; import java.util.Map; +import org.jetbrains.annotations.NotNull; +/** + * The {@code ArgumentPropertyRegistry} is responsible for managing the registration and + * retrieval of argument properties used in command parsing and execution. + * + *

      This class functions as a registry, allowing different argument properties to be registered + * and later retrieved or used when processing commands within the system. The properties + * might be tied to argument types, validation rules, or transformations.

      + */ public class ArgumentPropertyRegistry { private ArgumentPropertyRegistry() { @@ -145,7 +152,6 @@ public static void writeIdentifier(ByteBuf buf, ArgumentIdentifier identifier, } else { ProtocolUtils.writeString(buf, identifier.getIdentifier()); } - } /** @@ -272,7 +278,7 @@ public void serialize(BoolArgumentType object, ByteBuf buf, empty(id("minecraft:heightmap", mapSet(MINECRAFT_1_21_6, 51), mapSet(MINECRAFT_1_21_5, 50), mapSet(MINECRAFT_1_20_3, 49), mapSet(MINECRAFT_1_19_4, 47))); // 1.19.4 - empty(id("minecraft:uuid", mapSet(MINECRAFT_1_21_6, 56), mapSet(MINECRAFT_1_21_5, 54),mapSet(MINECRAFT_1_20_5, 53), mapSet(MINECRAFT_1_20_3, 48), + empty(id("minecraft:uuid", mapSet(MINECRAFT_1_21_6, 56), mapSet(MINECRAFT_1_21_5, 54), mapSet(MINECRAFT_1_20_5, 53), mapSet(MINECRAFT_1_20_3, 48), mapSet(MINECRAFT_1_19_4, 48), mapSet(MINECRAFT_1_19, 47))); // added in 1.16 empty(id("minecraft:loot_table", mapSet(MINECRAFT_1_21_6, 52), mapSet(MINECRAFT_1_21_5, 51), mapSet(MINECRAFT_1_20_5, 50))); @@ -287,4 +293,4 @@ public void serialize(BoolArgumentType object, ByteBuf buf, empty(id("minecraft:nbt")); // No longer in 1.19+ } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertySerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertySerializer.java index 25dcfd76c9..3649fec115 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertySerializer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertySerializer.java @@ -21,6 +21,16 @@ import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * The {@code ArgumentPropertySerializer} interface defines a contract for serializing and + * deserializing argument properties to and from a specific format. + * + *

      This interface allows implementations to convert argument properties into a serialized form, + * which can later be deserialized and restored to their original form. This is particularly useful + * for persisting command argument configurations or sending them across a network.

      + * + * @param the type of the argument property being serialized + */ public interface ArgumentPropertySerializer { @Nullable T deserialize(ByteBuf buf, ProtocolVersion protocolVersion); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java index 15416f8611..950f378415 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ModArgumentProperty.java @@ -28,6 +28,17 @@ import java.util.Collection; import java.util.concurrent.CompletableFuture; +/** + * Represents a mod-specific argument type with custom binary data attached. + * + *

      This class allows external mods or extensions to define their own command argument + * types, identified by a namespaced {@link ArgumentIdentifier} and accompanied by + * serialized {@link ByteBuf} data.

      + * + *

      Note: This type is not parseable or suggestible through Brigadier and exists primarily + * to preserve compatibility with extended command metadata during serialization and + * deserialization.

      + */ public class ModArgumentProperty implements ArgumentType { private final ArgumentIdentifier identifier; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java index 5e8e1daf12..eff680c43c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryIdArgumentSerializer.java @@ -21,6 +21,16 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * The {@code RegistryIdArgumentSerializer} handles serialization and deserialization + * of integer-based registry ID arguments. + * + *

      This serializer is used for command arguments that refer to elements in Minecraft + * registries (e.g., items, entities, dimensions) by their numerical registry ID.

      + * + *

      Values are encoded as variable-length integers using {@link ProtocolUtils} + * for compact transmission.

      + */ public class RegistryIdArgumentSerializer implements ArgumentPropertySerializer { static final RegistryIdArgumentSerializer REGISTRY_ID = new RegistryIdArgumentSerializer(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgument.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgument.java index 6d55b246fc..1c554e2179 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgument.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgument.java @@ -28,6 +28,15 @@ import java.util.List; import java.util.concurrent.CompletableFuture; +/** + * Represents a Brigadier {@link ArgumentType} for registry keys, which are typically + * namespaced resource locations (e.g., {@code minecraft:diamond_sword}). + * + *

      This argument type reads an unquoted string from input and treats it as a raw registry + * key. It does not validate the format or resolve the key against a known registry.

      + * + *

      Examples include simple strings, namespaced keys, or numeric-like identifiers.

      + */ public class RegistryKeyArgument implements ArgumentType { private static final List EXAMPLES = Arrays.asList("foo", "foo:bar", "012"); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentList.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentList.java index 2bf5f34514..86fe95f1db 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentList.java @@ -21,14 +21,25 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a list of {@link RegistryKeyArgument} objects. + * + *

      Used to manage and store multiple registry key arguments.

      + */ public final class RegistryKeyArgumentList { + /** + * Represents a registry key argument that can either be a resource or a tag. + */ public static class ResourceOrTag extends RegistryKeyArgument { public ResourceOrTag(String identifier) { super(identifier); } + /** + * Serializer for {@link ResourceOrTag}. + */ public static class Serializer implements ArgumentPropertySerializer { static final ResourceOrTag.Serializer REGISTRY = new ResourceOrTag.Serializer(); @@ -45,12 +56,18 @@ public void serialize(ResourceOrTag object, ByteBuf buf, ProtocolVersion protoco } } + /** + * Represents a registry key argument specifically for a resource or tag key. + */ public static class ResourceOrTagKey extends RegistryKeyArgument { public ResourceOrTagKey(String identifier) { super(identifier); } + /** + * Serializer for {@link ResourceOrTagKey}. + */ public static class Serializer implements ArgumentPropertySerializer { static final ResourceOrTagKey.Serializer REGISTRY = new ResourceOrTagKey.Serializer(); @@ -67,12 +84,18 @@ public void serialize(ResourceOrTagKey object, ByteBuf buf, ProtocolVersion prot } } + /** + * Represents a registry key argument for a resource. + */ public static class ResourceSelector extends RegistryKeyArgument { public ResourceSelector(String identifier) { super(identifier); } + /** + * Serializer for {@link ResourceSelector}. + */ public static class Serializer implements ArgumentPropertySerializer { static final ResourceSelector.Serializer REGISTRY = new ResourceSelector.Serializer(); @@ -89,12 +112,18 @@ public void serialize(ResourceSelector object, ByteBuf buf, ProtocolVersion prot } } + /** + * Represents a registry key argument for a resource key. + */ public static class ResourceKey extends RegistryKeyArgument { public ResourceKey(String identifier) { super(identifier); } + /** + * Serializer for {@link ResourceKey}. + */ public static class Serializer implements ArgumentPropertySerializer { static final ResourceKey.Serializer REGISTRY = new ResourceKey.Serializer(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentSerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentSerializer.java index 6ada6157b4..e2562c8534 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentSerializer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/RegistryKeyArgumentSerializer.java @@ -21,6 +21,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Serializer for {@link RegistryKeyArgument} objects. + * + *

      This class handles the serialization and deserialization of {@code RegistryKeyArgument} + * objects to and from a {@link ByteBuf} using the specified {@link ProtocolVersion}.

      + */ public class RegistryKeyArgumentSerializer implements ArgumentPropertySerializer { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/TimeArgumentSerializer.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/TimeArgumentSerializer.java index b026e8cc1f..5e4d9cedee 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/TimeArgumentSerializer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/TimeArgumentSerializer.java @@ -20,6 +20,12 @@ import com.velocitypowered.api.network.ProtocolVersion; import io.netty.buffer.ByteBuf; +/** + * Serializer for time-based arguments represented as {@link Integer}. + * + *

      This class handles the serialization and deserialization of time-related arguments, + * converting them to and from an {@link Integer} format.

      + */ public class TimeArgumentSerializer implements ArgumentPropertySerializer { static final TimeArgumentSerializer TIME = new TimeArgumentSerializer(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java index b0718090e9..c27c7199f5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatAcknowledgementPacket.java @@ -23,39 +23,44 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a packet sent to acknowledge the receipt of a chat message. + * This packet is used to confirm that a player or client has received and processed + * a chat message from the server. + */ public class ChatAcknowledgementPacket implements MinecraftPacket { - int offset; - - public ChatAcknowledgementPacket(int offset) { - this.offset = offset; - } - - public ChatAcknowledgementPacket() { - } - - @Override - public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - offset = ProtocolUtils.readVarInt(buf); - } - - @Override - public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - ProtocolUtils.writeVarInt(buf, offset); - } - - @Override - public boolean handle(MinecraftSessionHandler handler) { - return handler.handle(this); - } - - @Override - public String toString() { - return "ChatAcknowledgement{" + - "offset=" + offset + - '}'; - } - - public int offset() { - return offset; - } + int offset; + + public ChatAcknowledgementPacket(int offset) { + this.offset = offset; + } + + public ChatAcknowledgementPacket() { + } + + @Override + public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + offset = ProtocolUtils.readVarInt(buf); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + ProtocolUtils.writeVarInt(buf, offset); + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } + + @Override + public String toString() { + return "ChatAcknowledgement{" + + "offset=" + offset + + '}'; + } + + public int offset() { + return offset; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatHandler.java index 0cd2f44afe..af67506b30 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatHandler.java @@ -19,12 +19,28 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; +/** + * Represents a handler for processing chat-related packets in the game. + * This interface is generic and can handle different types of Minecraft packets that + * extend {@link MinecraftPacket}. + * + * @param the type of packet that this chat handler processes, which must + * extend {@link MinecraftPacket} + */ public interface ChatHandler { Class packetClass(); void handlePlayerChatInternal(T packet); + /** + * Handles a player chat event represented by the given {@link MinecraftPacket}. + * This default method provides a basic mechanism for processing chat-related packets that + * involve player messages. + * + * @param packet the {@link MinecraftPacket} representing the player chat event to handle + * @return {@code true} if the chat event was successfully handled, {@code false} otherwise + */ default boolean handlePlayerChat(MinecraftPacket packet) { if (packetClass().isInstance(packet)) { handlePlayerChatInternal(packetClass().cast(packet)); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatQueue.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatQueue.java index 14a563368f..0869ab99a6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatQueue.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatQueue.java @@ -21,12 +21,12 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.MinecraftPacket; import io.netty.channel.ChannelFuture; -import org.checkerframework.checker.nullness.qual.Nullable; import java.time.Instant; import java.util.BitSet; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A precisely ordered queue which allows for outside entries into the ordered queue through @@ -79,7 +79,8 @@ private void queueTask(Task task) { * @param timestamp the new {@link Instant} timestamp of this packet to update the internal chat state. * @param lastSeenMessages the new {@link LastSeenMessages} last seen messages to update the internal chat state. */ - public void queuePacket(Function> nextPacket, @Nullable Instant timestamp, @Nullable LastSeenMessages lastSeenMessages) { + public void queuePacket(Function> nextPacket, @Nullable Instant timestamp, + @Nullable LastSeenMessages lastSeenMessages) { queueTask((chatState, smc) -> { LastSeenMessages newLastSeenMessages = chatState.updateFromMessage(timestamp, lastSeenMessages); return nextPacket.apply(newLastSeenMessages).thenCompose(packet -> writePacket(packet, smc)); @@ -100,6 +101,12 @@ public void queuePacket(Function packe }); } + /** + * Handles the acknowledgement of a chat message or event by processing the given offset. + * This method is typically called when a chat message or command is acknowledged by the client or server. + * + * @param offset the offset representing the specific message or event being acknowledged + */ public void handleAcknowledgement(int offset) { queueTask((chatState, smc) -> { int ackCountToForward = chatState.accumulateAckCount(offset); @@ -138,16 +145,16 @@ private interface Task { *
    • If we last forwarded a chat or command packet from the client, we have a known 'last seen' that we can * reuse.
    • *
    • If we last forwarded a {@link ChatAcknowledgementPacket}, the previous 'last seen' cannot be reused. We - * cannot predict an up-to-date 'last seen', as we do not know which messages the client actually saw.
    • + * cannot predict an up to date 'last seen', as we do not know which messages the client actually saw. *
    • Therefore, we need to hold back any acknowledgement packets so that we can continue to reuse the last valid * 'last seen' state.
    • *
    • However, there is a limit to the number of messages that can remain unacknowledged on the server.
    • *
    • To address this, we know that if the client has moved its 'last seen' window far enough, we can fill in the - * gap with dummy 'last seen', and it will never be checked.
    • + * gap with stub 'last seen', and it will never be checked. *
    * - * Note that this is effectively unused for 1.20.5+ clients, as commands without any signature do not send 'last seen' - * updates. + *

    Note that this is effectively unused for 1.20.5+ clients, as commands without any signature do not send 'last seen' + * updates.

    */ public static class ChatState { private static final int MINIMUM_DELAYED_ACK_COUNT = LastSeenMessages.WINDOW_SIZE; @@ -160,6 +167,17 @@ public static class ChatState { private ChatState() { } + /** + * Updates the state of the {@link LastSeenMessages} and the timestamp based on a new message or event. + * This method processes the given timestamp and last seen messages to ensure the internal state is up to date. + * - If the provided {@link Instant} is not null, it updates the last known timestamp. + * - If the provided {@link LastSeenMessages} is not null, it flushes any delayed acknowledgements and updates the + * internal acknowledged messages, returning an adjusted {@link LastSeenMessages} with the offset applied. + * + * @param timestamp the optional {@link Instant} representing the new timestamp for the message or event + * @param lastSeenMessages the optional {@link LastSeenMessages} representing the last seen messages by the player + * @return the updated {@link LastSeenMessages} with the applied offset, or {@code null} if no updates were made + */ @Nullable public LastSeenMessages updateFromMessage(@Nullable Instant timestamp, @Nullable LastSeenMessages lastSeenMessages) { if (timestamp != null) { @@ -174,6 +192,16 @@ public LastSeenMessages updateFromMessage(@Nullable Instant timestamp, @Nullable return null; } + /** + * Accumulates the given acknowledgement count and determines if enough acknowledgements have been gathered to forward. + * - Adds the provided `ackCount` to the current delayed acknowledgement count. + * - If the accumulated acknowledgements exceed the {@link LastSeenMessages#WINDOW_SIZE}, the method resets the delayed + * acknowledgement count and returns the number of acknowledgements that should be forwarded. + * - If the threshold is not met, the method returns 0, indicating that no acknowledgements need to be forwarded yet. + * + * @param ackCount the number of acknowledgements to add to the accumulated count + * @return the number of acknowledgements that should be forwarded, or 0 if the threshold has not been reached + */ public int accumulateAckCount(int ackCount) { int delayedAckCount = this.delayedAckCount.addAndGet(ackCount); int ackCountToForward = delayedAckCount - MINIMUM_DELAYED_ACK_COUNT; @@ -186,6 +214,11 @@ public int accumulateAckCount(int ackCount) { return 0; } + /** + * Creates a snapshot of the current {@link LastSeenMessages} state. + * + * @return a new {@link LastSeenMessages} representing the current view + */ public LastSeenMessages createLastSeen() { return new LastSeenMessages(0, lastSeenMessages, (byte) 0); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatTimeKeeper.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatTimeKeeper.java index 94fc535678..9409a86f5b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatTimeKeeper.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatTimeKeeper.java @@ -19,6 +19,11 @@ import java.time.Instant; +/** + * Manages the timing and duration of chat messages within the game. + * The {@code ChatTimeKeeper} class tracks when chat messages are sent and provides mechanisms + * to determine how long a message has been displayed or to manage message expiration. + */ public class ChatTimeKeeper { private Instant lastTimestamp; @@ -27,6 +32,18 @@ public ChatTimeKeeper() { this.lastTimestamp = Instant.MIN; } + /** + * Updates the internal timestamp of the chat message or session. + * This method checks if the provided {@link Instant} is before the current stored timestamp. + * If it is, the internal timestamp is updated, and the method returns {@code false} to + * indicate that the update was not successful. + * If the provided {@link Instant} is valid, the timestamp is updated, + * and the method may return {@code true}. + * + * @param instant the {@link Instant} representing the new timestamp to update + * @return {@code true} if the timestamp was successfully updated, {@code false} + * if the provided instant is before the current timestamp + */ public boolean update(Instant instant) { if (instant.isBefore(this.lastTimestamp)) { this.lastTimestamp = instant; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatType.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatType.java index 66e4e98841..047066159c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatType.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ChatType.java @@ -17,6 +17,12 @@ package com.velocitypowered.proxy.protocol.packet.chat; +/** + * Represents different types of chat messages in the game, defining how a message should be + * handled and displayed. + * This enum categorizes various chat message types such as system messages, player chat, + * or game info. + */ public enum ChatType { CHAT((byte) 0), SYSTEM((byte) 1), @@ -31,4 +37,4 @@ public enum ChatType { public byte getId() { return raw; } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/CommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/CommandHandler.java index 8e39d78a30..31cd85c377 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/CommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/CommandHandler.java @@ -31,6 +31,14 @@ import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a handler for processing commands associated with specific types of Minecraft packets. + * This interface is generic and allows for handling different packet types that extend + * {@link MinecraftPacket}. + * + * @param the type of packet that this handler is responsible for, which + * must extend {@link MinecraftPacket} + */ public interface CommandHandler { Logger logger = LogManager.getLogger(CommandHandler.class); @@ -39,6 +47,14 @@ public interface CommandHandler { void handlePlayerCommandInternal(T packet); + /** + * Handles a player command associated with a given {@link MinecraftPacket}. + * This default method provides a mechanism for processing commands related to player + * actions within the game. + * + * @param packet the {@link MinecraftPacket} representing the player command to be handled + * @return {@code true} if the command was successfully handled, {@code false} otherwise + */ default boolean handlePlayerCommand(MinecraftPacket packet) { if (packetClass().isInstance(packet)) { handlePlayerCommandInternal(packetClass().cast(packet)); @@ -54,25 +70,45 @@ default CompletableFuture runCommand(VelocityServer server, .thenApply(hasRunPacketFunction); } + /** + * Queues the result of a player command for execution, managing the future result of the command. + * This method is designed to interact with the {@link VelocityServer} + * and {@link ConnectedPlayer} to + * handle the process of command execution, queuing, and response handling. + * + * @param server the {@link VelocityServer} instance responsible for managing the + * command execution + * @param player the {@link ConnectedPlayer} who initiated the command + * @param futurePacketCreator a {@link BiFunction} that creates a future packet based on + * the {@link CommandExecuteEvent} + * and {@link LastSeenMessages}, which will be used for sending + * a command result + * @param message the command message that the player sent + * @param timestamp the {@link Instant} when the command was executed + * @param lastSeenMessages the {@link LastSeenMessages} object containing the messages last + * seen by the player, + * or {@code null} if not applicable + * @param invocationInfo signing metadata for the event dispatch + */ default void queueCommandResult(VelocityServer server, ConnectedPlayer player, BiFunction> futurePacketCreator, String message, Instant timestamp, @Nullable LastSeenMessages lastSeenMessages, CommandExecuteEvent.InvocationInfo invocationInfo) { - CompletableFuture eventFuture = server.getCommandManager().callCommandEvent(player, message, - invocationInfo); - player.getChatQueue().queuePacket( + CompletableFuture eventFuture = server.getCommandManager().callCommandEvent(player, message, + invocationInfo); + player.getChatQueue().queuePacket( newLastSeenMessages -> eventFuture - .thenComposeAsync(event -> futurePacketCreator.apply(event, newLastSeenMessages)) - .thenApply(pkt -> { - if (server.getConfiguration().isLogCommandExecutions()) { - logger.info("{} -> executed command /{}", player, message); - } - return pkt; - }).exceptionally(e -> { - logger.info("Exception occurred while running command for {}", player.getUsername(), e); - player.sendMessage( - Component.translatable("velocity.command.generic-error", NamedTextColor.RED)); - return null; - }), timestamp, lastSeenMessages); + .thenComposeAsync(event -> futurePacketCreator.apply(event, newLastSeenMessages)) + .thenApply(pkt -> { + if (server.getConfiguration().isLogCommandExecutions()) { + logger.info("{} -> executed command /{}", player, message); + } + return pkt; + }).exceptionally(e -> { + logger.info("Exception occurred while running command for {}", player.getUsername(), e); + player.sendMessage( + Component.translatable("velocity.command.generic-error", NamedTextColor.RED)); + return null; + }), timestamp, lastSeenMessages); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ComponentHolder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ComponentHolder.java index 0b00332607..087756e1cd 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ComponentHolder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/ComponentHolder.java @@ -25,6 +25,9 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import net.kyori.adventure.nbt.BinaryTag; import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.BinaryTagType; @@ -47,10 +50,12 @@ import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - +/** + * Represents a holder for components used in chat or other text-based data in the Minecraft + * protocol. + * This class supports various formats including JSON and NBT (Named Binary Tag) for storing and + * transmitting text components. + */ public class ComponentHolder { private static final Logger logger = LogManager.getLogger(ComponentHolder.class); public static final int DEFAULT_MAX_STRING_SIZE = 262143; @@ -75,6 +80,14 @@ public ComponentHolder(ProtocolVersion version, BinaryTag binaryTag) { this.binaryTag = binaryTag; } + /** + * Retrieves the {@link Component} stored in this {@link ComponentHolder}. + * If the component is not yet initialized, it will attempt to deserialize it from either + * the JSON or NBT representation, depending on which is available. + * + * @return the {@link Component} stored in this holder + * @throws IllegalStateException if both the JSON and binary representations fail to deserialize + */ public Component getComponent() { if (component == null) { if (json != null) { @@ -95,6 +108,13 @@ public Component getComponent() { return component; } + /** + * Retrieves the JSON representation of the {@link Component} stored in this + * {@link ComponentHolder}. + * If the JSON string is not yet initialized, it will serialize the component into a JSON string. + * + * @return the JSON string representing the {@link Component} + */ public String getJson() { if (json == null) { json = ProtocolUtils.getJsonChatSerializer(version).serialize(getComponent()); @@ -102,6 +122,14 @@ public String getJson() { return json; } + /** + * Retrieves the NBT (Named Binary Tag) representation of the {@link Component} stored in this + * {@link ComponentHolder}. + * If the NBT tag is not yet initialized, it will serialize the component into an NBT + * representation. + * + * @return the {@link BinaryTag} representing the {@link Component} + */ public BinaryTag getBinaryTag() { if (binaryTag == null) { // TODO: replace this with adventure-text-serializer-nbt @@ -110,6 +138,16 @@ public BinaryTag getBinaryTag() { return binaryTag; } + /** + * Serializes a {@link JsonElement} into a {@link BinaryTag} format. + * This method converts JSON primitives (numbers, strings, booleans) and complex structures + * (arrays, objects) + * into their corresponding NBT representations. + * + * @param json the {@link JsonElement} to be serialized into a {@link BinaryTag} + * @return the {@link BinaryTag} representing the serialized JSON element + * @throws IllegalArgumentException if the JSON element is of an unsupported or unknown type + */ public static BinaryTag serialize(JsonElement json) { if (json instanceof JsonPrimitive jsonPrimitive) { if (jsonPrimitive.isNumber()) { @@ -162,36 +200,40 @@ public static BinaryTag serialize(JsonElement json) { } switch (listType.id()) { - case 1://BinaryTagTypes.BYTE: + case 1 -> { // BinaryTagTypes.BYTE: byte[] bytes = new byte[jsonArray.size()]; for (int i = 0; i < bytes.length; i++) { bytes[i] = jsonArray.get(i).getAsNumber().byteValue(); } return ByteArrayBinaryTag.byteArrayBinaryTag(bytes); - case 3://BinaryTagTypes.INT: + } + case 3 -> { // BinaryTagTypes.INT: int[] ints = new int[jsonArray.size()]; for (int i = 0; i < ints.length; i++) { ints[i] = jsonArray.get(i).getAsNumber().intValue(); } return IntArrayBinaryTag.intArrayBinaryTag(ints); - case 4://BinaryTagTypes.LONG: + } + case 4 -> { // BinaryTagTypes.LONG: long[] longs = new long[jsonArray.size()]; for (int i = 0; i < longs.length; i++) { longs[i] = jsonArray.get(i).getAsNumber().longValue(); } return LongArrayBinaryTag.longArrayBinaryTag(longs); - case 10://BinaryTagTypes.COMPOUND: - tagItems.replaceAll(tag -> { - if (tag.type() == BinaryTagTypes.COMPOUND) { - return tag; - } else { - return CompoundBinaryTag.builder().put("", tag).build(); - } - }); - break; + } + case 10 -> // BinaryTagTypes.COMPOUND: + tagItems.replaceAll(tag -> { + if (tag.type() == BinaryTagTypes.COMPOUND) { + return tag; + } else { + return CompoundBinaryTag.builder().put("", tag).build(); + } + }); + default -> { + } } return ListBinaryTag.listBinaryTag(listType, tagItems); @@ -200,21 +242,30 @@ public static BinaryTag serialize(JsonElement json) { return EndBinaryTag.endBinaryTag(); } + /** + * Deserializes a {@link BinaryTag} into a {@link JsonElement}. + * This method converts NBT (Named Binary Tag) data into its corresponding JSON representation, + * including handling of primitive types, arrays, and compound structures. + * + * @param tag the {@link BinaryTag} to be deserialized into a {@link JsonElement} + * @return the {@link JsonElement} representing the deserialized NBT data + * @throws IllegalArgumentException if the NBT tag type is unsupported or unknown + */ public static JsonElement deserialize(BinaryTag tag) { return switch (tag.type().id()) { - //BinaryTagTypes.BYTE + // BinaryTagTypes.BYTE case 1 -> new JsonPrimitive(((ByteBinaryTag) tag).value()); - //BinaryTagTypes.SHORT + // BinaryTagTypes.SHORT case 2 -> new JsonPrimitive(((ShortBinaryTag) tag).value()); - //BinaryTagTypes.INT: + // BinaryTagTypes.INT: case 3 -> new JsonPrimitive(((IntBinaryTag) tag).value()); - //BinaryTagTypes.LONG: + // BinaryTagTypes.LONG: case 4 -> new JsonPrimitive(((LongBinaryTag) tag).value()); - //BinaryTagTypes.FLOAT: + // BinaryTagTypes.FLOAT: case 5 -> new JsonPrimitive(((FloatBinaryTag) tag).value()); - //BinaryTagTypes.DOUBLE: + // BinaryTagTypes.DOUBLE: case 6 -> new JsonPrimitive(((DoubleBinaryTag) tag).value()); - //BinaryTagTypes.BYTE_ARRAY: + // BinaryTagTypes.BYTE_ARRAY: case 7 -> { byte[] byteArray = ((ByteArrayBinaryTag) tag).value(); @@ -225,9 +276,9 @@ public static JsonElement deserialize(BinaryTag tag) { yield jsonByteArray; } - //BinaryTagTypes.STRING: + // BinaryTagTypes.STRING: case 8 -> new JsonPrimitive(((StringBinaryTag) tag).value()); - //BinaryTagTypes.LIST: + // BinaryTagTypes.LIST: case 9 -> { ListBinaryTag items = (ListBinaryTag) tag; JsonArray jsonList = new JsonArray(items.size()); @@ -238,7 +289,7 @@ public static JsonElement deserialize(BinaryTag tag) { yield jsonList; } - //BinaryTagTypes.COMPOUND: + // BinaryTagTypes.COMPOUND: case 10 -> { CompoundBinaryTag compound = (CompoundBinaryTag) tag; JsonObject jsonObject = new JsonObject(); @@ -254,7 +305,7 @@ public static JsonElement deserialize(BinaryTag tag) { yield jsonObject; } - //BinaryTagTypes.INT_ARRAY: + // BinaryTagTypes.INT_ARRAY: case 11 -> { int[] intArray = ((IntArrayBinaryTag) tag).value(); @@ -265,7 +316,7 @@ public static JsonElement deserialize(BinaryTag tag) { yield jsonIntArray; } - //BinaryTagTypes.LONG_ARRAY: + // BinaryTagTypes.LONG_ARRAY: case 12 -> { long[] longArray = ((LongArrayBinaryTag) tag).value(); @@ -280,6 +331,19 @@ public static JsonElement deserialize(BinaryTag tag) { }; } + /** + * Reads a {@link ComponentHolder} from the provided {@link ByteBuf} using the specified + * {@link ProtocolVersion}. + * This method deserializes a component from either its binary (NBT) or JSON representation, + * depending on the protocol version. + * - For Minecraft versions 1.20.3 and later, it reads a binary tag. + * - For Minecraft versions 1.13 and later, it reads a JSON string with a size limit. + * - For earlier versions, it reads a standard JSON string. + * + * @param buf the {@link ByteBuf} containing the serialized component data + * @param version the {@link ProtocolVersion} indicating how the component should be deserialized + * @return a {@link ComponentHolder} containing the deserialized component + */ public static ComponentHolder read(ByteBuf buf, ProtocolVersion version) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) { return new ComponentHolder(version, @@ -291,6 +355,15 @@ public static ComponentHolder read(ByteBuf buf, ProtocolVersion version) { } } + /** + * Writes the {@link ComponentHolder}'s data to the provided {@link ByteBuf}. + * This method serializes the component into either its binary (NBT) or JSON representation + * based on the protocol version. + * - For Minecraft versions 1.20.3 and later, it writes the component as a binary tag (NBT). + * - For earlier versions, it writes the component as a JSON string. + * + * @param buf the {@link ByteBuf} where the component data will be written + */ public void write(ByteBuf buf) { if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_3)) { ProtocolUtils.writeBinaryTag(buf, version, getBinaryTag()); @@ -298,4 +371,4 @@ public void write(ByteBuf buf) { ProtocolUtils.writeString(buf, getJson()); } } -} \ No newline at end of file +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/LastSeenMessages.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/LastSeenMessages.java index c03e5f8c3f..8f41a6c832 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/LastSeenMessages.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/LastSeenMessages.java @@ -23,6 +23,10 @@ import java.util.Arrays; import java.util.BitSet; +/** + * Represents a collection of the last seen messages by a player or client. + * This class tracks the recent chat messages that the player has viewed. + */ public class LastSeenMessages { public static final int WINDOW_SIZE = 20; @@ -35,12 +39,26 @@ public LastSeenMessages() { this(0, new BitSet(), (byte) 0); } + /** + * Creates a new {@link LastSeenMessages} instance with the specified offset, acknowledged messages, and checksum. + * + * @param offset the starting index of the message window + * @param acknowledged a BitSet representing which messages have been acknowledged + * @param checksum the checksum for the message window data + */ public LastSeenMessages(int offset, BitSet acknowledged, byte checksum) { this.offset = offset; this.acknowledged = acknowledged; this.checksum = checksum; } + /** + * Constructs a new {@link LastSeenMessages} instance by decoding data from the provided + * {@link ByteBuf}. + * + * @param buf the buffer containing the serialized last seen messages data + * @param protocolVersion the protocol version (determines if checksum is written) + */ public LastSeenMessages(ByteBuf buf, ProtocolVersion protocolVersion) { this.offset = ProtocolUtils.readVarInt(buf); @@ -53,6 +71,12 @@ public LastSeenMessages(ByteBuf buf, ProtocolVersion protocolVersion) { } } + /** + * Encodes this {@link LastSeenMessages} instance into the provided {@link ByteBuf}. + * + * @param buf the buffer to write the data to + * @param protocolVersion the protocol version used for encoding + */ public void encode(ByteBuf buf, ProtocolVersion protocolVersion) { ProtocolUtils.writeVarInt(buf, offset); buf.writeBytes(Arrays.copyOf(acknowledged.toByteArray(), DIV_FLOOR)); @@ -75,10 +99,10 @@ public LastSeenMessages offset(final int offset) { @Override public String toString() { - return "LastSeenMessages{" + - "offset=" + offset + - ", acknowledged=" + acknowledged + - ", checksum=" + checksum + - '}'; + return "LastSeenMessages{" + + "offset=" + offset + + ", acknowledged=" + acknowledged + + ", checksum=" + checksum + + '}'; } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java index d07b798a52..41b6f6cbf3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/PlayerChatCompletionPacket.java @@ -23,6 +23,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a packet sent between the server and client to handle chat completion suggestions. + * This packet allows the server to send chat message completions or suggestions to the client, + * helping users complete commands or chat messages. + */ public class PlayerChatCompletionPacket implements MinecraftPacket { private String[] completions; @@ -71,6 +76,9 @@ public boolean handle(MinecraftSessionHandler handler) { return handler.handle(this); } + /** + * Represents the different actions that can be taken with chat completions. + */ public enum Action { ADD, REMOVE, diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java index e582364359..8ec1f5b22d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java @@ -22,37 +22,46 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket; import net.kyori.adventure.text.Component; +/** + * Abstract base class for handling rate-limited player command packets. + * + *

    Subclasses should implement {@link #handlePlayerCommandInternal(MinecraftPacket)} to define + * how individual command packets are processed. Rate limiting is enforced to prevent abuse.

    + * + * @param the type of {@link MinecraftPacket} this handler processes + */ public abstract class RateLimitedCommandHandler implements CommandHandler { - private final Player player; - private final VelocityServer velocityServer; + private final Player player; + private final VelocityServer velocityServer; - private int failedAttempts; + private int failedAttempts; - protected RateLimitedCommandHandler(Player player, VelocityServer velocityServer) { - this.player = player; - this.velocityServer = velocityServer; - } + protected RateLimitedCommandHandler(Player player, VelocityServer velocityServer) { + this.player = player; + this.velocityServer = velocityServer; + } - @Override - public boolean handlePlayerCommand(MinecraftPacket packet) { - if (packetClass().isInstance(packet)) { - if (!velocityServer.getCommandRateLimiter().attempt(player.getUniqueId())) { - if (velocityServer.getConfiguration().isKickOnCommandRateLimit() && failedAttempts++ >= velocityServer.getConfiguration().getKickAfterRateLimitedCommands()) { - player.disconnect(Component.translatable("velocity.kick.command-rate-limit")); - } - - if (velocityServer.getConfiguration().isForwardCommandsIfRateLimited()) { - return false; // Send the packet to the server - } - } else { - failedAttempts = 0; - } - - handlePlayerCommandInternal(packetClass().cast(packet)); - return true; + @Override + public boolean handlePlayerCommand(MinecraftPacket packet) { + if (packetClass().isInstance(packet)) { + if (!velocityServer.getCommandRateLimiter().attempt(player.getUniqueId())) { + if (velocityServer.getConfiguration().isKickOnCommandRateLimit() && failedAttempts++ + >= velocityServer.getConfiguration().getKickAfterRateLimitedCommands()) { + player.disconnect(Component.translatable("velocity.kick.command-rate-limit")); } - return false; + if (velocityServer.getConfiguration().isForwardCommandsIfRateLimited()) { + return false; // Send the packet to the server + } + } else { + failedAttempts = 0; + } + + handlePlayerCommandInternal(packetClass().cast(packet)); + return true; } + + return false; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RemoteChatSession.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RemoteChatSession.java index 9dd5950a97..13421cfbc6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RemoteChatSession.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RemoteChatSession.java @@ -26,6 +26,11 @@ import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a remote chat session that implements the {@link ChatSession} interface. + * This session is used for handling chat interactions that occur remotely, typically between + * a client and server, allowing for communication and session tracking. + */ public class RemoteChatSession implements ChatSession { private final @Nullable UUID sessionId; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java index 1a26affda4..a15aac01f9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/SystemChatPacket.java @@ -23,6 +23,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * Represents a packet sent from the server to the client to display system chat messages. + * This packet handles the communication of messages that are not player-generated, but instead + * come from the system or server itself. + */ public class SystemChatPacket implements MinecraftPacket { public SystemChatPacket() { @@ -47,7 +52,7 @@ public ComponentHolder getComponent() { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { component = ComponentHolder.read(buf, version); - if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)){ + if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_1)) { type = buf.readBoolean() ? ChatType.GAME_INFO : ChatType.SYSTEM; } else { type = ChatType.values()[ProtocolUtils.readVarInt(buf)]; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderFactory.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderFactory.java index b0d2f12af0..ac889a52b4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderFactory.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderFactory.java @@ -23,11 +23,22 @@ import com.velocitypowered.proxy.protocol.packet.chat.session.SessionChatBuilder; import java.util.function.Function; +/** + * Factory class for creating instances of chat builders. + * + *

    The {@code ChatBuilderFactory} is responsible for providing various builder instances + * used to construct chat-related components, such as messages, chat formats, or text components.

    + */ public class ChatBuilderFactory { private final ProtocolVersion version; private final Function builderFunction; + /** + * Creates a new {@code ChatBuilderFactory} for the specified protocol version. + * + * @param version the protocol version to be used by the chat builder factory + */ public ChatBuilderFactory(ProtocolVersion version) { this.version = version; if (version.noLessThan(ProtocolVersion.MINECRAFT_1_19_3)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderV2.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderV2.java index 9ac0286460..18cea35a2c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderV2.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/builder/ChatBuilderV2.java @@ -28,6 +28,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * An abstract class for building chat components in version 2 of the chat system. + * + *

    The {@code ChatBuilderV2} class provides the foundation for creating and formatting + * chat components, allowing subclasses to implement specific behaviors for constructing + * chat messages or text components.

    + */ public abstract class ChatBuilderV2 { protected final ProtocolVersion version; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatBuilder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatBuilder.java index d654c619c7..b8cd4f79d3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatBuilder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatBuilder.java @@ -26,6 +26,12 @@ import com.velocitypowered.proxy.protocol.packet.chat.builder.ChatBuilderV2; import net.kyori.adventure.text.Component; +/** + * A concrete implementation of {@link ChatBuilderV2} that uses keys to build chat components. + * + *

    The {@code KeyedChatBuilder} class extends the functionality of {@link ChatBuilderV2} by allowing + * chat components to be built using specific keys, enabling dynamic message construction.

    + */ public class KeyedChatBuilder extends ChatBuilderV2 { public KeyedChatBuilder(ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatHandler.java index f8fc906abb..edc2268bcc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedChatHandler.java @@ -30,6 +30,13 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +/** + * A handler for processing chat components based on specific keys. + * + *

    The {@code KeyedChatHandler} class is responsible for managing chat interactions or + * messages that keys identify. It implements the required interface or class + * to handle key-based chat processing.

    + */ public class KeyedChatHandler implements com.velocitypowered.proxy.protocol.packet.chat.ChatHandler { @@ -48,6 +55,15 @@ public Class packetClass() { return KeyedPlayerChatPacket.class; } + /** + * Logs an error and disconnects the player when a plugin attempts to cancel a signed chat message. + * + *

    This method handles the invalid behavior of canceling signed chat messages, which is no longer allowed + * starting from Minecraft version 1.19.1.

    + * + * @param logger the logger used to log the error + * @param player the player to disconnect due to the illegal action + */ public static void invalidCancel(Logger logger, ConnectedPlayer player) { logger.fatal("A plugin tried to cancel a signed chat message." + " This is no longer possible in 1.19.1 and newer. " @@ -56,6 +72,15 @@ public static void invalidCancel(Logger logger, ConnectedPlayer player) { + "Contact your network administrator.")); } + /** + * Logs an error and disconnects the player when a plugin attempts to modify a signed chat message. + * + *

    This method handles the invalid behavior of modifying signed chat messages, which is no longer allowed + * starting from Minecraft version 1.19.1.

    + * + * @param logger the logger used to log the error + * @param player the player to disconnect due to the illegal action + */ public static void invalidChange(Logger logger, ConnectedPlayer player) { logger.fatal("A plugin tried to change a signed chat message. " + "This is no longer possible in 1.19.1 and newer. " diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java index b10332f026..1be3ddddc5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java @@ -26,11 +26,24 @@ import java.util.concurrent.CompletableFuture; import net.kyori.adventure.text.Component; +/** + * Handles keyed player commands by implementing {@link RateLimitedCommandHandler}. + * + *

    The {@code KeyedCommandHandler} processes commands that are sent using + * {@link KeyedPlayerCommandPacket}. It provides the necessary logic for handling + * and executing commands associated with specific keys.

    + */ public class KeyedCommandHandler extends RateLimitedCommandHandler { private final ConnectedPlayer player; private final VelocityServer server; + /** + * Constructs a new {@code KeyedCommandHandler}. + * + * @param player the player sending the command + * @param server the proxy server instance + */ public KeyedCommandHandler(ConnectedPlayer player, VelocityServer server) { super(player, server); this.player = player; @@ -112,6 +125,7 @@ public void handlePlayerCommandInternal(KeyedPlayerCommandPacket packet) { } return null; }); - }, packet.getCommand(), packet.getTimestamp(), null, new CommandExecuteEvent.InvocationInfo(CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER)); + }, packet.getCommand(), packet.getTimestamp(), null, new CommandExecuteEvent.InvocationInfo( + CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER)); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java index 74fa88f5a5..bd62ad368b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerChatPacket.java @@ -29,6 +29,13 @@ import java.time.Instant; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a player chat packet with support for message signing and preview. + * + *

    The {@code KeyedPlayerChatPacket} handles player chat messages, supporting signed previews, + * message signatures, and previous message validation. It includes fields for tracking message + * signatures and handling expired messages.

    + */ public class KeyedPlayerChatPacket implements MinecraftPacket { private String message; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java index 0bb43ec8e9..9978243f5c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedPlayerCommandPacket.java @@ -35,6 +35,13 @@ import java.util.Map; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a player command packet with support for keyed commands. + * + *

    The {@code KeyedPlayerCommandPacket} handles player commands sent to the server, + * allowing for command execution based on specific keys. This packet can include additional + * information such as arguments and key-based identifiers for the command.

    + */ public class KeyedPlayerCommandPacket implements MinecraftPacket { private static final int MAX_NUM_ARGUMENTS = 8; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatBuilder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatBuilder.java index 77df43bb42..f61661e277 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatBuilder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatBuilder.java @@ -25,6 +25,13 @@ import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; +/** + * A concrete implementation of {@link ChatBuilderV2} for handling legacy chat formats. + * + *

    The {@code LegacyChatBuilder} is designed to support and build chat components + * using legacy chat formatting, such as the formats used in earlier versions of Minecraft. + * It extends the functionality of {@link ChatBuilderV2} to cater to older chat systems.

    + */ public class LegacyChatBuilder extends ChatBuilderV2 { public LegacyChatBuilder(ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatHandler.java index b7a641ca98..71dc842af7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatHandler.java @@ -23,6 +23,13 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.packet.chat.ChatHandler; +/** + * A handler for processing legacy chat packets, implementing {@link ChatHandler}. + * + *

    The {@code LegacyChatHandler} is responsible for handling and processing chat messages + * sent using {@link LegacyChatPacket}. This class provides the necessary logic for + * processing chat data using legacy Minecraft chat formats.

    + */ public class LegacyChatHandler implements ChatHandler { private final VelocityServer server; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java index 80b239d53b..b00fb1654f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java @@ -25,6 +25,13 @@ import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a legacy chat packet used in older versions of Minecraft. + * + *

    The {@code LegacyChatPacket} is responsible for holding and transmitting chat messages + * in the format used by legacy versions of Minecraft. It implements {@link MinecraftPacket} + * to ensure compatibility with the packet-handling system.

    + */ public class LegacyChatPacket implements MinecraftPacket { public static final byte CHAT_TYPE = (byte) 0; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java index 4f88ee34a6..3d5a7f5f88 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java @@ -21,15 +21,27 @@ import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.packet.chat.RateLimitedCommandHandler; - import java.time.Instant; import java.util.concurrent.CompletableFuture; +/** + * A handler for processing legacy commands, implementing {@link RateLimitedCommandHandler}. + * + *

    The {@code LegacyCommandHandler} processes and handles command packets that are sent + * using {@link LegacyChatPacket}. It provides the necessary logic to support legacy + * command formats and ensure compatibility with older Minecraft versions.

    + */ public class LegacyCommandHandler extends RateLimitedCommandHandler { private final ConnectedPlayer player; private final VelocityServer server; + /** + * Constructs a new {@code LegacyCommandHandler} for handling legacy command packets. + * + * @param player the connected player issuing the command + * @param server the Velocity server instance + */ public LegacyCommandHandler(ConnectedPlayer player, VelocityServer server) { super(player, server); this.player = player; @@ -64,6 +76,7 @@ public void handlePlayerCommandInternal(LegacyChatPacket packet) { } return null; }); - }, command, Instant.now(), null, new CommandExecuteEvent.InvocationInfo(CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER)); + }, command, Instant.now(), null, new CommandExecuteEvent.InvocationInfo( + CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER)); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java index eb74123fc7..8c9078a10d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatBuilder.java @@ -26,6 +26,13 @@ import com.velocitypowered.proxy.protocol.packet.chat.builder.ChatBuilderV2; import net.kyori.adventure.text.Component; +/** + * A concrete implementation of {@link ChatBuilderV2} for handling session-based chat messages. + * + *

    The {@code SessionChatBuilder} is designed to build chat components that are specific to + * a player's session, allowing customization and context-specific formatting of chat messages + * within the current session.

    + */ public class SessionChatBuilder extends ChatBuilderV2 { public SessionChatBuilder(ProtocolVersion version) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatHandler.java index 74b5747f92..621564a1ad 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionChatHandler.java @@ -26,11 +26,17 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.packet.chat.ChatHandler; import com.velocitypowered.proxy.protocol.packet.chat.ChatQueue; +import java.util.concurrent.CompletableFuture; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.util.concurrent.CompletableFuture; - +/** + * A handler for processing session-based chat packets, implementing {@link ChatHandler}. + * + *

    The {@code SessionChatHandler} processes and handles chat messages sent during a player's + * session using {@link SessionPlayerChatPacket}. It provides the logic for handling session-specific + * chat messages, ensuring the correct context and formatting within the session.

    + */ public class SessionChatHandler implements ChatHandler { private static final Logger logger = LogManager.getLogger(SessionChatHandler.class); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java index 6978f8ee26..83d10b5d3c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionCommandHandler.java @@ -22,17 +22,29 @@ import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.packet.chat.ChatAcknowledgementPacket; -import java.util.concurrent.CompletableFuture; - import com.velocitypowered.proxy.protocol.packet.chat.RateLimitedCommandHandler; +import java.util.concurrent.CompletableFuture; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * A handler for processing session-based commands, implementing {@link RateLimitedCommandHandler}. + * + *

    The {@code SessionCommandHandler} is responsible for handling commands that are specific + * to a player's session, using {@link SessionPlayerCommandPacket}. It provides logic to + * process commands that are tied to the context of the current session.

    + */ public class SessionCommandHandler extends RateLimitedCommandHandler { private final ConnectedPlayer player; private final VelocityServer server; + /** + * Constructs a new {@link SessionCommandHandler} for the specified player and server. + * + * @param player the connected player associated with this handler + * @param server the Velocity server instance + */ public SessionCommandHandler(ConnectedPlayer player, VelocityServer server) { super(player, server); this.player = player; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java index 8a00452c6c..4a63665c23 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerChatPacket.java @@ -25,6 +25,13 @@ import io.netty.buffer.ByteBuf; import java.time.Instant; +/** + * Represents a player chat packet specific to a session, implementing {@link MinecraftPacket}. + * + *

    The {@code SessionPlayerChatPacket} handles chat messages sent by a player during a session, + * and may include session-specific context, such as timestamps, message formatting, or other + * relevant session data.

    + */ public class SessionPlayerChatPacket implements MinecraftPacket { protected String message; @@ -100,6 +107,15 @@ protected static byte[] readMessageSignature(ByteBuf buf) { return signature; } + /** + * Creates a new {@code SessionPlayerChatPacket} with the specified last-seen messages. + * + *

    This method constructs a new {@code SessionPlayerChatPacket} instance that retains the + * current packet's properties, while updating the last seen messages.

    + * + * @param lastSeenMessages the last seen messages to associate with the new packet + * @return a new {@code SessionPlayerChatPacket} with the updated last seen messages + */ public SessionPlayerChatPacket withLastSeenMessages(LastSeenMessages lastSeenMessages) { SessionPlayerChatPacket packet = new SessionPlayerChatPacket(); packet.message = message; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java index f4ea3a1e2d..8a7ddd0dc1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java @@ -26,11 +26,17 @@ import com.velocitypowered.proxy.protocol.packet.chat.LastSeenMessages; import com.velocitypowered.proxy.util.except.QuietDecoderException; import io.netty.buffer.ByteBuf; -import org.checkerframework.checker.nullness.qual.Nullable; - import java.time.Instant; import java.util.List; +import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents a packet that handles player commands in a Minecraft session. + * + *

    This packet contains information about the player's command, timestamp, + * salt, argument signatures, and last seen messages for verification and + * processing.

    + */ public class SessionPlayerCommandPacket implements MinecraftPacket { protected String command; @@ -71,7 +77,8 @@ public boolean isSigned() { } public CommandExecuteEvent.SignedState getEventSignedState() { - return !this.argumentSignatures.isEmpty() ? CommandExecuteEvent.SignedState.SIGNED_WITH_ARGS : CommandExecuteEvent.SignedState.SIGNED_WITHOUT_ARGS; + return !this.argumentSignatures.isEmpty() ? CommandExecuteEvent.SignedState.SIGNED_WITH_ARGS + : CommandExecuteEvent.SignedState.SIGNED_WITHOUT_ARGS; } @Override @@ -81,15 +88,26 @@ public boolean handle(MinecraftSessionHandler handler) { @Override public String toString() { - return "SessionPlayerCommand{" + - "command='" + command + '\'' + - ", timeStamp=" + timeStamp + - ", salt=" + salt + - ", argumentSignatures=" + argumentSignatures + - ", lastSeenMessages=" + lastSeenMessages + - '}'; + return "SessionPlayerCommand{" + + "command='" + command + '\'' + + ", timeStamp=" + timeStamp + + ", salt=" + salt + + ", argumentSignatures=" + argumentSignatures + + ", lastSeenMessages=" + lastSeenMessages + + '}'; } + /** + * Returns a new instance of {@code SessionPlayerCommandPacket} with the specified + * {@code LastSeenMessages}. + * + *

    If {@code lastSeenMessages} is null, it creates an {@code UnsignedPlayerCommandPacket} + * instead. Otherwise, it creates a new {@code SessionPlayerCommandPacket} with the + * provided {@code lastSeenMessages}.

    + * + * @param lastSeenMessages the last seen messages to include in the packet, may be {@code null} + * @return a new instance of {@code SessionPlayerCommandPacket} or {@code UnsignedPlayerCommandPacket} + */ public SessionPlayerCommandPacket withLastSeenMessages(@Nullable LastSeenMessages lastSeenMessages) { if (lastSeenMessages == null) { UnsignedPlayerCommandPacket packet = new UnsignedPlayerCommandPacket(); @@ -105,6 +123,12 @@ public SessionPlayerCommandPacket withLastSeenMessages(@Nullable LastSeenMessage return packet; } + /** + * Represents a collection of argument signatures for commands. + * + *

    This class is responsible for handling the encoding and decoding of + * argument signatures associated with a player command in a Minecraft session.

    + */ public static class ArgumentSignatures { private final List entries; @@ -113,6 +137,16 @@ public ArgumentSignatures() { this.entries = List.of(); } + /** + * Constructs an {@code ArgumentSignatures} instance by decoding the signatures + * from the provided {@code ByteBuf}. + * + *

    This constructor reads the argument signatures from the buffer and ensures + * that the number of signatures does not exceed the allowed limit.

    + * + * @param buf the {@code ByteBuf} to decode the argument signatures from + * @throws QuietDecoderException if the number of argument signatures exceeds the allowed limit + */ public ArgumentSignatures(ByteBuf buf) { int size = ProtocolUtils.readVarInt(buf); if (size > 8) { @@ -130,20 +164,44 @@ public boolean isEmpty() { return this.entries.isEmpty(); } + /** + * Encodes the argument signatures into the provided {@code ByteBuf}. + * + *

    This method writes the number of argument signatures and each signature's + * details into the buffer for transmission.

    + * + * @param buf the {@code ByteBuf} to encode the argument signatures into + */ public void encode(ByteBuf buf) { ProtocolUtils.writeVarInt(buf, entries.size()); for (ArgumentSignature entry : entries) { entry.encode(buf); } } + + /** + * Returns a string representation of this {@code ArgumentSignatures} instance. + * + *

    The output includes a list of individual {@link ArgumentSignature} entries + * attached to this command packet.

    + * + * @return a human-readable string describing the argument signatures + */ @Override public String toString() { - return "ArgumentSignatures{" + - "entries=" + entries + - '}'; + return "ArgumentSignatures{" + + "entries=" + entries + + '}'; } } + /** + * Represents a single argument signature associated with a command. + * + *

    This class is responsible for handling the encoding and decoding of + * individual argument signatures, which consist of a name and a signature + * (byte array).

    + */ public static class ArgumentSignature { private final String name; @@ -161,9 +219,9 @@ public void encode(ByteBuf buf) { @Override public String toString() { - return "ArgumentSignature{" + - "name='" + name + '\'' + - '}'; + return "ArgumentSignature{" + + "name='" + name + '\'' + + '}'; } } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java index 915f0cfbc7..1953b07f0c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/UnsignedPlayerCommandPacket.java @@ -24,6 +24,13 @@ import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * Represents an unsigned player command packet, extending {@link SessionPlayerCommandPacket}. + * + *

    The {@code UnsignedPlayerCommandPacket} is used to handle player commands that are not + * signed. It inherits session-specific behavior from {@link SessionPlayerCommandPacket} + * while indicating that the command is unsigned.

    + */ public class UnsignedPlayerCommandPacket extends SessionPlayerCommandPacket { @Override @@ -52,8 +59,8 @@ public CommandExecuteEvent.SignedState getEventSignedState() { @Override public String toString() { - return "UnsignedPlayerCommandPacket{" + - "command='" + command + '\'' + - '}'; + return "UnsignedPlayerCommandPacket{" + + "command='" + command + '\'' + + '}'; } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java index 79c94b641b..50052654f3 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ActiveFeaturesPacket.java @@ -24,6 +24,13 @@ import io.netty.buffer.ByteBuf; import net.kyori.adventure.key.Key; +/** + * The {@code ActiveFeaturesPacket} class represents a packet that communicates the currently + * active features between the client and server in the Minecraft protocol. + * + *

    This packet is used to inform the client about which features are enabled or active, + * potentially based on server configurations or gameplay states.

    + */ public class ActiveFeaturesPacket implements MinecraftPacket { private Key[] activeFeatures; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java index 6a3618cb73..a9b415e9c8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundCustomReportDetailsPacket.java @@ -25,43 +25,47 @@ import java.util.HashMap; import java.util.Map; +/** + * Represents a packet sent from the server to the client, containing custom report details. + * This packet carries a map of key-value pairs, where each key and value are strings. + */ public class ClientboundCustomReportDetailsPacket implements MinecraftPacket { - private Map details; + private Map details; - public ClientboundCustomReportDetailsPacket() { - } + public ClientboundCustomReportDetailsPacket() { + } - public ClientboundCustomReportDetailsPacket(Map details) { - this.details = details; - } + public ClientboundCustomReportDetailsPacket(Map details) { + this.details = details; + } - @Override - public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - int detailsCount = ProtocolUtils.readVarInt(buf); + @Override + public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + int detailsCount = ProtocolUtils.readVarInt(buf); - this.details = new HashMap<>(detailsCount); - for (int i = 0; i < detailsCount; i++) { - details.put(ProtocolUtils.readString(buf), ProtocolUtils.readString(buf)); - } + this.details = new HashMap<>(detailsCount); + for (int i = 0; i < detailsCount; i++) { + details.put(ProtocolUtils.readString(buf), ProtocolUtils.readString(buf)); } + } - @Override - public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - ProtocolUtils.writeVarInt(buf, details.size()); + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + ProtocolUtils.writeVarInt(buf, details.size()); - details.forEach((key, detail) -> { - ProtocolUtils.writeString(buf, key); - ProtocolUtils.writeString(buf, detail); - }); - } + details.forEach((key, detail) -> { + ProtocolUtils.writeString(buf, key); + ProtocolUtils.writeString(buf, detail); + }); + } - @Override - public boolean handle(MinecraftSessionHandler handler) { - return handler.handle(this); - } + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } - public Map getDetails() { - return details; - } + public Map getDetails() { + return details; + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java index d37866d86a..58b531c27c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/ClientboundServerLinksPacket.java @@ -18,7 +18,6 @@ package com.velocitypowered.proxy.protocol.packet.config; import com.velocitypowered.api.network.ProtocolVersion; -import com.velocitypowered.api.util.ServerLink; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; @@ -27,64 +26,78 @@ import java.util.ArrayList; import java.util.List; +/** + * Represents a packet sent from the server to the client, containing server-related links. + * This packet carries a list of links (e.g., URLs or other resources) associated with the server. + */ public class ClientboundServerLinksPacket implements MinecraftPacket { - private List serverLinks; + private List serverLinks; - public ClientboundServerLinksPacket() { - } + public ClientboundServerLinksPacket() { + } - public ClientboundServerLinksPacket(List serverLinks) { - this.serverLinks = serverLinks; - } + public ClientboundServerLinksPacket(List serverLinks) { + this.serverLinks = serverLinks; + } - @Override - public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - int linksCount = ProtocolUtils.readVarInt(buf); + @Override + public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { + int linksCount = ProtocolUtils.readVarInt(buf); - this.serverLinks = new ArrayList<>(linksCount); - for (int i = 0; i < linksCount; i++) { - serverLinks.add(ServerLink.read(buf, version)); - } + this.serverLinks = new ArrayList<>(linksCount); + for (int i = 0; i < linksCount; i++) { + serverLinks.add(ServerLink.read(buf, version)); } + } - @Override - public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { - ProtocolUtils.writeVarInt(buf, serverLinks.size()); + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + ProtocolUtils.writeVarInt(buf, serverLinks.size()); - for (ServerLink serverLink : serverLinks) { - serverLink.write(buf); - } + for (ServerLink serverLink : serverLinks) { + serverLink.write(buf); } + } - @Override - public boolean handle(MinecraftSessionHandler handler) { - return handler.handle(this); - } + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } - public List getServerLinks() { - return serverLinks; - } + public List getServerLinks() { + return serverLinks; + } - public record ServerLink(int id, ComponentHolder displayName, String url) { + /** + * Represents a link to a server with an ID, display name, and URL. + * + *

    This record holds the server's identification number, a display name + * encapsulated in a {@code ComponentHolder}, and the server's URL as a string.

    + * + * @param id the unique identifier for the server + * @param displayName the display name of the server, represented by a {@code ComponentHolder} + * @param url the URL of the server + */ + public record ServerLink(int id, ComponentHolder displayName, String url) { - private static ServerLink read(ByteBuf buf, ProtocolVersion version) { - if (buf.readBoolean()) { - return new ServerLink(ProtocolUtils.readVarInt(buf), null, ProtocolUtils.readString(buf)); - } else { - return new ServerLink(-1, ComponentHolder.read(buf, version), ProtocolUtils.readString(buf)); - } - } + private static ServerLink read(ByteBuf buf, ProtocolVersion version) { + if (buf.readBoolean()) { + return new ServerLink(ProtocolUtils.readVarInt(buf), null, ProtocolUtils.readString(buf)); + } else { + return new ServerLink(-1, ComponentHolder.read(buf, version), ProtocolUtils.readString(buf)); + } + } - private void write(ByteBuf buf) { - if (id >= 0) { - buf.writeBoolean(true); - ProtocolUtils.writeVarInt(buf, id); - } else { - buf.writeBoolean(false); - displayName.write(buf); - } - ProtocolUtils.writeString(buf, url); - } + private void write(ByteBuf buf) { + if (id >= 0) { + buf.writeBoolean(true); + ProtocolUtils.writeVarInt(buf, id); + } else { + buf.writeBoolean(false); + displayName.write(buf); + } + ProtocolUtils.writeString(buf, url); } + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java index e9811f9fc2..07ca9c4bda 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductAcceptPacket.java @@ -23,6 +23,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; +/** + * A client-to-server packet indicating the player has accepted the server's + * code of conduct during the configuration stage. + * + *

    This packet has no payload and is represented as a singleton.

    + */ public class CodeOfConductAcceptPacket implements MinecraftPacket { public static final CodeOfConductAcceptPacket INSTANCE = new CodeOfConductAcceptPacket(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java index 41433307ef..11f934ebf1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java @@ -24,6 +24,13 @@ import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder; import io.netty.buffer.ByteBuf; +/** + * The {@code FinishedUpdatePacket} class represents a packet that signals the completion + * of an update process between the client and server in the Minecraft protocol. + * + *

    This packet is used to indicate that the client has finished receiving and processing + * an update, ensuring that further operations can proceed.

    + */ public class CodeOfConductPacket extends DeferredByteBufHolder implements MinecraftPacket { public CodeOfConductPacket() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java index 20d40fd4be..5a2afea5d1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/FinishedUpdatePacket.java @@ -23,6 +23,13 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * The {@code FinishedUpdatePacket} class represents a packet that signals the completion + * of an update process between the client and server in the Minecraft protocol. + * + *

    This packet is used to indicate that the client has finished receiving and processing + * an update, ensuring that further operations can proceed.

    + */ public class FinishedUpdatePacket implements MinecraftPacket { public static final FinishedUpdatePacket INSTANCE = new FinishedUpdatePacket(); @@ -41,7 +48,7 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, @Override public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion version) { + ProtocolVersion version) { return 0; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java index b3fb0de4fb..08e90baf92 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/KnownPacksPacket.java @@ -24,55 +24,74 @@ import com.velocitypowered.proxy.util.except.QuietDecoderException; import io.netty.buffer.ByteBuf; +/** + * The {@code KnownPacksPacket} class represents a packet that handles the synchronization + * of known resource packs between the client and server in the Minecraft protocol. + * + *

    This packet contains a list of {@link KnownPack} instances, each representing a resource + * pack with a namespace, identifier, and version. It allows the server to inform the client + * about available resource packs.

    + */ public class KnownPacksPacket implements MinecraftPacket { - private static final int MAX_LENGTH_PACKS = Integer.getInteger("velocity.max-known-packs", 64); - private static final QuietDecoderException TOO_MANY_PACKS = - new QuietDecoderException("too many known packs"); + private static final int MAX_LENGTH_PACKS = Integer.getInteger("velocity.max-known-packs", 64); + private static final QuietDecoderException TOO_MANY_PACKS = + new QuietDecoderException("too many known packs"); - private KnownPack[] packs; + private KnownPack[] packs; - @Override - public void decode(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion protocolVersion) { - final int packCount = ProtocolUtils.readVarInt(buf); - if (direction == ProtocolUtils.Direction.SERVERBOUND && packCount > MAX_LENGTH_PACKS) { - throw TOO_MANY_PACKS; - } - - final KnownPack[] packs = new KnownPack[packCount]; + @Override + public void decode(ByteBuf buf, ProtocolUtils.Direction direction, + ProtocolVersion protocolVersion) { + final int packCount = ProtocolUtils.readVarInt(buf); + if (direction == ProtocolUtils.Direction.SERVERBOUND && packCount > MAX_LENGTH_PACKS) { + throw TOO_MANY_PACKS; + } - for (int i = 0; i < packCount; i++) { - packs[i] = KnownPack.read(buf); - } + final KnownPack[] packs = new KnownPack[packCount]; - this.packs = packs; + for (int i = 0; i < packCount; i++) { + packs[i] = KnownPack.read(buf); } - @Override - public void encode(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion protocolVersion) { - ProtocolUtils.writeVarInt(buf, packs.length); + this.packs = packs; + } - for (KnownPack pack : packs) { - pack.write(buf); - } - } + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, + ProtocolVersion protocolVersion) { + ProtocolUtils.writeVarInt(buf, packs.length); - @Override - public boolean handle(MinecraftSessionHandler handler) { - return handler.handle(this); + for (KnownPack pack : packs) { + pack.write(buf); } + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } - public record KnownPack(String namespace, String id, String version) { - private static KnownPack read(ByteBuf buf) { - return new KnownPack(ProtocolUtils.readString(buf), ProtocolUtils.readString(buf), ProtocolUtils.readString(buf)); - } + /** + * The {@code KnownPack} record represents a known resource pack with a namespace, + * identifier, and version in the Minecraft protocol. + * + *

    It encapsulates the information needed to identify a resource pack, typically used + * for managing or synchronizing resource packs between the client and server.

    + * + * @param namespace the namespace of the resource pack (e.g., "minecraft" or a mod name) + * @param id the unique identifier of the resource pack within the namespace + * @param version the version of the resource pack + */ + public record KnownPack(String namespace, String id, String version) { + private static KnownPack read(ByteBuf buf) { + return new KnownPack(ProtocolUtils.readString(buf), ProtocolUtils.readString(buf), ProtocolUtils.readString(buf)); + } - private void write(ByteBuf buf) { - ProtocolUtils.writeString(buf, namespace); - ProtocolUtils.writeString(buf, id); - ProtocolUtils.writeString(buf, version); - } + private void write(ByteBuf buf) { + ProtocolUtils.writeString(buf, namespace); + ProtocolUtils.writeString(buf, id); + ProtocolUtils.writeString(buf, version); } + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java index 2d9ed230e6..e7dc200ea9 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/RegistrySyncPacket.java @@ -25,6 +25,18 @@ import com.velocitypowered.proxy.protocol.util.DeferredByteBufHolder; import io.netty.buffer.ByteBuf; +/** + * The {@code RegistrySyncPacket} class is responsible for synchronizing registry data + * between the server and client in Minecraft. + * + *

    This packet is used to ensure that the client has the same registry information as + * the server, covering aspects like blocks, items, entities, and other game elements + * that are part of Minecraft's internal registries.

    + * + *

    It extends the {@link DeferredByteBufHolder} class to handle deferred buffering + * operations for potentially large sets of registry data, which may include + * complex serialization processes.

    + */ public class RegistrySyncPacket extends DeferredByteBufHolder implements MinecraftPacket { public RegistrySyncPacket() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java index d41265ce56..8820c025fc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/StartUpdatePacket.java @@ -23,6 +23,16 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * The {@code StartUpdatePacket} class represents a packet that signals the + * start of an update process in the Minecraft protocol. + * + *

    This packet may be used to notify the client or server that a certain update + * process, such as data synchronization or gameplay changes, is about to begin.

    + * + *

    Its specific use depends on the version and context of the update, + * typically handled in the Minecraft networking layer.

    + */ public class StartUpdatePacket implements MinecraftPacket { public static final StartUpdatePacket INSTANCE = new StartUpdatePacket(); @@ -41,7 +51,7 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, @Override public int decodeExpectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion version) { + ProtocolVersion version) { return 0; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java index c0cf414e0c..5e0f9777f5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/TagsUpdatePacket.java @@ -24,9 +24,17 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction; import io.netty.buffer.ByteBuf; - import java.util.Map; +/** + * The {@code TagsUpdatePacket} class represents a packet sent to update the tags + * used by the Minecraft client. Tags are used in various parts of the game to group + * blocks, items, entities, and other objects under common categories. + * + *

    This packet is typically sent to clients when they join a server or when + * the server needs to update the list of tags for the client, ensuring that + * the client has the most up-to-date tag information.

    + */ public class TagsUpdatePacket implements MinecraftPacket { private Map> tags; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/legacyping/LegacyMinecraftPingVersion.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/legacyping/LegacyMinecraftPingVersion.java index d5ef296a41..cad0069180 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/legacyping/LegacyMinecraftPingVersion.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/legacyping/LegacyMinecraftPingVersion.java @@ -17,6 +17,16 @@ package com.velocitypowered.proxy.protocol.packet.legacyping; +/** + * The {@code LegacyMinecraftPingVersion} enum represents the various protocol versions + * used by older Minecraft clients during the server ping process. + * + *

    This enum is used to distinguish between the different legacy versions of Minecraft + * that have unique ping formats, ensuring compatibility with those older clients.

    + * + *

    Each constant in this enum corresponds to a specific version of Minecraft that + * requires a legacy server ping format.

    + */ public enum LegacyMinecraftPingVersion { MINECRAFT_1_3, MINECRAFT_1_4, diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java index 8641173e74..d8c0e8d76f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/GenericTitlePacket.java @@ -23,8 +23,21 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; import io.netty.buffer.ByteBuf; +/** + * The {@code GenericTitlePacket} class serves as the base class for all title-related packets + * in Minecraft. This class provides common functionality and properties for handling title, subtitle, + * action bar, and timing-related packets. + * + *

    Subclasses of {@code GenericTitlePacket} implement specific behavior for different types of title + * packets, such as titles, subtitles, and action bars.

    + */ public abstract class GenericTitlePacket implements MinecraftPacket { + /** + * The {@code ActionType} enum represents the different actions that can be performed with a title packet. + * Each action corresponds to a specific type of title operation, such as setting a title or subtitle, + * updating timing information, or resetting and hiding titles. + */ public enum ActionType { SET_TITLE(0), SET_SUBTITLE(1), @@ -45,7 +58,6 @@ public int getAction(ProtocolVersion version) { } } - private ActionType action; protected void setAction(ActionType action) { @@ -88,10 +100,9 @@ public void setFadeOut(int fadeOut) { throw new UnsupportedOperationException("Invalid function for this TitlePacket ActionType"); } - @Override public final void decode(ByteBuf buf, ProtocolUtils.Direction direction, - ProtocolVersion version) { + ProtocolVersion version) { throw new UnsupportedOperationException(); // encode only } @@ -103,7 +114,7 @@ public final void decode(ByteBuf buf, ProtocolUtils.Direction direction, * @return GenericTitlePacket instance that follows the invoker type/version */ public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolVersion version) { - GenericTitlePacket packet = null; + GenericTitlePacket packet; if (version.noLessThan(ProtocolVersion.MINECRAFT_1_17)) { packet = switch (type) { case SET_ACTION_BAR -> new TitleActionbarPacket(); @@ -111,7 +122,6 @@ public static GenericTitlePacket constructTitlePacket(ActionType type, ProtocolV case SET_TIMES -> new TitleTimesPacket(); case SET_TITLE -> new TitleTextPacket(); case HIDE, RESET -> new TitleClearPacket(); - default -> throw new IllegalArgumentException("Invalid ActionType"); }; } else { packet = new LegacyTitlePacket(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java index ebae8a9e5b..5b5b8b0f96 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/LegacyTitlePacket.java @@ -24,6 +24,16 @@ import io.netty.buffer.ByteBuf; import org.checkerframework.checker.nullness.qual.Nullable; +/** + * The {@code LegacyTitlePacket} class represents a packet that handles title-related functionality + * for older versions of Minecraft where title handling differs. + * + *

    This packet is used to send title and subtitle information using legacy methods for clients + * that do not support the newer title packet format.

    + * + *

    It extends the {@link GenericTitlePacket}, inheriting basic title properties but is specifically + * focused on legacy title implementations.

    + */ public class LegacyTitlePacket extends GenericTitlePacket { private @Nullable ComponentHolder component; @@ -51,10 +61,10 @@ && getAction() == ActionType.SET_ACTION_BAR) { buf.writeInt(stay); buf.writeInt(fadeOut); } - case HIDE, RESET -> {} + case HIDE, RESET -> { + } default -> throw new UnsupportedOperationException("Unknown action " + getAction()); } - } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java index f34983eaf9..5fb3c9a8bc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleActionbarPacket.java @@ -23,6 +23,16 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; import io.netty.buffer.ByteBuf; +/** + * The {@code TitleActionbarPacket} class represents a packet that handles the content of an action bar + * displayed to the player in Minecraft. + * + *

    This packet is used to send the text that appears in the action bar, which is a separate text line + * displayed above the hotbar on the player's screen.

    + * + *

    It extends the {@link GenericTitlePacket}, inheriting basic title properties and focusing on + * the content of the action bar.

    + */ public class TitleActionbarPacket extends GenericTitlePacket { private ComponentHolder component; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java index 1b3489691f..077ca5944a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleClearPacket.java @@ -22,6 +22,15 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * The {@code TitleClearPacket} class represents a packet that handles the clearing or removal of a title + * from the player's screen in Minecraft. + * + *

    This packet is used to instruct the client to clear any currently displayed title and subtitle.

    + * + *

    It extends the {@link GenericTitlePacket}, inheriting basic title properties but is specifically + * focused on clearing the title display.

    + */ public class TitleClearPacket extends GenericTitlePacket { public TitleClearPacket() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java index 0f375ae20a..3f44f3e958 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleSubtitlePacket.java @@ -23,6 +23,15 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; import io.netty.buffer.ByteBuf; +/** + * The {@code TitleSubtitlePacket} class represents a packet that handles the subtitle content for a title + * displayed to the player in Minecraft. + * + *

    This packet is used to send the subtitle text that appears below the main title on the player's screen.

    + * + *

    It extends the {@link GenericTitlePacket}, inheriting basic title properties and focusing + * on the subtitle content of the title.

    + */ public class TitleSubtitlePacket extends GenericTitlePacket { private ComponentHolder component; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java index ae75f5d618..171790755d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTextPacket.java @@ -23,6 +23,15 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder; import io.netty.buffer.ByteBuf; +/** + * The {@code TitleTextPacket} class represents a packet that handles the text content for a title + * displayed to the player in Minecraft. + * + *

    This packet is used to send the main title text to be displayed on the player's screen.

    + * + *

    It extends the {@link GenericTitlePacket}, inheriting basic title properties and focusing + * on the specific text content of the title.

    + */ public class TitleTextPacket extends GenericTitlePacket { private ComponentHolder component; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java index 8764a12fab..5b737af49e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/title/TitleTimesPacket.java @@ -22,6 +22,15 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +/** + * The {@code TitleTimesPacket} class represents a packet that handles the timing settings for a title in + * Minecraft, such as fade-in, stay, and fade-out durations. + * + *

    This packet is used to set the timing properties for a title displayed to the player.

    + * + *

    It extends the {@link GenericTitlePacket} to inherit basic title properties and adds specific timing + * controls for the title display.

    + */ public class TitleTimesPacket extends GenericTitlePacket { private int fadeIn; From 5957c067f5a13f35a7fbda01dcbc793cee33fe13 Mon Sep 17 00:00:00 2001 From: RootBeer Date: Mon, 26 Jan 2026 04:57:26 -0500 Subject: [PATCH 3/7] Resolve minor catch that has not been handled --- .../proxy/protocol/packet/chat/legacy/LegacyChatPacket.java | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java index cbe1e61374..942dc6cad5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyChatPacket.java @@ -52,6 +52,7 @@ private static int getMaxServerboundMessageLength() { try { return Integer.parseInt(value.trim()); } catch (final NumberFormatException e) { + // Exception has been handled } } return 100; From 24ee3ff2c0e850a6692a3dbee603e97866daa050 Mon Sep 17 00:00:00 2001 From: RootBeer Date: Mon, 26 Jan 2026 13:26:43 -0500 Subject: [PATCH 4/7] Apply suggested replacements --- .../proxy/protocol/packet/chat/RateLimitedCommandHandler.java | 4 ++-- .../proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java | 4 ++-- .../protocol/packet/chat/legacy/LegacyCommandHandler.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java index 8ec1f5b22d..4bddf35fab 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/RateLimitedCommandHandler.java @@ -46,8 +46,8 @@ protected RateLimitedCommandHandler(Player player, VelocityServer velocityServer public boolean handlePlayerCommand(MinecraftPacket packet) { if (packetClass().isInstance(packet)) { if (!velocityServer.getCommandRateLimiter().attempt(player.getUniqueId())) { - if (velocityServer.getConfiguration().isKickOnCommandRateLimit() && failedAttempts++ - >= velocityServer.getConfiguration().getKickAfterRateLimitedCommands()) { + if (velocityServer.getConfiguration().isKickOnCommandRateLimit() + && failedAttempts++ >= velocityServer.getConfiguration().getKickAfterRateLimitedCommands()) { player.disconnect(Component.translatable("velocity.kick.command-rate-limit")); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java index 1be3ddddc5..e52f4c9a6f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/keyed/KeyedCommandHandler.java @@ -125,7 +125,7 @@ public void handlePlayerCommandInternal(KeyedPlayerCommandPacket packet) { } return null; }); - }, packet.getCommand(), packet.getTimestamp(), null, new CommandExecuteEvent.InvocationInfo( - CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER)); + }, packet.getCommand(), packet.getTimestamp(), null, new CommandExecuteEvent.InvocationInfo(CommandExecuteEvent.SignedState.UNSUPPORTED, + CommandExecuteEvent.Source.PLAYER)); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java index 3d5a7f5f88..68ff4f4551 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/legacy/LegacyCommandHandler.java @@ -76,7 +76,7 @@ public void handlePlayerCommandInternal(LegacyChatPacket packet) { } return null; }); - }, command, Instant.now(), null, new CommandExecuteEvent.InvocationInfo( - CommandExecuteEvent.SignedState.UNSUPPORTED, CommandExecuteEvent.Source.PLAYER)); + }, command, Instant.now(), null, new CommandExecuteEvent.InvocationInfo(CommandExecuteEvent.SignedState.UNSUPPORTED, + CommandExecuteEvent.Source.PLAYER)); } } From 9c6a1b0e9fde0061251b1b73dba157a3733b5676 Mon Sep 17 00:00:00 2001 From: RootBeer Date: Tue, 27 Jan 2026 12:37:42 -0500 Subject: [PATCH 5/7] Remove deprecated inclusion of GraalVM --- proxy/build.gradle.kts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/proxy/build.gradle.kts b/proxy/build.gradle.kts index 5929692c5e..2fb40773c0 100644 --- a/proxy/build.gradle.kts +++ b/proxy/build.gradle.kts @@ -108,15 +108,6 @@ tasks { workingDir = file("run").also(File::mkdirs) standardInput = System.`in` // Doesn't work? } - - withType().configureEach { - options.compilerArgs.addAll( - listOf( - "-Alog4j.graalvm.groupId=${project.group}", - "-Alog4j.graalvm.artifactId=${project.name}" - ) - ) - } } val projectVersion = version as String From fc4e3c860f5d7ff479a0690a1f55f033c5979ebb Mon Sep 17 00:00:00 2001 From: RootBeer Date: Tue, 27 Jan 2026 14:35:57 -0500 Subject: [PATCH 6/7] Resolve codestyle/mistakes --- .../velocitypowered/api/proxy/server/ServerPing.java | 8 ++++---- .../packet/ClientboundSoundEntityPacket.java | 12 ++++++------ .../protocol/packet/config/CodeOfConductPacket.java | 9 +++++---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java index 4743d05e98..98ca3b752d 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/server/ServerPing.java @@ -504,9 +504,9 @@ public int getProtocol() { } /** - * Gets the legacy string name of the sample player. + * Gets the user-facing name of the server version. * - * @return the player name + * @return the version name */ public String getName() { return name; @@ -638,9 +638,9 @@ public static final class SamplePlayer { private final UUID id; /** - * Constructs a SamplePlayer from a {@link Component}-based name. + * Constructs a SamplePlayer with the given name and UUID. * - * @param name the name of the player as a {@link Component} + * @param name the name of the player * @param id the UUID of the player */ public SamplePlayer(String name, UUID id) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java index be81201c96..9ccebf3b03 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientboundSoundEntityPacket.java @@ -70,17 +70,17 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi buf.writeBoolean(fixedRange != null); if (fixedRange != null) { buf.writeFloat(fixedRange); + } - ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source()); + ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source()); - ProtocolUtils.writeVarInt(buf, emitterEntityId); + ProtocolUtils.writeVarInt(buf, emitterEntityId); - buf.writeFloat(sound.volume()); + buf.writeFloat(sound.volume()); - buf.writeFloat(sound.pitch()); + buf.writeFloat(sound.pitch()); - buf.writeLong(sound.seed().orElse(SEEDS_RANDOM.nextLong())); - } + buf.writeLong(sound.seed().orElse(SEEDS_RANDOM.nextLong())); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java index 11f934ebf1..37fdd92691 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/config/CodeOfConductPacket.java @@ -25,11 +25,12 @@ import io.netty.buffer.ByteBuf; /** - * The {@code FinishedUpdatePacket} class represents a packet that signals the completion - * of an update process between the client and server in the Minecraft protocol. + * A server-to-client packet containing the server's code of conduct. * - *

    This packet is used to indicate that the client has finished receiving and processing - * an update, ensuring that further operations can proceed.

    + *

    This packet is sent during the configuration stage to present the + * server-defined conduct rules to the client. The client may later + * respond with a {@link CodeOfConductAcceptPacket} to indicate + * acceptance.

    */ public class CodeOfConductPacket extends DeferredByteBufHolder implements MinecraftPacket { From db7849c4add4e882d544336ee10d31117b0e074a Mon Sep 17 00:00:00 2001 From: RootBeer Date: Tue, 27 Jan 2026 18:07:19 -0500 Subject: [PATCH 7/7] Bump spotless (again). Might as well include this in here since it appears significant --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b8a22e770b..5ad83ecc4d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ netty = "4.2.9.Final" [plugins] fill = "io.papermc.fill.gradle:1.0.10" shadow = "com.gradleup.shadow:9.3.1" -spotless = "com.diffplug.spotless:8.2.0" +spotless = "com.diffplug.spotless:8.2.1" [libraries] adventure-bom = "net.kyori:adventure-bom:4.26.1"