3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-16 21:10:30 +01:00

Convert Velocity buildscripts to Kotlin DSL (#918)

Spiritually indebted to #518 and @alexstaeding.

There's a minor break - we're going up to 3.2.0-SNAPSHOT as the API now compiles against Java 11. But this is more academic in practice.
Dieser Commit ist enthalten in:
Andrew Steinborn 2023-01-01 17:53:37 -05:00 committet von GitHub
Ursprung ffa4c95435
Commit d72d707b1c
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
300 geänderte Dateien mit 2880 neuen und 2169 gelöschten Zeilen

Datei anzeigen

@ -1,119 +0,0 @@
plugins {
id 'java-library'
id 'maven-publish'
id 'checkstyle'
}
apply plugin: 'org.cadixdev.licenser'
apply from: '../gradle/checkstyle.gradle'
apply from: '../gradle/publish.gradle'
apply plugin: 'com.github.johnrengelman.shadow'
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
license {
header = project.file('HEADER.txt')
}
sourceSets {
ap {
compileClasspath += main.compileClasspath + main.output
}
}
dependencies {
api 'com.google.code.gson:gson:2.9.0'
api "com.google.guava:guava:${guavaVersion}"
// DEPRECATED: Will be removed in Velocity Polymer
api 'com.moandjiezana.toml:toml4j:0.7.2'
api(platform("net.kyori:adventure-bom:${adventureVersion}"))
api("net.kyori:adventure-api")
api("net.kyori:adventure-text-serializer-gson")
api("net.kyori:adventure-text-serializer-legacy")
api("net.kyori:adventure-text-serializer-plain")
api("net.kyori:adventure-text-minimessage")
api "org.slf4j:slf4j-api:${slf4jVersion}"
api 'com.google.inject:guice:5.0.1'
api "org.checkerframework:checker-qual:${checkerFrameworkVersion}"
api 'com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT'
api "org.spongepowered:configurate-hocon:${configurateVersion}"
api "org.spongepowered:configurate-yaml:${configurateVersion}"
api "org.spongepowered:configurate-gson:${configurateVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
}
task javadocJar(type: Jar) {
classifier 'javadoc'
from javadoc
}
task sourcesJar(type: Jar) {
classifier 'sources'
from sourceSets.main.allSource
from sourceSets.ap.output
}
jar {
from sourceSets.ap.output
manifest {
attributes 'Automatic-Module-Name': 'com.velocitypowered.api'
}
}
shadowJar {
from sourceSets.ap.output
}
artifacts {
archives javadocJar
archives shadowJar
archives sourcesJar
}
javadoc {
options.encoding = 'UTF-8'
options.charSet = 'UTF-8'
options.source = '8'
options.links(
'https://www.slf4j.org/apidocs/',
'https://guava.dev/releases/25.1-jre/api/docs/',
'https://google.github.io/guice/api-docs/5.0.1/javadoc/',
'https://docs.oracle.com/en/java/javase/11/docs/api//',
"https://jd.adventure.kyori.net/api/${adventureVersion}/"
)
// Disable the crazy super-strict doclint tool in Java 8
options.addStringOption('Xdoclint:none', '-quiet')
// Mark sources as Java 8 source compatible
options.source = '8'
// Remove 'undefined' from seach paths when generating javadoc for a non-modular project (JDK-8215291)
if (JavaVersion.current() >= JavaVersion.VERSION_1_9 && JavaVersion.current() < JavaVersion.VERSION_12) {
options.addBooleanOption('-no-module-directories', true)
}
}
test {
useJUnitPlatform()
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
}
}
}

80
api/build.gradle.kts Normale Datei
Datei anzeigen

@ -0,0 +1,80 @@
plugins {
`java-library`
`maven-publish`
}
license {
header(project.file("HEADER.txt"))
}
java {
withJavadocJar()
withSourcesJar()
sourceSets["main"].java {
srcDir("src/ap/java")
}
}
val gsonVersion: String by project.extra
val guiceVersion: String by project.extra
val guavaVersion: String by project.extra
val adventureVersion: String by project.extra
val slf4jVersion: String by project.extra
val checkerFrameworkVersion: String by project.extra
val configurateVersion: String by project.extra
dependencies {
api("com.google.code.gson:gson:$gsonVersion")
api("com.google.guava:guava:$guavaVersion")
// DEPRECATED: Will be removed in Velocity Polymer
api("com.moandjiezana.toml:toml4j:0.7.2")
api(platform("net.kyori:adventure-bom:${adventureVersion}"))
api("net.kyori:adventure-api")
api("net.kyori:adventure-text-serializer-gson")
api("net.kyori:adventure-text-serializer-legacy")
api("net.kyori:adventure-text-serializer-plain")
api("net.kyori:adventure-text-minimessage")
api("org.slf4j:slf4j-api:$slf4jVersion")
api("com.google.inject:guice:$guiceVersion")
api("org.checkerframework:checker-qual:${checkerFrameworkVersion}")
api("com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT")
api("org.spongepowered:configurate-hocon:${configurateVersion}")
api("org.spongepowered:configurate-yaml:${configurateVersion}")
api("org.spongepowered:configurate-gson:${configurateVersion}")
}
tasks {
jar {
manifest {
attributes["Automatic-Module-Name"] = "com.velocitypowered.api"
}
}
withType<Javadoc> {
exclude("com/velocitypowered/api/plugin/ap/**")
val o = options as StandardJavadocDocletOptions
o.encoding = "UTF-8"
o.source = "8"
o.links(
"https://www.slf4j.org/apidocs/",
"https://guava.dev/releases/$guavaVersion/api/docs/",
"https://google.github.io/guice/api-docs/$guiceVersion/javadoc/",
"https://docs.oracle.com/en/java/javase/11/docs/api/",
"https://jd.adventure.kyori.net/api/$adventureVersion/"
)
// Disable the crazy super-strict doclint tool in Java 8
o.addStringOption("Xdoclint:none", "-quiet")
// Remove "undefined" from search paths when generating javadoc for a non-modular project (JDK-8215291)
if (JavaVersion.current() >= JavaVersion.VERSION_1_9 && JavaVersion.current() < JavaVersion.VERSION_12) {
o.addBooleanOption("-no-module-directories", true)
}
}
}

Datei anzeigen

@ -27,6 +27,9 @@ import javax.tools.Diagnostic;
import javax.tools.FileObject; import javax.tools.FileObject;
import javax.tools.StandardLocation; import javax.tools.StandardLocation;
/**
* Annotation processor for Velocity.
*/
@SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"}) @SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"})
public class PluginAnnotationProcessor extends AbstractProcessor { public class PluginAnnotationProcessor extends AbstractProcessor {

Datei anzeigen

@ -19,6 +19,9 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Serialized version of {@link com.velocitypowered.api.plugin.PluginDescription}.
*/
public final class SerializedPluginDescription { public final class SerializedPluginDescription {
public static final Pattern ID_PATTERN = Pattern.compile("[a-z][a-z0-9-_]{0,63}"); public static final Pattern ID_PATTERN = Pattern.compile("[a-z][a-z0-9-_]{0,63}");
@ -130,6 +133,9 @@ public final class SerializedPluginDescription {
+ '}'; + '}';
} }
/**
* Represents a dependency.
*/
public static final class Dependency { public static final class Dependency {
private final String id; private final String id;

Datei anzeigen

@ -84,6 +84,7 @@ public interface CommandManager {
/** /**
* Retrieves the {@link CommandMeta} from the specified command alias, if registered. * Retrieves the {@link CommandMeta} from the specified command alias, if registered.
*
* @param alias the command alias to lookup * @param alias the command alias to lookup
* @return an {@link CommandMeta} of the alias * @return an {@link CommandMeta} of the alias
*/ */

Datei anzeigen

@ -29,6 +29,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/** /**
* Constructs a CommandExecuteEvent. * Constructs a CommandExecuteEvent.
*
* @param commandSource the source executing the command * @param commandSource the source executing the command
* @param command the command being executed without first slash * @param command the command being executed without first slash
*/ */
@ -43,7 +44,8 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
} }
/** /**
* Gets the original command being executed without first slash. * Gets the original command being executed without the first slash.
*
* @return the original command being executed * @return the original command being executed
*/ */
public String getCommand() { public String getCommand() {
@ -108,6 +110,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/** /**
* Allows the command to be sent, without modification. * Allows the command to be sent, without modification.
*
* @return the allowed result * @return the allowed result
*/ */
public static CommandResult allowed() { public static CommandResult allowed() {
@ -116,6 +119,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/** /**
* Prevents the command from being executed. * Prevents the command from being executed.
*
* @return the denied result * @return the denied result
*/ */
public static CommandResult denied() { public static CommandResult denied() {
@ -123,7 +127,9 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
} }
/** /**
* Prevents the command from being executed, but forward command to server. * Forwards the command to server instead of executing it on the proxy. This is the
* default behavior when a command is not registered on Velocity.
*
* @return the forward result * @return the forward result
*/ */
public static CommandResult forwardToServer() { public static CommandResult forwardToServer() {
@ -132,6 +138,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/** /**
* Prevents the command from being executed on proxy, but forward command to server. * Prevents the command from being executed on proxy, but forward command to server.
*
* @param newCommand the command without first slash to use instead * @param newCommand the command without first slash to use instead
* @return a result with a new command being forwarded to server * @return a result with a new command being forwarded to server
*/ */
@ -141,7 +148,9 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
} }
/** /**
* Allows the command to be executed, but silently replaced old command with another. * Allows the command to be executed, but silently replaces the command with a different
* command.
*
* @param newCommand the command to use instead without first slash * @param newCommand the command to use instead without first slash
* @return a result with a new command * @return a result with a new command
*/ */

Datei anzeigen

@ -29,6 +29,7 @@ public class PlayerAvailableCommandsEvent {
/** /**
* Constructs an available commands event. * Constructs an available commands event.
*
* @param player the targeted player * @param player the targeted player
* @param rootNode the Brigadier root node * @param rootNode the Brigadier root node
*/ */

Datei anzeigen

@ -51,6 +51,9 @@ public final class DisconnectEvent {
+ '}'; + '}';
} }
/**
* The status of the connection when the player disconnected.
*/
public enum LoginStatus { public enum LoginStatus {
SUCCESSFUL_LOGIN, SUCCESSFUL_LOGIN,

Datei anzeigen

@ -37,6 +37,7 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
/** /**
* Creates a new instance. * Creates a new instance.
*
* @param connection the connection logging into the proxy * @param connection the connection logging into the proxy
* @param username the player's username * @param username the player's username
*/ */

Datei anzeigen

@ -35,6 +35,7 @@ public final class GameProfileRequestEvent {
/** /**
* Creates a new instance. * Creates a new instance.
*
* @param connection the connection connecting to the proxy * @param connection the connection connecting to the proxy
* @param originalProfile the original {@link GameProfile} for the user * @param originalProfile the original {@link GameProfile} for the user
* @param onlineMode whether or not the user connected in online or offline mode * @param onlineMode whether or not the user connected in online or offline mode

Datei anzeigen

@ -35,6 +35,7 @@ public final class KickedFromServerEvent implements
/** /**
* Creates a {@code KickedFromServerEvent} instance. * Creates a {@code KickedFromServerEvent} instance.
*
* @param player the player affected * @param player the player affected
* @param server the server the player disconnected from * @param server the server the player disconnected from
* @param originalReason the reason for being kicked, optional * @param originalReason the reason for being kicked, optional

Datei anzeigen

@ -28,6 +28,7 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
/** /**
* Constructs a PlayerChatEvent. * Constructs a PlayerChatEvent.
*
* @param player the player sending the message * @param player the player sending the message
* @param message the message being sent * @param message the message being sent
*/ */
@ -96,6 +97,7 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
/** /**
* Allows the message to be sent, without modification. * Allows the message to be sent, without modification.
*
* @return the allowed result * @return the allowed result
*/ */
public static ChatResult allowed() { public static ChatResult allowed() {
@ -104,6 +106,7 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
/** /**
* Prevents the message from being sent. * Prevents the message from being sent.
*
* @return the denied result * @return the denied result
*/ */
public static ChatResult denied() { public static ChatResult denied() {
@ -111,7 +114,8 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
} }
/** /**
* Allows the message to be sent, but silently replaced with another. * Allows the message to be sent, but silently replaces it with another.
*
* @param message the message to use instead * @param message the message to use instead
* @return a result with a new message * @return a result with a new message
*/ */

Datei anzeigen

@ -28,6 +28,7 @@ public class PlayerChooseInitialServerEvent {
/** /**
* Constructs a PlayerChooseInitialServerEvent. * Constructs a PlayerChooseInitialServerEvent.
*
* @param player the player that was connected * @param player the player that was connected
* @param initialServer the initial server selected, may be {@code null} * @param initialServer the initial server selected, may be {@code null}
*/ */
@ -46,9 +47,10 @@ public class PlayerChooseInitialServerEvent {
/** /**
* Sets the new initial server. * Sets the new initial server.
*
* @param server the initial server the player should connect to * @param server the initial server the player should connect to
*/ */
public void setInitialServer(RegisteredServer server) { public void setInitialServer(@Nullable RegisteredServer server) {
this.initialServer = server; this.initialServer = server;
} }

Datei anzeigen

@ -30,6 +30,7 @@ public class PlayerResourcePackStatusEvent {
/** /**
* Instantiates this event. * Instantiates this event.
*
* @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent * @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent
* (Player, Status, ResourcePackInfo)} instead. * (Player, Status, ResourcePackInfo)} instead.
*/ */

Datei anzeigen

@ -33,6 +33,7 @@ public final class ServerConnectedEvent {
/** /**
* Constructs a ServerConnectedEvent. * Constructs a ServerConnectedEvent.
*
* @param player the player that was connected * @param player the player that was connected
* @param server the server the player was connected to * @param server the server the player was connected to
* @param previousServer the server the player was previously connected to, null if none * @param previousServer the server the player was previously connected to, null if none

Datei anzeigen

@ -37,6 +37,7 @@ public class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
/** /**
* Constructs a new {@code ServerLoginPluginMessageEvent}. * Constructs a new {@code ServerLoginPluginMessageEvent}.
*
* @param connection the connection on which the plugin message was sent * @param connection the connection on which the plugin message was sent
* @param identifier the channel identifier for the message sent * @param identifier the channel identifier for the message sent
* @param contents the contents of the message * @param contents the contents of the message
@ -114,6 +115,9 @@ public class ServerLoginPluginMessageEvent implements ResultedEvent<ResponseResu
+ '}'; + '}';
} }
/**
* The result class, containing a response to the login plugin message sent by the server.
*/
public static class ResponseResult implements ResultedEvent.Result { public static class ResponseResult implements ResultedEvent.Result {
private static final ResponseResult UNKNOWN = new ResponseResult(null); private static final ResponseResult UNKNOWN = new ResponseResult(null);

Datei anzeigen

@ -33,6 +33,7 @@ public final class ServerPreConnectEvent implements
/** /**
* Creates the ServerPreConnectEvent. * Creates the ServerPreConnectEvent.
*
* @param player the player who is connecting to a server * @param player the player who is connecting to a server
* @param originalServer the server the player was trying to connect to * @param originalServer the server the player was trying to connect to
*/ */
@ -43,6 +44,7 @@ public final class ServerPreConnectEvent implements
/** /**
* Creates the ServerPreConnectEvent. * Creates the ServerPreConnectEvent.
*
* @param player the player who is connecting to a server * @param player the player who is connecting to a server
* @param originalServer the server the player was trying to connect to * @param originalServer the server the player was trying to connect to
* @param previousServer the server the player ís connected to * @param previousServer the server the player ís connected to
@ -57,6 +59,7 @@ public final class ServerPreConnectEvent implements
/** /**
* Returns the player connecting to the server. * Returns the player connecting to the server.
*
* @return the player connecting to the server * @return the player connecting to the server
*/ */
public Player getPlayer() { public Player getPlayer() {
@ -77,6 +80,7 @@ public final class ServerPreConnectEvent implements
* Returns the server that the player originally tried to connect to. To get the server the * Returns the server that the player originally tried to connect to. To get the server the
* player will connect to, see the {@link ServerResult} of this event. To get the server the * player will connect to, see the {@link ServerResult} of this event. To get the server the
* player is currently on when this event is fired, use {@link #getPreviousServer()}. * player is currently on when this event is fired, use {@link #getPreviousServer()}.
*
* @return the server that the player originally tried to connect to * @return the server that the player originally tried to connect to
*/ */
public RegisteredServer getOriginalServer() { public RegisteredServer getOriginalServer() {
@ -88,6 +92,7 @@ public final class ServerPreConnectEvent implements
* {@link Player#getCurrentServer()} as the current server might get reset after server kicks to * {@link Player#getCurrentServer()} as the current server might get reset after server kicks to
* prevent connection issues. This is {@code null} if they were not connected to another server * prevent connection issues. This is {@code null} if they were not connected to another server
* beforehand (for instance, if the player has just joined the proxy). * beforehand (for instance, if the player has just joined the proxy).
*
* @return the server the player is currently connected to. * @return the server the player is currently connected to.
*/ */
public @Nullable RegisteredServer getPreviousServer() { public @Nullable RegisteredServer getPreviousServer() {
@ -137,6 +142,7 @@ public final class ServerPreConnectEvent implements
* Returns a result that will prevent players from connecting to another server. If this result * Returns a result that will prevent players from connecting to another server. If this result
* is used, then {@link ConnectionRequestBuilder#connect()}'s result will have the status * is used, then {@link ConnectionRequestBuilder#connect()}'s result will have the status
* {@link Status#CONNECTION_CANCELLED}. * {@link Status#CONNECTION_CANCELLED}.
*
* @return a result to deny conneections * @return a result to deny conneections
*/ */
public static ServerResult denied() { public static ServerResult denied() {
@ -145,6 +151,7 @@ public final class ServerPreConnectEvent implements
/** /**
* Allows the player to connect to the specified server. * Allows the player to connect to the specified server.
*
* @param server the new server to connect to * @param server the new server to connect to
* @return a result to allow the player to connect to the specified server * @return a result to allow the player to connect to the specified server
*/ */

Datei anzeigen

@ -28,7 +28,7 @@ public class ServerResourcePackSendEvent implements ResultedEvent<ResultedEvent.
/** /**
* Constructs a new ServerResourcePackSendEvent. * Constructs a new ServerResourcePackSendEvent.
* *
* @param receivedResourcePack The resource pack the server sent. * @param receivedResourcePack The resource pack the server sent.
* @param serverConnection The connection this occurred on. * @param serverConnection The connection this occurred on.
*/ */

Datei anzeigen

@ -29,6 +29,7 @@ public class TabCompleteEvent {
/** /**
* Constructs a new TabCompleteEvent instance. * Constructs a new TabCompleteEvent instance.
*
* @param player the player * @param player the player
* @param partialMessage the partial message * @param partialMessage the partial message
* @param suggestions the initial list of suggestions * @param suggestions the initial list of suggestions
@ -41,6 +42,7 @@ public class TabCompleteEvent {
/** /**
* Returns the player requesting the tab completion. * Returns the player requesting the tab completion.
*
* @return the requesting player * @return the requesting player
*/ */
public Player getPlayer() { public Player getPlayer() {
@ -49,6 +51,7 @@ public class TabCompleteEvent {
/** /**
* Returns the message being partially completed. * Returns the message being partially completed.
*
* @return the partial message * @return the partial message
*/ */
public String getPartialMessage() { public String getPartialMessage() {
@ -57,6 +60,7 @@ public class TabCompleteEvent {
/** /**
* Returns all the suggestions provided to the user, as a mutable list. * Returns all the suggestions provided to the user, as a mutable list.
*
* @return the suggestions * @return the suggestions
*/ */
public List<String> getSuggestions() { public List<String> getSuggestions() {

Datei anzeigen

@ -7,6 +7,9 @@
package com.velocitypowered.api.plugin; package com.velocitypowered.api.plugin;
/**
* Thrown if a JAR in the plugin directory does not look valid.
*/
public class InvalidPluginException extends Exception { public class InvalidPluginException extends Exception {
public InvalidPluginException() { public InvalidPluginException() {

Datei anzeigen

@ -27,6 +27,7 @@ public final class PluginDependency {
/** /**
* Creates a new instance. * Creates a new instance.
*
* @param id the plugin ID * @param id the plugin ID
* @param version an optional version * @param version an optional version
* @param optional whether or not this dependency is optional * @param optional whether or not this dependency is optional

Datei anzeigen

@ -12,14 +12,33 @@ import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Allows the server to communicate with a client logging into the proxy using login plugin * Represents a connextion that is in the login phase. This is most useful in conjunction
* messages. * for login plugin messages.
*/ */
public interface LoginPhaseConnection extends InboundConnection, KeyIdentifiable { public interface LoginPhaseConnection extends InboundConnection, KeyIdentifiable {
/**
* Sends a login plugin message to the client, and provides a consumer to react to the
* response to the client. The login process will not continue until there are no more
* login plugin messages that require responses.
*
* @param identifier the channel identifier to use
* @param contents the message to send
* @param consumer the consumer that will respond to the message
*/
void sendLoginPluginMessage(ChannelIdentifier identifier, byte[] contents, void sendLoginPluginMessage(ChannelIdentifier identifier, byte[] contents,
MessageConsumer consumer); MessageConsumer consumer);
/**
* Consumes the message.
*/
interface MessageConsumer { interface MessageConsumer {
/**
* Consumes the message and responds to it.
*
* @param responseBody the message from the client, if any
*/
void onMessageResponse(byte @Nullable [] responseBody); void onMessageResponse(byte @Nullable [] responseBody);
} }
} }

Datei anzeigen

@ -32,13 +32,17 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.text.event.HoverEventSource;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Represents a player who is connected to the proxy. * Represents a player who is connected to the proxy.
*/ */
public interface Player extends CommandSource, Identified, InboundConnection, public interface Player extends
ChannelMessageSource, ChannelMessageSink, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable { /* Fundamental Velocity interfaces */
CommandSource, InboundConnection, ChannelMessageSource, ChannelMessageSink,
/* Adventure-specific interfaces */
Identified, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable {
/** /**
* Returns the player's current username. * Returns the player's current username.
@ -48,8 +52,8 @@ public interface Player extends CommandSource, Identified, InboundConnection,
String getUsername(); String getUsername();
/** /**
* Returns the locale the proxy will use to send messages translated via the Adventure global translator. * Returns the locale the proxy will use to send messages translated via the Adventure global
* By default, the value of {@link PlayerSettings#getLocale()} is used. * translator. By default, the value of {@link PlayerSettings#getLocale()} is used.
* *
* <p>This can be {@code null} when the client has not yet connected to any server.</p> * <p>This can be {@code null} when the client has not yet connected to any server.</p>
* *

Datei anzeigen

@ -30,6 +30,7 @@ public interface IdentifiedKey extends KeySigned {
/** /**
* Validates a signature against this public key. * Validates a signature against this public key.
*
* @param signature the signature data * @param signature the signature data
* @param toVerify the signed data * @param toVerify the signed data
* *
@ -53,6 +54,9 @@ public interface IdentifiedKey extends KeySigned {
*/ */
Revision getKeyRevision(); Revision getKeyRevision();
/**
* The different versions of player keys, per Minecraft version.
*/
enum Revision { enum Revision {
GENERIC_V1(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19)), GENERIC_V1(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19)),
LINKED_V2(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19_1)); LINKED_V2(ImmutableSet.of(), ImmutableSet.of(ProtocolVersion.MINECRAFT_1_19_1));

Datei anzeigen

@ -7,15 +7,18 @@
package com.velocitypowered.api.proxy.crypto; package com.velocitypowered.api.proxy.crypto;
import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Identifies a type with a public RSA signature. * Identifies a type with a public RSA signature.
*/ */
public interface KeyIdentifiable { public interface KeyIdentifiable {
/** /**
* Returns the timed identified key of the object context. * Returns the timed identified key of the object context. This is only available if the client
* <p>Only available in 1.19 and newer</p> * is running Minecraft 1.19 or newer.
*
* @return the key or null if not available * @return the key or null if not available
*/ */
IdentifiedKey getIdentifiedKey(); @Nullable IdentifiedKey getIdentifiedKey();
} }

Datei anzeigen

@ -12,6 +12,9 @@ import java.security.PublicKey;
import java.time.Instant; import java.time.Instant;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the signature of a signed object.
*/
public interface KeySigned { public interface KeySigned {
/** /**

Datei anzeigen

@ -9,6 +9,9 @@ package com.velocitypowered.api.proxy.crypto;
import java.util.UUID; import java.util.UUID;
/**
* A signed message.
*/
public interface SignedMessage extends KeySigned { public interface SignedMessage extends KeySigned {
/** /**

Datei anzeigen

@ -7,7 +7,8 @@
package com.velocitypowered.api.proxy.messages; package com.velocitypowered.api.proxy.messages;
import com.google.common.base.Preconditions; import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -49,13 +50,16 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
* @return a new channel identifier * @return a new channel identifier
*/ */
public static MinecraftChannelIdentifier create(String namespace, String name) { public static MinecraftChannelIdentifier create(String namespace, String name) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(namespace), "namespace is null or empty"); checkArgument(!Strings.isNullOrEmpty(namespace), "namespace is null or empty");
Preconditions.checkArgument(name != null, "namespace is null or empty"); checkArgument(name != null, "namespace is null or empty");
Preconditions.checkArgument(VALID_IDENTIFIER_REGEX.matcher(namespace).matches(), checkArgument(VALID_IDENTIFIER_REGEX.matcher(namespace).matches(),
"namespace is not valid, must match: %s got %s", VALID_IDENTIFIER_REGEX.toString(), namespace); "namespace is not valid, must match: %s got %s",
Preconditions VALID_IDENTIFIER_REGEX.toString(),
.checkArgument(VALID_IDENTIFIER_REGEX.matcher(name).matches(), namespace);
"name is not valid, must match: %s got %s", VALID_IDENTIFIER_REGEX.toString(), name); checkArgument(VALID_IDENTIFIER_REGEX.matcher(name).matches(),
"name is not valid, must match: %s got %s",
VALID_IDENTIFIER_REGEX.toString(),
name);
return new MinecraftChannelIdentifier(namespace, name); return new MinecraftChannelIdentifier(namespace, name);
} }

Datei anzeigen

@ -67,12 +67,18 @@ public interface PlayerSettings {
*/ */
boolean isClientListingAllowed(); boolean isClientListingAllowed();
/**
* The client's current chat display mode.
*/
enum ChatMode { enum ChatMode {
SHOWN, SHOWN,
COMMANDS_ONLY, COMMANDS_ONLY,
HIDDEN HIDDEN
} }
/**
* The player's selected dominant hand.
*/
enum MainHand { enum MainHand {
LEFT, LEFT,
RIGHT RIGHT

Datei anzeigen

@ -10,6 +10,9 @@ package com.velocitypowered.api.proxy.player;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the information for a resource pack to apply that can be sent to the client.
*/
public interface ResourcePackInfo { public interface ResourcePackInfo {
/** /**
@ -75,12 +78,12 @@ public interface ResourcePackInfo {
ResourcePackInfo.Builder asBuilder(); ResourcePackInfo.Builder asBuilder();
/** /**
* Returns a copy of this {@link ResourcePackInfo} instance as a builder with the new URL as the pack URL so that * Returns a copy of this {@link ResourcePackInfo} instance as a builder, using the new URL.
* it can be modified. * <p/>
* It is <b>not</b> guaranteed that * It is <b>not</b> guaranteed that
* {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)} is true. * {@code resourcePackInfo.asBuilder(resourcePackInfo.getUrl()).build().equals(resourcePackInfo)}
* That is due to the transient {@link ResourcePackInfo#getOrigin()} and * is true, because the {@link ResourcePackInfo#getOrigin()} and
* {@link ResourcePackInfo#getOriginalOrigin()} fields. * {@link ResourcePackInfo#getOriginalOrigin()} fields are transient.
* *
* @param newUrl The new URL to use in the updated builder. * @param newUrl The new URL to use in the updated builder.
* *
@ -88,6 +91,9 @@ public interface ResourcePackInfo {
*/ */
ResourcePackInfo.Builder asBuilder(String newUrl); ResourcePackInfo.Builder asBuilder(String newUrl);
/**
* Builder for {@link ResourcePackInfo} instances.
*/
interface Builder { interface Builder {
/** /**

Datei anzeigen

@ -10,6 +10,9 @@ package com.velocitypowered.api.proxy.player;
import java.util.Objects; import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents what, if any, extended parts of the skin this player has.
*/
public final class SkinParts { public final class SkinParts {
private final byte bitmask; private final byte bitmask;

Datei anzeigen

@ -121,7 +121,7 @@ public interface TabListEntry extends KeyIdentifiable {
TabListEntry setGameMode(int gameMode); TabListEntry setGameMode(int gameMode);
/** /**
* Whether or not the entry is listed, when listed they will be visible to other players in the tab list. * Returns whether or not this player will be visible to other players in the tab list.
* *
* @return Whether this entry is listed; only changeable in 1.19.3 and above * @return Whether this entry is listed; only changeable in 1.19.3 and above
*/ */
@ -193,7 +193,7 @@ public interface TabListEntry extends KeyIdentifiable {
/** /**
* Sets the {@link IdentifiedKey} of the {@link TabListEntry}. * Sets the {@link IdentifiedKey} of the {@link TabListEntry}.
* <p>This is only intended and only works for players currently <b>not</b> connected to this proxy.</p> * <p>This only works for players currently <b>not</b> connected to this proxy.</p>
* <p>For any player currently connected to this proxy this will be filled automatically.</p> * <p>For any player currently connected to this proxy this will be filled automatically.</p>
* <p>Will ignore mismatching key revisions data.</p> * <p>Will ignore mismatching key revisions data.</p>
* *

Datei anzeigen

@ -245,6 +245,7 @@ public final class QueryResponse {
/** /**
* Sets the hostname for the response. * Sets the hostname for the response.
*
* @param hostname the hostname to set * @param hostname the hostname to set
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -255,6 +256,7 @@ public final class QueryResponse {
/** /**
* Sets the game version for the response. * Sets the game version for the response.
*
* @param gameVersion the game version to set * @param gameVersion the game version to set
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -265,6 +267,7 @@ public final class QueryResponse {
/** /**
* Sets the map that will appear in the response. * Sets the map that will appear in the response.
*
* @param map the map to set * @param map the map to set
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -275,6 +278,7 @@ public final class QueryResponse {
/** /**
* Sets the players that are currently claimed to be online. * Sets the players that are currently claimed to be online.
*
* @param currentPlayers a non-negative number representing all players online * @param currentPlayers a non-negative number representing all players online
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -286,6 +290,7 @@ public final class QueryResponse {
/** /**
* Sets the maximum number of players this server purportedly can hold. * Sets the maximum number of players this server purportedly can hold.
*
* @param maxPlayers a non-negative number representing the maximum number of builders * @param maxPlayers a non-negative number representing the maximum number of builders
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -297,6 +302,7 @@ public final class QueryResponse {
/** /**
* Sets the host where this proxy is running. * Sets the host where this proxy is running.
*
* @param proxyHost the host where the proxy is running * @param proxyHost the host where the proxy is running
* @return this instance, for chaining * @return this instance, for chaining
*/ */
@ -307,6 +313,7 @@ public final class QueryResponse {
/** /**
* Sets the port where this proxy is running. * Sets the port where this proxy is running.
*
* @param proxyPort the port where the proxy is running * @param proxyPort the port where the proxy is running
* @return this instance, for chaining * @return this instance, for chaining
*/ */
@ -319,6 +326,7 @@ public final class QueryResponse {
/** /**
* Adds the specified players to the player list. * Adds the specified players to the player list.
*
* @param players the players to add * @param players the players to add
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -329,6 +337,7 @@ public final class QueryResponse {
/** /**
* Adds the specified players to the player list. * Adds the specified players to the player list.
*
* @param players the players to add * @param players the players to add
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -339,6 +348,7 @@ public final class QueryResponse {
/** /**
* Removes all players from the builder. This does not affect {@link #getCurrentPlayers()}. * Removes all players from the builder. This does not affect {@link #getCurrentPlayers()}.
*
* @return this builder, for chaining * @return this builder, for chaining
*/ */
public Builder clearPlayers() { public Builder clearPlayers() {
@ -348,6 +358,7 @@ public final class QueryResponse {
/** /**
* Sets the proxy version. * Sets the proxy version.
*
* @param proxyVersion the proxy version to set * @param proxyVersion the proxy version to set
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -358,6 +369,7 @@ public final class QueryResponse {
/** /**
* Adds the specified plugins to the plugins list. * Adds the specified plugins to the plugins list.
*
* @param plugins the plugins to add * @param plugins the plugins to add
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -368,6 +380,7 @@ public final class QueryResponse {
/** /**
* Adds the specified plugins to the plugins list. * Adds the specified plugins to the plugins list.
*
* @param plugins the plugins to add * @param plugins the plugins to add
* @return this builder, for chaining * @return this builder, for chaining
*/ */

Datei anzeigen

@ -191,6 +191,7 @@ public final class ServerPing {
/** /**
* Uses the modified {@code mods} list in the response. * Uses the modified {@code mods} list in the response.
*
* @param mods the mods list to use * @param mods the mods list to use
* @return this build, for chaining * @return this build, for chaining
*/ */
@ -240,6 +241,7 @@ public final class ServerPing {
/** /**
* Uses the information from this builder to create a new {@link ServerPing} instance. The * Uses the information from this builder to create a new {@link ServerPing} instance. The
* builder can be re-used after this event has been called. * builder can be re-used after this event has been called.
*
* @return a new {@link ServerPing} instance * @return a new {@link ServerPing} instance
*/ */
public ServerPing build() { public ServerPing build() {
@ -303,6 +305,12 @@ public final class ServerPing {
} }
} }
/**
* Represents the version of the server sent to the client. A protocol version
* that does not match the client's protocol version will show up on the server
* list as an incompatible version, but the client will still permit the user
* to connect to the server anyway.
*/
public static final class Version { public static final class Version {
private final int protocol; private final int protocol;
@ -310,6 +318,7 @@ public final class ServerPing {
/** /**
* Creates a new instance. * Creates a new instance.
*
* @param protocol the protocol version as an integer * @param protocol the protocol version as an integer
* @param name a friendly name for the protocol version * @param name a friendly name for the protocol version
*/ */
@ -352,6 +361,10 @@ public final class ServerPing {
} }
} }
/**
* Represents what the players the server purports to have online, its maximum capacity,
* and a sample of players on the server.
*/
public static final class Players { public static final class Players {
private final int online; private final int online;
@ -360,6 +373,7 @@ public final class ServerPing {
/** /**
* Creates a new instance. * Creates a new instance.
*
* @param online the number of online players * @param online the number of online players
* @param max the maximum number of players * @param max the maximum number of players
* @param sample a sample of players on the server * @param sample a sample of players on the server
@ -410,6 +424,9 @@ public final class ServerPing {
} }
} }
/**
* A player returned in the sample field of the server ping players field.
*/
public static final class SamplePlayer { public static final class SamplePlayer {
private final String name; private final String name;

Datei anzeigen

@ -7,6 +7,9 @@
package com.velocitypowered.api.scheduler; package com.velocitypowered.api.scheduler;
/**
* Enumerates all possible task statuses.
*/
public enum TaskStatus { public enum TaskStatus {
/** /**
* The task is scheduled and is currently running. * The task is scheduled and is currently running.

Datei anzeigen

@ -24,6 +24,7 @@ public final class GameProfile {
/** /**
* Creates a new Mojang game profile. * Creates a new Mojang game profile.
*
* @param id the UUID for the profile * @param id the UUID for the profile
* @param name the profile's username * @param name the profile's username
* @param properties properties for the profile * @param properties properties for the profile
@ -35,6 +36,7 @@ public final class GameProfile {
/** /**
* Creates a new Mojang game profile. * Creates a new Mojang game profile.
*
* @param undashedId the undashed, Mojang-style UUID for the profile * @param undashedId the undashed, Mojang-style UUID for the profile
* @param name the profile's username * @param name the profile's username
* @param properties properties for the profile * @param properties properties for the profile
@ -53,6 +55,7 @@ public final class GameProfile {
/** /**
* Returns the undashed, Mojang-style UUID. * Returns the undashed, Mojang-style UUID.
*
* @return the undashed UUID * @return the undashed UUID
*/ */
public String getUndashedId() { public String getUndashedId() {
@ -61,6 +64,7 @@ public final class GameProfile {
/** /**
* Returns the UUID associated with this game profile. * Returns the UUID associated with this game profile.
*
* @return the UUID * @return the UUID
*/ */
public UUID getId() { public UUID getId() {
@ -69,6 +73,7 @@ public final class GameProfile {
/** /**
* Returns the username associated with this profile. * Returns the username associated with this profile.
*
* @return the username * @return the username
*/ */
public String getName() { public String getName() {
@ -77,6 +82,7 @@ public final class GameProfile {
/** /**
* Returns an immutable list of profile properties associated with this profile. * Returns an immutable list of profile properties associated with this profile.
*
* @return the properties associated with this profile * @return the properties associated with this profile
*/ */
public List<Property> getProperties() { public List<Property> getProperties() {
@ -183,6 +189,7 @@ public final class GameProfile {
/** /**
* Creates a profile property entry. * Creates a profile property entry.
*
* @param name the name of the property * @param name the name of the property
* @param value the value of the property * @param value the value of the property
* @param signature the Mojang signature for the property * @param signature the Mojang signature for the property

Datei anzeigen

@ -13,6 +13,9 @@ import com.google.gson.annotations.SerializedName;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/**
* Represents the information for a Forge mod list.
*/
public final class ModInfo { public final class ModInfo {
public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of()); public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of());
@ -20,6 +23,12 @@ public final class ModInfo {
private final String type; private final String type;
private final List<Mod> modList; private final List<Mod> modList;
/**
* Constructs a new ModInfo instance.
*
* @param type the Forge server list version to use
* @param modList the mods to present to the client
*/
public ModInfo(String type, List<Mod> modList) { public ModInfo(String type, List<Mod> modList) {
this.type = Preconditions.checkNotNull(type, "type"); this.type = Preconditions.checkNotNull(type, "type");
this.modList = ImmutableList.copyOf(modList); this.modList = ImmutableList.copyOf(modList);
@ -58,6 +67,9 @@ public final class ModInfo {
return Objects.hash(type, modList); return Objects.hash(type, modList);
} }
/**
* Represents a mod to send to the client.
*/
public static final class Mod { public static final class Mod {
@SerializedName("modid") @SerializedName("modid")

Datei anzeigen

@ -1,59 +0,0 @@
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '7.1.0' apply false
id 'org.cadixdev.licenser' version '0.6.1' apply false
}
allprojects {
group 'com.velocitypowered'
version '3.1.2-SNAPSHOT'
ext {
// dependency versions
adventureVersion = '4.12.0'
junitVersion = '5.9.0'
slf4jVersion = '1.7.30'
log4jVersion = '2.19.0'
nettyVersion = '4.1.86.Final'
guavaVersion = '25.1-jre'
checkerFrameworkVersion = '3.6.1'
configurateVersion = '3.7.3'
getCurrentShortRevision = {
new ByteArrayOutputStream().withStream { os ->
exec {
executable = "git"
args = ["rev-parse", "HEAD"]
standardOutput = os
}
return os.toString().trim().substring(0, 8)
}
}
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
repositories {
mavenLocal()
mavenCentral()
// for kyoripowered dependencies
maven {
url 'https://oss.sonatype.org/content/groups/public/'
}
// Velocity repo
maven {
url "https://nexus.velocitypowered.com/repository/maven-public/"
}
}
test {
reports {
junitXml.required = true
}
}
}

47
build.gradle.kts Normale Datei
Datei anzeigen

@ -0,0 +1,47 @@
import com.velocitypowered.script.VelocityCheckstylePlugin
import com.velocitypowered.script.VelocityPublishPlugin
import org.cadixdev.gradle.licenser.Licenser
plugins {
`java-library`
id("org.cadixdev.licenser") version "0.6.1"
}
val junitVersion: String by project.extra
subprojects {
group = "com.velocitypowered"
version = "3.2.0-SNAPSHOT"
apply<JavaLibraryPlugin>()
apply<Licenser>()
apply<VelocityCheckstylePlugin>()
apply<VelocityPublishPlugin>()
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
repositories {
mavenCentral()
// kyoripowered
maven("https://oss.sonatype.org/content/groups/public/")
// velocity
maven("https://nexus.velocitypowered.com/repository/maven-public/")
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
}
tasks {
test {
useJUnitPlatform()
reports {
junitXml.required.set(true)
}
}
}
}

27
buildSrc/build.gradle.kts Normale Datei
Datei anzeigen

@ -0,0 +1,27 @@
plugins {
`kotlin-dsl`
checkstyle
id("net.kyori.indra.publishing") version "2.0.6"
}
repositories {
mavenCentral()
maven("https://plugins.gradle.org/m2")
}
gradlePlugin {
plugins {
register("set-manifest-impl-version") {
id = "set-manifest-impl-version"
implementationClass = "com.velocitypowered.script.SetManifestImplVersionPlugin"
}
register("velocity-checkstyle") {
id = "velocity-checkstyle"
implementationClass = "com.velocitypowered.script.VelocityCheckstylePlugin"
}
register("velocity-publish") {
id = "velocity-publish"
implementationClass = "com.velocitypowered.script.VelocityPublishPlugin"
}
}
}

Datei anzeigen

@ -0,0 +1,54 @@
/*
* Copyright (C) 2018 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.script
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.jvm.tasks.Jar
import org.gradle.kotlin.dsl.withType
import java.io.ByteArrayOutputStream
class SetManifestImplVersionPlugin : Plugin<Project> {
override fun apply(target: Project) = target.afterEvaluate { configure() }
private fun Project.configure() {
val currentShortRevision = ByteArrayOutputStream().use {
exec {
executable = "git"
args = listOf("rev-parse", "HEAD")
standardOutput = it
}
it.toString().trim().substring(0, 8)
}
tasks.withType<Jar> {
manifest {
val buildNumber = System.getenv("BUILD_NUMBER")
var velocityHumanVersion: String
if (project.version.toString().endsWith("-SNAPSHOT")) {
if (buildNumber != null) {
velocityHumanVersion = "${project.version} (git-$currentShortRevision-b$buildNumber)"
} else {
velocityHumanVersion = "${project.version} (git-$currentShortRevision)"
}
} else {
velocityHumanVersion = archiveVersion.get()
}
attributes["Implementation-Version"] = velocityHumanVersion
}
}
}
}

Datei anzeigen

@ -0,0 +1,38 @@
/*
* Copyright (C) 2018 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.script
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.quality.CheckstyleExtension
import org.gradle.api.plugins.quality.CheckstylePlugin
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
class VelocityCheckstylePlugin : Plugin<Project> {
override fun apply(target: Project) = target.configure()
private fun Project.configure() {
apply<CheckstylePlugin>()
extensions.configure<CheckstyleExtension> {
configFile = project.rootProject.file("config/checkstyle/checkstyle.xml")
maxErrors = 0
maxWarnings = 0
toolVersion = "10.6.0"
}
}
}

Datei anzeigen

@ -0,0 +1,72 @@
/*
* Copyright (C) 2018 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.script
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.repositories.PasswordCredentials
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.getByType
class VelocityPublishPlugin : Plugin<Project> {
override fun apply(target: Project) = target.afterEvaluate {
if (target.name != "velocity-proxy") {
configure()
}
}
private fun Project.configure() {
apply<JavaBasePlugin>()
apply<MavenPublishPlugin>()
extensions.configure<PublishingExtension> {
repositories {
maven {
credentials(PasswordCredentials::class.java)
name = "paper"
val base = "https://papermc.io/repo/repository/maven-"
val releasesRepoUrl = "$base-releases/"
val snapshotsRepoUrl = "$base-snapshots/"
setUrl(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
}
}
publications {
create<MavenPublication>("maven") {
from(components["java"])
pom {
name.set("Velocity")
description.set("The modern, next-generation Minecraft server proxy")
url.set("https://www.velocitypowered.com")
scm {
url.set("https://github.com/PaperMC/Velocity")
connection.set("scm:git:https://github.com/PaperMC/Velocity.git")
developerConnection.set("scm:git:https://github.com/PaperMC/Velocity.git")
}
}
}
}
}
}
}

Datei anzeigen

@ -1,7 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!DOCTYPE module PUBLIC <!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd"> "https://checkstyle.org/dtds/configuration_1_3.dtd">
<!-- <!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style Checkstyle configuration that checks the Google coding conventions from Google Java Style
@ -16,10 +16,9 @@
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov. Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
--> -->
<!-- <module name="Checker">
Developer notes: Fix MissingJavadocMethod/Type RequireEmptyLineBeforeBlockTagGroup and CustomImportOrder <module name="SuppressWarningsFilter"/>
-->
<module name = "Checker">
<property name="charset" value="UTF-8"/> <property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/> <property name="severity" value="warning"/>
@ -33,7 +32,7 @@
<!-- https://checkstyle.org/config_filters.html#SuppressionFilter --> <!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter"> <module name="SuppressionFilter">
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}" <property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
default="checkstyle-suppressions.xml" /> default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/> <property name="optional" value="true"/>
</module> </module>
@ -45,7 +44,7 @@
<module name="LineLength"> <module name="LineLength">
<property name="fileExtensions" value="java"/> <property name="fileExtensions" value="java"/>
<property name="max" value="120"/> <property name="max" value="100"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/> <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module> </module>
@ -54,9 +53,9 @@
<module name="IllegalTokenText"> <module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/> <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format" <property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/> value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message" <property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/> value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module> </module>
<module name="AvoidEscapedUnicodeCharacters"> <module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/> <property name="allowEscapesForControlCharacters" value="true"/>
@ -71,15 +70,15 @@
<module name="EmptyBlock"> <module name="EmptyBlock">
<property name="option" value="TEXT"/> <property name="option" value="TEXT"/>
<property name="tokens" <property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/> value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module> </module>
<module name="NeedBraces"> <module name="NeedBraces">
<property name="tokens" <property name="tokens"
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/> value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module> </module>
<module name="LeftCurly"> <module name="LeftCurly">
<property name="tokens" <property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF, value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT, INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
@ -88,14 +87,14 @@
<module name="RightCurly"> <module name="RightCurly">
<property name="id" value="RightCurlySame"/> <property name="id" value="RightCurlySame"/>
<property name="tokens" <property name="tokens"
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
LITERAL_DO"/> LITERAL_DO"/>
</module> </module>
<module name="RightCurly"> <module name="RightCurly">
<property name="id" value="RightCurlyAlone"/> <property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/> <property name="option" value="alone"/>
<property name="tokens" <property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT, value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF, INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/> COMPACT_CTOR_DEF"/>
</module> </module>
@ -105,13 +104,7 @@
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1] <property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
or preceding-sibling::*[last()][self::LCURLY]]"/> or preceding-sibling::*[last()][self::LCURLY]]"/>
</module> </module>
<module name="WhitespaceAfter"> <module name="WhitespaceAfter" />
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_RETURN,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, LITERAL_FINALLY, DO_WHILE, ELLIPSIS,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_CATCH, LAMBDA,
LITERAL_YIELD, LITERAL_CASE"/>
</module>
<module name="WhitespaceAround"> <module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/> <property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/> <property name="allowEmptyLambdas" value="true"/>
@ -120,7 +113,7 @@
<property name="allowEmptyLoops" value="true"/> <property name="allowEmptyLoops" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/> <property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens" <property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
@ -128,10 +121,10 @@
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR, NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/> SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed" <message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks
may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/> may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded" <message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/> value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module> </module>
<module name="OneStatementPerLine"/> <module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/> <module name="MultipleVariableDeclarations"/>
@ -142,7 +135,7 @@
<module name="ModifierOrder"/> <module name="ModifierOrder"/>
<module name="EmptyLineSeparator"> <module name="EmptyLineSeparator">
<property name="tokens" <property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF, value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF, STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/> COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/> <property name="allowNoEmptyLineBetweenFields" value="true"/>
@ -177,79 +170,79 @@
<module name="PackageName"> <module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/> <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/> value="Package name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="TypeName"> <module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/> ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/> value="Type name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="MemberName"> <module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/> <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/> value="Member name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="ParameterName"> <module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/> <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/> value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="LambdaParameterName"> <module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/> <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/> value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="CatchParameterName"> <module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/> <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/> value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="LocalVariableName"> <module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/> <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/> value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="PatternVariableName"> <module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/> <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/> value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="ClassTypeParameterName"> <module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/> <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/> value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="RecordComponentName"> <module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/> <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/> value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="RecordTypeParameterName"> <module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/> <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/> value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="MethodTypeParameterName"> <module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/> <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/> value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="InterfaceTypeParameterName"> <module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/> <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/> value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="NoFinalizer"/> <module name="NoFinalizer"/>
<module name="GenericWhitespace"> <module name="GenericWhitespace">
<message key="ws.followed" <message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/> value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded" <message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/> value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow" <message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/> value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded" <message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/> value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module> </module>
<module name="Indentation"> <module name="Indentation">
<property name="basicOffset" value="2"/> <property name="basicOffset" value="2"/>
@ -261,9 +254,9 @@
</module> </module>
<module name="AbbreviationAsWordInName"> <module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/> <property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/> <property name="allowedAbbreviationLength" value="0"/>
<property name="tokens" <property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF, value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF, PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/> RECORD_COMPONENT_DEF"/>
</module> </module>
@ -278,18 +271,18 @@
</module> </module>
<module name="MethodParamPad"> <module name="MethodParamPad">
<property name="tokens" <property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF, value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/> SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
</module> </module>
<module name="NoWhitespaceBefore"> <module name="NoWhitespaceBefore">
<property name="tokens" <property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/> LABELED_STAT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/> <property name="allowLineBreaks" value="true"/>
</module> </module>
<module name="ParenPad"> <module name="ParenPad">
<property name="tokens" <property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF, value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW, EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA, METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
@ -298,14 +291,14 @@
<module name="OperatorWrap"> <module name="OperatorWrap">
<property name="option" value="NL"/> <property name="option" value="NL"/>
<property name="tokens" <property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF,
TYPE_EXTENSION_AND "/> TYPE_EXTENSION_AND "/>
</module> </module>
<module name="AnnotationLocation"> <module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/> <property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens" <property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
RECORD_DEF, COMPACT_CTOR_DEF"/> RECORD_DEF, COMPACT_CTOR_DEF"/>
</module> </module>
<module name="AnnotationLocation"> <module name="AnnotationLocation">
@ -318,15 +311,14 @@
<module name="JavadocTagContinuationIndentation"/> <module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc"> <module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments" <property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/> value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module> </module>
<module name="JavadocParagraph"/> <module name="JavadocParagraph"/>
<!-- <module name="RequireEmptyLineBeforeBlockTagGroup"/> <module name="RequireEmptyLineBeforeBlockTagGroup"/>
-->
<module name="AtclauseOrder"> <module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/> <property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target" <property name="target"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/> value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
</module> </module>
<module name="JavadocMethod"> <module name="JavadocMethod">
<property name="accessModifiers" value="public"/> <property name="accessModifiers" value="public"/>
@ -335,7 +327,7 @@
<property name="allowedAnnotations" value="Override, Test"/> <property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/> <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module> </module>
<!-- <module name="MissingJavadocMethod"> <module name="MissingJavadocMethod">
<property name="scope" value="public"/> <property name="scope" value="public"/>
<property name="minLineCount" value="2"/> <property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/> <property name="allowedAnnotations" value="Override, Test"/>
@ -345,15 +337,14 @@
<module name="MissingJavadocType"> <module name="MissingJavadocType">
<property name="scope" value="protected"/> <property name="scope" value="protected"/>
<property name="tokens" <property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/> RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/> <property name="excludeScope" value="nothing"/>
</module> </module>
-->
<module name="MethodName"> <module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/> <property name="format" value="^[a-z][a-z0-9]\w*$"/>
<message key="name.invalidPattern" <message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/> value="Method name ''{0}'' must match pattern ''{1}''."/>
</module> </module>
<module name="SingleLineJavadoc"/> <module name="SingleLineJavadoc"/>
<module name="EmptyCatchBlock"> <module name="EmptyCatchBlock">
@ -365,8 +356,21 @@
<!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter --> <!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
<module name="SuppressionXpathFilter"> <module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}" <property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" /> default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/> <property name="optional" value="true"/>
</module> </module>
<module name="SuppressWarningsHolder" />
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)" />
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)" />
<property name="checkFormat" value="$1" />
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="CHECKSTYLE.SUPPRESS\: ([\w\|]+)"/>
<!-- $1 refers to the first match group in the regex defined in commentFormat -->
<property name="checkFormat" value="$1"/>
<!-- The check is suppressed in the next line of code after the comment -->
<property name="influenceFormat" value="1"/>
</module>
</module> </module>
</module> </module>

26
gradle.properties Normale Datei
Datei anzeigen

@ -0,0 +1,26 @@
# API dependencies.
gsonVersion=2.9.0
junitVersion=5.9.0
slf4jVersion=1.7.30
adventureVersion=4.12.0
guavaVersion=25.1-jre
checkerFrameworkVersion=3.6.1
configurateVersion=3.7.3
guiceVersion=5.0.1
# Proxy dependencies.
log4jVersion=2.19.0
nettyVersion=4.1.86.Final
flareVersion=2.0.1
asyncHttpClientVersion=2.12.3
bstatsVersion=2.2.1
caffeineVersion=3.1.1
lmbdaVersion=2.0.0
nightConfigVersion=3.6.4
completableFuturesVersion=0.3.5
adventureFacetVersion=4.1.2
fastutilVersion=8.5.8
disruptorVersion=3.4.4
jansiVersion=3.21.0
terminalConsoleAppenderVersion=1.3.0
joptSimpleVersion=5.0.4

Datei anzeigen

@ -1,8 +0,0 @@
checkstyle {
toolVersion '10.3.1'
configFile new File(project.rootDir, ['config', 'checkstyle', 'checkstyle.xml'].join(File.separator))
// The build should immediately fail if we have errors.
maxErrors = 0
maxWarnings = 0
}

Datei anzeigen

@ -1,13 +0,0 @@
publishing {
repositories {
maven {
credentials(PasswordCredentials.class)
name = 'paper'
def base = 'https://papermc.io/repo/repository/maven'
def releasesRepoUrl = "$base-releases/"
def snapshotsRepoUrl = "$base-snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}

Datei anzeigen

@ -1,39 +0,0 @@
plugins {
id 'java-library'
id 'checkstyle'
id 'maven-publish'
}
apply plugin: 'org.cadixdev.licenser'
apply from: '../gradle/checkstyle.gradle'
apply from: '../gradle/publish.gradle'
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
license {
header = project.rootProject.file('HEADER.txt')
}
dependencies {
implementation "com.google.guava:guava:${guavaVersion}"
implementation "io.netty:netty-handler:${nettyVersion}"
implementation "org.checkerframework:checker-qual:${checkerFrameworkVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
}
test {
useJUnitPlatform()
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}

18
native/build.gradle.kts Normale Datei
Datei anzeigen

@ -0,0 +1,18 @@
plugins {
`java-library`
`maven-publish`
}
license {
header(project.rootProject.file("HEADER.txt"))
}
val guavaVersion: String by project.extra
val nettyVersion: String by project.extra
val checkerFrameworkVersion: String by project.extra
dependencies {
implementation("com.google.guava:guava:${guavaVersion}")
implementation("io.netty:netty-handler:${nettyVersion}")
implementation("org.checkerframework:checker-qual:${checkerFrameworkVersion}")
}

Datei anzeigen

@ -19,6 +19,9 @@ package com.velocitypowered.natives;
import com.velocitypowered.natives.util.BufferPreference; import com.velocitypowered.natives.util.BufferPreference;
/**
* Generic interface for any Velocity native.
*/
public interface Native { public interface Native {
BufferPreference preferredBufferType(); BufferPreference preferredBufferType();
} }

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.natives; package com.velocitypowered.natives;
/**
* Thrown when we cannot set up a variant of a native library.
*/
public class NativeSetupException extends RuntimeException { public class NativeSetupException extends RuntimeException {
public NativeSetupException() { public NativeSetupException() {

Datei anzeigen

@ -28,6 +28,7 @@ class CompressorUtils {
/** /**
* Ensures that the buffer does not go over {@code max}. * Ensures that the buffer does not go over {@code max}.
*
* @param buf the buffer for check * @param buf the buffer for check
* @param max the maximum size for the buffer * @param max the maximum size for the buffer
* @throws DataFormatException if the buffer becomes too bug * @throws DataFormatException if the buffer becomes too bug

Datei anzeigen

@ -28,6 +28,9 @@ import java.util.zip.DataFormatException;
import java.util.zip.Deflater; import java.util.zip.Deflater;
import java.util.zip.Inflater; import java.util.zip.Inflater;
/**
* Implements deflate compression by wrapping {@link Deflater} and {@link Inflater}.
*/
public class JavaVelocityCompressor implements VelocityCompressor { public class JavaVelocityCompressor implements VelocityCompressor {
public static final VelocityCompressorFactory FACTORY = JavaVelocityCompressor::new; public static final VelocityCompressorFactory FACTORY = JavaVelocityCompressor::new;

Datei anzeigen

@ -22,6 +22,9 @@ import com.velocitypowered.natives.util.BufferPreference;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException; import java.util.zip.DataFormatException;
/**
* Implements deflate compression using the {@code libdeflate} native C library.
*/
public class LibdeflateVelocityCompressor implements VelocityCompressor { public class LibdeflateVelocityCompressor implements VelocityCompressor {
public static final VelocityCompressorFactory FACTORY = LibdeflateVelocityCompressor::new; public static final VelocityCompressorFactory FACTORY = LibdeflateVelocityCompressor::new;

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.natives.compression; package com.velocitypowered.natives.compression;
/**
* Factory for {@link VelocityCompressor}.
*/
public interface VelocityCompressorFactory { public interface VelocityCompressorFactory {
VelocityCompressor create(int level); VelocityCompressor create(int level);

Datei anzeigen

@ -26,6 +26,9 @@ import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException; import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
/**
* Implements AES-CFB8 encryption/decryption using {@link Cipher}.
*/
public class JavaVelocityCipher implements VelocityCipher { public class JavaVelocityCipher implements VelocityCipher {
public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() { public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() {

Datei anzeigen

@ -23,6 +23,9 @@ import io.netty.buffer.ByteBuf;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
/**
* Implements AES-CFB8 encryption/decryption using a native library.
*/
public class NativeVelocityCipher implements VelocityCipher { public class NativeVelocityCipher implements VelocityCipher {
public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() { public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() {

Datei anzeigen

@ -21,6 +21,15 @@ import com.velocitypowered.natives.Disposable;
import com.velocitypowered.natives.Native; import com.velocitypowered.natives.Native;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/**
* Implements an AES-CFB8 cipher that either encrypts or decrypts connection data.
*/
public interface VelocityCipher extends Disposable, Native { public interface VelocityCipher extends Disposable, Native {
/**
* Encrypts the given {@link ByteBuf} in-place.
*
* @param source the buffer to encrypt
*/
void process(ByteBuf source); void process(ByteBuf source);
} }

Datei anzeigen

@ -20,6 +20,9 @@ package com.velocitypowered.natives.encryption;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
/**
* A factory interface for {@link VelocityCipher}.
*/
public interface VelocityCipherFactory { public interface VelocityCipherFactory {
VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException; VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException;

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.natives.util; package com.velocitypowered.natives.util;
/**
* Emumerates Netty buffer preferences and requirements for use with Netty.
*/
public enum BufferPreference { public enum BufferPreference {
/** /**
* A heap buffer is required. * A heap buffer is required.

Datei anzeigen

@ -21,6 +21,9 @@ import com.velocitypowered.natives.Native;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
/**
* Additional utilities for {@link ByteBuf}.
*/
public class MoreByteBufUtils { public class MoreByteBufUtils {
private MoreByteBufUtils() { private MoreByteBufUtils() {
throw new AssertionError(); throw new AssertionError();

Datei anzeigen

@ -22,6 +22,11 @@ import java.util.function.BooleanSupplier;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A loader for native code.
*
* @param <T> the interface of the instance to load
*/
public final class NativeCodeLoader<T> implements Supplier<T> { public final class NativeCodeLoader<T> implements Supplier<T> {
private final Variant<T> selected; private final Variant<T> selected;

Datei anzeigen

@ -21,6 +21,9 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
/**
* Statically-computed constraints for native code.
*/
public class NativeConstraints { public class NativeConstraints {
private static final boolean NATIVES_ENABLED = !Boolean.getBoolean("velocity.natives-disabled"); private static final boolean NATIVES_ENABLED = !Boolean.getBoolean("velocity.natives-disabled");
private static final boolean IS_AMD64; private static final boolean IS_AMD64;

Datei anzeigen

@ -31,6 +31,9 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
/**
* Enumerates all supported natives for Velocity.
*/
public class Natives { public class Natives {
private Natives() { private Natives() {

Datei anzeigen

@ -1,162 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
plugins {
id 'java'
id 'checkstyle'
}
apply plugin: 'org.cadixdev.licenser'
apply from: '../gradle/checkstyle.gradle'
apply plugin: 'com.github.johnrengelman.shadow'
license {
header = project.rootProject.file('HEADER.txt')
}
jar {
manifest {
def buildNumber = System.getenv("BUILD_NUMBER") ?: "unknown"
def version
if (project.version.endsWith("-SNAPSHOT")) {
version = "${project.version} (git-${project.ext.getCurrentShortRevision()}-b${buildNumber})"
} else {
version = "${project.version}"
}
attributes 'Main-Class': 'com.velocitypowered.proxy.Velocity'
attributes 'Implementation-Title': "Velocity"
attributes 'Implementation-Version': version
attributes 'Implementation-Vendor': "Velocity Contributors"
attributes 'Multi-Release': 'true'
}
}
shadowJar {
transform(Log4j2PluginsCacheFileTransformer)
}
tasks.withType(Checkstyle) {
exclude('**/com/velocitypowered/proxy/protocol/packet/*.java')
}
dependencies {
// Note: we depend on the API twice, first the main sourceset, and then the annotation processor.
implementation project(':velocity-api')
implementation project(':velocity-api').sourceSets.ap.output
implementation project(':velocity-native')
implementation "io.netty:netty-codec:${nettyVersion}"
implementation "io.netty:netty-codec-haproxy:${nettyVersion}"
implementation "io.netty:netty-codec-http:${nettyVersion}"
implementation "io.netty:netty-handler:${nettyVersion}"
implementation "io.netty:netty-transport-native-epoll:${nettyVersion}"
implementation "io.netty:netty-transport-native-epoll:${nettyVersion}:linux-x86_64"
implementation "io.netty:netty-transport-native-epoll:${nettyVersion}:linux-aarch_64"
implementation "org.apache.logging.log4j:log4j-api:${log4jVersion}"
implementation "org.apache.logging.log4j:log4j-core:${log4jVersion}"
implementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
implementation "org.apache.logging.log4j:log4j-iostreams:${log4jVersion}"
implementation "org.apache.logging.log4j:log4j-jul:${log4jVersion}"
implementation 'net.sf.jopt-simple:jopt-simple:5.0.4' // command-line options
implementation 'net.minecrell:terminalconsoleappender:1.3.0'
runtimeOnly 'org.jline:jline-terminal-jansi:3.21.0' // Needed for JLine
runtimeOnly 'com.lmax:disruptor:3.4.4' // Async loggers
implementation 'it.unimi.dsi:fastutil-core:8.5.8'
implementation(platform("net.kyori:adventure-bom:${adventureVersion}"))
implementation("net.kyori:adventure-nbt")
implementation("net.kyori:adventure-platform-facet:4.1.2")
implementation 'org.asynchttpclient:async-http-client:2.12.3'
implementation 'com.spotify:completable-futures:0.3.5'
implementation 'com.electronwill.night-config:toml:3.6.4'
implementation 'org.bstats:bstats-base:2.2.1'
implementation 'org.lanternpowered:lmbda:2.0.0'
implementation 'com.github.ben-manes.caffeine:caffeine:3.1.1'
implementation 'space.vectrix.flare:flare:2.0.1'
implementation 'space.vectrix.flare:flare-fastutil:2.0.1'
compileOnly 'com.github.spotbugs:spotbugs-annotations:4.4.0'
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
testImplementation "org.mockito:mockito-core:3.+"
}
test {
useJUnitPlatform()
}
shadowJar {
// 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/**'
exclude 'it/unimi/dsi/fastutil/doubles/**'
exclude 'it/unimi/dsi/fastutil/floats/**'
exclude 'it/unimi/dsi/fastutil/longs/**'
exclude 'it/unimi/dsi/fastutil/shorts/**'
// 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
// IntCollection, and we need Int2ObjectMap
exclude 'it/unimi/dsi/fastutil/ints/*Int2Boolean*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Byte*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Char*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Double*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Float*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Int*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Long*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Short*'
exclude 'it/unimi/dsi/fastutil/ints/*Int2Reference*'
exclude 'it/unimi/dsi/fastutil/ints/IntAVL*'
exclude 'it/unimi/dsi/fastutil/ints/IntArray*'
exclude 'it/unimi/dsi/fastutil/ints/*IntBi*'
exclude 'it/unimi/dsi/fastutil/ints/Int*Pair'
exclude 'it/unimi/dsi/fastutil/ints/IntLinked*'
exclude 'it/unimi/dsi/fastutil/ints/IntList*'
exclude 'it/unimi/dsi/fastutil/ints/IntHeap*'
exclude 'it/unimi/dsi/fastutil/ints/IntOpen*'
exclude 'it/unimi/dsi/fastutil/ints/IntRB*'
exclude 'it/unimi/dsi/fastutil/ints/IntSorted*'
exclude 'it/unimi/dsi/fastutil/ints/*Priority*'
exclude 'it/unimi/dsi/fastutil/ints/*BigList*'
// Try to exclude everything BUT Object2Int{LinkedOpen,Open,CustomOpen}HashMap
exclude 'it/unimi/dsi/fastutil/objects/*ObjectArray*'
exclude 'it/unimi/dsi/fastutil/objects/*ObjectAVL*'
exclude 'it/unimi/dsi/fastutil/objects/*Object*Big*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Boolean*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Byte*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Char*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Double*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Float*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2IntArray*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2IntAVL*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2IntRB*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Long*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Object*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Reference*'
exclude 'it/unimi/dsi/fastutil/objects/*Object2Short*'
exclude 'it/unimi/dsi/fastutil/objects/*ObjectRB*'
exclude 'it/unimi/dsi/fastutil/objects/*Reference*'
// Exclude Checker Framework annotations
exclude 'org/checkerframework/checker/**'
relocate 'org.bstats', 'com.velocitypowered.proxy.bstats'
}
artifacts {
archives shadowJar
}

159
proxy/build.gradle.kts Normale Datei
Datei anzeigen

@ -0,0 +1,159 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
plugins {
application
`set-manifest-impl-version`
id("com.github.johnrengelman.shadow") version "7.1.0"
}
license {
header(project.rootProject.file("HEADER.txt"))
}
application {
mainClass.set("com.velocitypowered.proxy.Velocity")
}
tasks {
withType<Checkstyle> {
exclude("**/com/velocitypowered/proxy/protocol/packet/**")
}
jar {
manifest {
attributes["Implementation-Title"] = "Velocity"
attributes["Implementation-Vendor"] = "Velocity Contributors"
attributes["Multi-Release"] = "true"
}
}
shadowJar {
transform(Log4j2PluginsCacheFileTransformer::class.java)
// 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/**")
exclude("it/unimi/dsi/fastutil/doubles/**")
exclude("it/unimi/dsi/fastutil/floats/**")
exclude("it/unimi/dsi/fastutil/longs/**")
exclude("it/unimi/dsi/fastutil/shorts/**")
// 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
// IntCollection, and we need Int2ObjectMap
exclude("it/unimi/dsi/fastutil/ints/*Int2Boolean*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Byte*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Char*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Double*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Float*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Int*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Long*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Short*")
exclude("it/unimi/dsi/fastutil/ints/*Int2Reference*")
exclude("it/unimi/dsi/fastutil/ints/IntAVL*")
exclude("it/unimi/dsi/fastutil/ints/IntArray*")
exclude("it/unimi/dsi/fastutil/ints/*IntBi*")
exclude("it/unimi/dsi/fastutil/ints/Int*Pair")
exclude("it/unimi/dsi/fastutil/ints/IntLinked*")
exclude("it/unimi/dsi/fastutil/ints/IntList*")
exclude("it/unimi/dsi/fastutil/ints/IntHeap*")
exclude("it/unimi/dsi/fastutil/ints/IntOpen*")
exclude("it/unimi/dsi/fastutil/ints/IntRB*")
exclude("it/unimi/dsi/fastutil/ints/IntSorted*")
exclude("it/unimi/dsi/fastutil/ints/*Priority*")
exclude("it/unimi/dsi/fastutil/ints/*BigList*")
// Try to exclude everything BUT Object2Int{LinkedOpen,Open,CustomOpen}HashMap
exclude("it/unimi/dsi/fastutil/objects/*ObjectArray*")
exclude("it/unimi/dsi/fastutil/objects/*ObjectAVL*")
exclude("it/unimi/dsi/fastutil/objects/*Object*Big*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Boolean*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Byte*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Char*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Double*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Float*")
exclude("it/unimi/dsi/fastutil/objects/*Object2IntArray*")
exclude("it/unimi/dsi/fastutil/objects/*Object2IntAVL*")
exclude("it/unimi/dsi/fastutil/objects/*Object2IntRB*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Long*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Object*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Reference*")
exclude("it/unimi/dsi/fastutil/objects/*Object2Short*")
exclude("it/unimi/dsi/fastutil/objects/*ObjectRB*")
exclude("it/unimi/dsi/fastutil/objects/*Reference*")
// Exclude Checker Framework annotations
exclude("org/checkerframework/checker/**")
relocate("org.bstats", "com.velocitypowered.proxy.bstats")
}
}
val adventureVersion: String by project.extra
val adventureFacetVersion: String by project.extra
val asyncHttpClientVersion: String by project.extra
val bstatsVersion: String by project.extra
val caffeineVersion: String by project.extra
val completableFuturesVersion: String by project.extra
val disruptorVersion: String by project.extra
val fastutilVersion: String by project.extra
val flareVersion: String by project.extra
val jansiVersion: String by project.extra
val joptSimpleVersion: String by project.extra
val lmbdaVersion: String by project.extra
val log4jVersion: String by project.extra
val nettyVersion: String by project.extra
val nightConfigVersion: String by project.extra
val semver4jVersion: String by project.extra
val terminalConsoleAppenderVersion: String by project.extra
dependencies {
implementation(project(":velocity-api"))
implementation(project(":velocity-native"))
implementation("io.netty:netty-codec:${nettyVersion}")
implementation("io.netty:netty-codec-haproxy:${nettyVersion}")
implementation("io.netty:netty-codec-http:${nettyVersion}")
implementation("io.netty:netty-handler:${nettyVersion}")
implementation("io.netty:netty-transport-native-epoll:${nettyVersion}")
implementation("io.netty:netty-transport-native-epoll:${nettyVersion}:linux-x86_64")
implementation("io.netty:netty-transport-native-epoll:${nettyVersion}:linux-aarch_64")
implementation("org.apache.logging.log4j:log4j-api:${log4jVersion}")
implementation("org.apache.logging.log4j:log4j-core:${log4jVersion}")
implementation("org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}")
implementation("org.apache.logging.log4j:log4j-iostreams:${log4jVersion}")
implementation("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
implementation("net.sf.jopt-simple:jopt-simple:$joptSimpleVersion") // command-line options
implementation("net.minecrell:terminalconsoleappender:$terminalConsoleAppenderVersion")
runtimeOnly("org.jline:jline-terminal-jansi:$jansiVersion") // Needed for JLine
runtimeOnly("com.lmax:disruptor:$disruptorVersion") // Async loggers
implementation("it.unimi.dsi:fastutil-core:$fastutilVersion")
implementation(platform("net.kyori:adventure-bom:$adventureVersion"))
implementation("net.kyori:adventure-nbt")
implementation("net.kyori:adventure-platform-facet:$adventureFacetVersion")
implementation("org.asynchttpclient:async-http-client:$asyncHttpClientVersion")
implementation("com.spotify:completable-futures:$completableFuturesVersion")
implementation("com.electronwill.night-config:toml:$nightConfigVersion")
implementation("org.bstats:bstats-base:$bstatsVersion")
implementation("org.lanternpowered:lmbda:$lmbdaVersion")
implementation("com.github.ben-manes.caffeine:caffeine:$caffeineVersion")
implementation("space.vectrix.flare:flare:$flareVersion")
implementation("space.vectrix.flare:flare-fastutil:$flareVersion")
compileOnly("com.github.spotbugs:spotbugs-annotations:4.4.0")
testImplementation("org.mockito:mockito-core:3.+")
}

Datei anzeigen

@ -35,6 +35,9 @@ import org.bstats.charts.SingleLineChart;
import org.bstats.config.MetricsConfig; import org.bstats.config.MetricsConfig;
import org.bstats.json.JsonObjectBuilder; import org.bstats.json.JsonObjectBuilder;
/**
* Initializes bStats.
*/
public class Metrics { public class Metrics {
private MetricsBase metricsBase; private MetricsBase metricsBase;

Datei anzeigen

@ -26,7 +26,11 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Holds parsed command line options.
*/
public final class ProxyOptions { public final class ProxyOptions {
private static final Logger logger = LogManager.getLogger(ProxyOptions.class); private static final Logger logger = LogManager.getLogger(ProxyOptions.class);
private final boolean help; private final boolean help;
private final @Nullable Integer port; private final @Nullable Integer port;
@ -37,7 +41,7 @@ public final class ProxyOptions {
final OptionSpec<Void> help = parser.acceptsAll(Arrays.asList("h", "help"), "Print help") final OptionSpec<Void> help = parser.acceptsAll(Arrays.asList("h", "help"), "Print help")
.forHelp(); .forHelp();
final OptionSpec<Integer> port = parser.acceptsAll(Arrays.asList("p", "port"), final OptionSpec<Integer> port = parser.acceptsAll(Arrays.asList("p", "port"),
"Specify the bind port to be used. The configuration bind port will be ignored.") "Specify the bind port to be used. The configuration bind port will be ignored.")
.withRequiredArg().ofType(Integer.class); .withRequiredArg().ofType(Integer.class);
final OptionSet set = parser.parse(args); final OptionSet set = parser.parse(args);

Datei anzeigen

@ -23,6 +23,10 @@ import java.text.DecimalFormat;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
/**
* The main class. Responsible for parsing command line arguments and then launching the
* proxy.
*/
public class Velocity { public class Velocity {
private static final Logger logger; private static final Logger logger;
@ -50,6 +54,7 @@ public class Velocity {
/** /**
* Main method that the JVM will call when {@code java -jar velocity.jar} is executed. * Main method that the JVM will call when {@code java -jar velocity.jar} is executed.
*
* @param args the arguments to the proxy * @param args the arguments to the proxy
*/ */
public static void main(String... args) { public static void main(String... args) {

Datei anzeigen

@ -57,7 +57,7 @@ import com.velocitypowered.proxy.scheduler.VelocityScheduler;
import com.velocitypowered.proxy.server.ServerMap; import com.velocitypowered.proxy.server.ServerMap;
import com.velocitypowered.proxy.util.AddressUtil; import com.velocitypowered.proxy.util.AddressUtil;
import com.velocitypowered.proxy.util.ClosestLocaleMatcher; import com.velocitypowered.proxy.util.ClosestLocaleMatcher;
import com.velocitypowered.proxy.util.FileSystemUtils; import com.velocitypowered.proxy.util.ResourceUtils;
import com.velocitypowered.proxy.util.VelocityChannelRegistrar; import com.velocitypowered.proxy.util.VelocityChannelRegistrar;
import com.velocitypowered.proxy.util.bossbar.AdventureBossBarManager; import com.velocitypowered.proxy.util.bossbar.AdventureBossBarManager;
import com.velocitypowered.proxy.util.ratelimit.Ratelimiter; import com.velocitypowered.proxy.util.ratelimit.Ratelimiter;
@ -105,6 +105,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Implementation of {@link ProxyServer}.
*/
public class VelocityServer implements ProxyServer, ForwardingAudience { public class VelocityServer implements ProxyServer, ForwardingAudience {
private static final Logger logger = LogManager.getLogger(VelocityServer.class); private static final Logger logger = LogManager.getLogger(VelocityServer.class);
@ -250,7 +253,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
.create(Key.key("velocity", "translations")); .create(Key.key("velocity", "translations"));
translationRegistry.defaultLocale(Locale.US); translationRegistry.defaultLocale(Locale.US);
try { try {
FileSystemUtils.visitResources(VelocityServer.class, path -> { ResourceUtils.visitResources(VelocityServer.class, path -> {
logger.info("Loading localizations..."); logger.info("Loading localizations...");
final Path langPath = Path.of("lang"); final Path langPath = Path.of("lang");
@ -275,7 +278,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
}); });
} }
Files.walk(langPath).forEach(file -> { Files.walk(langPath).forEach(file -> {
if (!Files.isRegularFile(file)) { if (!Files.isRegularFile(file)) {
return; return;
@ -468,10 +470,10 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
} }
/** /**
* Shuts down the proxy, kicking players with the specified {@param reason}. * Shuts down the proxy, kicking players with the specified reason.
* *
* @param explicitExit whether the user explicitly shut down the proxy * @param explicitExit whether the user explicitly shut down the proxy
* @param reason message to kick online players with * @param reason message to kick online players with
*/ */
public void shutdown(boolean explicitExit, Component reason) { public void shutdown(boolean explicitExit, Component reason) {
if (eventManager == null || pluginManager == null || cm == null || scheduler == null) { if (eventManager == null || pluginManager == null || cm == null || scheduler == null) {
@ -502,8 +504,8 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
// makes sure that all the disconnect events are being fired // makes sure that all the disconnect events are being fired
CompletableFuture<Void> playersTeardownFuture = CompletableFuture.allOf(players.stream() CompletableFuture<Void> playersTeardownFuture = CompletableFuture.allOf(players.stream()
.map(ConnectedPlayer::getTeardownFuture) .map(ConnectedPlayer::getTeardownFuture)
.toArray((IntFunction<CompletableFuture<Void>[]>) CompletableFuture[]::new)); .toArray((IntFunction<CompletableFuture<Void>[]>) CompletableFuture[]::new));
playersTeardownFuture.get(10, TimeUnit.SECONDS); playersTeardownFuture.get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) { } catch (TimeoutException e) {
@ -580,6 +582,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
/** /**
* Checks if the {@code connection} can be registered with the proxy. * Checks if the {@code connection} can be registered with the proxy.
*
* @param connection the connection to check * @param connection the connection to check
* @return {@code true} if we can register the connection, {@code false} if not * @return {@code true} if we can register the connection, {@code false} if not
*/ */
@ -591,9 +594,10 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
return !(connectionsByName.containsKey(lowerName) return !(connectionsByName.containsKey(lowerName)
|| connectionsByUuid.containsKey(connection.getUniqueId())); || connectionsByUuid.containsKey(connection.getUniqueId()));
} }
/** /**
* Attempts to register the {@code connection} with the proxy. * Attempts to register the {@code connection} with the proxy.
*
* @param connection the connection to register * @param connection the connection to register
* @return {@code true} if we registered the connection, {@code false} if not * @return {@code true} if we registered the connection, {@code false} if not
*/ */
@ -650,7 +654,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
return getAllPlayers().stream().filter(p -> p.getUsername() return getAllPlayers().stream().filter(p -> p.getUsername()
.regionMatches(true, 0, partialName, 0, partialName.length())) .regionMatches(true, 0, partialName, 0, partialName.length()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override @Override
@ -659,7 +663,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
return getAllServers().stream().filter(s -> s.getServerInfo().getName() return getAllServers().stream().filter(s -> s.getServerInfo().getName()
.regionMatches(true, 0, partialName, 0, partialName.length())) .regionMatches(true, 0, partialName, 0, partialName.length()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override @Override

Datei anzeigen

@ -32,9 +32,8 @@ import org.checkerframework.checker.lock.qual.GuardedBy;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Copies the nodes of a {@link RootCommandNode} to a possibly non-empty * Copies the nodes of a {@link RootCommandNode} to a possibly non-empty destination
* destination {@link RootCommandNode}, respecting the requirements satisfied * {@link RootCommandNode}, respecting the requirements satisfied by a given command source.
* by a given command source.
* *
* @param <S> the type of the source to inject the nodes for * @param <S> the type of the source to inject the nodes for
*/ */
@ -55,13 +54,13 @@ public final class CommandGraphInjector<S> {
// the root node we are copying nodes from to the destination node. // the root node we are copying nodes from to the destination node.
/** /**
* Adds the node from the root node of this injector to the given root node, * Adds the node from the root node of this injector to the given root node, respecting the
* respecting the requirements satisfied by the given source. * requirements satisfied by the given source.
* *
* <p>Prior to adding a literal with the same name as one previously contained * <p>Prior to adding a literal with the same name as one previously contained
* in the destination node, the old node is removed from the destination node. * in the destination node, the old node is removed from the destination node.
* *
* @param dest the root node to add the permissible nodes to * @param dest the root node to add the permissible nodes to
* @param source the command source to inject the nodes for * @param source the command source to inject the nodes for
*/ */
public void inject(final RootCommandNode<S> dest, final S source) { public void inject(final RootCommandNode<S> dest, final S source) {
@ -69,7 +68,7 @@ public final class CommandGraphInjector<S> {
try { try {
final RootCommandNode<S> origin = this.dispatcher.getRoot(); final RootCommandNode<S> origin = this.dispatcher.getRoot();
final CommandContextBuilder<S> rootContext = final CommandContextBuilder<S> rootContext =
new CommandContextBuilder<>(this.dispatcher, source, origin, 0); new CommandContextBuilder<>(this.dispatcher, source, origin, 0);
// Filter alias nodes // Filter alias nodes
for (final CommandNode<S> node : origin.getChildren()) { for (final CommandNode<S> node : origin.getChildren()) {
@ -78,7 +77,7 @@ public final class CommandGraphInjector<S> {
} }
final CommandContextBuilder<S> context = rootContext.copy() final CommandContextBuilder<S> context = rootContext.copy()
.withNode(node, ALIAS_RANGE); .withNode(node, ALIAS_RANGE);
if (!node.canUse(context, ALIAS_READER)) { if (!node.canUse(context, ALIAS_READER)) {
continue; continue;
} }
@ -86,7 +85,7 @@ public final class CommandGraphInjector<S> {
final LiteralCommandNode<S> asLiteral = (LiteralCommandNode<S>) node; final LiteralCommandNode<S> asLiteral = (LiteralCommandNode<S>) node;
final LiteralCommandNode<S> copy = asLiteral.createBuilder().build(); final LiteralCommandNode<S> copy = asLiteral.createBuilder().build();
final VelocityArgumentCommandNode<S, ?> argsNode = final VelocityArgumentCommandNode<S, ?> argsNode =
VelocityCommands.getArgumentsNode(asLiteral); VelocityCommands.getArgumentsNode(asLiteral);
if (argsNode == null) { if (argsNode == null) {
// This literal is associated to a BrigadierCommand, filter normally. // This literal is associated to a BrigadierCommand, filter normally.
this.copyChildren(node, copy, source); this.copyChildren(node, copy, source);
@ -126,7 +125,7 @@ public final class CommandGraphInjector<S> {
} }
private void copyChildren(final CommandNode<S> parent, final CommandNode<S> dest, private void copyChildren(final CommandNode<S> parent, final CommandNode<S> dest,
final S source) { final S source) {
for (final CommandNode<S> child : parent.getChildren()) { for (final CommandNode<S> child : parent.getChildren()) {
final CommandNode<S> filtered = this.filterNode(child, source); final CommandNode<S> filtered = this.filterNode(child, source);
if (filtered != null) { if (filtered != null) {

Datei anzeigen

@ -50,8 +50,8 @@ import org.checkerframework.checker.lock.qual.GuardedBy;
* Provides suggestions for a given command input. * Provides suggestions for a given command input.
* *
* <p>Similar to {@link CommandDispatcher#getCompletionSuggestions(ParseResults)}, except it * <p>Similar to {@link CommandDispatcher#getCompletionSuggestions(ParseResults)}, except it
* avoids fully parsing the given input and performs exactly one requirement predicate check * avoids fully parsing the given input and performs exactly one requirement predicate check per
* per considered node. * considered node.
* *
* @param <S> the type of the command source * @param <S> the type of the command source
*/ */
@ -74,31 +74,31 @@ final class SuggestionsProvider<S> {
/** /**
* Provides suggestions for the given input and source. * Provides suggestions for the given input and source.
* *
* @param input the partial input * @param input the partial input
* @param source the command source invoking the command * @param source the command source invoking the command
* @return a future that completes with the suggestions * @return a future that completes with the suggestions
*/ */
public CompletableFuture<Suggestions> provideSuggestions(final String input, final S source) { public CompletableFuture<Suggestions> provideSuggestions(final String input, final S source) {
final CommandContextBuilder<S> context = new CommandContextBuilder<>( final CommandContextBuilder<S> context = new CommandContextBuilder<>(
this.dispatcher, source, this.dispatcher.getRoot(), 0); this.dispatcher, source, this.dispatcher.getRoot(), 0);
return this.provideSuggestions(new StringReader(input), context); return this.provideSuggestions(new StringReader(input), context);
} }
/** /**
* Provides suggestions for the given input and context. * Provides suggestions for the given input and context.
* *
* @param reader the input reader * @param reader the input reader
* @param context an empty context * @param context an empty context
* @return a future that completes with the suggestions * @return a future that completes with the suggestions
*/ */
private CompletableFuture<Suggestions> provideSuggestions( private CompletableFuture<Suggestions> provideSuggestions(
final StringReader reader, final CommandContextBuilder<S> context) { final StringReader reader, final CommandContextBuilder<S> context) {
lock.lock(); lock.lock();
try { try {
final StringRange aliasRange = this.consumeAlias(reader); final StringRange aliasRange = this.consumeAlias(reader);
final String alias = aliasRange.get(reader).toLowerCase(Locale.ENGLISH); final String alias = aliasRange.get(reader).toLowerCase(Locale.ENGLISH);
final LiteralCommandNode<S> literal = final LiteralCommandNode<S> literal =
(LiteralCommandNode<S>) context.getRootNode().getChild(alias); (LiteralCommandNode<S>) context.getRootNode().getChild(alias);
final boolean hasArguments = reader.canRead(); final boolean hasArguments = reader.canRead();
if (hasArguments) { if (hasArguments) {
@ -119,9 +119,9 @@ final class SuggestionsProvider<S> {
private StringRange consumeAlias(final StringReader reader) { private StringRange consumeAlias(final StringReader reader) {
final int firstSep = reader.getString().indexOf( final int firstSep = reader.getString().indexOf(
CommandDispatcher.ARGUMENT_SEPARATOR_CHAR, reader.getCursor()); CommandDispatcher.ARGUMENT_SEPARATOR_CHAR, reader.getCursor());
final StringRange range = StringRange.between( final StringRange range = StringRange.between(
reader.getCursor(), firstSep == -1 ? reader.getTotalLength() : firstSep); reader.getCursor(), firstSep == -1 ? reader.getTotalLength() : firstSep);
reader.setCursor(range.getEnd()); reader.setCursor(range.getEnd());
return range; return range;
} }
@ -130,7 +130,7 @@ final class SuggestionsProvider<S> {
* Returns whether a literal node with the given lowercase name should be considered for * Returns whether a literal node with the given lowercase name should be considered for
* suggestions given the specified input. * suggestions given the specified input.
* *
* @param name the lowercase literal name * @param name the lowercase literal name
* @param input the partial input * @param input the partial input
* @return true if the literal should be considered; false otherwise * @return true if the literal should be considered; false otherwise
*/ */
@ -141,12 +141,12 @@ final class SuggestionsProvider<S> {
/** /**
* Returns alias suggestions for the given input. * Returns alias suggestions for the given input.
* *
* @param reader the input reader * @param reader the input reader
* @param contextSoFar an empty context * @param contextSoFar an empty context
* @return a future that completes with the suggestions * @return a future that completes with the suggestions
*/ */
private CompletableFuture<Suggestions> provideAliasSuggestions( private CompletableFuture<Suggestions> provideAliasSuggestions(
final StringReader reader, final CommandContextBuilder<S> contextSoFar) { final StringReader reader, final CommandContextBuilder<S> contextSoFar) {
final S source = contextSoFar.getSource(); final S source = contextSoFar.getSource();
// Lowercase the alias here so all comparisons can be case-sensitive (cheaper) // Lowercase the alias here so all comparisons can be case-sensitive (cheaper)
// TODO Is this actually faster? It may incur an allocation // TODO Is this actually faster? It may incur an allocation
@ -166,7 +166,7 @@ final class SuggestionsProvider<S> {
if (shouldConsider(alias, input) && node.canUse(source)) { if (shouldConsider(alias, input) && node.canUse(source)) {
final CommandContextBuilder<S> context = contextSoFar.copy() final CommandContextBuilder<S> context = contextSoFar.copy()
.withNode(node, ALIAS_SUGGESTION_RANGE); .withNode(node, ALIAS_SUGGESTION_RANGE);
if (node.canUse(context, reader)) { if (node.canUse(context, reader)) {
// LiteralCommandNode#listSuggestions is case insensitive // LiteralCommandNode#listSuggestions is case insensitive
final SuggestionsBuilder builder = new SuggestionsBuilder(input, 0); final SuggestionsBuilder builder = new SuggestionsBuilder(input, 0);
@ -179,19 +179,19 @@ final class SuggestionsProvider<S> {
} }
/** /**
* Merges the suggestions provided by the {@link Command} associated to the given * Merges the suggestions provided by the {@link Command} associated to the given alias node and
* alias node and the hints given during registration for the given input. * the hints given during registration for the given input.
* *
* <p>The context is not mutated by this method. The reader's cursor may be modified. * <p>The context is not mutated by this method. The reader's cursor may be modified.
* *
* @param alias the alias node * @param alias the alias node
* @param reader the input reader * @param reader the input reader
* @param contextSoFar the context, containing {@code alias} * @param contextSoFar the context, containing {@code alias}
* @return a future that completes with the suggestions * @return a future that completes with the suggestions
*/ */
private CompletableFuture<Suggestions> provideArgumentsSuggestions( private CompletableFuture<Suggestions> provideArgumentsSuggestions(
final LiteralCommandNode<S> alias, final StringReader reader, final LiteralCommandNode<S> alias, final StringReader reader,
final CommandContextBuilder<S> contextSoFar) { final CommandContextBuilder<S> contextSoFar) {
final S source = contextSoFar.getSource(); final S source = contextSoFar.getSource();
final String fullInput = reader.getString(); final String fullInput = reader.getString();
final VelocityArgumentCommandNode<S, ?> argsNode = VelocityCommands.getArgumentsNode(alias); final VelocityArgumentCommandNode<S, ?> argsNode = VelocityCommands.getArgumentsNode(alias);
@ -227,7 +227,7 @@ final class SuggestionsProvider<S> {
// Ask the command for suggestions via the arguments node // Ask the command for suggestions via the arguments node
reader.setCursor(start); reader.setCursor(start);
final CompletableFuture<Suggestions> cmdSuggestions = final CompletableFuture<Suggestions> cmdSuggestions =
this.getArgumentsNodeSuggestions(argsNode, reader, context); this.getArgumentsNodeSuggestions(argsNode, reader, context);
final boolean hasHints = alias.getChildren().size() > 1; final boolean hasHints = alias.getChildren().size() > 1;
if (!hasHints) { if (!hasHints) {
return this.merge(fullInput, cmdSuggestions); return this.merge(fullInput, cmdSuggestions);
@ -236,24 +236,24 @@ final class SuggestionsProvider<S> {
// Parse the hint nodes to get remaining suggestions // Parse the hint nodes to get remaining suggestions
reader.setCursor(start); reader.setCursor(start);
final CompletableFuture<Suggestions> hintSuggestions = final CompletableFuture<Suggestions> hintSuggestions =
this.getHintSuggestions(alias, reader, contextSoFar); this.getHintSuggestions(alias, reader, contextSoFar);
return this.merge(fullInput, cmdSuggestions, hintSuggestions); return this.merge(fullInput, cmdSuggestions, hintSuggestions);
} }
/** /**
* Returns the suggestions provided by the {@link Command} associated to * Returns the suggestions provided by the {@link Command} associated to the specified arguments
* the specified arguments node for the given input. * node for the given input.
* *
* <p>The reader and context are not mutated by this method. * <p>The reader and context are not mutated by this method.
* *
* @param node the arguments node of the command * @param node the arguments node of the command
* @param reader the input reader * @param reader the input reader
* @param context the context, containing an alias node and {@code node} * @param context the context, containing an alias node and {@code node}
* @return a future that completes with the suggestions * @return a future that completes with the suggestions
*/ */
private CompletableFuture<Suggestions> getArgumentsNodeSuggestions( private CompletableFuture<Suggestions> getArgumentsNodeSuggestions(
final VelocityArgumentCommandNode<S, ?> node, final StringReader reader, final VelocityArgumentCommandNode<S, ?> node, final StringReader reader,
final CommandContextBuilder<S> context) { final CommandContextBuilder<S> context) {
final int start = reader.getCursor(); final int start = reader.getCursor();
final String fullInput = reader.getString(); final String fullInput = reader.getString();
final CommandContext<S> built = context.build(fullInput); final CommandContext<S> built = context.build(fullInput);
@ -271,14 +271,14 @@ final class SuggestionsProvider<S> {
* *
* <p>The reader and context are not mutated by this method. * <p>The reader and context are not mutated by this method.
* *
* @param alias the alias node * @param alias the alias node
* @param reader the input reader * @param reader the input reader
* @param context the context, containing {@code alias} * @param context the context, containing {@code alias}
* @return a future that completes with the suggestions * @return a future that completes with the suggestions
*/ */
private CompletableFuture<Suggestions> getHintSuggestions( private CompletableFuture<Suggestions> getHintSuggestions(
final LiteralCommandNode<S> alias, final StringReader reader, final LiteralCommandNode<S> alias, final StringReader reader,
final CommandContextBuilder<S> context) { final CommandContextBuilder<S> context) {
final ParseResults<S> parse = this.parseHints(alias, reader, context); final ParseResults<S> parse = this.parseHints(alias, reader, context);
try { try {
return this.dispatcher.getCompletionSuggestions(parse); return this.dispatcher.getCompletionSuggestions(parse);
@ -290,20 +290,20 @@ final class SuggestionsProvider<S> {
} }
/** /**
* Parses the hint nodes under the given node, which is either an alias node of * Parses the hint nodes under the given node, which is either an alias node of a {@link Command}
* a {@link Command} or another hint node. * or another hint node.
* *
* <p>The reader and context are not mutated by this method. * <p>The reader and context are not mutated by this method.
* *
* @param node the node to parse * @param node the node to parse
* @param originalReader the input reader * @param originalReader the input reader
* @param contextSoFar the context, containing the alias node of the command * @param contextSoFar the context, containing the alias node of the command
* @return the parse results containing the parsed hint nodes * @return the parse results containing the parsed hint nodes
* @see VelocityCommandMeta#copyHints(CommandMeta) for the conditions under which the returned * @see VelocityCommandMeta#copyHints(CommandMeta) for the conditions under which the returned
* hints can be suggested to a {@link CommandSource}. * hints can be suggested to a {@link CommandSource}.
*/ */
private ParseResults<S> parseHints(final CommandNode<S> node, final StringReader originalReader, private ParseResults<S> parseHints(final CommandNode<S> node, final StringReader originalReader,
final CommandContextBuilder<S> contextSoFar) { final CommandContextBuilder<S> contextSoFar) {
// This is a stripped-down version of CommandDispatcher#parseNodes that doesn't // This is a stripped-down version of CommandDispatcher#parseNodes that doesn't
// check the requirements are satisfied and ignores redirects, neither of which // check the requirements are satisfied and ignores redirects, neither of which
// are used by hint nodes. Parsing errors are ignored. // are used by hint nodes. Parsing errors are ignored.
@ -350,17 +350,16 @@ final class SuggestionsProvider<S> {
} }
/** /**
* Returns a future that is completed with the result of merging the {@link Suggestions} * Returns a future that is completed with the result of merging the {@link Suggestions} the given
* the given futures complete with. The results of the futures that complete exceptionally * futures complete with. The results of the futures that complete exceptionally are ignored.
* are ignored.
* *
* @param fullInput the command input * @param fullInput the command input
* @param futures the futures that complete with the suggestions * @param futures the futures that complete with the suggestions
* @return the future that completes with the merged suggestions * @return the future that completes with the merged suggestions
*/ */
@SafeVarargs @SafeVarargs
private CompletableFuture<Suggestions> merge( private CompletableFuture<Suggestions> merge(
final String fullInput, final CompletableFuture<Suggestions>... futures) { final String fullInput, final CompletableFuture<Suggestions>... futures) {
// https://github.com/Mojang/brigadier/pull/81 // https://github.com/Mojang/brigadier/pull/81
return CompletableFuture.allOf(futures).handle((unused, throwable) -> { return CompletableFuture.allOf(futures).handle((unused, throwable) -> {
final List<Suggestions> suggestions = new ArrayList<>(futures.length); final List<Suggestions> suggestions = new ArrayList<>(futures.length);

Datei anzeigen

@ -54,6 +54,9 @@ import org.checkerframework.checker.lock.qual.GuardedBy;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.VisibleForTesting; import org.jetbrains.annotations.VisibleForTesting;
/**
* Impelements Velocity's command handler.
*/
public class VelocityCommandManager implements CommandManager { public class VelocityCommandManager implements CommandManager {
private final @GuardedBy("lock") CommandDispatcher<CommandSource> dispatcher; private final @GuardedBy("lock") CommandDispatcher<CommandSource> dispatcher;
@ -76,9 +79,9 @@ public class VelocityCommandManager implements CommandManager {
this.eventManager = Preconditions.checkNotNull(eventManager); this.eventManager = Preconditions.checkNotNull(eventManager);
final RootCommandNode<CommandSource> root = this.dispatcher.getRoot(); final RootCommandNode<CommandSource> root = this.dispatcher.getRoot();
this.registrars = ImmutableList.of( this.registrars = ImmutableList.of(
new BrigadierCommandRegistrar(root, this.lock.writeLock()), new BrigadierCommandRegistrar(root, this.lock.writeLock()),
new SimpleCommandRegistrar(root, this.lock.writeLock()), new SimpleCommandRegistrar(root, this.lock.writeLock()),
new RawCommandRegistrar(root, this.lock.writeLock())); new RawCommandRegistrar(root, this.lock.writeLock()));
this.suggestionsProvider = new SuggestionsProvider<>(this.dispatcher, this.lock.readLock()); this.suggestionsProvider = new SuggestionsProvider<>(this.dispatcher, this.lock.readLock());
this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock()); this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock());
this.commandMetas = new ConcurrentHashMap<>(); this.commandMetas = new ConcurrentHashMap<>();
@ -118,24 +121,24 @@ public class VelocityCommandManager implements CommandManager {
} }
} }
throw new IllegalArgumentException( throw new IllegalArgumentException(
command + " does not implement a registrable Command subinterface"); command + " does not implement a registrable Command subinterface");
} }
/** /**
* Attempts to register the given command if it implements the * Attempts to register the given command if it implements the
* {@linkplain CommandRegistrar#registrableSuperInterface() registrable superinterface} * {@linkplain CommandRegistrar#registrableSuperInterface() registrable superinterface} of the
* of the given registrar. * given registrar.
* *
* @param registrar the registrar to register the command * @param registrar the registrar to register the command
* @param command the command to register * @param command the command to register
* @param meta the command metadata * @param meta the command metadata
* @param <T> the type of the command * @param <T> the type of the command
* @return true if the command implements the registrable superinterface of the registrar; * @return true if the command implements the registrable superinterface of the registrar; false
* false otherwise. * otherwise.
* @throws IllegalArgumentException if the registrar cannot register the command * @throws IllegalArgumentException if the registrar cannot register the command
*/ */
private <T extends Command> boolean tryRegister(final CommandRegistrar<T> registrar, private <T extends Command> boolean tryRegister(final CommandRegistrar<T> registrar,
final Command command, final CommandMeta meta) { final Command command, final CommandMeta meta) {
final Class<T> superInterface = registrar.registrableSuperInterface(); final Class<T> superInterface = registrar.registrableSuperInterface();
if (!superInterface.isInstance(command)) { if (!superInterface.isInstance(command)) {
return false; return false;
@ -188,7 +191,7 @@ public class VelocityCommandManager implements CommandManager {
/** /**
* Fires a {@link CommandExecuteEvent}. * Fires a {@link CommandExecuteEvent}.
* *
* @param source the source to execute the command for * @param source the source to execute the command for
* @param cmdLine the command to execute * @param cmdLine the command to execute
* @return the {@link CompletableFuture} of the event * @return the {@link CompletableFuture} of the event
*/ */
@ -251,10 +254,9 @@ public class VelocityCommandManager implements CommandManager {
/** /**
* Returns suggestions to fill in the given command. * Returns suggestions to fill in the given command.
* *
* @param source the source to execute the command for * @param source the source to execute the command for
* @param cmdLine the partially completed command * @param cmdLine the partially completed command
* @return a {@link CompletableFuture} eventually completed with a {@link List}, * @return a {@link CompletableFuture} eventually completed with a {@link List}, possibly empty
* possibly empty
*/ */
public CompletableFuture<List<String>> offerSuggestions(final CommandSource source, public CompletableFuture<List<String>> offerSuggestions(final CommandSource source,
final String cmdLine) { final String cmdLine) {
@ -265,10 +267,10 @@ public class VelocityCommandManager implements CommandManager {
/** /**
* Returns suggestions to fill in the given command. * Returns suggestions to fill in the given command.
* *
* @param source the source to execute the command for * @param source the source to execute the command for
* @param cmdLine the partially completed command * @param cmdLine the partially completed command
* @return a {@link CompletableFuture} eventually completed with {@link Suggestions}, * @return a {@link CompletableFuture} eventually completed with {@link Suggestions}, possibly
* possibly empty * empty
*/ */
public CompletableFuture<Suggestions> offerBrigadierSuggestions( public CompletableFuture<Suggestions> offerBrigadierSuggestions(
final CommandSource source, final String cmdLine) { final CommandSource source, final String cmdLine) {
@ -281,14 +283,15 @@ public class VelocityCommandManager implements CommandManager {
} catch (final Throwable e) { } catch (final Throwable e) {
// Again, plugins are naughty // Again, plugins are naughty
return CompletableFuture.failedFuture( return CompletableFuture.failedFuture(
new RuntimeException("Unable to provide suggestions for " + cmdLine + " for " + source, e)); new RuntimeException("Unable to provide suggestions for " + cmdLine + " for " + source,
e));
} }
} }
/** /**
* Parses the given command input. * Parses the given command input.
* *
* @param input the normalized command input, without the leading slash ('/') * @param input the normalized command input, without the leading slash ('/')
* @param source the command source to parse the command for * @param source the command source to parse the command for
* @return the parse results * @return the parse results
*/ */
@ -307,8 +310,8 @@ public class VelocityCommandManager implements CommandManager {
try { try {
// A RootCommandNode may only contain LiteralCommandNode children instances // A RootCommandNode may only contain LiteralCommandNode children instances
return dispatcher.getRoot().getChildren().stream() return dispatcher.getRoot().getChildren().stream()
.map(CommandNode::getName) .map(CommandNode::getName)
.collect(ImmutableList.toImmutableList()); .collect(ImmutableList.toImmutableList());
} finally { } finally {
lock.readLock().unlock(); lock.readLock().unlock();
} }

Datei anzeigen

@ -33,6 +33,9 @@ import java.util.stream.Stream;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Handles building commands for plugins to register.
*/
public final class VelocityCommandMeta implements CommandMeta { public final class VelocityCommandMeta implements CommandMeta {
static final class Builder implements CommandMeta.Builder { static final class Builder implements CommandMeta.Builder {
@ -44,7 +47,7 @@ public final class VelocityCommandMeta implements CommandMeta {
public Builder(final String alias) { public Builder(final String alias) {
Preconditions.checkNotNull(alias, "alias"); Preconditions.checkNotNull(alias, "alias");
this.aliases = ImmutableSet.<String>builder() this.aliases = ImmutableSet.<String>builder()
.add(alias.toLowerCase(Locale.ENGLISH)); .add(alias.toLowerCase(Locale.ENGLISH));
this.hints = ImmutableList.builder(); this.hints = ImmutableList.builder();
this.plugin = null; this.plugin = null;
} }
@ -87,12 +90,12 @@ public final class VelocityCommandMeta implements CommandMeta {
} }
/** /**
* Creates a node to use for hinting the arguments of a {@link Command}. Hint nodes are * Creates a node to use for hinting the arguments of a {@link Command}. Hint nodes are sent to
* sent to 1.13+ clients and the proxy uses them for providing suggestions. * 1.13+ clients and the proxy uses them for providing suggestions.
* *
* <p>A hint node is used to provide suggestions if and only if the requirements of * <p>A hint node is used to provide suggestions if and only if the requirements of
* the corresponding {@link CommandNode} are satisfied. The requirement predicate * the corresponding {@link CommandNode} are satisfied. The requirement predicate of the returned
* of the returned node always returns {@code false}. * node always returns {@code false}.
* *
* @param hint the node containing hinting metadata * @param hint the node containing hinting metadata
* @return the hinting command node * @return the hinting command node
@ -101,8 +104,8 @@ public final class VelocityCommandMeta implements CommandMeta {
// We need to perform a deep copy of the hint to prevent the user // We need to perform a deep copy of the hint to prevent the user
// from modifying the nodes and adding a Command or a redirect. // from modifying the nodes and adding a Command or a redirect.
final ArgumentBuilder<CommandSource, ?> builder = hint.createBuilder() final ArgumentBuilder<CommandSource, ?> builder = hint.createBuilder()
// Requirement checking is performed by SuggestionProvider // Requirement checking is performed by SuggestionProvider
.requires(source -> false); .requires(source -> false);
for (final CommandNode<CommandSource> child : hint.getChildren()) { for (final CommandNode<CommandSource> child : hint.getChildren()) {
builder.then(copyForHinting(child)); builder.then(copyForHinting(child));
} }
@ -125,9 +128,9 @@ public final class VelocityCommandMeta implements CommandMeta {
private final Object plugin; private final Object plugin;
private VelocityCommandMeta( private VelocityCommandMeta(
final Set<String> aliases, final Set<String> aliases,
final List<CommandNode<CommandSource>> hints, final List<CommandNode<CommandSource>> hints,
final @Nullable Object plugin final @Nullable Object plugin
) { ) {
this.aliases = aliases; this.aliases = aliases;
this.hints = hints; this.hints = hints;

Datei anzeigen

@ -38,10 +38,9 @@ import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* Provides utility methods common to most {@link Command} implementations. * Provides utility methods common to most {@link Command} implementations. In particular,
* In particular, {@link InvocableCommand} implementations use the same logic for * {@link InvocableCommand} implementations use the same logic for creating and parsing the alias
* creating and parsing the alias and arguments command nodes, which is contained * and arguments command nodes, which is contained in this class.
* in this class.
*/ */
public final class VelocityCommands { public final class VelocityCommands {
@ -51,7 +50,7 @@ public final class VelocityCommands {
* Normalizes the given command input. * Normalizes the given command input.
* *
* @param input the raw command input, without the leading slash ('/') * @param input the raw command input, without the leading slash ('/')
* @param trim whether to remove leading and trailing whitespace from the input * @param trim whether to remove leading and trailing whitespace from the input
* @return the normalized command input * @return the normalized command input
*/ */
static String normalizeInput(final String input, final boolean trim) { static String normalizeInput(final String input, final boolean trim) {
@ -60,7 +59,7 @@ public final class VelocityCommands {
if (firstSep != -1) { if (firstSep != -1) {
// Aliases are case-insensitive, arguments are not // Aliases are case-insensitive, arguments are not
return command.substring(0, firstSep).toLowerCase(Locale.ENGLISH) return command.substring(0, firstSep).toLowerCase(Locale.ENGLISH)
+ command.substring(firstSep); + command.substring(firstSep);
} else { } else {
return command.toLowerCase(Locale.ENGLISH); return command.toLowerCase(Locale.ENGLISH);
} }
@ -85,18 +84,19 @@ public final class VelocityCommands {
public static final String ARGS_NODE_NAME = "arguments"; public static final String ARGS_NODE_NAME = "arguments";
/** /**
* Returns the parsed arguments that come after the command alias, or {@code fallback} if * Returns the parsed arguments that come after the command alias, or {@code fallback} if no
* no arguments were provided. * arguments were provided.
* *
* @param arguments the map of parsed arguments, as returned by * @param arguments the map of parsed arguments, as returned by
* {@link CommandContext#getArguments()} or {@link CommandContextBuilder#getArguments()} * {@link CommandContext#getArguments()} or
* @param type the type class of the arguments * {@link CommandContextBuilder#getArguments()}
* @param fallback the value to return if no arguments were provided * @param type the type class of the arguments
* @param <V> the type of the arguments * @param fallback the value to return if no arguments were provided
* @param <V> the type of the arguments
* @return the command arguments * @return the command arguments
*/ */
public static <V> V readArguments(final Map<String, ? extends ParsedArgument<?, ?>> arguments, public static <V> V readArguments(final Map<String, ? extends ParsedArgument<?, ?>> arguments,
final Class<V> type, final V fallback) { final Class<V> type, final V fallback) {
final ParsedArgument<?, ?> argument = arguments.get(ARGS_NODE_NAME); final ParsedArgument<?, ?> argument = arguments.get(ARGS_NODE_NAME);
if (argument == null) { if (argument == null) {
return fallback; // either no arguments were given or this isn't an InvocableCommand return fallback; // either no arguments were given or this isn't an InvocableCommand
@ -106,15 +106,15 @@ public final class VelocityCommands {
return type.cast(result); return type.cast(result);
} catch (final ClassCastException e) { } catch (final ClassCastException e) {
throw new IllegalArgumentException("Parsed argument is of type " + result.getClass() throw new IllegalArgumentException("Parsed argument is of type " + result.getClass()
+ ", expected " + type, e); + ", expected " + type, e);
} }
} }
// Alias nodes // Alias nodes
/** /**
* Returns whether a literal node with the given name can be added to * Returns whether a literal node with the given name can be added to the {@link RootCommandNode}
* the {@link RootCommandNode} associated to a {@link CommandManager}. * associated to a {@link CommandManager}.
* *
* <p>This is an internal method and should not be used in user-facing * <p>This is an internal method and should not be used in user-facing
* methods. Instead, they should lowercase the given aliases themselves. * methods. Instead, they should lowercase the given aliases themselves.
@ -130,11 +130,11 @@ public final class VelocityCommands {
* Creates a copy of the given literal with the specified name. * Creates a copy of the given literal with the specified name.
* *
* @param original the literal node to copy * @param original the literal node to copy
* @param newName the name of the returned literal node * @param newName the name of the returned literal node
* @return a copy of the literal with the given name * @return a copy of the literal with the given name
*/ */
public static LiteralCommandNode<CommandSource> shallowCopy( public static LiteralCommandNode<CommandSource> shallowCopy(
final LiteralCommandNode<CommandSource> original, final String newName) { final LiteralCommandNode<CommandSource> original, final String newName) {
// Brigadier resolves the redirect of a node if further input can be parsed. // Brigadier resolves the redirect of a node if further input can be parsed.
// Let <bar> be a literal node having a redirect to a <foo> literal. Then, // Let <bar> be a literal node having a redirect to a <foo> literal. Then,
// the context returned by CommandDispatcher#parseNodes when given the input // the context returned by CommandDispatcher#parseNodes when given the input
@ -145,11 +145,11 @@ public final class VelocityCommands {
Preconditions.checkNotNull(original, "original"); Preconditions.checkNotNull(original, "original");
Preconditions.checkNotNull(newName, "secondaryAlias"); Preconditions.checkNotNull(newName, "secondaryAlias");
final LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder final LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder
.<CommandSource>literal(newName) .<CommandSource>literal(newName)
.requires(original.getRequirement()) .requires(original.getRequirement())
.requiresWithContext(original.getContextRequirement()) .requiresWithContext(original.getContextRequirement())
.forward(original.getRedirect(), original.getRedirectModifier(), original.isFork()) .forward(original.getRedirect(), original.getRedirectModifier(), original.isFork())
.executes(original.getCommand()); .executes(original.getCommand());
for (final CommandNode<CommandSource> child : original.getChildren()) { for (final CommandNode<CommandSource> child : original.getChildren()) {
builder.then(child); builder.then(child);
} }
@ -159,15 +159,15 @@ public final class VelocityCommands {
// Arguments node // Arguments node
/** /**
* Returns the arguments node for the command represented by the given alias node, * Returns the arguments node for the command represented by the given alias node, if present;
* if present; otherwise returns {@code null}. * otherwise returns {@code null}.
* *
* @param alias the alias node * @param alias the alias node
* @param <S> the type of the command source * @param <S> the type of the command source
* @return the arguments node, or null if not present * @return the arguments node, or null if not present
*/ */
static <S> @Nullable VelocityArgumentCommandNode<S, ?> getArgumentsNode( static <S> @Nullable VelocityArgumentCommandNode<S, ?> getArgumentsNode(
final LiteralCommandNode<S> alias) { final LiteralCommandNode<S> alias) {
final CommandNode<S> node = alias.getChild(ARGS_NODE_NAME); final CommandNode<S> node = alias.getChild(ARGS_NODE_NAME);
if (node instanceof VelocityArgumentCommandNode) { if (node instanceof VelocityArgumentCommandNode) {
return (VelocityArgumentCommandNode<S, ?>) node; return (VelocityArgumentCommandNode<S, ?>) node;

Datei anzeigen

@ -27,8 +27,8 @@ import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
* An argument type that parses the remaining contents of a {@link StringReader}, * An argument type that parses the remaining contents of a {@link StringReader}, splitting the
* splitting the input into words and placing the results in a string array. * input into words and placing the results in a string array.
*/ */
public final class StringArrayArgumentType implements ArgumentType<String[]> { public final class StringArrayArgumentType implements ArgumentType<String[]> {
@ -36,10 +36,11 @@ public final class StringArrayArgumentType implements ArgumentType<String[]> {
public static final String[] EMPTY = new String[0]; public static final String[] EMPTY = new String[0];
private static final Splitter WORD_SPLITTER = private static final Splitter WORD_SPLITTER =
Splitter.on(CommandDispatcher.ARGUMENT_SEPARATOR_CHAR); Splitter.on(CommandDispatcher.ARGUMENT_SEPARATOR_CHAR);
private static final List<String> EXAMPLES = Arrays.asList("word", "some words"); private static final List<String> EXAMPLES = Arrays.asList("word", "some words");
private StringArrayArgumentType() {} private StringArrayArgumentType() {
}
@Override @Override
public String[] parse(final StringReader reader) throws CommandSyntaxException { public String[] parse(final StringReader reader) throws CommandSyntaxException {

Datei anzeigen

@ -31,20 +31,20 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* @param <T> the type of the argument to parse * @param <T> the type of the argument to parse
*/ */
public final class VelocityArgumentBuilder<S, T> public final class VelocityArgumentBuilder<S, T>
extends ArgumentBuilder<S, VelocityArgumentBuilder<S, T>> { extends ArgumentBuilder<S, VelocityArgumentBuilder<S, T>> {
/** /**
* Creates a builder for creating {@link VelocityArgumentCommandNode}s with * Creates a builder for creating {@link VelocityArgumentCommandNode}s with the given name and
* the given name and type. * type.
* *
* @param name the name of the node * @param name the name of the node
* @param type the type of the argument to parse * @param type the type of the argument to parse
* @param <S> the type of the command source * @param <S> the type of the command source
* @param <T> the type of the argument to parse * @param <T> the type of the argument to parse
* @return a builder * @return a builder
*/ */
public static <S, T> VelocityArgumentBuilder<S, T> velocityArgument(final String name, public static <S, T> VelocityArgumentBuilder<S, T> velocityArgument(final String name,
final ArgumentType<T> type) { final ArgumentType<T> type) {
Preconditions.checkNotNull(name, "name"); Preconditions.checkNotNull(name, "name");
Preconditions.checkNotNull(type, "type"); Preconditions.checkNotNull(type, "type");
return new VelocityArgumentBuilder<>(name, type); return new VelocityArgumentBuilder<>(name, type);
@ -82,7 +82,7 @@ public final class VelocityArgumentBuilder<S, T>
@Override @Override
public VelocityArgumentCommandNode<S, T> build() { public VelocityArgumentCommandNode<S, T> build() {
return new VelocityArgumentCommandNode<>(this.name, this.type, getCommand(), getRequirement(), return new VelocityArgumentCommandNode<>(this.name, this.type, getCommand(), getRequirement(),
getContextRequirement(), getRedirect(), getRedirectModifier(), isFork(), getContextRequirement(), getRedirect(), getRedirectModifier(), isFork(),
this.suggestionsProvider); this.suggestionsProvider);
} }
} }

Datei anzeigen

@ -40,9 +40,9 @@ import java.util.function.BiPredicate;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
* An argument node that uses the given (possibly custom) {@link ArgumentType} * An argument node that uses the given (possibly custom) {@link ArgumentType} for parsing, while
* for parsing, while maintaining compatibility with the vanilla client. * maintaining compatibility with the vanilla client. The argument type must be greedy and accept
* The argument type must be greedy and accept any input. * any input.
* *
* @param <S> the type of the command source * @param <S> the type of the command source
* @param <T> the type of the argument to parse * @param <T> the type of the argument to parse
@ -52,25 +52,25 @@ public class VelocityArgumentCommandNode<S, T> extends ArgumentCommandNode<S, St
private final ArgumentType<T> type; private final ArgumentType<T> type;
VelocityArgumentCommandNode( VelocityArgumentCommandNode(
final String name, final ArgumentType<T> type, final Command<S> command, final String name, final ArgumentType<T> type, final Command<S> command,
final Predicate<S> requirement, final Predicate<S> requirement,
final BiPredicate<CommandContextBuilder<S>, ImmutableStringReader> contextRequirement, final BiPredicate<CommandContextBuilder<S>, ImmutableStringReader> contextRequirement,
final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks,
final SuggestionProvider<S> customSuggestions) { final SuggestionProvider<S> customSuggestions) {
super(name, StringArgumentType.greedyString(), command, requirement, contextRequirement, super(name, StringArgumentType.greedyString(), command, requirement, contextRequirement,
redirect, modifier, forks, customSuggestions); redirect, modifier, forks, customSuggestions);
this.type = Preconditions.checkNotNull(type, "type"); this.type = Preconditions.checkNotNull(type, "type");
} }
@Override @Override
public void parse(final StringReader reader, final CommandContextBuilder<S> contextBuilder) public void parse(final StringReader reader, final CommandContextBuilder<S> contextBuilder)
throws CommandSyntaxException { throws CommandSyntaxException {
// Same as super, except we use the rich ArgumentType // Same as super, except we use the rich ArgumentType
final int start = reader.getCursor(); final int start = reader.getCursor();
final T result = this.type.parse(reader); final T result = this.type.parse(reader);
if (reader.canRead()) { if (reader.canRead()) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException() throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException()
.createWithContext(reader, "Expected greedy ArgumentType to parse all input"); .createWithContext(reader, "Expected greedy ArgumentType to parse all input");
} }
final ParsedArgument<S, T> parsed = new ParsedArgument<>(start, reader.getCursor(), result); final ParsedArgument<S, T> parsed = new ParsedArgument<>(start, reader.getCursor(), result);
@ -80,8 +80,8 @@ public class VelocityArgumentCommandNode<S, T> extends ArgumentCommandNode<S, St
@Override @Override
public CompletableFuture<Suggestions> listSuggestions( public CompletableFuture<Suggestions> listSuggestions(
final CommandContext<S> context, final SuggestionsBuilder builder) final CommandContext<S> context, final SuggestionsBuilder builder)
throws CommandSyntaxException { throws CommandSyntaxException {
if (getCustomSuggestions() == null) { if (getCustomSuggestions() == null) {
return Suggestions.empty(); return Suggestions.empty();
} }

Datei anzeigen

@ -21,6 +21,9 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
/**
* Basic, common command messages.
*/
public class CommandMessages { public class CommandMessages {
public static final TranslatableComponent PLAYERS_ONLY = Component.translatable( public static final TranslatableComponent PLAYERS_ONLY = Component.translatable(

Datei anzeigen

@ -40,6 +40,9 @@ import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
/**
* Implements the Velocity default {@code /glist} command.
*/
public class GlistCommand { public class GlistCommand {
private static final String SERVER_ARG = "server"; private static final String SERVER_ARG = "server";
@ -55,22 +58,22 @@ public class GlistCommand {
*/ */
public void register() { public void register() {
LiteralCommandNode<CommandSource> totalNode = LiteralArgumentBuilder LiteralCommandNode<CommandSource> totalNode = LiteralArgumentBuilder
.<CommandSource>literal("glist") .<CommandSource>literal("glist")
.requires(source -> .requires(source ->
source.getPermissionValue("velocity.command.glist") == Tristate.TRUE) source.getPermissionValue("velocity.command.glist") == Tristate.TRUE)
.executes(this::totalCount) .executes(this::totalCount)
.build(); .build();
ArgumentCommandNode<CommandSource, String> serverNode = RequiredArgumentBuilder ArgumentCommandNode<CommandSource, String> serverNode = RequiredArgumentBuilder
.<CommandSource, String>argument(SERVER_ARG, StringArgumentType.string()) .<CommandSource, String>argument(SERVER_ARG, StringArgumentType.string())
.suggests((context, builder) -> { .suggests((context, builder) -> {
for (RegisteredServer server : server.getAllServers()) { for (RegisteredServer server : server.getAllServers()) {
builder.suggest(server.getServerInfo().getName()); builder.suggest(server.getServerInfo().getName());
} }
builder.suggest("all"); builder.suggest("all");
return builder.buildFuture(); return builder.buildFuture();
}) })
.executes(this::serverCount) .executes(this::serverCount)
.build(); .build();
totalNode.addChild(serverNode); totalNode.addChild(serverNode);
server.getCommandManager().register(new BrigadierCommand(totalNode)); server.getCommandManager().register(new BrigadierCommand(totalNode));
} }

Datei anzeigen

@ -39,6 +39,9 @@ import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
/**
* Implements Velocity's {@code /server} command.
*/
public class ServerCommand implements SimpleCommand { public class ServerCommand implements SimpleCommand {
public static final int MAX_SERVERS_TO_LIST = 50; public static final int MAX_SERVERS_TO_LIST = 50;
@ -54,7 +57,7 @@ public class ServerCommand implements SimpleCommand {
final String[] args = invocation.arguments(); final String[] args = invocation.arguments();
if (!(source instanceof Player)) { if (!(source instanceof Player)) {
source.sendMessage(Identity.nil(), CommandMessages.PLAYERS_ONLY); source.sendMessage(CommandMessages.PLAYERS_ONLY);
return; return;
} }
@ -63,9 +66,8 @@ public class ServerCommand implements SimpleCommand {
// Trying to connect to a server. // Trying to connect to a server.
String serverName = args[0]; String serverName = args[0];
Optional<RegisteredServer> toConnect = server.getServer(serverName); Optional<RegisteredServer> toConnect = server.getServer(serverName);
if (!toConnect.isPresent()) { if (toConnect.isEmpty()) {
player.sendMessage(Identity.nil(), CommandMessages.SERVER_DOES_NOT_EXIST player.sendMessage(CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
.args(Component.text(serverName)));
return; return;
} }
@ -78,14 +80,14 @@ public class ServerCommand implements SimpleCommand {
private void outputServerInformation(Player executor) { private void outputServerInformation(Player executor) {
String currentServer = executor.getCurrentServer().map(ServerConnection::getServerInfo) String currentServer = executor.getCurrentServer().map(ServerConnection::getServerInfo)
.map(ServerInfo::getName).orElse("<unknown>"); .map(ServerInfo::getName).orElse("<unknown>");
executor.sendMessage(Identity.nil(), Component.translatable( executor.sendMessage(Component.translatable(
"velocity.command.server-current-server", "velocity.command.server-current-server",
NamedTextColor.YELLOW, NamedTextColor.YELLOW,
Component.text(currentServer))); Component.text(currentServer)));
List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server); List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server);
if (servers.size() > MAX_SERVERS_TO_LIST) { if (servers.size() > MAX_SERVERS_TO_LIST) {
executor.sendMessage(Identity.nil(), Component.translatable( executor.sendMessage(Component.translatable(
"velocity.command.server-too-many", NamedTextColor.RED)); "velocity.command.server-too-many", NamedTextColor.RED));
return; return;
} }
@ -103,7 +105,7 @@ public class ServerCommand implements SimpleCommand {
} }
} }
executor.sendMessage(Identity.nil(), serverListBuilder.build()); executor.sendMessage(serverListBuilder.build());
} }
private TextComponent formatServerComponent(String currentPlayerServer, RegisteredServer server) { private TextComponent formatServerComponent(String currentPlayerServer, RegisteredServer server) {
@ -113,9 +115,11 @@ public class ServerCommand implements SimpleCommand {
int connectedPlayers = server.getPlayersConnected().size(); int connectedPlayers = server.getPlayersConnected().size();
TranslatableComponent playersTextComponent; TranslatableComponent playersTextComponent;
if (connectedPlayers == 1) { if (connectedPlayers == 1) {
playersTextComponent = Component.translatable("velocity.command.server-tooltip-player-online"); playersTextComponent = Component.translatable(
"velocity.command.server-tooltip-player-online");
} else { } else {
playersTextComponent = Component.translatable("velocity.command.server-tooltip-players-online"); playersTextComponent = Component.translatable(
"velocity.command.server-tooltip-players-online");
} }
playersTextComponent = playersTextComponent.args(Component.text(connectedPlayers)); playersTextComponent = playersTextComponent.args(Component.text(connectedPlayers));
if (serverInfo.getName().equals(currentPlayerServer)) { if (serverInfo.getName().equals(currentPlayerServer)) {
@ -130,9 +134,10 @@ public class ServerCommand implements SimpleCommand {
serverTextComponent = serverTextComponent.color(NamedTextColor.GRAY) serverTextComponent = serverTextComponent.color(NamedTextColor.GRAY)
.clickEvent(ClickEvent.runCommand("/server " + serverInfo.getName())) .clickEvent(ClickEvent.runCommand("/server " + serverInfo.getName()))
.hoverEvent( .hoverEvent(
showText(Component.translatable("velocity.command.server-tooltip-offer-connect-server") showText(
.append(Component.newline()) Component.translatable("velocity.command.server-tooltip-offer-connect-server")
.append(playersTextComponent)) .append(Component.newline())
.append(playersTextComponent))
); );
} }
return serverTextComponent; return serverTextComponent;
@ -142,7 +147,7 @@ public class ServerCommand implements SimpleCommand {
public List<String> suggest(final SimpleCommand.Invocation invocation) { public List<String> suggest(final SimpleCommand.Invocation invocation) {
final String[] currentArgs = invocation.arguments(); final String[] currentArgs = invocation.arguments();
Stream<String> possibilities = server.getAllServers().stream() Stream<String> possibilities = server.getAllServers().stream()
.map(rs -> rs.getServerInfo().getName()); .map(rs -> rs.getServerInfo().getName());
if (currentArgs.length == 0) { if (currentArgs.length == 0) {
return possibilities.collect(Collectors.toList()); return possibilities.collect(Collectors.toList());

Datei anzeigen

@ -27,31 +27,38 @@ import com.velocitypowered.proxy.VelocityServer;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
public final class ShutdownCommand { /**
private ShutdownCommand() {} * Shuts down the proxy.
*/
public final class ShutdownCommand {
private ShutdownCommand() {
}
/** /**
* Creates a Velocity Shutdown Command. * Creates a Velocity Shutdown Command.
*
* @param server the proxy instance * @param server the proxy instance
* @return the Shutdown Command * @return the Shutdown Command
*/ */
public static BrigadierCommand command(final VelocityServer server) { public static BrigadierCommand command(final VelocityServer server) {
return new BrigadierCommand(LiteralArgumentBuilder.<CommandSource>literal("shutdown") return new BrigadierCommand(LiteralArgumentBuilder.<CommandSource>literal("shutdown")
.requires(source -> source == server.getConsoleCommandSource()) .requires(source -> source == server.getConsoleCommandSource())
.executes(context -> {
server.shutdown(true);
return Command.SINGLE_SUCCESS;
})
.then(RequiredArgumentBuilder.<CommandSource, String>argument("reason", StringArgumentType.greedyString())
.executes(context -> { .executes(context -> {
String reason = context.getArgument("reason", String.class); server.shutdown(true);
server.shutdown(true, MiniMessage.miniMessage().deserialize(
MiniMessage.miniMessage().serialize(
LegacyComponentSerializer.legacy('&').deserialize(reason)
)
));
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}) })
).build()); .then(RequiredArgumentBuilder.<CommandSource, String>argument("reason",
StringArgumentType.greedyString())
.executes(context -> {
String reason = context.getArgument("reason", String.class);
server.shutdown(true, MiniMessage.miniMessage().deserialize(
MiniMessage.miniMessage().serialize(
LegacyComponentSerializer.legacy('&').deserialize(reason)
)
));
return Command.SINGLE_SUCCESS;
})
).build());
} }
} }

Datei anzeigen

@ -60,6 +60,9 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Implements the {@code /velocity} command and friends.
*/
public class VelocityCommand implements SimpleCommand { public class VelocityCommand implements SimpleCommand {
private interface SubCommand { private interface SubCommand {
@ -125,9 +128,9 @@ public class VelocityCommand implements SimpleCommand {
if (currentArgs.length == 0) { if (currentArgs.length == 0) {
return commands.entrySet().stream() return commands.entrySet().stream()
.filter(e -> e.getValue().hasPermission(source, new String[0])) .filter(e -> e.getValue().hasPermission(source, new String[0]))
.map(Map.Entry::getKey) .map(Map.Entry::getKey)
.collect(ImmutableList.toImmutableList()); .collect(ImmutableList.toImmutableList());
} }
if (currentArgs.length == 1) { if (currentArgs.length == 1) {
@ -353,11 +356,11 @@ public class VelocityCommand implements SimpleCommand {
JsonObject servers = new JsonObject(); JsonObject servers = new JsonObject();
for (RegisteredServer iter : allServers) { for (RegisteredServer iter : allServers) {
servers.add(iter.getServerInfo().getName(), servers.add(iter.getServerInfo().getName(),
InformationUtils.collectServerInfo(iter)); InformationUtils.collectServerInfo(iter));
} }
JsonArray connectOrder = new JsonArray(); JsonArray connectOrder = new JsonArray();
List<String> attemptedConnectionOrder = ImmutableList.copyOf( List<String> attemptedConnectionOrder = ImmutableList.copyOf(
server.getConfiguration().getAttemptConnectionOrder()); server.getConfiguration().getAttemptConnectionOrder());
for (String s : attemptedConnectionOrder) { for (String s : attemptedConnectionOrder) {
connectOrder.add(s); connectOrder.add(s);
} }
@ -366,7 +369,7 @@ public class VelocityCommand implements SimpleCommand {
proxyConfig.add("servers", servers); proxyConfig.add("servers", servers);
proxyConfig.add("connectOrder", connectOrder); proxyConfig.add("connectOrder", connectOrder);
proxyConfig.add("forcedHosts", proxyConfig.add("forcedHosts",
InformationUtils.collectForcedHosts(server.getConfiguration())); InformationUtils.collectForcedHosts(server.getConfiguration()));
JsonObject dump = new JsonObject(); JsonObject dump = new JsonObject();
dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion())); dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion()));
@ -383,7 +386,8 @@ public class VelocityCommand implements SimpleCommand {
source.sendMessage(Component.text( source.sendMessage(Component.text(
"An anonymised report containing useful information about " "An anonymised report containing useful information about "
+ "this proxy has been saved at " + dumpPath.toAbsolutePath(), NamedTextColor.GREEN)); + "this proxy has been saved at " + dumpPath.toAbsolutePath(),
NamedTextColor.GREEN));
} catch (IOException e) { } catch (IOException e) {
logger.error("Failed to complete dump command, " logger.error("Failed to complete dump command, "
+ "the executor was interrupted: " + e.getMessage()); + "the executor was interrupted: " + e.getMessage());

Datei anzeigen

@ -27,14 +27,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Creates command invocation objects from a command context builder or * Creates command invocation objects from a command context builder or a command context.
* a command context.
* *
* <p>Let {@code builder} be a command context builder, and {@code context} * <p>Let {@code builder} be a command context builder, and {@code context}
* a context returned by calling {@link CommandContextBuilder#build(String)} on * a context returned by calling {@link CommandContextBuilder#build(String)} on {@code builder}. The
* {@code builder}. The invocations returned by {@link #create(CommandContext)} * invocations returned by {@link #create(CommandContext)} when given {@code context}, and
* when given {@code context}, and {@link #create(CommandContextBuilder)} when * {@link #create(CommandContextBuilder)} when given {@code builder} are equal.
* given {@code builder} are equal.
* *
* @param <I> the type of the built invocation * @param <I> the type of the built invocation
*/ */
@ -63,16 +61,17 @@ public interface CommandInvocationFactory<I extends CommandInvocation<?>> {
/** /**
* Creates an invocation from the given parsed nodes and arguments. * Creates an invocation from the given parsed nodes and arguments.
* *
* @param source the command source * @param source the command source
* @param nodes the list of parsed nodes, as returned by {@link CommandContext#getNodes()} and * @param nodes the list of parsed nodes, as returned by {@link CommandContext#getNodes()} and
* {@link CommandContextBuilder#getNodes()} * {@link CommandContextBuilder#getNodes()}
* @param arguments the list of parsed arguments, as returned by * @param arguments the list of parsed arguments, as returned by
* {@link CommandContext#getArguments()} and {@link CommandContextBuilder#getArguments()} * {@link CommandContext#getArguments()} and
* {@link CommandContextBuilder#getArguments()}
* @return the built invocation context * @return the built invocation context
*/ */
// This provides an abstraction over methods common to CommandContext and CommandContextBuilder. // This provides an abstraction over methods common to CommandContext and CommandContextBuilder.
// Annoyingly, they mostly have the same getters but one is (correctly) not a subclass of // Annoyingly, they mostly have the same getters but one is (correctly) not a subclass of
// the other. Subclasses may override the methods above to obtain class-specific data. // the other. Subclasses may override the methods above to obtain class-specific data.
I create(final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes, I create(final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes,
final Map<String, ? extends ParsedArgument<?, ?>> arguments); final Map<String, ? extends ParsedArgument<?, ?>> arguments);
} }

Datei anzeigen

@ -22,12 +22,16 @@ import com.mojang.brigadier.context.ParsedArgument;
import com.mojang.brigadier.context.ParsedCommandNode; import com.mojang.brigadier.context.ParsedCommandNode;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.RawCommand; import com.velocitypowered.api.command.RawCommand;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.proxy.command.VelocityCommands; import com.velocitypowered.proxy.command.VelocityCommands;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/**
* Implements {@link RawCommand.Invocation}.
*/
public final class RawCommandInvocation extends AbstractCommandInvocation<String> public final class RawCommandInvocation extends AbstractCommandInvocation<String>
implements RawCommand.Invocation { implements RawCommand.Invocation {
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
@ -35,8 +39,8 @@ public final class RawCommandInvocation extends AbstractCommandInvocation<String
@Override @Override
public RawCommand.Invocation create( public RawCommand.Invocation create(
final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes, final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes,
final Map<String, ? extends ParsedArgument<?, ?>> arguments) { final Map<String, ? extends ParsedArgument<?, ?>> arguments) {
final String alias = VelocityCommands.readAlias(nodes); final String alias = VelocityCommands.readAlias(nodes);
final String args = VelocityCommands.readArguments(arguments, String.class, ""); final String args = VelocityCommands.readArguments(arguments, String.class, "");
return new RawCommandInvocation(source, alias, args); return new RawCommandInvocation(source, alias, args);
@ -46,7 +50,7 @@ public final class RawCommandInvocation extends AbstractCommandInvocation<String
private final String alias; private final String alias;
private RawCommandInvocation(final CommandSource source, private RawCommandInvocation(final CommandSource source,
final String alias, final String arguments) { final String alias, final String arguments) {
super(source, arguments); super(source, arguments);
this.alias = Preconditions.checkNotNull(alias, "alias"); this.alias = Preconditions.checkNotNull(alias, "alias");
} }
@ -82,9 +86,9 @@ public final class RawCommandInvocation extends AbstractCommandInvocation<String
@Override @Override
public String toString() { public String toString() {
return "RawCommandInvocation{" return "RawCommandInvocation{"
+ "source='" + this.source() + '\'' + "source='" + this.source() + '\''
+ ", alias='" + this.alias + '\'' + ", alias='" + this.alias + '\''
+ ", arguments='" + this.arguments() + '\'' + ", arguments='" + this.arguments() + '\''
+ '}'; + '}';
} }
} }

Datei anzeigen

@ -28,8 +28,11 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/**
* Implements {@link SimpleCommand.Invocation}.
*/
public final class SimpleCommandInvocation extends AbstractCommandInvocation<String[]> public final class SimpleCommandInvocation extends AbstractCommandInvocation<String[]>
implements SimpleCommand.Invocation { implements SimpleCommand.Invocation {
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
@ -37,11 +40,11 @@ public final class SimpleCommandInvocation extends AbstractCommandInvocation<Str
@Override @Override
public SimpleCommand.Invocation create( public SimpleCommand.Invocation create(
final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes, final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes,
final Map<String, ? extends ParsedArgument<?, ?>> arguments) { final Map<String, ? extends ParsedArgument<?, ?>> arguments) {
final String alias = VelocityCommands.readAlias(nodes); final String alias = VelocityCommands.readAlias(nodes);
final String[] args = VelocityCommands.readArguments( final String[] args = VelocityCommands.readArguments(
arguments, String[].class, StringArrayArgumentType.EMPTY); arguments, String[].class, StringArrayArgumentType.EMPTY);
return new SimpleCommandInvocation(source, alias, args); return new SimpleCommandInvocation(source, alias, args);
} }
} }
@ -49,7 +52,7 @@ public final class SimpleCommandInvocation extends AbstractCommandInvocation<Str
private final String alias; private final String alias;
SimpleCommandInvocation(final CommandSource source, final String alias, SimpleCommandInvocation(final CommandSource source, final String alias,
final String[] arguments) { final String[] arguments) {
super(source, arguments); super(source, arguments);
this.alias = Preconditions.checkNotNull(alias, "alias"); this.alias = Preconditions.checkNotNull(alias, "alias");
} }
@ -85,9 +88,9 @@ public final class SimpleCommandInvocation extends AbstractCommandInvocation<Str
@Override @Override
public String toString() { public String toString() {
return "SimpleCommandInvocation{" return "SimpleCommandInvocation{"
+ "source='" + this.source() + '\'' + "source='" + this.source() + '\''
+ ", alias='" + this.alias + '\'' + ", alias='" + this.alias + '\''
+ ", arguments='" + Arrays.toString(this.arguments()) + '\'' + ", arguments='" + Arrays.toString(this.arguments()) + '\''
+ '}'; + '}';
} }
} }

Datei anzeigen

@ -53,9 +53,9 @@ abstract class AbstractCommandRegistrar<T extends Command> implements CommandReg
} }
protected void register(final LiteralCommandNode<CommandSource> node, protected void register(final LiteralCommandNode<CommandSource> node,
final String secondaryAlias) { final String secondaryAlias) {
final LiteralCommandNode<CommandSource> copy = final LiteralCommandNode<CommandSource> copy =
VelocityCommands.shallowCopy(node, secondaryAlias); VelocityCommands.shallowCopy(node, secondaryAlias);
this.register(copy); this.register(copy);
} }
} }

Datei anzeigen

@ -23,8 +23,8 @@ import com.velocitypowered.api.command.Command;
import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.command.CommandMeta;
/** /**
* Creates and registers the {@link LiteralCommandNode} representations of * Creates and registers the {@link LiteralCommandNode} representations of a given {@link Command}
* a given {@link Command} in a {@link RootCommandNode}. * in a {@link RootCommandNode}.
* *
* @param <T> the type of the command to register * @param <T> the type of the command to register
*/ */
@ -33,16 +33,16 @@ public interface CommandRegistrar<T extends Command> {
/** /**
* Registers the given command. * Registers the given command.
* *
* @param meta the command metadata, including the case-insensitive aliases * @param meta the command metadata, including the case-insensitive aliases
* @param command the command to register * @param command the command to register
* @throws IllegalArgumentException if the given command cannot be registered * @throws IllegalArgumentException if the given command cannot be registered
*/ */
void register(final CommandMeta meta, final T command); void register(final CommandMeta meta, final T command);
/** /**
* Returns the superclass or superinterface of all {@link Command} classes * Returns the superclass or superinterface of all {@link Command} classes compatible with this
* compatible with this registrar. Note that {@link #register(CommandMeta, Command)} * registrar. Note that {@link #register(CommandMeta, Command)} may impose additional restrictions
* may impose additional restrictions on individual {@link Command} instances. * on individual {@link Command} instances.
* *
* @return the superclass of all the classes compatible with this registrar * @return the superclass of all the classes compatible with this registrar
*/ */

Datei anzeigen

@ -42,14 +42,14 @@ import java.util.function.Predicate;
* {@link InvocableCommand} in a root node. * {@link InvocableCommand} in a root node.
*/ */
abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>, abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
I extends CommandInvocation<A>, A> extends AbstractCommandRegistrar<T> { I extends CommandInvocation<A>, A> extends AbstractCommandRegistrar<T> {
private final CommandInvocationFactory<I> invocationFactory; private final CommandInvocationFactory<I> invocationFactory;
private final ArgumentType<A> argumentsType; private final ArgumentType<A> argumentsType;
protected InvocableCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock, protected InvocableCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock,
final CommandInvocationFactory<I> invocationFactory, final CommandInvocationFactory<I> invocationFactory,
final ArgumentType<A> argumentsType) { final ArgumentType<A> argumentsType) {
super(root, lock); super(root, lock);
this.invocationFactory = Preconditions.checkNotNull(invocationFactory, "invocationFactory"); this.invocationFactory = Preconditions.checkNotNull(invocationFactory, "invocationFactory");
this.argumentsType = Preconditions.checkNotNull(argumentsType, "argumentsType"); this.argumentsType = Preconditions.checkNotNull(argumentsType, "argumentsType");
@ -61,7 +61,7 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
final String primaryAlias = aliases.next(); final String primaryAlias = aliases.next();
final LiteralCommandNode<CommandSource> literal = final LiteralCommandNode<CommandSource> literal =
this.createLiteral(command, meta, primaryAlias); this.createLiteral(command, meta, primaryAlias);
this.register(literal); this.register(literal);
while (aliases.hasNext()) { while (aliases.hasNext()) {
@ -71,7 +71,7 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
} }
private LiteralCommandNode<CommandSource> createLiteral(final T command, final CommandMeta meta, private LiteralCommandNode<CommandSource> createLiteral(final T command, final CommandMeta meta,
final String alias) { final String alias) {
final Predicate<CommandContextBuilder<CommandSource>> requirement = context -> { final Predicate<CommandContextBuilder<CommandSource>> requirement = context -> {
final I invocation = invocationFactory.create(context); final I invocation = invocationFactory.create(context);
return command.hasPermission(invocation); return command.hasPermission(invocation);
@ -83,35 +83,35 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
}; };
final LiteralCommandNode<CommandSource> literal = LiteralArgumentBuilder final LiteralCommandNode<CommandSource> literal = LiteralArgumentBuilder
.<CommandSource>literal(alias) .<CommandSource>literal(alias)
.requiresWithContext((context, reader) -> { .requiresWithContext((context, reader) -> {
if (reader.canRead()) { if (reader.canRead()) {
// InvocableCommands do not follow a tree-like permissions checking structure. // InvocableCommands do not follow a tree-like permissions checking structure.
// Thus, a CommandSource may be able to execute a command with arguments while // Thus, a CommandSource may be able to execute a command with arguments while
// not being able to execute the argument-less variant. // not being able to execute the argument-less variant.
// Only check for permissions once parsing is complete. // Only check for permissions once parsing is complete.
return true; return true;
} }
return requirement.test(context); return requirement.test(context);
}) })
.executes(callback) .executes(callback)
.build(); .build();
final ArgumentCommandNode<CommandSource, String> arguments = VelocityArgumentBuilder final ArgumentCommandNode<CommandSource, String> arguments = VelocityArgumentBuilder
.<CommandSource, A>velocityArgument(VelocityCommands.ARGS_NODE_NAME, argumentsType) .<CommandSource, A>velocityArgument(VelocityCommands.ARGS_NODE_NAME, argumentsType)
.requiresWithContext((context, reader) -> requirement.test(context)) .requiresWithContext((context, reader) -> requirement.test(context))
.executes(callback) .executes(callback)
.suggests((context, builder) -> { .suggests((context, builder) -> {
final I invocation = invocationFactory.create(context); final I invocation = invocationFactory.create(context);
return command.suggestAsync(invocation).thenApply(suggestions -> { return command.suggestAsync(invocation).thenApply(suggestions -> {
for (String value : suggestions) { for (String value : suggestions) {
Preconditions.checkNotNull(value, "suggestion"); Preconditions.checkNotNull(value, "suggestion");
builder.suggest(value); builder.suggest(value);
} }
return builder.build(); return builder.build();
}); });
}) })
.build(); .build();
literal.addChild(arguments); literal.addChild(arguments);
// Add hinting nodes // Add hinting nodes

Datei anzeigen

@ -28,7 +28,7 @@ import java.util.concurrent.locks.Lock;
* Registers {@link RawCommand}s in a root node. * Registers {@link RawCommand}s in a root node.
*/ */
public final class RawCommandRegistrar public final class RawCommandRegistrar
extends InvocableCommandRegistrar<RawCommand, RawCommand.Invocation, String> { extends InvocableCommandRegistrar<RawCommand, RawCommand.Invocation, String> {
public RawCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock) { public RawCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock) {
super(root, lock, RawCommandInvocation.FACTORY, StringArgumentType.greedyString()); super(root, lock, RawCommandInvocation.FACTORY, StringArgumentType.greedyString());

Datei anzeigen

@ -28,7 +28,7 @@ import java.util.concurrent.locks.Lock;
* Registers {@link SimpleCommand}s in a root node. * Registers {@link SimpleCommand}s in a root node.
*/ */
public final class SimpleCommandRegistrar public final class SimpleCommandRegistrar
extends InvocableCommandRegistrar<SimpleCommand, SimpleCommand.Invocation, String[]> { extends InvocableCommandRegistrar<SimpleCommand, SimpleCommand.Invocation, String[]> {
public SimpleCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock) { public SimpleCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock) {
super(root, lock, SimpleCommandInvocation.FACTORY, StringArrayArgumentType.INSTANCE); super(root, lock, SimpleCommandInvocation.FACTORY, StringArrayArgumentType.INSTANCE);

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.proxy.config; package com.velocitypowered.proxy.config;
/**
* Supported passthrough modes for ping passthrough.
*/
public enum PingPassthroughMode { public enum PingPassthroughMode {
DISABLED, DISABLED,
MODS, MODS,

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.proxy.config; package com.velocitypowered.proxy.config;
/**
* Supported player info forwarding methods.
*/
public enum PlayerInfoForwarding { public enum PlayerInfoForwarding {
NONE, NONE,
LEGACY, LEGACY,

Datei anzeigen

@ -52,29 +52,45 @@ import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Velocity's configuration.
*/
public class VelocityConfiguration implements ProxyConfig { public class VelocityConfiguration implements ProxyConfig {
private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class); private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class);
@Expose private String bind = "0.0.0.0:25577"; @Expose
@Expose private String motd = "&3A Velocity Server"; private String bind = "0.0.0.0:25577";
@Expose private int showMaxPlayers = 500; @Expose
@Expose private boolean onlineMode = true; private String motd = "&3A Velocity Server";
@Expose private boolean preventClientProxyConnections = false; @Expose
@Expose private PlayerInfoForwarding playerInfoForwardingMode = PlayerInfoForwarding.NONE; private int showMaxPlayers = 500;
@Expose
private boolean onlineMode = true;
@Expose
private boolean preventClientProxyConnections = false;
@Expose
private PlayerInfoForwarding playerInfoForwardingMode = PlayerInfoForwarding.NONE;
private byte[] forwardingSecret = generateRandomString(12).getBytes(StandardCharsets.UTF_8); private byte[] forwardingSecret = generateRandomString(12).getBytes(StandardCharsets.UTF_8);
@Expose private boolean announceForge = false; @Expose
@Expose private boolean onlineModeKickExistingPlayers = false; private boolean announceForge = false;
@Expose private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED; @Expose
private boolean onlineModeKickExistingPlayers = false;
@Expose
private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED;
private final Servers servers; private final Servers servers;
private final ForcedHosts forcedHosts; private final ForcedHosts forcedHosts;
@Expose private final Advanced advanced; @Expose
@Expose private final Query query; private final Advanced advanced;
@Expose
private final Query query;
private final Metrics metrics; private final Metrics metrics;
@Expose private boolean enablePlayerAddressLogging = true; @Expose
private boolean enablePlayerAddressLogging = true;
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent; private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
private @Nullable Favicon favicon; private @Nullable Favicon favicon;
@Expose private boolean forceKeyAuthentication = true; // Added in 1.19 @Expose
private boolean forceKeyAuthentication = true; // Added in 1.19
private VelocityConfiguration(Servers servers, ForcedHosts forcedHosts, Advanced advanced, private VelocityConfiguration(Servers servers, ForcedHosts forcedHosts, Advanced advanced,
Query query, Metrics metrics) { Query query, Metrics metrics) {
@ -112,6 +128,7 @@ public class VelocityConfiguration implements ProxyConfig {
/** /**
* Attempts to validate the configuration. * Attempts to validate the configuration.
*
* @return {@code true} if the configuration is sound, {@code false} if not * @return {@code true} if the configuration is sound, {@code false} if not
*/ */
public boolean validate() { public boolean validate() {
@ -408,6 +425,7 @@ public class VelocityConfiguration implements ProxyConfig {
/** /**
* Reads the Velocity configuration from {@code path}. * Reads the Velocity configuration from {@code path}.
*
* @param path the path to read from * @param path the path to read from
* @return the deserialized Velocity configuration * @return the deserialized Velocity configuration
* @throws IOException if we could not read from the {@code path}. * @throws IOException if we could not read from the {@code path}.
@ -455,23 +473,25 @@ public class VelocityConfiguration implements ProxyConfig {
configVersion = 1.0; configVersion = 1.0;
} }
// Whether or not this config version is older than 2.0 which uses the deprecated "forwarding-secret" parameter // Whether or not this config version is older than 2.0 which uses the deprecated
// "forwarding-secret" parameter
boolean legacyConfig = configVersion < 2.0; boolean legacyConfig = configVersion < 2.0;
String forwardingSecretString; String forwardingSecretString;
byte[] forwardingSecret; byte[] forwardingSecret;
// Handle the previous (version 1.0) config // Handle the previous (version 1.0) config
// There is duplicate/old code here in effort to make the future commit which abandons legacy config handling // There is duplicate/old code here in effort to make the future commit which abandons legacy
// easier to implement. All that would be required is removing the if statement here and keeping the contents // config handling easier to implement. All that would be required is removing the if statement
// of the else block (with slight tidying). // here and keeping the contents of the else block (with slight tidying).
if (legacyConfig) { if (legacyConfig) {
logger.warn("You are currently using a deprecated configuration version. The \"forwarding-secret\"" logger.warn(
+ " parameter has been recognized as a security concern and has been removed in config version 2.0." "You are currently using a deprecated configuration version. The \"forwarding-secret\""
+ " It's recommended you rename your current \"velocity.toml\" to something else to allow Velocity" + " parameter is a security hazard and was removed in config version 2.0."
+ " to generate a config file of the new version. You may then configure that file as you normally would." + " You should rename your current \"velocity.toml\" to something else to allow"
+ " The only differences are the config-version and \"forwarding-secret\" has been replaced" + " Velocity to generate a config file for the new version. You may then configure "
+ " by \"forwarding-secret-file\"."); + " that file as you normally would. The only differences are the config-version "
+ "and \"forwarding-secret\" has been replaced by \"forwarding-secret-file\".");
// Default legacy handling // Default legacy handling
forwardingSecretString = System.getenv() forwardingSecretString = System.getenv()
@ -493,7 +513,8 @@ public class VelocityConfiguration implements ProxyConfig {
if (Files.isRegularFile(secretPath)) { if (Files.isRegularFile(secretPath)) {
forwardingSecretString = String.join("", Files.readAllLines(secretPath)); forwardingSecretString = String.join("", Files.readAllLines(secretPath));
} else { } else {
throw new RuntimeException("The file " + forwardSecretFile + " is not a valid file or it is a directory."); throw new RuntimeException(
"The file " + forwardSecretFile + " is not a valid file or it is a directory.");
} }
} else { } else {
throw new RuntimeException("The forwarding-secret-file does not exist."); throw new RuntimeException("The forwarding-secret-file does not exist.");
@ -505,7 +526,7 @@ public class VelocityConfiguration implements ProxyConfig {
if (configVersion == 1.0 || configVersion == 2.0) { if (configVersion == 1.0 || configVersion == 2.0) {
config.set("force-key-authentication", config.getOrElse("force-key-authentication", true)); config.set("force-key-authentication", config.getOrElse("force-key-authentication", true));
config.setComment("force-key-authentication", config.setComment("force-key-authentication",
"Should the proxy enforce the new public key security standard? By default, this is on."); "Should the proxy enforce the new public key security standard? By default, this is on.");
config.set("config-version", configVersion == 2.0 ? "2.5" : "1.5"); config.set("config-version", configVersion == 2.0 ? "2.5" : "1.5");
mustResave = true; mustResave = true;
} }
@ -632,12 +653,11 @@ public class VelocityConfiguration implements ProxyConfig {
} }
/** /**
* TOML requires keys to match a regex of {@code [A-Za-z0-9_-]} unless it is wrapped in * TOML requires keys to match a regex of {@code [A-Za-z0-9_-]} unless it is wrapped in quotes;
* quotes; however, the TOML parser returns the key with the quotes so we need to clean the * however, the TOML parser returns the key with the quotes so we need to clean the server name
* server name before we pass it onto server registration to keep proper server name behavior. * before we pass it onto server registration to keep proper server name behavior.
* *
* @param name the server name to clean * @param name the server name to clean
*
* @return the cleaned server name * @return the cleaned server name
*/ */
private String cleanServerName(String name) { private String cleanServerName(String name) {
@ -705,19 +725,32 @@ public class VelocityConfiguration implements ProxyConfig {
private static class Advanced { private static class Advanced {
@Expose private int compressionThreshold = 256; @Expose
@Expose private int compressionLevel = -1; private int compressionThreshold = 256;
@Expose private int loginRatelimit = 3000; @Expose
@Expose private int connectionTimeout = 5000; private int compressionLevel = -1;
@Expose private int readTimeout = 30000; @Expose
@Expose private boolean proxyProtocol = false; private int loginRatelimit = 3000;
@Expose private boolean tcpFastOpen = false; @Expose
@Expose private boolean bungeePluginMessageChannel = true; private int connectionTimeout = 5000;
@Expose private boolean showPingRequests = false; @Expose
@Expose private boolean failoverOnUnexpectedServerDisconnect = true; private int readTimeout = 30000;
@Expose private boolean announceProxyCommands = true; @Expose
@Expose private boolean logCommandExecutions = false; private boolean proxyProtocol = false;
@Expose private boolean logPlayerConnections = true; @Expose
private boolean tcpFastOpen = false;
@Expose
private boolean bungeePluginMessageChannel = true;
@Expose
private boolean showPingRequests = false;
@Expose
private boolean failoverOnUnexpectedServerDisconnect = true;
@Expose
private boolean announceProxyCommands = true;
@Expose
private boolean logCommandExecutions = false;
@Expose
private boolean logPlayerConnections = true;
private Advanced() { private Advanced() {
} }
@ -819,10 +852,14 @@ public class VelocityConfiguration implements ProxyConfig {
private static class Query { private static class Query {
@Expose private boolean queryEnabled = false; @Expose
@Expose private int queryPort = 25577; private boolean queryEnabled = false;
@Expose private String queryMap = "Velocity"; @Expose
@Expose private boolean showPlugins = false; private int queryPort = 25577;
@Expose
private String queryMap = "Velocity";
@Expose
private boolean showPlugins = false;
private Query() { private Query() {
} }
@ -870,7 +907,11 @@ public class VelocityConfiguration implements ProxyConfig {
} }
} }
/**
* Configuration for metrics.
*/
public static class Metrics { public static class Metrics {
private boolean enabled = true; private boolean enabled = true;
private Metrics(CommentedConfig toml) { private Metrics(CommentedConfig toml) {

Datei anzeigen

@ -42,13 +42,13 @@ public interface ConnectionType {
BackendConnectionPhase getInitialBackendPhase(); BackendConnectionPhase getInitialBackendPhase();
/** /**
* Adds properties to the {@link GameProfile} if required. If any properties * Adds properties to the {@link GameProfile} if required. If any properties are added, the
* are added, the returned {@link GameProfile} will be a copy. * returned {@link GameProfile} will be a copy.
* *
* @param original The original {@link GameProfile} * @param original The original {@link GameProfile}
* @param forwardingType The Velocity {@link PlayerInfoForwarding} * @param forwardingType The Velocity {@link PlayerInfoForwarding}
* @return The {@link GameProfile} with the properties added in. * @return The {@link GameProfile} with the properties added in.
*/ */
GameProfile addGameProfileTokensIfRequired(GameProfile original, GameProfile addGameProfileTokensIfRequired(GameProfile original,
PlayerInfoForwarding forwardingType); PlayerInfoForwarding forwardingType);
} }

Datei anzeigen

@ -29,9 +29,8 @@ import com.velocitypowered.proxy.connection.util.ConnectionTypeImpl;
public final class ConnectionTypes { public final class ConnectionTypes {
/** /**
* Indicates that the connection has yet to reach the * Indicates that the connection has yet to reach the point where we have a definitive answer as
* point where we have a definitive answer as to what * to what type of connection we have.
* type of connection we have.
*/ */
public static final ConnectionType UNDETERMINED = public static final ConnectionType UNDETERMINED =
new ConnectionTypeImpl(ClientConnectionPhases.VANILLA, BackendConnectionPhases.UNKNOWN); new ConnectionTypeImpl(ClientConnectionPhases.VANILLA, BackendConnectionPhases.UNKNOWN);
@ -46,8 +45,7 @@ public final class ConnectionTypes {
LegacyForgeHandshakeClientPhase.NOT_STARTED, BackendConnectionPhases.UNKNOWN); LegacyForgeHandshakeClientPhase.NOT_STARTED, BackendConnectionPhases.UNKNOWN);
/** /**
* Indicates that the connection is a 1.8-1.12 Forge * Indicates that the connection is a 1.8-1.12 Forge connection.
* connection.
*/ */
public static final ConnectionType LEGACY_FORGE = new LegacyForgeConnectionType(); public static final ConnectionType LEGACY_FORGE = new LegacyForgeConnectionType();

Datei anzeigen

@ -87,8 +87,9 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Initializes a new {@link MinecraftConnection} instance. * Initializes a new {@link MinecraftConnection} instance.
*
* @param channel the channel on the connection * @param channel the channel on the connection
* @param server the Velocity instance * @param server the Velocity instance
*/ */
public MinecraftConnection(Channel channel, VelocityServer server) { public MinecraftConnection(Channel channel, VelocityServer server) {
this.channel = channel; this.channel = channel;
@ -211,6 +212,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Writes and immediately flushes a message to the connection. * Writes and immediately flushes a message to the connection.
*
* @param msg the message to write * @param msg the message to write
*/ */
public void write(Object msg) { public void write(Object msg) {
@ -223,6 +225,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Writes, but does not flush, a message to the connection. * Writes, but does not flush, a message to the connection.
*
* @param msg the message to write * @param msg the message to write
*/ */
public void delayedWrite(Object msg) { public void delayedWrite(Object msg) {
@ -244,6 +247,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Closes the connection after writing the {@code msg}. * Closes the connection after writing the {@code msg}.
*
* @param msg the message to write * @param msg the message to write
*/ */
public void closeWith(Object msg) { public void closeWith(Object msg) {
@ -273,6 +277,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Immediately closes the connection. * Immediately closes the connection.
*
* @param markKnown whether the disconnection is known * @param markKnown whether the disconnection is known
*/ */
public void close(boolean markKnown) { public void close(boolean markKnown) {
@ -319,6 +324,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Determines whether or not the channel should continue reading data automaticaly. * Determines whether or not the channel should continue reading data automaticaly.
*
* @param autoReading whether or not we should read data automatically * @param autoReading whether or not we should read data automatically
*/ */
public void setAutoReading(boolean autoReading) { public void setAutoReading(boolean autoReading) {
@ -337,6 +343,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Changes the state of the Minecraft connection. * Changes the state of the Minecraft connection.
*
* @param state the new state * @param state the new state
*/ */
public void setState(StateRegistry state) { public void setState(StateRegistry state) {
@ -353,6 +360,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Sets the new protocol version for the connection. * Sets the new protocol version for the connection.
*
* @param protocolVersion the protocol version to use * @param protocolVersion the protocol version to use
*/ */
public void setProtocolVersion(ProtocolVersion protocolVersion) { public void setProtocolVersion(ProtocolVersion protocolVersion) {
@ -380,6 +388,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Sets the session handler for this connection. * Sets the session handler for this connection.
*
* @param sessionHandler the handler to use * @param sessionHandler the handler to use
*/ */
public void setSessionHandler(MinecraftSessionHandler sessionHandler) { public void setSessionHandler(MinecraftSessionHandler sessionHandler) {
@ -399,6 +408,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Sets the compression threshold on the connection. You are responsible for sending * Sets the compression threshold on the connection. You are responsible for sending
* {@link com.velocitypowered.proxy.protocol.packet.SetCompression} beforehand. * {@link com.velocitypowered.proxy.protocol.packet.SetCompression} beforehand.
*
* @param threshold the compression threshold to use * @param threshold the compression threshold to use
*/ */
public void setCompressionThreshold(int threshold) { public void setCompressionThreshold(int threshold) {
@ -440,6 +450,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Enables encryption on the connection. * Enables encryption on the connection.
*
* @param secret the secret key negotiated between the client and the server * @param secret the secret key negotiated between the client and the server
* @throws GeneralSecurityException if encryption can't be enabled * @throws GeneralSecurityException if encryption can't be enabled
*/ */
@ -471,6 +482,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Gets the detected {@link ConnectionType}. * Gets the detected {@link ConnectionType}.
*
* @return The {@link ConnectionType} * @return The {@link ConnectionType}
*/ */
public ConnectionType getType() { public ConnectionType getType() {
@ -479,6 +491,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/** /**
* Sets the detected {@link ConnectionType}. * Sets the detected {@link ConnectionType}.
*
* @param connectionType The {@link ConnectionType} * @param connectionType The {@link ConnectionType}
*/ */
public void setType(ConnectionType connectionType) { public void setType(ConnectionType connectionType) {

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.proxy.connection; package com.velocitypowered.proxy.connection;
/**
* Marker interface for something that can be associated with a {@link MinecraftConnection}.
*/
public interface MinecraftConnectionAssociation { public interface MinecraftConnectionAssociation {
} }

Datei anzeigen

@ -63,6 +63,9 @@ import com.velocitypowered.proxy.protocol.packet.title.TitleTextPacket;
import com.velocitypowered.proxy.protocol.packet.title.TitleTimesPacket; import com.velocitypowered.proxy.protocol.packet.title.TitleTimesPacket;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/**
* Interface for dispatching received Minecraft packets.
*/
public interface MinecraftSessionHandler { public interface MinecraftSessionHandler {
default boolean beforeHandle() { default boolean beforeHandle() {

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.proxy.connection; package com.velocitypowered.proxy.connection;
/**
* Various useful constants.
*/
public class VelocityConstants { public class VelocityConstants {
private VelocityConstants() { private VelocityConstants() {

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen