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.StandardLocation;
/**
* Annotation processor for Velocity.
*/
@SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"})
public class PluginAnnotationProcessor extends AbstractProcessor {

Datei anzeigen

@ -19,6 +19,9 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Serialized version of {@link com.velocitypowered.api.plugin.PluginDescription}.
*/
public final class SerializedPluginDescription {
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 {
private final String id;

Datei anzeigen

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

Datei anzeigen

@ -29,6 +29,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/**
* Constructs a CommandExecuteEvent.
*
* @param commandSource the source executing the command
* @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
*/
public String getCommand() {
@ -108,6 +110,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/**
* Allows the command to be sent, without modification.
*
* @return the allowed result
*/
public static CommandResult allowed() {
@ -116,6 +119,7 @@ public final class CommandExecuteEvent implements ResultedEvent<CommandResult> {
/**
* Prevents the command from being executed.
*
* @return the denied result
*/
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
*/
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.
*
* @param newCommand the command without first slash to use instead
* @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
* @return a result with a new command
*/

Datei anzeigen

@ -29,6 +29,7 @@ public class PlayerAvailableCommandsEvent {
/**
* Constructs an available commands event.
*
* @param player the targeted player
* @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 {
SUCCESSFUL_LOGIN,

Datei anzeigen

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

Datei anzeigen

@ -35,6 +35,7 @@ public final class GameProfileRequestEvent {
/**
* Creates a new instance.
*
* @param connection the connection connecting to the proxy
* @param originalProfile the original {@link GameProfile} for the user
* @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.
*
* @param player the player affected
* @param server the server the player disconnected from
* @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.
*
* @param player the player sending the message
* @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.
*
* @return the allowed result
*/
public static ChatResult allowed() {
@ -104,6 +106,7 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
/**
* Prevents the message from being sent.
*
* @return the denied result
*/
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
* @return a result with a new message
*/

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -33,6 +33,7 @@ public final class ServerConnectedEvent {
/**
* Constructs a ServerConnectedEvent.
*
* @param player the player that was connected
* @param server the server the player was connected to
* @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}.
*
* @param connection the connection on which the plugin message was sent
* @param identifier the channel identifier for the message sent
* @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 {
private static final ResponseResult UNKNOWN = new ResponseResult(null);

Datei anzeigen

@ -33,6 +33,7 @@ public final class ServerPreConnectEvent implements
/**
* Creates the ServerPreConnectEvent.
*
* @param player the player who is connecting to a server
* @param originalServer the server the player was trying to connect to
*/
@ -43,6 +44,7 @@ public final class ServerPreConnectEvent implements
/**
* Creates the ServerPreConnectEvent.
*
* @param player the player who is connecting to a server
* @param originalServer the server the player was trying to connect 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.
*
* @return the player connecting to the server
*/
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
* 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()}.
*
* @return the server that the player originally tried to connect to
*/
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
* 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).
*
* @return the server the player is currently connected to.
*/
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
* is used, then {@link ConnectionRequestBuilder#connect()}'s result will have the status
* {@link Status#CONNECTION_CANCELLED}.
*
* @return a result to deny conneections
*/
public static ServerResult denied() {
@ -145,6 +151,7 @@ public final class ServerPreConnectEvent implements
/**
* Allows the player to connect to the specified server.
*
* @param server the new server to connect to
* @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.
*
*
* @param receivedResourcePack The resource pack the server sent.
* @param serverConnection The connection this occurred on.
*/

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -27,6 +27,7 @@ public final class PluginDependency {
/**
* Creates a new instance.
*
* @param id the plugin ID
* @param version an optional version
* @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;
/**
* Allows the server to communicate with a client logging into the proxy using login plugin
* messages.
* Represents a connextion that is in the login phase. This is most useful in conjunction
* for login plugin messages.
*/
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,
MessageConsumer consumer);
/**
* Consumes the message.
*/
interface MessageConsumer {
/**
* Consumes the message and responds to it.
*
* @param responseBody the message from the client, if any
*/
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.HoverEventSource;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull;
/**
* Represents a player who is connected to the proxy.
*/
public interface Player extends CommandSource, Identified, InboundConnection,
ChannelMessageSource, ChannelMessageSink, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable {
public interface Player extends
/* Fundamental Velocity interfaces */
CommandSource, InboundConnection, ChannelMessageSource, ChannelMessageSink,
/* Adventure-specific interfaces */
Identified, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable {
/**
* Returns the player's current username.
@ -48,8 +52,8 @@ public interface Player extends CommandSource, Identified, InboundConnection,
String getUsername();
/**
* Returns the locale the proxy will use to send messages translated via the Adventure global translator.
* By default, the value of {@link PlayerSettings#getLocale()} is used.
* Returns the locale the proxy will use to send messages translated via the Adventure global
* 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>
*

Datei anzeigen

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

Datei anzeigen

@ -7,15 +7,18 @@
package com.velocitypowered.api.proxy.crypto;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Identifies a type with a public RSA signature.
*/
public interface KeyIdentifiable {
/**
* Returns the timed identified key of the object context.
* <p>Only available in 1.19 and newer</p>
* Returns the timed identified key of the object context. This is only available if the client
* is running Minecraft 1.19 or newer.
*
* @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 org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the signature of a signed object.
*/
public interface KeySigned {
/**

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -121,7 +121,7 @@ public interface TabListEntry extends KeyIdentifiable {
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
*/
@ -193,7 +193,7 @@ public interface TabListEntry extends KeyIdentifiable {
/**
* 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>Will ignore mismatching key revisions data.</p>
*

Datei anzeigen

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

Datei anzeigen

@ -191,6 +191,7 @@ public final class ServerPing {
/**
* Uses the modified {@code mods} list in the response.
*
* @param mods the mods list to use
* @return this build, for chaining
*/
@ -240,6 +241,7 @@ public final class ServerPing {
/**
* 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.
*
* @return a new {@link ServerPing} instance
*/
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 {
private final int protocol;
@ -310,6 +318,7 @@ public final class ServerPing {
/**
* Creates a new instance.
*
* @param protocol the protocol version as an integer
* @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 {
private final int online;
@ -360,6 +373,7 @@ public final class ServerPing {
/**
* Creates a new instance.
*
* @param online the number of online players
* @param max the maximum number of players
* @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 {
private final String name;

Datei anzeigen

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

Datei anzeigen

@ -24,6 +24,7 @@ public final class GameProfile {
/**
* Creates a new Mojang game profile.
*
* @param id the UUID for the profile
* @param name the profile's username
* @param properties properties for the profile
@ -35,6 +36,7 @@ public final class GameProfile {
/**
* Creates a new Mojang game profile.
*
* @param undashedId the undashed, Mojang-style UUID for the profile
* @param name the profile's username
* @param properties properties for the profile
@ -53,6 +55,7 @@ public final class GameProfile {
/**
* Returns the undashed, Mojang-style UUID.
*
* @return the undashed UUID
*/
public String getUndashedId() {
@ -61,6 +64,7 @@ public final class GameProfile {
/**
* Returns the UUID associated with this game profile.
*
* @return the UUID
*/
public UUID getId() {
@ -69,6 +73,7 @@ public final class GameProfile {
/**
* Returns the username associated with this profile.
*
* @return the username
*/
public String getName() {
@ -77,6 +82,7 @@ public final class GameProfile {
/**
* Returns an immutable list of profile properties associated with this profile.
*
* @return the properties associated with this profile
*/
public List<Property> getProperties() {
@ -183,6 +189,7 @@ public final class GameProfile {
/**
* Creates a profile property entry.
*
* @param name the name of the property
* @param value the value of 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.Objects;
/**
* Represents the information for a Forge mod list.
*/
public final class ModInfo {
public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of());
@ -20,6 +23,12 @@ public final class ModInfo {
private final String type;
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) {
this.type = Preconditions.checkNotNull(type, "type");
this.modList = ImmutableList.copyOf(modList);
@ -58,6 +67,9 @@ public final class ModInfo {
return Objects.hash(type, modList);
}
/**
* Represents a mod to send to the client.
*/
public static final class Mod {
@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"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
@ -16,10 +16,9 @@
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<!--
Developer notes: Fix MissingJavadocMethod/Type RequireEmptyLineBeforeBlockTagGroup and CustomImportOrder
-->
<module name = "Checker">
<module name="Checker">
<module name="SuppressWarningsFilter"/>
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
@ -33,7 +32,7 @@
<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter">
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
default="checkstyle-suppressions.xml" />
default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/>
</module>
@ -45,7 +44,7 @@
<module name="LineLength">
<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://"/>
</module>
@ -54,9 +53,9 @@
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<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"
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 name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
@ -71,15 +70,15 @@
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<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 name="NeedBraces">
<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 name="LeftCurly">
<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,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
@ -88,14 +87,14 @@
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<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"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<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,
COMPACT_CTOR_DEF"/>
</module>
@ -105,13 +104,7 @@
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
or preceding-sibling::*[last()][self::LCURLY]]"/>
</module>
<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="WhitespaceAfter" />
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyLambdas" value="true"/>
@ -120,7 +113,7 @@
<property name="allowEmptyLoops" value="true"/>
<property name="ignoreEnhancedForColon" value="false"/>
<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,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
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,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<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)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
@ -142,7 +135,7 @@
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<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,
COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
@ -177,79 +170,79 @@
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LambdaParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
@ -261,9 +254,9 @@
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
<property name="allowedAbbreviationLength" value="0"/>
<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,
RECORD_COMPONENT_DEF"/>
</module>
@ -278,18 +271,18 @@
</module>
<module name="MethodParamPad">
<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"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad">
<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,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
@ -298,14 +291,14 @@
<module name="OperatorWrap">
<property name="option" value="NL"/>
<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,
TYPE_EXTENSION_AND "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<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"/>
</module>
<module name="AnnotationLocation">
@ -318,15 +311,14 @@
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<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 name="JavadocParagraph"/>
<!-- <module name="RequireEmptyLineBeforeBlockTagGroup"/>
-->
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<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 name="JavadocMethod">
<property name="accessModifiers" value="public"/>
@ -335,7 +327,7 @@
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<!-- <module name="MissingJavadocMethod">
<module name="MissingJavadocMethod">
<property name="scope" value="public"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
@ -345,15 +337,14 @@
<module name="MissingJavadocType">
<property name="scope" value="protected"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
RECORD_DEF, ANNOTATION_DEF"/>
<property name="excludeScope" value="nothing"/>
</module>
-->
<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"
value="Method name ''{0}'' must match pattern ''{1}''."/>
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc"/>
<module name="EmptyCatchBlock">
@ -365,8 +356,21 @@
<!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
<module name="SuppressionXpathFilter">
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" />
default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/>
</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>

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;
/**
* Generic interface for any Velocity native.
*/
public interface Native {
BufferPreference preferredBufferType();
}

Datei anzeigen

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

Datei anzeigen

@ -28,6 +28,7 @@ class CompressorUtils {
/**
* Ensures that the buffer does not go over {@code max}.
*
* @param buf the buffer for check
* @param max the maximum size for the buffer
* @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.Inflater;
/**
* Implements deflate compression by wrapping {@link Deflater} and {@link Inflater}.
*/
public class JavaVelocityCompressor implements VelocityCompressor {
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 java.util.zip.DataFormatException;
/**
* Implements deflate compression using the {@code libdeflate} native C library.
*/
public class LibdeflateVelocityCompressor implements VelocityCompressor {
public static final VelocityCompressorFactory FACTORY = LibdeflateVelocityCompressor::new;

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.natives.util;
/**
* Emumerates Netty buffer preferences and requirements for use with Netty.
*/
public enum BufferPreference {
/**
* 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.ByteBufAllocator;
/**
* Additional utilities for {@link ByteBuf}.
*/
public class MoreByteBufUtils {
private MoreByteBufUtils() {
throw new AssertionError();

Datei anzeigen

@ -22,6 +22,11 @@ import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
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> {
private final Variant<T> selected;

Datei anzeigen

@ -21,6 +21,9 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.function.BooleanSupplier;
/**
* Statically-computed constraints for native code.
*/
public class NativeConstraints {
private static final boolean NATIVES_ENABLED = !Boolean.getBoolean("velocity.natives-disabled");
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.StandardCopyOption;
/**
* Enumerates all supported natives for Velocity.
*/
public class 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.json.JsonObjectBuilder;
/**
* Initializes bStats.
*/
public class Metrics {
private MetricsBase metricsBase;

Datei anzeigen

@ -26,7 +26,11 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Holds parsed command line options.
*/
public final class ProxyOptions {
private static final Logger logger = LogManager.getLogger(ProxyOptions.class);
private final boolean help;
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")
.forHelp();
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);
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.Logger;
/**
* The main class. Responsible for parsing command line arguments and then launching the
* proxy.
*/
public class Velocity {
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.
*
* @param args the arguments to the proxy
*/
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.util.AddressUtil;
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.bossbar.AdventureBossBarManager;
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.Nullable;
/**
* Implementation of {@link ProxyServer}.
*/
public class VelocityServer implements ProxyServer, ForwardingAudience {
private static final Logger logger = LogManager.getLogger(VelocityServer.class);
@ -250,7 +253,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
.create(Key.key("velocity", "translations"));
translationRegistry.defaultLocale(Locale.US);
try {
FileSystemUtils.visitResources(VelocityServer.class, path -> {
ResourceUtils.visitResources(VelocityServer.class, path -> {
logger.info("Loading localizations...");
final Path langPath = Path.of("lang");
@ -275,7 +278,6 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
});
}
Files.walk(langPath).forEach(file -> {
if (!Files.isRegularFile(file)) {
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 reason message to kick online players with
* @param reason message to kick online players with
*/
public void shutdown(boolean explicitExit, Component reason) {
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
CompletableFuture<Void> playersTeardownFuture = CompletableFuture.allOf(players.stream()
.map(ConnectedPlayer::getTeardownFuture)
.toArray((IntFunction<CompletableFuture<Void>[]>) CompletableFuture[]::new));
.map(ConnectedPlayer::getTeardownFuture)
.toArray((IntFunction<CompletableFuture<Void>[]>) CompletableFuture[]::new));
playersTeardownFuture.get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) {
@ -580,6 +582,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
/**
* Checks if the {@code connection} can be registered with the proxy.
*
* @param connection the connection to check
* @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)
|| connectionsByUuid.containsKey(connection.getUniqueId()));
}
/**
* Attempts to register the {@code connection} with the proxy.
*
* @param connection the connection to register
* @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()
.regionMatches(true, 0, partialName, 0, partialName.length()))
.collect(Collectors.toList());
.collect(Collectors.toList());
}
@Override
@ -659,7 +663,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
return getAllServers().stream().filter(s -> s.getServerInfo().getName()
.regionMatches(true, 0, partialName, 0, partialName.length()))
.collect(Collectors.toList());
.collect(Collectors.toList());
}
@Override

Datei anzeigen

@ -32,9 +32,8 @@ import org.checkerframework.checker.lock.qual.GuardedBy;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Copies the nodes of a {@link RootCommandNode} to a possibly non-empty
* destination {@link RootCommandNode}, respecting the requirements satisfied
* by a given command source.
* Copies the nodes of a {@link RootCommandNode} to a possibly non-empty destination
* {@link RootCommandNode}, respecting the requirements satisfied by a given command source.
*
* @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.
/**
* Adds the node from the root node of this injector to the given root node,
* respecting the requirements satisfied by the given source.
* Adds the node from the root node of this injector to the given root node, respecting the
* requirements satisfied by the given source.
*
* <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.
*
* @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
*/
public void inject(final RootCommandNode<S> dest, final S source) {
@ -69,7 +68,7 @@ public final class CommandGraphInjector<S> {
try {
final RootCommandNode<S> origin = this.dispatcher.getRoot();
final CommandContextBuilder<S> rootContext =
new CommandContextBuilder<>(this.dispatcher, source, origin, 0);
new CommandContextBuilder<>(this.dispatcher, source, origin, 0);
// Filter alias nodes
for (final CommandNode<S> node : origin.getChildren()) {
@ -78,7 +77,7 @@ public final class CommandGraphInjector<S> {
}
final CommandContextBuilder<S> context = rootContext.copy()
.withNode(node, ALIAS_RANGE);
.withNode(node, ALIAS_RANGE);
if (!node.canUse(context, ALIAS_READER)) {
continue;
}
@ -86,7 +85,7 @@ public final class CommandGraphInjector<S> {
final LiteralCommandNode<S> asLiteral = (LiteralCommandNode<S>) node;
final LiteralCommandNode<S> copy = asLiteral.createBuilder().build();
final VelocityArgumentCommandNode<S, ?> argsNode =
VelocityCommands.getArgumentsNode(asLiteral);
VelocityCommands.getArgumentsNode(asLiteral);
if (argsNode == null) {
// This literal is associated to a BrigadierCommand, filter normally.
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,
final S source) {
final S source) {
for (final CommandNode<S> child : parent.getChildren()) {
final CommandNode<S> filtered = this.filterNode(child, source);
if (filtered != null) {

Datei anzeigen

@ -50,8 +50,8 @@ import org.checkerframework.checker.lock.qual.GuardedBy;
* Provides suggestions for a given command input.
*
* <p>Similar to {@link CommandDispatcher#getCompletionSuggestions(ParseResults)}, except it
* avoids fully parsing the given input and performs exactly one requirement predicate check
* per considered node.
* avoids fully parsing the given input and performs exactly one requirement predicate check per
* considered node.
*
* @param <S> the type of the command source
*/
@ -74,31 +74,31 @@ final class SuggestionsProvider<S> {
/**
* 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
* @return a future that completes with the suggestions
*/
public CompletableFuture<Suggestions> provideSuggestions(final String input, final S source) {
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);
}
/**
* Provides suggestions for the given input and context.
*
* @param reader the input reader
* @param reader the input reader
* @param context an empty context
* @return a future that completes with the suggestions
*/
private CompletableFuture<Suggestions> provideSuggestions(
final StringReader reader, final CommandContextBuilder<S> context) {
final StringReader reader, final CommandContextBuilder<S> context) {
lock.lock();
try {
final StringRange aliasRange = this.consumeAlias(reader);
final String alias = aliasRange.get(reader).toLowerCase(Locale.ENGLISH);
final LiteralCommandNode<S> literal =
(LiteralCommandNode<S>) context.getRootNode().getChild(alias);
(LiteralCommandNode<S>) context.getRootNode().getChild(alias);
final boolean hasArguments = reader.canRead();
if (hasArguments) {
@ -119,9 +119,9 @@ final class SuggestionsProvider<S> {
private StringRange consumeAlias(final StringReader reader) {
final int firstSep = reader.getString().indexOf(
CommandDispatcher.ARGUMENT_SEPARATOR_CHAR, reader.getCursor());
CommandDispatcher.ARGUMENT_SEPARATOR_CHAR, reader.getCursor());
final StringRange range = StringRange.between(
reader.getCursor(), firstSep == -1 ? reader.getTotalLength() : firstSep);
reader.getCursor(), firstSep == -1 ? reader.getTotalLength() : firstSep);
reader.setCursor(range.getEnd());
return range;
}
@ -130,7 +130,7 @@ final class SuggestionsProvider<S> {
* Returns whether a literal node with the given lowercase name should be considered for
* suggestions given the specified input.
*
* @param name the lowercase literal name
* @param name the lowercase literal name
* @param input the partial input
* @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.
*
* @param reader the input reader
* @param reader the input reader
* @param contextSoFar an empty context
* @return a future that completes with the suggestions
*/
private CompletableFuture<Suggestions> provideAliasSuggestions(
final StringReader reader, final CommandContextBuilder<S> contextSoFar) {
final StringReader reader, final CommandContextBuilder<S> contextSoFar) {
final S source = contextSoFar.getSource();
// Lowercase the alias here so all comparisons can be case-sensitive (cheaper)
// 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)) {
final CommandContextBuilder<S> context = contextSoFar.copy()
.withNode(node, ALIAS_SUGGESTION_RANGE);
.withNode(node, ALIAS_SUGGESTION_RANGE);
if (node.canUse(context, reader)) {
// LiteralCommandNode#listSuggestions is case insensitive
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
* alias node and the hints given during registration for the given input.
* Merges the suggestions provided by the {@link Command} associated to the given alias node and
* 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.
*
* @param alias the alias node
* @param reader the input reader
* @param alias the alias node
* @param reader the input reader
* @param contextSoFar the context, containing {@code alias}
* @return a future that completes with the suggestions
*/
private CompletableFuture<Suggestions> provideArgumentsSuggestions(
final LiteralCommandNode<S> alias, final StringReader reader,
final CommandContextBuilder<S> contextSoFar) {
final LiteralCommandNode<S> alias, final StringReader reader,
final CommandContextBuilder<S> contextSoFar) {
final S source = contextSoFar.getSource();
final String fullInput = reader.getString();
final VelocityArgumentCommandNode<S, ?> argsNode = VelocityCommands.getArgumentsNode(alias);
@ -227,7 +227,7 @@ final class SuggestionsProvider<S> {
// Ask the command for suggestions via the arguments node
reader.setCursor(start);
final CompletableFuture<Suggestions> cmdSuggestions =
this.getArgumentsNodeSuggestions(argsNode, reader, context);
this.getArgumentsNodeSuggestions(argsNode, reader, context);
final boolean hasHints = alias.getChildren().size() > 1;
if (!hasHints) {
return this.merge(fullInput, cmdSuggestions);
@ -236,24 +236,24 @@ final class SuggestionsProvider<S> {
// Parse the hint nodes to get remaining suggestions
reader.setCursor(start);
final CompletableFuture<Suggestions> hintSuggestions =
this.getHintSuggestions(alias, reader, contextSoFar);
this.getHintSuggestions(alias, reader, contextSoFar);
return this.merge(fullInput, cmdSuggestions, hintSuggestions);
}
/**
* Returns the suggestions provided by the {@link Command} associated to
* the specified arguments node for the given input.
* Returns the suggestions provided by the {@link Command} associated to the specified arguments
* node for the given input.
*
* <p>The reader and context are not mutated by this method.
*
* @param node the arguments node of the command
* @param reader the input reader
* @param node the arguments node of the command
* @param reader the input reader
* @param context the context, containing an alias node and {@code node}
* @return a future that completes with the suggestions
*/
private CompletableFuture<Suggestions> getArgumentsNodeSuggestions(
final VelocityArgumentCommandNode<S, ?> node, final StringReader reader,
final CommandContextBuilder<S> context) {
final VelocityArgumentCommandNode<S, ?> node, final StringReader reader,
final CommandContextBuilder<S> context) {
final int start = reader.getCursor();
final String fullInput = reader.getString();
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.
*
* @param alias the alias node
* @param reader the input reader
* @param alias the alias node
* @param reader the input reader
* @param context the context, containing {@code alias}
* @return a future that completes with the suggestions
*/
private CompletableFuture<Suggestions> getHintSuggestions(
final LiteralCommandNode<S> alias, final StringReader reader,
final CommandContextBuilder<S> context) {
final LiteralCommandNode<S> alias, final StringReader reader,
final CommandContextBuilder<S> context) {
final ParseResults<S> parse = this.parseHints(alias, reader, context);
try {
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
* a {@link Command} or another hint node.
* Parses the hint nodes under the given node, which is either an alias node of a {@link Command}
* or another hint node.
*
* <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 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
* @see VelocityCommandMeta#copyHints(CommandMeta) for the conditions under which the returned
* hints can be suggested to a {@link CommandSource}.
*/
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
// check the requirements are satisfied and ignores redirects, neither of which
// 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}
* the given futures complete with. The results of the futures that complete exceptionally
* are ignored.
* Returns a future that is completed with the result of merging the {@link Suggestions} the given
* futures complete with. The results of the futures that complete exceptionally are ignored.
*
* @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
*/
@SafeVarargs
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
return CompletableFuture.allOf(futures).handle((unused, throwable) -> {
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.jetbrains.annotations.VisibleForTesting;
/**
* Impelements Velocity's command handler.
*/
public class VelocityCommandManager implements CommandManager {
private final @GuardedBy("lock") CommandDispatcher<CommandSource> dispatcher;
@ -76,9 +79,9 @@ public class VelocityCommandManager implements CommandManager {
this.eventManager = Preconditions.checkNotNull(eventManager);
final RootCommandNode<CommandSource> root = this.dispatcher.getRoot();
this.registrars = ImmutableList.of(
new BrigadierCommandRegistrar(root, this.lock.writeLock()),
new SimpleCommandRegistrar(root, this.lock.writeLock()),
new RawCommandRegistrar(root, this.lock.writeLock()));
new BrigadierCommandRegistrar(root, this.lock.writeLock()),
new SimpleCommandRegistrar(root, this.lock.writeLock()),
new RawCommandRegistrar(root, this.lock.writeLock()));
this.suggestionsProvider = new SuggestionsProvider<>(this.dispatcher, this.lock.readLock());
this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock());
this.commandMetas = new ConcurrentHashMap<>();
@ -118,24 +121,24 @@ public class VelocityCommandManager implements CommandManager {
}
}
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
* {@linkplain CommandRegistrar#registrableSuperInterface() registrable superinterface}
* of the given registrar.
* {@linkplain CommandRegistrar#registrableSuperInterface() registrable superinterface} of the
* given registrar.
*
* @param registrar the registrar to register the command
* @param command the command to register
* @param meta the command metadata
* @param <T> the type of the command
* @return true if the command implements the registrable superinterface of the registrar;
* false otherwise.
* @param command the command to register
* @param meta the command metadata
* @param <T> the type of the command
* @return true if the command implements the registrable superinterface of the registrar; false
* otherwise.
* @throws IllegalArgumentException if the registrar cannot register the command
*/
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();
if (!superInterface.isInstance(command)) {
return false;
@ -188,7 +191,7 @@ public class VelocityCommandManager implements CommandManager {
/**
* 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
* @return the {@link CompletableFuture} of the event
*/
@ -251,10 +254,9 @@ public class VelocityCommandManager implements CommandManager {
/**
* 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
* @return a {@link CompletableFuture} eventually completed with a {@link List},
* possibly empty
* @return a {@link CompletableFuture} eventually completed with a {@link List}, possibly empty
*/
public CompletableFuture<List<String>> offerSuggestions(final CommandSource source,
final String cmdLine) {
@ -265,10 +267,10 @@ public class VelocityCommandManager implements CommandManager {
/**
* 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
* @return a {@link CompletableFuture} eventually completed with {@link Suggestions},
* possibly empty
* @return a {@link CompletableFuture} eventually completed with {@link Suggestions}, possibly
* empty
*/
public CompletableFuture<Suggestions> offerBrigadierSuggestions(
final CommandSource source, final String cmdLine) {
@ -281,14 +283,15 @@ public class VelocityCommandManager implements CommandManager {
} catch (final Throwable e) {
// Again, plugins are naughty
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.
*
* @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
* @return the parse results
*/
@ -307,8 +310,8 @@ public class VelocityCommandManager implements CommandManager {
try {
// A RootCommandNode may only contain LiteralCommandNode children instances
return dispatcher.getRoot().getChildren().stream()
.map(CommandNode::getName)
.collect(ImmutableList.toImmutableList());
.map(CommandNode::getName)
.collect(ImmutableList.toImmutableList());
} finally {
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.Nullable;
/**
* Handles building commands for plugins to register.
*/
public final class VelocityCommandMeta implements CommandMeta {
static final class Builder implements CommandMeta.Builder {
@ -44,7 +47,7 @@ public final class VelocityCommandMeta implements CommandMeta {
public Builder(final String alias) {
Preconditions.checkNotNull(alias, "alias");
this.aliases = ImmutableSet.<String>builder()
.add(alias.toLowerCase(Locale.ENGLISH));
.add(alias.toLowerCase(Locale.ENGLISH));
this.hints = ImmutableList.builder();
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
* sent to 1.13+ clients and the proxy uses them for providing suggestions.
* Creates a node to use for hinting the arguments of a {@link Command}. Hint nodes are sent to
* 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
* the corresponding {@link CommandNode} are satisfied. The requirement predicate
* of the returned node always returns {@code false}.
* the corresponding {@link CommandNode} are satisfied. The requirement predicate of the returned
* node always returns {@code false}.
*
* @param hint the node containing hinting metadata
* @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
// from modifying the nodes and adding a Command or a redirect.
final ArgumentBuilder<CommandSource, ?> builder = hint.createBuilder()
// Requirement checking is performed by SuggestionProvider
.requires(source -> false);
// Requirement checking is performed by SuggestionProvider
.requires(source -> false);
for (final CommandNode<CommandSource> child : hint.getChildren()) {
builder.then(copyForHinting(child));
}
@ -125,9 +128,9 @@ public final class VelocityCommandMeta implements CommandMeta {
private final Object plugin;
private VelocityCommandMeta(
final Set<String> aliases,
final List<CommandNode<CommandSource>> hints,
final @Nullable Object plugin
final Set<String> aliases,
final List<CommandNode<CommandSource>> hints,
final @Nullable Object plugin
) {
this.aliases = aliases;
this.hints = hints;

Datei anzeigen

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

Datei anzeigen

@ -27,8 +27,8 @@ import java.util.Collection;
import java.util.List;
/**
* An argument type that parses the remaining contents of a {@link StringReader},
* splitting the input into words and placing the results in a string array.
* An argument type that parses the remaining contents of a {@link StringReader}, splitting the
* input into words and placing the results in a string array.
*/
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];
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 StringArrayArgumentType() {}
private StringArrayArgumentType() {
}
@Override
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
*/
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
* the given name and type.
* Creates a builder for creating {@link VelocityArgumentCommandNode}s with the given name and
* type.
*
* @param name the name of the node
* @param type the type of the argument to parse
* @param <S> the type of the command source
* @param <T> the type of the argument to parse
* @param <S> the type of the command source
* @param <T> the type of the argument to parse
* @return a builder
*/
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(type, "type");
return new VelocityArgumentBuilder<>(name, type);
@ -82,7 +82,7 @@ public final class VelocityArgumentBuilder<S, T>
@Override
public VelocityArgumentCommandNode<S, T> build() {
return new VelocityArgumentCommandNode<>(this.name, this.type, getCommand(), getRequirement(),
getContextRequirement(), getRedirect(), getRedirectModifier(), isFork(),
this.suggestionsProvider);
getContextRequirement(), getRedirect(), getRedirectModifier(), isFork(),
this.suggestionsProvider);
}
}

Datei anzeigen

@ -40,9 +40,9 @@ import java.util.function.BiPredicate;
import java.util.function.Predicate;
/**
* An argument node that uses the given (possibly custom) {@link ArgumentType}
* for parsing, while maintaining compatibility with the vanilla client.
* The argument type must be greedy and accept any input.
* An argument node that uses the given (possibly custom) {@link ArgumentType} for parsing, while
* maintaining compatibility with the vanilla client. The argument type must be greedy and accept
* any input.
*
* @param <S> the type of the command source
* @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;
VelocityArgumentCommandNode(
final String name, final ArgumentType<T> type, final Command<S> command,
final Predicate<S> requirement,
final BiPredicate<CommandContextBuilder<S>, ImmutableStringReader> contextRequirement,
final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks,
final SuggestionProvider<S> customSuggestions) {
final String name, final ArgumentType<T> type, final Command<S> command,
final Predicate<S> requirement,
final BiPredicate<CommandContextBuilder<S>, ImmutableStringReader> contextRequirement,
final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks,
final SuggestionProvider<S> customSuggestions) {
super(name, StringArgumentType.greedyString(), command, requirement, contextRequirement,
redirect, modifier, forks, customSuggestions);
redirect, modifier, forks, customSuggestions);
this.type = Preconditions.checkNotNull(type, "type");
}
@Override
public void parse(final StringReader reader, final CommandContextBuilder<S> contextBuilder)
throws CommandSyntaxException {
throws CommandSyntaxException {
// Same as super, except we use the rich ArgumentType
final int start = reader.getCursor();
final T result = this.type.parse(reader);
if (reader.canRead()) {
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);
@ -80,8 +80,8 @@ public class VelocityArgumentCommandNode<S, T> extends ArgumentCommandNode<S, St
@Override
public CompletableFuture<Suggestions> listSuggestions(
final CommandContext<S> context, final SuggestionsBuilder builder)
throws CommandSyntaxException {
final CommandContext<S> context, final SuggestionsBuilder builder)
throws CommandSyntaxException {
if (getCustomSuggestions() == null) {
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.format.NamedTextColor;
/**
* Basic, common command messages.
*/
public class CommandMessages {
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.format.NamedTextColor;
/**
* Implements the Velocity default {@code /glist} command.
*/
public class GlistCommand {
private static final String SERVER_ARG = "server";
@ -55,22 +58,22 @@ public class GlistCommand {
*/
public void register() {
LiteralCommandNode<CommandSource> totalNode = LiteralArgumentBuilder
.<CommandSource>literal("glist")
.requires(source ->
source.getPermissionValue("velocity.command.glist") == Tristate.TRUE)
.executes(this::totalCount)
.build();
.<CommandSource>literal("glist")
.requires(source ->
source.getPermissionValue("velocity.command.glist") == Tristate.TRUE)
.executes(this::totalCount)
.build();
ArgumentCommandNode<CommandSource, String> serverNode = RequiredArgumentBuilder
.<CommandSource, String>argument(SERVER_ARG, StringArgumentType.string())
.suggests((context, builder) -> {
for (RegisteredServer server : server.getAllServers()) {
builder.suggest(server.getServerInfo().getName());
}
builder.suggest("all");
return builder.buildFuture();
})
.executes(this::serverCount)
.build();
.<CommandSource, String>argument(SERVER_ARG, StringArgumentType.string())
.suggests((context, builder) -> {
for (RegisteredServer server : server.getAllServers()) {
builder.suggest(server.getServerInfo().getName());
}
builder.suggest("all");
return builder.buildFuture();
})
.executes(this::serverCount)
.build();
totalNode.addChild(serverNode);
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.format.NamedTextColor;
/**
* Implements Velocity's {@code /server} command.
*/
public class ServerCommand implements SimpleCommand {
public static final int MAX_SERVERS_TO_LIST = 50;
@ -54,7 +57,7 @@ public class ServerCommand implements SimpleCommand {
final String[] args = invocation.arguments();
if (!(source instanceof Player)) {
source.sendMessage(Identity.nil(), CommandMessages.PLAYERS_ONLY);
source.sendMessage(CommandMessages.PLAYERS_ONLY);
return;
}
@ -63,9 +66,8 @@ public class ServerCommand implements SimpleCommand {
// Trying to connect to a server.
String serverName = args[0];
Optional<RegisteredServer> toConnect = server.getServer(serverName);
if (!toConnect.isPresent()) {
player.sendMessage(Identity.nil(), CommandMessages.SERVER_DOES_NOT_EXIST
.args(Component.text(serverName)));
if (toConnect.isEmpty()) {
player.sendMessage(CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
return;
}
@ -78,14 +80,14 @@ public class ServerCommand implements SimpleCommand {
private void outputServerInformation(Player executor) {
String currentServer = executor.getCurrentServer().map(ServerConnection::getServerInfo)
.map(ServerInfo::getName).orElse("<unknown>");
executor.sendMessage(Identity.nil(), Component.translatable(
executor.sendMessage(Component.translatable(
"velocity.command.server-current-server",
NamedTextColor.YELLOW,
Component.text(currentServer)));
List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server);
if (servers.size() > MAX_SERVERS_TO_LIST) {
executor.sendMessage(Identity.nil(), Component.translatable(
executor.sendMessage(Component.translatable(
"velocity.command.server-too-many", NamedTextColor.RED));
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) {
@ -113,9 +115,11 @@ public class ServerCommand implements SimpleCommand {
int connectedPlayers = server.getPlayersConnected().size();
TranslatableComponent playersTextComponent;
if (connectedPlayers == 1) {
playersTextComponent = Component.translatable("velocity.command.server-tooltip-player-online");
playersTextComponent = Component.translatable(
"velocity.command.server-tooltip-player-online");
} 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));
if (serverInfo.getName().equals(currentPlayerServer)) {
@ -130,9 +134,10 @@ public class ServerCommand implements SimpleCommand {
serverTextComponent = serverTextComponent.color(NamedTextColor.GRAY)
.clickEvent(ClickEvent.runCommand("/server " + serverInfo.getName()))
.hoverEvent(
showText(Component.translatable("velocity.command.server-tooltip-offer-connect-server")
.append(Component.newline())
.append(playersTextComponent))
showText(
Component.translatable("velocity.command.server-tooltip-offer-connect-server")
.append(Component.newline())
.append(playersTextComponent))
);
}
return serverTextComponent;
@ -142,7 +147,7 @@ public class ServerCommand implements SimpleCommand {
public List<String> suggest(final SimpleCommand.Invocation invocation) {
final String[] currentArgs = invocation.arguments();
Stream<String> possibilities = server.getAllServers().stream()
.map(rs -> rs.getServerInfo().getName());
.map(rs -> rs.getServerInfo().getName());
if (currentArgs.length == 0) {
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.serializer.legacy.LegacyComponentSerializer;
public final class ShutdownCommand {
private ShutdownCommand() {}
/**
* Shuts down the proxy.
*/
public final class ShutdownCommand {
private ShutdownCommand() {
}
/**
* Creates a Velocity Shutdown Command.
*
* @param server the proxy instance
* @return the Shutdown Command
*/
public static BrigadierCommand command(final VelocityServer server) {
return new BrigadierCommand(LiteralArgumentBuilder.<CommandSource>literal("shutdown")
.requires(source -> source == server.getConsoleCommandSource())
.executes(context -> {
server.shutdown(true);
return Command.SINGLE_SUCCESS;
})
.then(RequiredArgumentBuilder.<CommandSource, String>argument("reason", StringArgumentType.greedyString())
.requires(source -> source == server.getConsoleCommandSource())
.executes(context -> {
String reason = context.getArgument("reason", String.class);
server.shutdown(true, MiniMessage.miniMessage().deserialize(
MiniMessage.miniMessage().serialize(
LegacyComponentSerializer.legacy('&').deserialize(reason)
)
));
server.shutdown(true);
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.checkerframework.checker.nullness.qual.NonNull;
/**
* Implements the {@code /velocity} command and friends.
*/
public class VelocityCommand implements SimpleCommand {
private interface SubCommand {
@ -125,9 +128,9 @@ public class VelocityCommand implements SimpleCommand {
if (currentArgs.length == 0) {
return commands.entrySet().stream()
.filter(e -> e.getValue().hasPermission(source, new String[0]))
.map(Map.Entry::getKey)
.collect(ImmutableList.toImmutableList());
.filter(e -> e.getValue().hasPermission(source, new String[0]))
.map(Map.Entry::getKey)
.collect(ImmutableList.toImmutableList());
}
if (currentArgs.length == 1) {
@ -353,11 +356,11 @@ public class VelocityCommand implements SimpleCommand {
JsonObject servers = new JsonObject();
for (RegisteredServer iter : allServers) {
servers.add(iter.getServerInfo().getName(),
InformationUtils.collectServerInfo(iter));
InformationUtils.collectServerInfo(iter));
}
JsonArray connectOrder = new JsonArray();
List<String> attemptedConnectionOrder = ImmutableList.copyOf(
server.getConfiguration().getAttemptConnectionOrder());
server.getConfiguration().getAttemptConnectionOrder());
for (String s : attemptedConnectionOrder) {
connectOrder.add(s);
}
@ -366,7 +369,7 @@ public class VelocityCommand implements SimpleCommand {
proxyConfig.add("servers", servers);
proxyConfig.add("connectOrder", connectOrder);
proxyConfig.add("forcedHosts",
InformationUtils.collectForcedHosts(server.getConfiguration()));
InformationUtils.collectForcedHosts(server.getConfiguration()));
JsonObject dump = new JsonObject();
dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion()));
@ -383,7 +386,8 @@ public class VelocityCommand implements SimpleCommand {
source.sendMessage(Component.text(
"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) {
logger.error("Failed to complete dump command, "
+ "the executor was interrupted: " + e.getMessage());

Datei anzeigen

@ -27,14 +27,12 @@ import java.util.List;
import java.util.Map;
/**
* Creates command invocation objects from a command context builder or
* a command context.
* Creates command invocation objects from a command context builder or a command context.
*
* <p>Let {@code builder} be a command context builder, and {@code context}
* a context returned by calling {@link CommandContextBuilder#build(String)} on
* {@code builder}. The invocations returned by {@link #create(CommandContext)}
* when given {@code context}, and {@link #create(CommandContextBuilder)} when
* given {@code builder} are equal.
* a context returned by calling {@link CommandContextBuilder#build(String)} on {@code builder}. The
* invocations returned by {@link #create(CommandContext)} when given {@code context}, and
* {@link #create(CommandContextBuilder)} when given {@code builder} are equal.
*
* @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.
*
* @param source the command source
* @param nodes the list of parsed nodes, as returned by {@link CommandContext#getNodes()} and
* {@link CommandContextBuilder#getNodes()}
* @param source the command source
* @param nodes the list of parsed nodes, as returned by {@link CommandContext#getNodes()} and
* {@link CommandContextBuilder#getNodes()}
* @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
*/
// 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
// the other. Subclasses may override the methods above to obtain class-specific data.
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.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.RawCommand;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.proxy.command.VelocityCommands;
import java.util.List;
import java.util.Map;
/**
* Implements {@link RawCommand.Invocation}.
*/
public final class RawCommandInvocation extends AbstractCommandInvocation<String>
implements RawCommand.Invocation {
implements RawCommand.Invocation {
public static final Factory FACTORY = new Factory();
@ -35,8 +39,8 @@ public final class RawCommandInvocation extends AbstractCommandInvocation<String
@Override
public RawCommand.Invocation create(
final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes,
final Map<String, ? extends ParsedArgument<?, ?>> arguments) {
final CommandSource source, final List<? extends ParsedCommandNode<?>> nodes,
final Map<String, ? extends ParsedArgument<?, ?>> arguments) {
final String alias = VelocityCommands.readAlias(nodes);
final String args = VelocityCommands.readArguments(arguments, String.class, "");
return new RawCommandInvocation(source, alias, args);
@ -46,7 +50,7 @@ public final class RawCommandInvocation extends AbstractCommandInvocation<String
private final String alias;
private RawCommandInvocation(final CommandSource source,
final String alias, final String arguments) {
final String alias, final String arguments) {
super(source, arguments);
this.alias = Preconditions.checkNotNull(alias, "alias");
}
@ -82,9 +86,9 @@ public final class RawCommandInvocation extends AbstractCommandInvocation<String
@Override
public String toString() {
return "RawCommandInvocation{"
+ "source='" + this.source() + '\''
+ ", alias='" + this.alias + '\''
+ ", arguments='" + this.arguments() + '\''
+ '}';
+ "source='" + this.source() + '\''
+ ", alias='" + this.alias + '\''
+ ", arguments='" + this.arguments() + '\''
+ '}';
}
}

Datei anzeigen

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

Datei anzeigen

@ -23,8 +23,8 @@ import com.velocitypowered.api.command.Command;
import com.velocitypowered.api.command.CommandMeta;
/**
* Creates and registers the {@link LiteralCommandNode} representations of
* a given {@link Command} in a {@link RootCommandNode}.
* Creates and registers the {@link LiteralCommandNode} representations of a given {@link Command}
* in a {@link RootCommandNode}.
*
* @param <T> the type of the command to register
*/
@ -33,16 +33,16 @@ public interface CommandRegistrar<T extends 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
* @throws IllegalArgumentException if the given command cannot be registered
*/
void register(final CommandMeta meta, final T command);
/**
* Returns the superclass or superinterface of all {@link Command} classes
* compatible with this registrar. Note that {@link #register(CommandMeta, Command)}
* may impose additional restrictions on individual {@link Command} instances.
* Returns the superclass or superinterface of all {@link Command} classes compatible with this
* registrar. Note that {@link #register(CommandMeta, Command)} may impose additional restrictions
* on individual {@link Command} instances.
*
* @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.
*/
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 ArgumentType<A> argumentsType;
protected InvocableCommandRegistrar(final RootCommandNode<CommandSource> root, final Lock lock,
final CommandInvocationFactory<I> invocationFactory,
final ArgumentType<A> argumentsType) {
final CommandInvocationFactory<I> invocationFactory,
final ArgumentType<A> argumentsType) {
super(root, lock);
this.invocationFactory = Preconditions.checkNotNull(invocationFactory, "invocationFactory");
this.argumentsType = Preconditions.checkNotNull(argumentsType, "argumentsType");
@ -61,7 +61,7 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
final String primaryAlias = aliases.next();
final LiteralCommandNode<CommandSource> literal =
this.createLiteral(command, meta, primaryAlias);
this.createLiteral(command, meta, primaryAlias);
this.register(literal);
while (aliases.hasNext()) {
@ -71,7 +71,7 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
}
private LiteralCommandNode<CommandSource> createLiteral(final T command, final CommandMeta meta,
final String alias) {
final String alias) {
final Predicate<CommandContextBuilder<CommandSource>> requirement = context -> {
final I invocation = invocationFactory.create(context);
return command.hasPermission(invocation);
@ -83,35 +83,35 @@ abstract class InvocableCommandRegistrar<T extends InvocableCommand<I>,
};
final LiteralCommandNode<CommandSource> literal = LiteralArgumentBuilder
.<CommandSource>literal(alias)
.requiresWithContext((context, reader) -> {
if (reader.canRead()) {
// InvocableCommands do not follow a tree-like permissions checking structure.
// Thus, a CommandSource may be able to execute a command with arguments while
// not being able to execute the argument-less variant.
// Only check for permissions once parsing is complete.
return true;
}
return requirement.test(context);
})
.executes(callback)
.build();
.<CommandSource>literal(alias)
.requiresWithContext((context, reader) -> {
if (reader.canRead()) {
// InvocableCommands do not follow a tree-like permissions checking structure.
// Thus, a CommandSource may be able to execute a command with arguments while
// not being able to execute the argument-less variant.
// Only check for permissions once parsing is complete.
return true;
}
return requirement.test(context);
})
.executes(callback)
.build();
final ArgumentCommandNode<CommandSource, String> arguments = VelocityArgumentBuilder
.<CommandSource, A>velocityArgument(VelocityCommands.ARGS_NODE_NAME, argumentsType)
.requiresWithContext((context, reader) -> requirement.test(context))
.executes(callback)
.suggests((context, builder) -> {
final I invocation = invocationFactory.create(context);
return command.suggestAsync(invocation).thenApply(suggestions -> {
for (String value : suggestions) {
Preconditions.checkNotNull(value, "suggestion");
builder.suggest(value);
}
return builder.build();
});
})
.build();
.<CommandSource, A>velocityArgument(VelocityCommands.ARGS_NODE_NAME, argumentsType)
.requiresWithContext((context, reader) -> requirement.test(context))
.executes(callback)
.suggests((context, builder) -> {
final I invocation = invocationFactory.create(context);
return command.suggestAsync(invocation).thenApply(suggestions -> {
for (String value : suggestions) {
Preconditions.checkNotNull(value, "suggestion");
builder.suggest(value);
}
return builder.build();
});
})
.build();
literal.addChild(arguments);
// Add hinting nodes

Datei anzeigen

@ -28,7 +28,7 @@ import java.util.concurrent.locks.Lock;
* Registers {@link RawCommand}s in a root node.
*/
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) {
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.
*/
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) {
super(root, lock, SimpleCommandInvocation.FACTORY, StringArrayArgumentType.INSTANCE);

Datei anzeigen

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

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.proxy.config;
/**
* Supported player info forwarding methods.
*/
public enum PlayerInfoForwarding {
NONE,
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.Nullable;
/**
* Velocity's configuration.
*/
public class VelocityConfiguration implements ProxyConfig {
private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class);
@Expose private String bind = "0.0.0.0:25577";
@Expose private String motd = "&3A Velocity Server";
@Expose private int showMaxPlayers = 500;
@Expose private boolean onlineMode = true;
@Expose private boolean preventClientProxyConnections = false;
@Expose private PlayerInfoForwarding playerInfoForwardingMode = PlayerInfoForwarding.NONE;
@Expose
private String bind = "0.0.0.0:25577";
@Expose
private String motd = "&3A Velocity Server";
@Expose
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);
@Expose private boolean announceForge = false;
@Expose private boolean onlineModeKickExistingPlayers = false;
@Expose private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED;
@Expose
private boolean announceForge = false;
@Expose
private boolean onlineModeKickExistingPlayers = false;
@Expose
private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED;
private final Servers servers;
private final ForcedHosts forcedHosts;
@Expose private final Advanced advanced;
@Expose private final Query query;
@Expose
private final Advanced advanced;
@Expose
private final Query query;
private final Metrics metrics;
@Expose private boolean enablePlayerAddressLogging = true;
@Expose
private boolean enablePlayerAddressLogging = true;
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
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,
Query query, Metrics metrics) {
@ -112,6 +128,7 @@ public class VelocityConfiguration implements ProxyConfig {
/**
* Attempts to validate the configuration.
*
* @return {@code true} if the configuration is sound, {@code false} if not
*/
public boolean validate() {
@ -408,6 +425,7 @@ public class VelocityConfiguration implements ProxyConfig {
/**
* Reads the Velocity configuration from {@code path}.
*
* @param path the path to read from
* @return the deserialized Velocity configuration
* @throws IOException if we could not read from the {@code path}.
@ -455,23 +473,25 @@ public class VelocityConfiguration implements ProxyConfig {
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;
String forwardingSecretString;
byte[] forwardingSecret;
// 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
// easier to implement. All that would be required is removing the if statement here and keeping the contents
// of the else block (with slight tidying).
// There is duplicate/old code here in effort to make the future commit which abandons legacy
// config handling easier to implement. All that would be required is removing the if statement
// here and keeping the contents of the else block (with slight tidying).
if (legacyConfig) {
logger.warn("You are currently using a deprecated configuration version. The \"forwarding-secret\""
+ " parameter has been recognized as a security concern and has been removed in config version 2.0."
+ " It's recommended you rename your current \"velocity.toml\" to something else to allow Velocity"
+ " to generate a config file of the new version. You may then configure that file as you normally would."
+ " The only differences are the config-version and \"forwarding-secret\" has been replaced"
+ " by \"forwarding-secret-file\".");
logger.warn(
"You are currently using a deprecated configuration version. The \"forwarding-secret\""
+ " parameter is a security hazard and was removed in config version 2.0."
+ " You should rename your current \"velocity.toml\" to something else to allow"
+ " Velocity to generate a config file for the new version. You may then configure "
+ " 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
forwardingSecretString = System.getenv()
@ -493,7 +513,8 @@ public class VelocityConfiguration implements ProxyConfig {
if (Files.isRegularFile(secretPath)) {
forwardingSecretString = String.join("", Files.readAllLines(secretPath));
} 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 {
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) {
config.set("force-key-authentication", config.getOrElse("force-key-authentication", true));
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");
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
* quotes; however, the TOML parser returns the key with the quotes so we need to clean the
* server name before we pass it onto server registration to keep proper server name behavior.
* TOML requires keys to match a regex of {@code [A-Za-z0-9_-]} unless it is wrapped in quotes;
* however, the TOML parser returns the key with the quotes so we need to clean the server name
* before we pass it onto server registration to keep proper server name behavior.
*
* @param name the server name to clean
*
* @return the cleaned server name
*/
private String cleanServerName(String name) {
@ -705,19 +725,32 @@ public class VelocityConfiguration implements ProxyConfig {
private static class Advanced {
@Expose private int compressionThreshold = 256;
@Expose private int compressionLevel = -1;
@Expose private int loginRatelimit = 3000;
@Expose private int connectionTimeout = 5000;
@Expose private int readTimeout = 30000;
@Expose private boolean proxyProtocol = false;
@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;
@Expose
private int compressionThreshold = 256;
@Expose
private int compressionLevel = -1;
@Expose
private int loginRatelimit = 3000;
@Expose
private int connectionTimeout = 5000;
@Expose
private int readTimeout = 30000;
@Expose
private boolean proxyProtocol = false;
@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() {
}
@ -819,10 +852,14 @@ public class VelocityConfiguration implements ProxyConfig {
private static class Query {
@Expose private boolean queryEnabled = false;
@Expose private int queryPort = 25577;
@Expose private String queryMap = "Velocity";
@Expose private boolean showPlugins = false;
@Expose
private boolean queryEnabled = false;
@Expose
private int queryPort = 25577;
@Expose
private String queryMap = "Velocity";
@Expose
private boolean showPlugins = false;
private Query() {
}
@ -870,7 +907,11 @@ public class VelocityConfiguration implements ProxyConfig {
}
}
/**
* Configuration for metrics.
*/
public static class Metrics {
private boolean enabled = true;
private Metrics(CommentedConfig toml) {

Datei anzeigen

@ -42,13 +42,13 @@ public interface ConnectionType {
BackendConnectionPhase getInitialBackendPhase();
/**
* Adds properties to the {@link GameProfile} if required. If any properties
* are added, the returned {@link GameProfile} will be a copy.
* Adds properties to the {@link GameProfile} if required. If any properties are added, the
* 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}
* @return The {@link GameProfile} with the properties added in.
*/
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 {
/**
* Indicates that the connection has yet to reach the
* point where we have a definitive answer as to what
* type of connection we have.
* Indicates that the connection has yet to reach the point where we have a definitive answer as
* to what type of connection we have.
*/
public static final ConnectionType UNDETERMINED =
new ConnectionTypeImpl(ClientConnectionPhases.VANILLA, BackendConnectionPhases.UNKNOWN);
@ -46,8 +45,7 @@ public final class ConnectionTypes {
LegacyForgeHandshakeClientPhase.NOT_STARTED, BackendConnectionPhases.UNKNOWN);
/**
* Indicates that the connection is a 1.8-1.12 Forge
* connection.
* Indicates that the connection is a 1.8-1.12 Forge connection.
*/
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.
*
* @param channel the channel on the connection
* @param server the Velocity instance
* @param server the Velocity instance
*/
public MinecraftConnection(Channel channel, VelocityServer server) {
this.channel = channel;
@ -211,6 +212,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Writes and immediately flushes a message to the connection.
*
* @param msg the message to write
*/
public void write(Object msg) {
@ -223,6 +225,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Writes, but does not flush, a message to the connection.
*
* @param msg the message to write
*/
public void delayedWrite(Object msg) {
@ -244,6 +247,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Closes the connection after writing the {@code msg}.
*
* @param msg the message to write
*/
public void closeWith(Object msg) {
@ -273,6 +277,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Immediately closes the connection.
*
* @param markKnown whether the disconnection is known
*/
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.
*
* @param autoReading whether or not we should read data automatically
*/
public void setAutoReading(boolean autoReading) {
@ -337,6 +343,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Changes the state of the Minecraft connection.
*
* @param state the new state
*/
public void setState(StateRegistry state) {
@ -353,6 +360,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Sets the new protocol version for the connection.
*
* @param protocolVersion the protocol version to use
*/
public void setProtocolVersion(ProtocolVersion protocolVersion) {
@ -380,6 +388,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Sets the session handler for this connection.
*
* @param sessionHandler the handler to use
*/
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
* {@link com.velocitypowered.proxy.protocol.packet.SetCompression} beforehand.
*
* @param threshold the compression threshold to use
*/
public void setCompressionThreshold(int threshold) {
@ -440,6 +450,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Enables encryption on the connection.
*
* @param secret the secret key negotiated between the client and the server
* @throws GeneralSecurityException if encryption can't be enabled
*/
@ -471,6 +482,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Gets the detected {@link ConnectionType}.
*
* @return The {@link ConnectionType}
*/
public ConnectionType getType() {
@ -479,6 +491,7 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
/**
* Sets the detected {@link ConnectionType}.
*
* @param connectionType The {@link ConnectionType}
*/
public void setType(ConnectionType connectionType) {

Datei anzeigen

@ -17,6 +17,9 @@
package com.velocitypowered.proxy.connection;
/**
* Marker interface for something that can be associated with a {@link MinecraftConnection}.
*/
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 io.netty.buffer.ByteBuf;
/**
* Interface for dispatching received Minecraft packets.
*/
public interface MinecraftSessionHandler {
default boolean beforeHandle() {

Datei anzeigen

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

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