Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-12-24 23:30:26 +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:
Ursprung
ffa4c95435
Commit
d72d707b1c
119
api/build.gradle
119
api/build.gradle
@ -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
80
api/build.gradle.kts
Normale Datei
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -29,6 +29,7 @@ public class PlayerAvailableCommandsEvent {
|
||||
|
||||
/**
|
||||
* Constructs an available commands event.
|
||||
*
|
||||
* @param player the targeted player
|
||||
* @param rootNode the Brigadier root node
|
||||
*/
|
||||
|
@ -51,6 +51,9 @@ public final class DisconnectEvent {
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* The status of the connection when the player disconnected.
|
||||
*/
|
||||
public enum LoginStatus {
|
||||
|
||||
SUCCESSFUL_LOGIN,
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ public class PlayerResourcePackStatusEvent {
|
||||
|
||||
/**
|
||||
* Instantiates this event.
|
||||
*
|
||||
* @deprecated Use {@link PlayerResourcePackStatusEvent#PlayerResourcePackStatusEvent
|
||||
* (Player, Status, ResourcePackInfo)} instead.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
*
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,9 @@ package com.velocitypowered.api.proxy.crypto;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A signed message.
|
||||
*/
|
||||
public interface SignedMessage extends KeySigned {
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
*
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
59
build.gradle
59
build.gradle
@ -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
47
build.gradle.kts
Normale Datei
@ -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
27
buildSrc/build.gradle.kts
Normale Datei
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
26
gradle.properties
Normale Datei
@ -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
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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
18
native/build.gradle.kts
Normale Datei
@ -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}")
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
package com.velocitypowered.natives.compression;
|
||||
|
||||
/**
|
||||
* Factory for {@link VelocityCompressor}.
|
||||
*/
|
||||
public interface VelocityCompressorFactory {
|
||||
|
||||
VelocityCompressor create(int level);
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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
159
proxy/build.gradle.kts
Normale Datei
@ -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.+")
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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() + '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
@ -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()) + '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
package com.velocitypowered.proxy.config;
|
||||
|
||||
/**
|
||||
* Supported passthrough modes for ping passthrough.
|
||||
*/
|
||||
public enum PingPassthroughMode {
|
||||
DISABLED,
|
||||
MODS,
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
package com.velocitypowered.proxy.config;
|
||||
|
||||
/**
|
||||
* Supported player info forwarding methods.
|
||||
*/
|
||||
public enum PlayerInfoForwarding {
|
||||
NONE,
|
||||
LEGACY,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
package com.velocitypowered.proxy.connection;
|
||||
|
||||
/**
|
||||
* Marker interface for something that can be associated with a {@link MinecraftConnection}.
|
||||
*/
|
||||
public interface MinecraftConnectionAssociation {
|
||||
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren