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

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

View File

@@ -24,7 +24,7 @@ dependencies {
api(libs.guava)
// 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<Javadoc> {
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")
}
}

View File

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

View File

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

View File

@@ -25,7 +25,7 @@ public interface CommandSource extends Audience, PermissionSubject {
* @param message MiniMessage content
* @see <a href="https://docs.advntr.dev/minimessage/format.html">MiniMessage docs</a>
* for more information on the format.
**/
*/
default void sendRichMessage(final @NotNull String message) {
this.sendMessage(MiniMessage.miniMessage().deserialize(message, this));
}
@@ -38,7 +38,7 @@ public interface CommandSource extends Audience, PermissionSubject {
* @see <a href="https://docs.advntr.dev/minimessage/">MiniMessage docs</a>
* and <a href="https://docs.advntr.dev/minimessage/dynamic-replacements">MiniMessage Placeholders docs</a>
* for more information on the format.
**/
*/
default void sendRichMessage(
final @NotNull String message,
final @NotNull TagResolver @NotNull... resolvers

View File

@@ -20,6 +20,12 @@ import org.jetbrains.annotations.NotNull;
*/
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);
}

View File

@@ -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);
}

View File

@@ -13,12 +13,28 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* Represents an interface to perform direct dispatch of an event. This makes integration easier to
* 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 <E> the event type this handler accepts
*/
@FunctionalInterface
public interface EventHandler<E> {
/**
* 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.
*
* <p>If asynchronous handling is not implemented, the event is executed synchronously
* and this method returns {@code null}.</p>
*
* @param event the event to handle
* @return an {@link EventTask} representing the async task, or {@code null} if not async
*/
default @Nullable EventTask executeAsync(E event) {
execute(event);
return null;

View File

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

View File

@@ -12,7 +12,34 @@ package com.velocitypowered.api.event;
*/
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.

View File

@@ -15,6 +15,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Indicates an event that has a result attached to it.
*
* @param <R> the type of result associated with the event
*/
public interface ResultedEvent<R extends ResultedEvent.Result> {
@@ -70,10 +72,20 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
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 @@ public interface ResultedEvent<R extends ResultedEvent.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 interface ResultedEvent<R extends ResultedEvent.Result> {
return status;
}
/**
* Returns the denial reason component, if present.
*
* @return an {@link Optional} containing the reason component if the result is denied
*/
public Optional<Component> getReasonComponent() {
return Optional.ofNullable(reason);
}
@@ -114,10 +137,22 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
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);

View File

@@ -106,6 +106,8 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/**
* Represents information about a command invocation, including its signed state and source.
*
* @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 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
this.command = command;
}
/**
* Returns the command to be executed, if it was overridden.
*
* @return an {@link Optional} containing the new command string (without leading slash),
* or empty if no override is present
*/
public Optional<String> getCommand() {
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;
}

View File

@@ -37,10 +37,20 @@ public class PlayerAvailableCommandsEvent {
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;
}

View File

@@ -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 final class ConnectionHandshakeEvent {
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;
}

View File

@@ -17,12 +17,10 @@ import com.velocitypowered.api.proxy.Player;
* Operations on the provided player, aside from basic data retrieval operations, may behave in
* undefined ways.
*
* <p>
* Velocity typically fires this event asynchronously and does not wait for a response. However,
* <p>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.
* </p>
* {@link AwaitingEvent} contract.</p>
*/
@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 final class DisconnectEvent {
*/
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
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,15 +21,31 @@ public final class PlayerChannelRegisterEvent {
private final Player player;
private final List<ChannelIdentifier> channels;
/**
* Constructs a new PlayerChannelRegisterEvent.
*
* @param player the player who sent the plugin message
* @param channels the list of channels the player is registering
*/
public PlayerChannelRegisterEvent(Player player, List<ChannelIdentifier> channels) {
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<ChannelIdentifier> getChannels() {
return channels;
}

View File

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

View File

@@ -38,10 +38,20 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
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 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
this.message = message;
}
/**
* Gets the (possibly modified) chat message to be sent.
*
* @return an {@link Optional} containing the message, or empty if none
*/
public Optional<String> getMessage() {
return Optional.ofNullable(message);
}

View File

@@ -37,10 +37,20 @@ public class PlayerChooseInitialServerEvent {
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<RegisteredServer> getInitialServer() {
return Optional.ofNullable(initialServer);
}

View File

@@ -29,10 +29,20 @@ public final class PlayerClientBrandEvent {
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;
}

View File

@@ -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;
}

View File

@@ -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 class PlayerResourcePackStatusEvent {
/**
* 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 class PlayerResourcePackStatusEvent {
/**
* 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) {

View File

@@ -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;
}

View File

@@ -45,14 +45,29 @@ public final class ServerConnectedEvent {
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<RegisteredServer> getPreviousServer() {
return Optional.ofNullable(previousServer);
}

View File

@@ -63,10 +63,20 @@ public class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
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 class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
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 class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
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);

View File

@@ -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");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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;
}

View File

@@ -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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -21,6 +21,9 @@ import java.util.Set;
* Represents each Minecraft protocol version.
*/
public enum ProtocolVersion implements Ordered<ProtocolVersion> {
/**
* Represents an unknown protocol version.
*/
UNKNOWN(-1, "Unknown") {
@Override
public boolean isUnknown() {
@@ -32,6 +35,9 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
return false;
}
},
/**
* Represents legacy protocol versions before 1.7.
*/
LEGACY(-2, "Legacy") {
@Override
public boolean isLegacy() {
@@ -43,57 +49,201 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
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;

View File

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

View File

@@ -12,18 +12,37 @@ package com.velocitypowered.api.plugin;
*/
public class InvalidPluginException extends Exception {
/**
* 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);
}

View File

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

View File

@@ -150,6 +150,8 @@ public interface Player extends
/**
* Returns the player's game profile.
*
* @return the player's profile
*/
GameProfile getGameProfile();
@@ -313,6 +315,7 @@ public interface Player extends
/**
* {@inheritDoc}
*
* <p><strong>Note that this method does not send a plugin message to the server the player
* is connected to.</strong> You should only use this method if you are trying to communicate
* with a mod that is installed on the player's client.</p>
@@ -336,7 +339,6 @@ public interface Player extends
Component.text(getUsername()))));
}
/**
* Gets the player's client brand.
*
@@ -384,7 +386,6 @@ public interface Player extends
/**
* {@inheritDoc}
*
*
* @apiNote <b>This method is not currently implemented in Velocity
* and will not perform any actions.</b>
* @see #playSound(Sound, Sound.Emitter)

View File

@@ -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<Revision> {
/**
* Represents the original key revision introduced in Minecraft 1.19.
* Keys are not tied to a specific player identity.
*/
GENERIC_V1(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19)),
/**
* 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<Revision> backwardsCompatibleTo;
@@ -70,10 +77,20 @@ public interface IdentifiedKey extends KeySigned {
this.applicableTo = applicableTo;
}
/**
* Returns the set of revisions that this revision is backwards-compatible with.
*
* @return a set of compatible earlier revisions
*/
public Set<Revision> getBackwardsCompatibleTo() {
return backwardsCompatibleTo;
}
/**
* Returns the set of Minecraft protocol versions this revision applies to.
*
* @return a set of applicable protocol versions
*/
public Set<ProtocolVersion> getApplicableTo() {
return applicableTo;
}

View File

@@ -34,7 +34,6 @@ public interface KeySigned {
*/
Instant getExpiryTemporal();
/**
* Check if the signature has expired.
*
@@ -56,6 +55,7 @@ public interface KeySigned {
* 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()}.
*
* <p>DOES NOT WORK YET FOR MESSAGES AND COMMANDS!</p>
* Addendum: Does not work for 1.19.1 until the user has authenticated.
*

View File

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

View File

@@ -84,14 +84,29 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
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);
}

View File

@@ -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 @@ public interface PlayerSettings {
* 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 @@ public interface PlayerSettings {
* 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
}
}

View File

@@ -87,7 +87,6 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
/**
* Returns a copy of this {@link ResourcePackInfo} instance as a builder, using the new URL.
* <p/>
* It is <b>not</b> guaranteed that
* {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)}
* is true, because the {@link ResourcePackInfo#getOrigin()} and
@@ -108,6 +107,7 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* 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 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* 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 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* 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 @@ public interface ResourcePackInfo extends ResourcePackRequestLike {
* 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);

View File

@@ -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;
}

View File

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

View File

@@ -147,7 +147,6 @@ public final class QueryResponse {
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 final class QueryResponse {
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<String> 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);
}

View File

@@ -32,11 +32,21 @@ public final class ServerInfo implements Comparable<ServerInfo> {
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 final class ServerInfo implements Comparable<ServerInfo> {
}
@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 class ServerInfo implements Comparable<ServerInfo> {
}
@Override
public final int hashCode() {
public int hashCode() {
return Objects.hash(name, address);
}

View File

@@ -22,7 +22,6 @@ import java.util.UUID;
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 final class ServerPing {
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<Players> 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<Favicon> getFavicon() {
return Optional.ofNullable(favicon);
}
/**
* Gets the mod info sent to the client.
*
* @return the mod info, or empty if not present
*/
public Optional<ModInfo> getModinfo() {
return Optional.ofNullable(modinfo);
}
@@ -139,6 +171,11 @@ public final class ServerPing {
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 final class ServerPing {
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<SamplePlayer> getSamplePlayers() {
return samplePlayers;
}
/**
* Gets the description component currently set in the builder.
*
* @return the server description, or empty if unset
*/
public Optional<Component> getDescriptionComponent() {
return Optional.ofNullable(description);
}
/**
* Gets the favicon currently set in the builder.
*
* @return the favicon, or empty if none
*/
public Optional<Favicon> 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<ModInfo.Mod> getMods() {
return mods;
}
@@ -417,10 +494,20 @@ public final class ServerPing {
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 user-facing name of the server version.
*
* @return the version name
*/
public String getName() {
return name;
}
@@ -474,14 +561,29 @@ public final class ServerPing {
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<SamplePlayer> getSample() {
return sample == null ? ImmutableList.of() : sample;
}
@@ -519,22 +621,47 @@ public final class ServerPing {
*/
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 with the given name and UUID.
*
* @param name the name of the player
* @param id the UUID of the player
*/
public SamplePlayer(String name, UUID id) {
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;
}

View File

@@ -200,14 +200,29 @@ public final class GameProfile {
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;
}

View File

@@ -18,6 +18,10 @@ import java.util.Objects;
*/
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 final class ModInfo {
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<Mod> getMods() {
return modList;
}
@@ -89,10 +103,20 @@ public final class ModInfo {
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;
}

View File

@@ -33,14 +33,29 @@ public final class ProxyVersion {
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;
}

View File

@@ -38,6 +38,7 @@ public final class ServerLink {
*
* @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 final class ServerLink {
*
* @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 final class ServerLink {
* @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 servers 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 servers 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
}

View File

@@ -3,12 +3,12 @@ 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"
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"
@@ -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"

View File

@@ -14,10 +14,6 @@ application {
}
tasks {
withType<Checkstyle> {
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

View File

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

View File

@@ -37,7 +37,7 @@ import org.jetbrains.annotations.NotNull;
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<UUID, ResourcePackInfo> outstandingResourcePacks =

View File

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

View File

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

View File

@@ -633,7 +633,7 @@ public enum ProtocolUtils {
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 enum ProtocolUtils {
}
/**
* Writes an byte array for legacy version 1.7 to the specified {@code buf}
* Writes an byte array for legacy version 1.7 to the specified {@code buf}.
*
* @param b array
* @param buf buf
@@ -695,7 +695,7 @@ public enum ProtocolUtils {
}
/**
* Writes an {@link ByteBuf} for legacy version 1.7 to the specified {@code buf}
* Writes an {@link ByteBuf} for legacy version 1.7 to the specified {@code buf}.
*
* @param b array
* @param buf buf

View File

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

View File

@@ -29,6 +29,10 @@ import java.util.UUID;
import net.kyori.adventure.bossbar.BossBar;
import 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<BossBar.Color> 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 class BossBarPacket implements MinecraftPacket {
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 class BossBarPacket implements MinecraftPacket {
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 class BossBarPacket implements MinecraftPacket {
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 class BossBarPacket implements MinecraftPacket {
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 class BossBarPacket implements MinecraftPacket {
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 class BossBarPacket implements MinecraftPacket {
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 class BossBarPacket implements MinecraftPacket {
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 -> {
@@ -244,7 +299,8 @@ public class BossBarPacket implements MinecraftPacket {
ProtocolUtils.writeVarInt(buf, overlay);
buf.writeByte(flags);
}
case REMOVE -> {}
case REMOVE -> {
}
case UPDATE_PERCENT -> buf.writeFloat(percent);
case UPDATE_NAME -> {
if (name == null) {
@@ -264,7 +320,7 @@ public class BossBarPacket implements MinecraftPacket {
private static byte serializeFlags(Set<BossBar.Flag> 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;
}

View File

@@ -23,6 +23,14 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
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.
*
* <p>This packet is typically used to signal the start or end of a packet sequence that
* are sent together, enabling efficient transmission and processing of related data.</p>
*/
public final class BundleDelimiterPacket implements MinecraftPacket {
public static final BundleDelimiterPacket INSTANCE = new BundleDelimiterPacket();

View File

@@ -23,9 +23,13 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import 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 class ClientSettingsPacket implements MinecraftPacket {
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 class ClientSettingsPacket implements MinecraftPacket {
@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

View File

@@ -25,6 +25,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
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;

View File

@@ -22,11 +22,16 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
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.
*
* <p>This is sent by the server when a sound should be played at the location of a
* specific entity, with optional fixed range and seed.</p>
*/
public class ClientboundSoundEntityPacket implements MinecraftPacket {
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,8 +68,9 @@ public class ClientboundSoundEntityPacket implements MinecraftPacket {
ProtocolUtils.writeMinimalKey(buf, sound.name());
buf.writeBoolean(fixedRange != null);
if (fixedRange != null)
if (fixedRange != null) {
buf.writeFloat(fixedRange);
}
ProtocolUtils.writeSoundSource(buf, protocolVersion, sound.source());

View File

@@ -22,18 +22,24 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.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.
*
* <p>This packet supports specifying a {@link Sound.Source}, a {@link Key} sound identifier,
* or both together. If neither is specified, the client will stop all currently playing sounds.</p>
*/
public class ClientboundStopSoundPacket implements MinecraftPacket {
private @Nullable Sound.Source source;
private @Nullable Key soundName;
public ClientboundStopSoundPacket() {}
public ClientboundStopSoundPacket() {
}
public ClientboundStopSoundPacket(SoundStop soundStop) {
this(soundStop.source(), soundStop.sound());

View File

@@ -25,6 +25,11 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
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;

View File

@@ -23,6 +23,13 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
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.
*
* <p>This packet is used during the configuration phase (1.21.6+) to
* instruct the client to dismiss an active dialog window.</p>
*/
public class DialogClearPacket implements MinecraftPacket {
public static final DialogClearPacket INSTANCE = new DialogClearPacket();

View File

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

View File

@@ -28,6 +28,12 @@ import io.netty.buffer.ByteBuf;
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 @@ public class DisconnectPacket implements MinecraftPacket {
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");
@@ -76,6 +88,14 @@ public class DisconnectPacket implements MinecraftPacket {
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

View File

@@ -26,6 +26,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
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 = "";

View File

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

View File

@@ -27,6 +27,12 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
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.

View File

@@ -26,6 +26,10 @@ import com.velocitypowered.proxy.protocol.packet.chat.ComponentHolder;
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;

View File

@@ -21,13 +21,19 @@ import com.google.common.collect.ImmutableSet;
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 class JoinGamePacket implements MinecraftPacket {
@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

View File

@@ -23,6 +23,11 @@ import com.velocitypowered.proxy.protocol.MinecraftPacket;
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;

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