Merge remote-tracking branch 'github/dev/3.0.0'
All checks were successful
SteamWarCI Build successful

# Conflicts:
#	proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/SessionPlayerCommandPacket.java
This commit is contained in:
Lixfel
2025-04-01 07:06:14 +02:00
67 changed files with 731 additions and 238 deletions

View File

@ -61,6 +61,7 @@ tasks {
o.encoding = "UTF-8"
o.source = "17"
o.use()
o.links(
"https://www.slf4j.org/apidocs/",
"https://guava.dev/releases/${libs.guava.get().version}/api/docs/",

View File

@ -27,7 +27,7 @@ public interface CommandSource extends Audience, PermissionSubject {
* for more information on the format.
**/
default void sendRichMessage(final @NotNull String message) {
this.sendMessage(MiniMessage.miniMessage().deserialize(message));
this.sendMessage(MiniMessage.miniMessage().deserialize(message, this));
}
/**
@ -43,7 +43,7 @@ public interface CommandSource extends Audience, PermissionSubject {
final @NotNull String message,
final @NotNull TagResolver @NotNull... resolvers
) {
this.sendMessage(MiniMessage.miniMessage().deserialize(message, resolvers));
this.sendMessage(MiniMessage.miniMessage().deserialize(message, this, resolvers));
}
/**

View File

@ -12,6 +12,14 @@ package com.velocitypowered.api.event;
*/
public enum PostOrder {
FIRST, EARLY, NORMAL, LATE, LAST, CUSTOM
FIRST, EARLY, NORMAL, LATE, LAST,
/**
* Previously used to specify that {@link Subscribe#priority()} should be used.
*
* @deprecated No longer required, you only need to specify {@link Subscribe#priority()}.
*/
@Deprecated
CUSTOM
}

View File

@ -32,12 +32,9 @@ public @interface Subscribe {
* The priority of this event handler. Priorities are used to determine the order in which event
* handlers are called. The higher the priority, the earlier the event handler will be called.
*
* <p>Note that due to compatibility constraints, you must specify {@link PostOrder#CUSTOM}
* in order to use this field.</p>
*
* @return the priority
*/
short priority() default Short.MIN_VALUE;
short priority() default 0;
/**
* Whether the handler must be called asynchronously. By default, all event handlers are called

View File

@ -9,7 +9,6 @@ package com.velocitypowered.api.event.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
import com.mojang.brigadier.tree.RootCommandNode;
import com.velocitypowered.api.event.annotation.AwaitingEvent;
import com.velocitypowered.api.proxy.Player;
@ -21,7 +20,6 @@ import com.velocitypowered.api.proxy.Player;
* client.
*/
@AwaitingEvent
@Beta
public class PlayerAvailableCommandsEvent {
private final Player player;

View File

@ -7,7 +7,6 @@
package com.velocitypowered.api.event.player;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
@ -18,7 +17,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* available in {@link Player#getCurrentServer()}. Velocity will not wait on this event to finish
* firing.
*/
@Beta
public class ServerPostConnectEvent {
private final Player player;
private final RegisteredServer previousServer;

View File

@ -7,7 +7,6 @@
package com.velocitypowered.api.event.proxy.server;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
@ -23,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
* @param registeredServer A {@link RegisteredServer} that has been registered.
* @since 3.3.0
*/
@Beta
public record ServerRegisteredEvent(@NotNull RegisteredServer registeredServer) {
public ServerRegisteredEvent {
Preconditions.checkNotNull(registeredServer, "registeredServer");

View File

@ -7,7 +7,6 @@
package com.velocitypowered.api.event.proxy.server;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
@ -23,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
* @param unregisteredServer A {@link RegisteredServer} that has been unregistered.
* @since 3.3.0
*/
@Beta
public record ServerUnregisteredEvent(@NotNull RegisteredServer unregisteredServer) {
public ServerUnregisteredEvent {
Preconditions.checkNotNull(unregisteredServer, "unregisteredServer");

View File

@ -89,7 +89,8 @@ public enum ProtocolVersion implements Ordered<ProtocolVersion> {
MINECRAFT_1_20_5(766, "1.20.5", "1.20.6"),
MINECRAFT_1_21(767, "1.21", "1.21.1"),
MINECRAFT_1_21_2(768, "1.21.2", "1.21.3"),
MINECRAFT_1_21_4(769, "1.21.4");
MINECRAFT_1_21_4(769, "1.21.4"),
MINECRAFT_1_21_5(770, /*1073742067,*/ "1.21.5");
private static final int SNAPSHOT_BIT = 30;

View File

@ -7,6 +7,7 @@
package com.velocitypowered.api.proxy;
import com.velocitypowered.api.network.HandshakeIntent;
import com.velocitypowered.api.network.ProtocolState;
import com.velocitypowered.api.network.ProtocolVersion;
import java.net.InetSocketAddress;
@ -60,4 +61,11 @@ public interface InboundConnection {
* @return the protocol state of the connection
*/
ProtocolState getProtocolState();
/**
* Returns the initial intent for the connection.
*
* @return the intent of the connection
*/
HandshakeIntent getHandshakeIntent();
}

View File

@ -41,6 +41,13 @@ public interface ProxyServer extends Audience {
*/
void shutdown();
/**
* Returns whether the proxy is currently shutting down.
*
* @return {@code true} if the proxy is shutting down, {@code false} otherwise
*/
boolean isShuttingDown();
/**
* Closes all listening endpoints for this server.
* This includes the main minecraft listener and query channel.

View File

@ -40,6 +40,7 @@ public interface TabList {
* Adds a {@link TabListEntry} to the {@link Player}'s tab list.
*
* @param entry to add to the tab list
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
*/
void addEntry(TabListEntry entry);
@ -47,6 +48,7 @@ public interface TabList {
* Adds a {@link Iterable} of {@link TabListEntry}'s to the {@link Player}'s tab list.
*
* @param entries to add to the tab list
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
*/
default void addEntries(Iterable<TabListEntry> entries) {
for (TabListEntry entry : entries) {
@ -58,6 +60,7 @@ public interface TabList {
* Adds an array of {@link TabListEntry}'s to the {@link Player}'s tab list.
*
* @param entries to add to the tab list
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
*/
default void addEntries(TabListEntry... entries) {
for (TabListEntry entry : entries) {
@ -187,6 +190,26 @@ public interface TabList {
* @deprecated Internal usage. Use {@link TabListEntry.Builder} instead.
*/
@Deprecated
default TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder) {
return buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder, true);
}
/**
* Represents an entry in a {@link Player}'s tab list.
*
* @param profile the profile
* @param displayName the display name
* @param latency the latency
* @param gameMode the game mode
* @param chatSession the chat session
* @param listed the visible status of entry
* @param listOrder the order/priority of entry in the tab list
* @param showHat the visibility of this entry's hat layer
* @return the entry
* @deprecated Internal usage. Use {@link TabListEntry.Builder} instead.
*/
@Deprecated
TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder);
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder, boolean showHat);
}

View File

@ -80,7 +80,7 @@ public interface TabListEntry extends KeyIdentifiable {
* <li>150-300 will display 4 bars</li>
* <li>300-600 will display 3 bars</li>
* <li>600-1000 will display 2 bars</li>
* <li>A latency move than 1 second will display 1 bar</li>
* <li>A latency greater than 1 second will display 1 bar</li>
* </ul>
*
* @return latency set for {@code this} entry
@ -160,6 +160,27 @@ public interface TabListEntry extends KeyIdentifiable {
return this;
}
/**
* Returns whether this entry's hat layer is shown in the tab list.
*
* @return whether to show this entry's hat layer
* @sinceMinecraft 1.21.4
*/
default boolean isShowHat() {
return true;
}
/**
* Sets whether to show this entry's hat layer in the tab list.
*
* @param showHat whether to show this entry's hat layer
* @return {@code this}, for chaining
* @sinceMinecraft 1.21.4
*/
default TabListEntry setShowHat(boolean showHat) {
return this;
}
/**
* Returns a {@link Builder} to create a {@link TabListEntry}.
*
@ -183,6 +204,7 @@ public interface TabListEntry extends KeyIdentifiable {
private int gameMode = 0;
private boolean listed = true;
private int listOrder = 0;
private boolean showHat;
private @Nullable ChatSession chatSession;
@ -268,7 +290,7 @@ public interface TabListEntry extends KeyIdentifiable {
* Sets whether this entry should be visible.
*
* @param listed to set
* @return ${code this}, for chaining
* @return {@code this}, for chaining
* @see TabListEntry#isListed()
*/
public Builder listed(boolean listed) {
@ -280,7 +302,7 @@ public interface TabListEntry extends KeyIdentifiable {
* Sets the order/priority of this entry in the tab list.
*
* @param order to set
* @return ${code this}, for chaining
* @return {@code this}, for chaining
* @sinceMinecraft 1.21.2
* @see TabListEntry#getListOrder()
*/
@ -289,6 +311,18 @@ public interface TabListEntry extends KeyIdentifiable {
return this;
}
/**
* Sets whether this entry's hat layer should be shown in the tab list.
*
* @param showHat to set
* @return {@code this}, for chaining
* @see TabListEntry#isShowHat()
*/
public Builder showHat(boolean showHat) {
this.showHat = showHat;
return this;
}
/**
* Constructs the {@link TabListEntry} specified by {@code this} {@link Builder}.
*
@ -301,7 +335,7 @@ public interface TabListEntry extends KeyIdentifiable {
if (profile == null) {
throw new IllegalStateException("The GameProfile must be set when building a TabListEntry");
}
return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder);
return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder, showHat);
}
}
}

View File

@ -15,6 +15,7 @@ import java.util.Objects;
import java.util.concurrent.TimeUnit;
import net.kyori.adventure.builder.AbstractBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Contains the parameters used to ping a {@link RegisteredServer}.
@ -30,10 +31,12 @@ public final class PingOptions {
public static final PingOptions DEFAULT = PingOptions.builder().build();
private final ProtocolVersion protocolVersion;
private final long timeout;
private final String virtualHost;
private PingOptions(final Builder builder) {
this.protocolVersion = builder.protocolVersion;
this.timeout = builder.timeout;
this.virtualHost = builder.virtualHost;
}
/**
@ -54,6 +57,16 @@ public final class PingOptions {
return this.timeout;
}
/**
* The virtual host to pass to the server for the ping.
*
* @return the virtual hostname to pass to the server for the ping
* @since 3.4.0
*/
public @Nullable String getVirtualHost() {
return this.virtualHost;
}
/**
* Create a new builder to assign values to a new PingOptions.
*
@ -68,10 +81,9 @@ public final class PingOptions {
if (o == null) {
return false;
}
if (!(o instanceof PingOptions)) {
if (!(o instanceof final PingOptions other)) {
return false;
}
final PingOptions other = (PingOptions) o;
return Objects.equals(this.protocolVersion, other.protocolVersion)
&& Objects.equals(this.timeout, other.timeout);
}
@ -97,6 +109,7 @@ public final class PingOptions {
public static final class Builder implements AbstractBuilder<PingOptions> {
private ProtocolVersion protocolVersion = ProtocolVersion.UNKNOWN;
private long timeout = 0;
private String virtualHost = null;
private Builder() {
}
@ -146,6 +159,18 @@ public final class PingOptions {
return this;
}
/**
* Sets the virtual host to pass to the server for the ping.
*
* @param virtualHost the virtual hostname to pass to the server for the ping
* @return this builder
* @since 3.4.0
*/
public Builder virtualHost(final @Nullable String virtualHost) {
this.virtualHost = virtualHost;
return this;
}
/**
* Create a new {@link PingOptions} with the values of this Builder.
*

View File

@ -14,6 +14,7 @@ import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.api.util.ModInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -160,31 +161,79 @@ public final class ServerPing {
}
/**
* Uses the modified {@code version} info in the response.
*
* @param version version info to set
* @return this builder, for chaining
*/
public Builder version(Version version) {
this.version = Preconditions.checkNotNull(version, "version");
return this;
}
/**
* Uses the modified {@code onlinePlayers} number in the response.
*
* @param onlinePlayers number for online players to set
* @return this builder, for chaining
*/
public Builder onlinePlayers(int onlinePlayers) {
this.onlinePlayers = onlinePlayers;
return this;
}
/**
* Uses the modified {@code maximumPlayers} number in the response.
* <b>This will not modify the actual maximum players that can join the server.</b>
*
* @param maximumPlayers number for maximum players to set
* @return this builder, for chaining
*/
public Builder maximumPlayers(int maximumPlayers) {
this.maximumPlayers = maximumPlayers;
return this;
}
/**
* Uses the modified {@code players} array in the response.
*
* @param players array of SamplePlayers to add
* @return this builder, for chaining
*/
public Builder samplePlayers(SamplePlayer... players) {
this.samplePlayers.addAll(Arrays.asList(players));
return this;
}
/**
* Uses the modified {@code players} collection in the response.
*
* @param players collection of SamplePlayers to add
* @return this builder, for chaining
*/
public Builder samplePlayers(Collection<SamplePlayer> players) {
this.samplePlayers.addAll(players);
return this;
}
/**
* Uses the modified {@code modType} in the response.
*
* @param modType the mod type to set
* @return this builder, for chaining
*/
public Builder modType(String modType) {
this.modType = Preconditions.checkNotNull(modType, "modType");
return this;
}
/**
* Uses the modified {@code mods} array in the response.
*
* @param mods array of mods to use
* @return this builder, for chaining
*/
public Builder mods(ModInfo.Mod... mods) {
this.mods.addAll(Arrays.asList(mods));
return this;
@ -194,7 +243,7 @@ public final class ServerPing {
* Uses the modified {@code mods} list in the response.
*
* @param mods the mods list to use
* @return this build, for chaining
* @return this builder, for chaining
*/
public Builder mods(ModInfo mods) {
Preconditions.checkNotNull(mods, "mods");
@ -204,36 +253,74 @@ public final class ServerPing {
return this;
}
/**
* Clears the current list of mods to use in the response.
*
* @return this builder, for chaining
*/
public Builder clearMods() {
this.mods.clear();
return this;
}
/**
* Clears the current list of PlayerSamples to use in the response.
*
* @return this builder, for chaining
*/
public Builder clearSamplePlayers() {
this.samplePlayers.clear();
return this;
}
/**
* Defines the server as mod incompatible in the response.
*
* @return this builder, for chaining
*/
public Builder notModCompatible() {
this.nullOutModinfo = true;
return this;
}
/**
* Enables nulling Players in the response.
* This will display the player count as {@code ???}.
*
* @return this builder, for chaining
*/
public Builder nullPlayers() {
this.nullOutPlayers = true;
return this;
}
/**
* Uses the {@code description} Component in the response.
*
* @param description Component to use as the description.
* @return this builder, for chaining
*/
public Builder description(net.kyori.adventure.text.Component description) {
this.description = Preconditions.checkNotNull(description, "description");
return this;
}
/**
* Uses the {@code favicon} in the response.
*
* @param favicon Favicon instance to use.
* @return this builder, for chaining
*/
public Builder favicon(Favicon favicon) {
this.favicon = Preconditions.checkNotNull(favicon, "favicon");
return this;
}
/**
* Clears the current favicon used in the response.
*
* @return this builder, for chaining
*/
public Builder clearFavicon() {
this.favicon = null;
return this;

View File

@ -76,9 +76,17 @@ public final class ModInfo {
private final String id;
private final String version;
/**
* Creates a new mod info.
*
* @param id the mod identifier
* @param version the mod version
*/
public Mod(String id, String version) {
this.id = Preconditions.checkNotNull(id, "id");
this.version = Preconditions.checkNotNull(version, "version");
Preconditions.checkArgument(id.length() < 128, "mod id is too long");
Preconditions.checkArgument(version.length() < 128, "mod version is too long");
}
public String getId() {