3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-06 00:00:47 +01:00

Reformat with Google code style and enforce Checkstyle.

Fixes #125
Dieser Commit ist enthalten in:
Andrew Steinborn 2018-10-27 23:45:35 -04:00
Ursprung 53aa92db92
Commit 25b5e00125
208 geänderte Dateien mit 12851 neuen und 11620 gelöschten Zeilen

Datei anzeigen

@ -2,9 +2,11 @@ plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '2.0.4'
id 'maven-publish'
id 'checkstyle'
}
apply from: '../gradle/checkerframework.gradle'
apply from: '../gradle/checkstyle.gradle'
sourceSets {
ap {

Datei anzeigen

@ -3,7 +3,11 @@ package com.velocitypowered.api.plugin.ap;
import com.google.gson.Gson;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.PluginDescription;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Objects;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
@ -16,14 +20,10 @@ import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Objects;
import java.util.Set;
@SupportedAnnotationTypes({"com.velocitypowered.api.plugin.Plugin"})
public class PluginAnnotationProcessor extends AbstractProcessor {
private ProcessingEnvironment environment;
private String pluginClassFound;
private boolean warnedAboutMultiplePlugins;
@ -46,7 +46,8 @@ public class PluginAnnotationProcessor extends AbstractProcessor {
for (Element element : roundEnv.getElementsAnnotatedWith(Plugin.class)) {
if (element.getKind() != ElementKind.CLASS) {
environment.getMessager().printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated with "
environment.getMessager()
.printMessage(Diagnostic.Kind.ERROR, "Only classes can be annotated with "
+ Plugin.class.getCanonicalName());
return false;
}
@ -55,8 +56,10 @@ public class PluginAnnotationProcessor extends AbstractProcessor {
if (Objects.equals(pluginClassFound, qualifiedName.toString())) {
if (!warnedAboutMultiplePlugins) {
environment.getMessager().printMessage(Diagnostic.Kind.WARNING, "Velocity does not yet currently support " +
"multiple plugins. We are using " + pluginClassFound + " for your plugin's main class.");
environment.getMessager()
.printMessage(Diagnostic.Kind.WARNING, "Velocity does not yet currently support " +
"multiple plugins. We are using " + pluginClassFound
+ " for your plugin's main class.");
warnedAboutMultiplePlugins = true;
}
return false;
@ -65,21 +68,25 @@ public class PluginAnnotationProcessor extends AbstractProcessor {
Plugin plugin = element.getAnnotation(Plugin.class);
if (!PluginDescription.ID_PATTERN.matcher(plugin.id()).matches()) {
environment.getMessager().printMessage(Diagnostic.Kind.ERROR, "Invalid ID for plugin "
+ qualifiedName + ". IDs must start alphabetically, have alphanumeric characters, and can " +
+ qualifiedName
+ ". IDs must start alphabetically, have alphanumeric characters, and can " +
"contain dashes or underscores.");
return false;
}
// All good, generate the velocity-plugin.json.
SerializedPluginDescription description = SerializedPluginDescription.from(plugin, qualifiedName.toString());
SerializedPluginDescription description = SerializedPluginDescription
.from(plugin, qualifiedName.toString());
try {
FileObject object = environment.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "velocity-plugin.json");
FileObject object = environment.getFiler()
.createResource(StandardLocation.CLASS_OUTPUT, "", "velocity-plugin.json");
try (Writer writer = new BufferedWriter(object.openWriter())) {
new Gson().toJson(description, writer);
}
pluginClassFound = qualifiedName.toString();
} catch (IOException e) {
environment.getMessager().printMessage(Diagnostic.Kind.ERROR, "Unable to generate plugin file");
environment.getMessager()
.printMessage(Diagnostic.Kind.ERROR, "Unable to generate plugin file");
}
}

Datei anzeigen

@ -4,15 +4,15 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.Nullable;
public class SerializedPluginDescription {
// @Nullable is used here to make GSON skip these in the serialized file
private final String id;
private final @Nullable String name;
@ -23,7 +23,8 @@ public class SerializedPluginDescription {
private final @Nullable List<Dependency> dependencies;
private final String main;
public SerializedPluginDescription(String id, String name, String version, String description, String url,
public SerializedPluginDescription(String id, String name, String version, String description,
String url,
List<String> authors, List<Dependency> dependencies, String main) {
this.id = Preconditions.checkNotNull(id, "id");
this.name = Strings.emptyToNull(name);
@ -31,7 +32,8 @@ public class SerializedPluginDescription {
this.description = Strings.emptyToNull(description);
this.url = Strings.emptyToNull(url);
this.authors = authors == null || authors.isEmpty() ? ImmutableList.of() : authors;
this.dependencies = dependencies == null || dependencies.isEmpty() ? ImmutableList.of() : dependencies;
this.dependencies =
dependencies == null || dependencies.isEmpty() ? ImmutableList.of() : dependencies;
this.main = Preconditions.checkNotNull(main, "main");
}
@ -40,8 +42,10 @@ public class SerializedPluginDescription {
for (com.velocitypowered.api.plugin.Dependency dependency : plugin.dependencies()) {
dependencies.add(new Dependency(dependency.id(), dependency.optional()));
}
return new SerializedPluginDescription(plugin.id(), plugin.name(), plugin.version(), plugin.description(), plugin.url(),
Arrays.stream(plugin.authors()).filter(author -> !author.isEmpty()).collect(Collectors.toList()), dependencies, qualifiedName);
return new SerializedPluginDescription(plugin.id(), plugin.name(), plugin.version(),
plugin.description(), plugin.url(),
Arrays.stream(plugin.authors()).filter(author -> !author.isEmpty())
.collect(Collectors.toList()), dependencies, qualifiedName);
}
public String getId() {
@ -78,8 +82,12 @@ public class SerializedPluginDescription {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SerializedPluginDescription that = (SerializedPluginDescription) o;
return Objects.equals(id, that.id) &&
Objects.equals(name, that.name) &&
@ -111,6 +119,7 @@ public class SerializedPluginDescription {
}
public static class Dependency {
private final String id;
private final boolean optional;
@ -129,8 +138,12 @@ public class SerializedPluginDescription {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Dependency that = (Dependency) o;
return optional == that.optional &&
Objects.equals(id, that.id);

Datei anzeigen

@ -1,17 +1,18 @@
package com.velocitypowered.api.command;
import com.google.common.collect.ImmutableList;
import java.util.List;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
/**
* Represents a command that can be executed by a {@link CommandSource}, such as a {@link com.velocitypowered.api.proxy.Player}
* or the console.
* Represents a command that can be executed by a {@link CommandSource}, such as a {@link
* com.velocitypowered.api.proxy.Player} or the console.
*/
public interface Command {
/**
* Executes the command for the specified {@link CommandSource}.
*
* @param source the source of this command
* @param args the arguments for this command
*/
@ -19,6 +20,7 @@ public interface Command {
/**
* Provides tab complete suggestions for a command for a specified {@link CommandSource}.
*
* @param source the source to run the command for
* @param currentArgs the current, partial arguments for this command
* @return tab complete suggestions
@ -28,8 +30,8 @@ public interface Command {
}
/**
* Tests to check if the {@code source} has permission to use this command
* with the provided {@code args}.
* Tests to check if the {@code source} has permission to use this command with the provided
* {@code args}.
*
* <p>If this method returns false, the handling will be forwarded onto
* the players current server.</p>

Datei anzeigen

@ -4,8 +4,10 @@ package com.velocitypowered.api.command;
* Represents an interface to register a command executor with the proxy.
*/
public interface CommandManager {
/**
* Registers the specified command with the manager with the specified aliases.
*
* @param command the command to register
* @param aliases the alias to use
*/
@ -13,12 +15,14 @@ public interface CommandManager {
/**
* Unregisters a command.
*
* @param alias the command alias to unregister
*/
void unregister(String alias);
/**
* Attempts to execute a command from the specified {@code cmdLine}.
*
* @param source the command's source
* @param cmdLine the command to run
* @return true if the command was found and executed, false if it was not

Datei anzeigen

@ -7,8 +7,10 @@ import net.kyori.text.Component;
* Represents something that can be used to run a {@link Command}.
*/
public interface CommandSource extends PermissionSubject {
/**
* Sends the specified {@code component} to the invoker.
*
* @param component the text component to send
*/
void sendMessage(Component component);

Datei anzeigen

@ -1,10 +1,11 @@
package com.velocitypowered.api.event;
/**
* Represents an interface to perform direct dispatch of an event. This makes integration easier to achieve with platforms
* such as RxJava.
* Represents an interface to perform direct dispatch of an event. This makes integration easier to
* achieve with platforms such as RxJava.
*/
@FunctionalInterface
public interface EventHandler<E> {
void execute(E event);
}

Datei anzeigen

@ -6,15 +6,20 @@ import java.util.concurrent.CompletableFuture;
* Allows plugins to register and deregister listeners for event handlers.
*/
public interface EventManager {
/**
* Requests that the specified {@code listener} listen for events and associate it with the {@code plugin}.
* Requests that the specified {@code listener} listen for events and associate it with the {@code
* plugin}.
*
* @param plugin the plugin to associate with the listener
* @param listener the listener to register
*/
void register(Object plugin, Object listener);
/**
* Requests that the specified {@code handler} listen for events and associate it with the {@code plugin}.
* Requests that the specified {@code handler} listen for events and associate it with the {@code
* plugin}.
*
* @param plugin the plugin to associate with the handler
* @param eventClass the class for the event handler to register
* @param handler the handler to register
@ -25,18 +30,23 @@ public interface EventManager {
}
/**
* Requests that the specified {@code handler} listen for events and associate it with the {@code plugin}.
* Requests that the specified {@code handler} listen for events and associate it with the {@code
* plugin}.
*
* @param plugin the plugin to associate with the handler
* @param eventClass the class for the event handler to register
* @param postOrder the order in which events should be posted to the handler
* @param handler the handler to register
* @param <E> the event type to handle
*/
<E> void register(Object plugin, Class<E> eventClass, PostOrder postOrder, EventHandler<E> handler);
<E> void register(Object plugin, Class<E> eventClass, PostOrder postOrder,
EventHandler<E> handler);
/**
* Fires the specified event to the event bus asynchronously. This allows Velocity to continue servicing connections
* while a plugin handles a potentially long-running operation such as a database query.
* Fires the specified event to the event bus asynchronously. This allows Velocity to continue
* servicing connections while a plugin handles a potentially long-running operation such as a
* database query.
*
* @param event the event to fire
* @return a {@link CompletableFuture} representing the posted event
*/
@ -44,6 +54,7 @@ public interface EventManager {
/**
* Posts the specified event to the event bus and discards the result.
*
* @param event the event to fire
*/
default void fireAndForget(Object event) {
@ -52,12 +63,14 @@ public interface EventManager {
/**
* Unregisters all listeners for the specified {@code plugin}.
*
* @param plugin the plugin to deregister listeners for
*/
void unregisterListeners(Object plugin);
/**
* Unregisters a specific listener for a specific plugin.
*
* @param plugin the plugin associated with the listener
* @param listener the listener to deregister
*/
@ -65,6 +78,7 @@ public interface EventManager {
/**
* Unregisters a specific event handler for a specific plugin.
*
* @param plugin the plugin to associate with the handler
* @param handler the handler to register
* @param <E> the event type to handle

Datei anzeigen

@ -1,8 +1,7 @@
package com.velocitypowered.api.event;
/**
* Represents the order an event will be posted to a listener method, relative
* to other listeners.
* Represents the order an event will be posted to a listener method, relative to other listeners.
*/
public enum PostOrder {

Datei anzeigen

@ -1,25 +1,26 @@
package com.velocitypowered.api.event;
import com.google.common.base.Preconditions;
import java.util.Optional;
import net.kyori.text.Component;
import net.kyori.text.serializer.ComponentSerializers;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Optional;
/**
* Indicates an event that has a result attached to it.
*/
public interface ResultedEvent<R extends ResultedEvent.Result> {
/**
* Returns the result associated with this event.
*
* @return the result of this event
*/
R getResult();
/**
* Sets the result of this event. The result must be non-null.
*
* @param result the new result
*/
void setResult(R result);
@ -28,9 +29,11 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
* Represents a result for an event.
*/
interface Result {
/**
* Returns whether or not the event is allowed to proceed. Plugins may choose to skip denied events, and the
* proxy will respect the result of this method.
* Returns whether or not the event is allowed to proceed. Plugins may choose to skip denied
* events, and the proxy will respect the result of this method.
*
* @return whether or not the event is allowed to proceed
*/
boolean isAllowed();
@ -40,6 +43,7 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
* A generic "allowed/denied" result.
*/
final class GenericResult implements Result {
private static final GenericResult ALLOWED = new GenericResult(true);
private static final GenericResult DENIED = new GenericResult(false);
@ -72,6 +76,7 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
* Represents an "allowed/denied" result with a reason allowed for denial.
*/
final class ComponentResult implements Result {
private static final ComponentResult ALLOWED = new ComponentResult(true, null);
private final boolean status;

Datei anzeigen

@ -7,6 +7,7 @@ import com.velocitypowered.api.proxy.InboundConnection;
* This event is fired when a handshake is established between a client and Velocity.
*/
public final class ConnectionHandshakeEvent {
private final InboundConnection connection;
public ConnectionHandshakeEvent(InboundConnection connection) {

Datei anzeigen

@ -4,10 +4,11 @@ import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.Player;
/**
* This event is fired when a player disconnects from the proxy. Operations on the provided player, aside from basic
* data retrieval operations, may behave in undefined ways.
* This event is fired when a player disconnects from the proxy. Operations on the provided player,
* aside from basic data retrieval operations, may behave in undefined ways.
*/
public final class DisconnectEvent {
private final Player player;
public DisconnectEvent(Player player) {

Datei anzeigen

@ -5,9 +5,11 @@ import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.proxy.Player;
/**
* This event is fired once the player has been authenticated but before they connect to a server on the proxy.
* This event is fired once the player has been authenticated but before they connect to a server on
* the proxy.
*/
public final class LoginEvent implements ResultedEvent<ResultedEvent.ComponentResult> {
private final Player player;
private ComponentResult result;

Datei anzeigen

@ -7,22 +7,22 @@ import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Arrays;
/**
* This event is fired when a plugin message is sent to the proxy, either from a client ({@link com.velocitypowered.api.proxy.Player})
* or a server ({@link com.velocitypowered.api.proxy.ServerConnection}).
* This event is fired when a plugin message is sent to the proxy, either from a client ({@link
* com.velocitypowered.api.proxy.Player}) or a server ({@link com.velocitypowered.api.proxy.ServerConnection}).
*/
public final class PluginMessageEvent implements ResultedEvent<PluginMessageEvent.ForwardResult> {
private final ChannelMessageSource source;
private final ChannelMessageSink target;
private final ChannelIdentifier identifier;
private final byte[] data;
private ForwardResult result;
public PluginMessageEvent(ChannelMessageSource source, ChannelMessageSink target, ChannelIdentifier identifier, byte[] data) {
public PluginMessageEvent(ChannelMessageSource source, ChannelMessageSink target,
ChannelIdentifier identifier, byte[] data) {
this.source = Preconditions.checkNotNull(source, "source");
this.target = Preconditions.checkNotNull(target, "target");
this.identifier = Preconditions.checkNotNull(identifier, "identifier");
@ -75,6 +75,7 @@ public final class PluginMessageEvent implements ResultedEvent<PluginMessageEven
* A result determining whether or not to forward this message on.
*/
public static final class ForwardResult implements ResultedEvent.Result {
private static final ForwardResult ALLOWED = new ForwardResult(true);
private static final ForwardResult DENIED = new ForwardResult(false);

Datei anzeigen

@ -4,8 +4,8 @@ import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.Player;
/**
* This event is fired once the player has been successfully authenticated and
* fully initialized and player will be connected to server after this event
* This event is fired once the player has been successfully authenticated and fully initialized and
* player will be connected to server after this event
*/
public final class PostLoginEvent {

Datei anzeigen

@ -3,17 +3,18 @@ package com.velocitypowered.api.event.connection;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.proxy.InboundConnection;
import java.util.Optional;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Optional;
/**
* This event is fired when a player has initiated a connection with the proxy but before the proxy authenticates the
* player with Mojang or before the player's proxy connection is fully established (for offline mode).
* This event is fired when a player has initiated a connection with the proxy but before the proxy
* authenticates the player with Mojang or before the player's proxy connection is fully established
* (for offline mode).
*/
public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLoginComponentResult> {
private final InboundConnection connection;
private final String username;
private PreLoginComponentResult result;
@ -52,13 +53,17 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
}
/**
* Represents an "allowed/allowed with forced online\offline mode/denied" result with a reason allowed for denial.
* Represents an "allowed/allowed with forced online\offline mode/denied" result with a reason
* allowed for denial.
*/
public static final class PreLoginComponentResult implements ResultedEvent.Result {
private static final PreLoginComponentResult ALLOWED = new PreLoginComponentResult(Result.ALLOWED, null);
private static final PreLoginComponentResult FORCE_ONLINEMODE = new PreLoginComponentResult(Result.FORCE_ONLINE, null);
private static final PreLoginComponentResult FORCE_OFFLINEMODE = new PreLoginComponentResult(Result.FORCE_OFFLINE, null);
private static final PreLoginComponentResult ALLOWED = new PreLoginComponentResult(
Result.ALLOWED, null);
private static final PreLoginComponentResult FORCE_ONLINEMODE = new PreLoginComponentResult(
Result.FORCE_ONLINE, null);
private static final PreLoginComponentResult FORCE_OFFLINEMODE = new PreLoginComponentResult(
Result.FORCE_OFFLINE, null);
private final Result result;
private final @Nullable Component reason;
@ -100,8 +105,8 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
}
/**
* Returns a result indicating the connection will be allowed through
* the proxy.
* Returns a result indicating the connection will be allowed through the proxy.
*
* @return the allowed result
*/
public static PreLoginComponentResult allowed() {
@ -109,10 +114,10 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
}
/**
* Returns a result indicating the connection will be allowed through
* the proxy, but the connection will be forced to use online mode
* provided that the proxy is in offline mode. This acts similarly to
* {@link #allowed()} on an online-mode proxy.
* Returns a result indicating the connection will be allowed through the proxy, but the
* connection will be forced to use online mode provided that the proxy is in offline mode. This
* acts similarly to {@link #allowed()} on an online-mode proxy.
*
* @return the result
*/
public static PreLoginComponentResult forceOnlineMode() {
@ -120,9 +125,9 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
}
/**
* Returns a result indicating the connection will be allowed through
* the proxy, but the connection will be forced to use offline mode even
* when proxy running in online mode
* Returns a result indicating the connection will be allowed through the proxy, but the
* connection will be forced to use offline mode even when proxy running in online mode
*
* @return the result
*/
public static PreLoginComponentResult forceOfflineMode() {
@ -131,6 +136,7 @@ public final class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLogin
/**
* Denies the login with the specified reason.
*
* @param reason the reason for disallowing the connection
* @return a new result
*/

Datei anzeigen

@ -12,6 +12,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* <p>This event is only called once per subject, on initialisation.</p>
*/
public final class PermissionsSetupEvent {
private final PermissionSubject subject;
private final PermissionProvider defaultProvider;
private PermissionProvider provider;
@ -26,8 +27,7 @@ public final class PermissionsSetupEvent {
}
/**
* Uses the provider function to obtain a {@link PermissionFunction} for
* the subject.
* Uses the provider function to obtain a {@link PermissionFunction} for the subject.
*
* @param subject the subject
* @return the obtained permission function

Datei anzeigen

@ -6,17 +6,20 @@ import com.velocitypowered.api.util.GameProfile;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* This event is fired after the {@link com.velocitypowered.api.event.connection.PreLoginEvent} in order to set up the
* game profile for the user. This can be used to configure a custom profile for a user, i.e. skin replacement.
* This event is fired after the {@link com.velocitypowered.api.event.connection.PreLoginEvent} in
* order to set up the game profile for the user. This can be used to configure a custom profile for
* a user, i.e. skin replacement.
*/
public final class GameProfileRequestEvent {
private final String username;
private final InboundConnection connection;
private final GameProfile originalProfile;
private final boolean onlineMode;
private @Nullable GameProfile gameProfile;
public GameProfileRequestEvent(InboundConnection connection, GameProfile originalProfile, boolean onlineMode) {
public GameProfileRequestEvent(InboundConnection connection, GameProfile originalProfile,
boolean onlineMode) {
this.connection = Preconditions.checkNotNull(connection, "connection");
this.originalProfile = Preconditions.checkNotNull(originalProfile, "originalProfile");
this.username = originalProfile.getName();
@ -40,9 +43,10 @@ public final class GameProfileRequestEvent {
}
/**
* Returns the game profile that will be used to initialize the connection with. Should no profile be currently
* specified, the one generated by the proxy (for offline mode) or retrieved from the Mojang session servers (for
* online mode) will be returned instead.
* Returns the game profile that will be used to initialize the connection with. Should no profile
* be currently specified, the one generated by the proxy (for offline mode) or retrieved from the
* Mojang session servers (for online mode) will be returned instead.
*
* @return the user's {@link GameProfile}
*/
public GameProfile getGameProfile() {
@ -50,11 +54,15 @@ public final class GameProfileRequestEvent {
}
/**
* Sets the game profile to use for this connection. It is invalid to use this method on an online-mode connection.
* @param gameProfile the profile to use for the connection, {@code null} uses the original profile
* Sets the game profile to use for this connection. It is invalid to use this method on an
* online-mode connection.
*
* @param gameProfile the profile to use for the connection, {@code null} uses the original
* profile
*/
public void setGameProfile(@Nullable GameProfile gameProfile) {
Preconditions.checkState(!onlineMode, "Connection is in online mode, profiles can not be faked");
Preconditions
.checkState(!onlineMode, "Connection is in online mode, profiles can not be faked");
this.gameProfile = gameProfile;
}

Datei anzeigen

@ -8,17 +8,20 @@ import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* Fired when a player is kicked from a server. You may either allow Velocity to kick the player (with an optional reason
* override) or redirect the player to a separate server.
* Fired when a player is kicked from a server. You may either allow Velocity to kick the player
* (with an optional reason override) or redirect the player to a separate server.
*/
public final class KickedFromServerEvent implements ResultedEvent<KickedFromServerEvent.ServerKickResult> {
public final class KickedFromServerEvent implements
ResultedEvent<KickedFromServerEvent.ServerKickResult> {
private final Player player;
private final RegisteredServer server;
private final Component originalReason;
private final boolean duringLogin;
private ServerKickResult result;
public KickedFromServerEvent(Player player, RegisteredServer server, Component originalReason, boolean duringLogin, Component fancyReason) {
public KickedFromServerEvent(Player player, RegisteredServer server, Component originalReason,
boolean duringLogin, Component fancyReason) {
this.player = Preconditions.checkNotNull(player, "player");
this.server = Preconditions.checkNotNull(server, "server");
this.originalReason = Preconditions.checkNotNull(originalReason, "originalReason");
@ -55,12 +58,15 @@ public final class KickedFromServerEvent implements ResultedEvent<KickedFromServ
/**
* Represents the base interface for {@link KickedFromServerEvent} results.
*/
public interface ServerKickResult extends ResultedEvent.Result {}
public interface ServerKickResult extends ResultedEvent.Result {
}
/**
* Tells the proxy to disconnect the player with the specified reason.
*/
public static final class DisconnectPlayer implements ServerKickResult {
private final Component component;
private DisconnectPlayer(Component component) {
@ -78,6 +84,7 @@ public final class KickedFromServerEvent implements ResultedEvent<KickedFromServ
/**
* Creates a new {@link DisconnectPlayer} with the specified reason.
*
* @param reason the reason to use when disconnecting the player
* @return the disconnect result
*/
@ -87,10 +94,11 @@ public final class KickedFromServerEvent implements ResultedEvent<KickedFromServ
}
/**
* Tells the proxy to redirect the player to another server. No messages will be sent from the proxy
* when this result is used.
* Tells the proxy to redirect the player to another server. No messages will be sent from the
* proxy when this result is used.
*/
public static final class RedirectPlayer implements ServerKickResult {
private final RegisteredServer server;
private RedirectPlayer(RegisteredServer server) {
@ -108,6 +116,7 @@ public final class KickedFromServerEvent implements ResultedEvent<KickedFromServ
/**
* Creates a new redirect result to forward the player to the specified {@code server}.
*
* @param server the server to send the player to
* @return the redirect result
*/

Datei anzeigen

@ -3,15 +3,15 @@ package com.velocitypowered.api.event.player;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.proxy.Player;
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Optional;
/**
* This event is fired when a player types in a chat message.
*/
public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.ChatResult> {
private final Player player;
private final String message;
private ChatResult result;
@ -53,6 +53,7 @@ public final class PlayerChatEvent implements ResultedEvent<PlayerChatEvent.Chat
* Represents the result of the {@link PlayerChatEvent}.
*/
public static final class ChatResult implements ResultedEvent.Result {
private static final ChatResult ALLOWED = new ChatResult(true, null);
private static final ChatResult DENIED = new ChatResult(false, null);

Datei anzeigen

@ -8,6 +8,7 @@ import com.velocitypowered.api.util.ModInfo;
* This event is fired when the players ModInfo is changed.
*/
public final class PlayerModInfoEvent {
private final Player player;
private final ModInfo modInfo;

Datei anzeigen

@ -5,6 +5,7 @@ import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.player.PlayerSettings;
public final class PlayerSettingsChangedEvent {
private final Player player;
private final PlayerSettings playerSettings;

Datei anzeigen

@ -5,10 +5,11 @@ import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
/**
* This event is fired once the player has successfully connected to the target server and the connection to the previous
* server has been de-established.
* This event is fired once the player has successfully connected to the target server and the
* connection to the previous server has been de-established.
*/
public final class ServerConnectedEvent {
private final Player player;
private final RegisteredServer server;

Datei anzeigen

@ -4,14 +4,15 @@ import com.google.common.base.Preconditions;
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* This event is fired before the player connects to a server.
*/
public final class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEvent.ServerResult> {
public final class ServerPreConnectEvent implements
ResultedEvent<ServerPreConnectEvent.ServerResult> {
private final Player player;
private final RegisteredServer originalServer;
private ServerResult result;
@ -53,6 +54,7 @@ public final class ServerPreConnectEvent implements ResultedEvent<ServerPreConne
* Represents the result of the {@link ServerPreConnectEvent}.
*/
public static class ServerResult implements ResultedEvent.Result {
private static final ServerResult DENIED = new ServerResult(null);
private final @Nullable RegisteredServer server;

Datei anzeigen

@ -1,9 +1,11 @@
package com.velocitypowered.api.event.proxy;
/**
* This event is fired by the proxy after plugins have been loaded but before the proxy starts accepting connections.
* This event is fired by the proxy after plugins have been loaded but before the proxy starts
* accepting connections.
*/
public final class ProxyInitializeEvent {
@Override
public String toString() {
return "ProxyInitializeEvent";

Datei anzeigen

@ -8,6 +8,7 @@ import com.velocitypowered.api.proxy.server.ServerPing;
* This event is fired when a server list ping request is sent by a remote client.
*/
public final class ProxyPingEvent {
private final InboundConnection connection;
private ServerPing ping;

Datei anzeigen

@ -1,10 +1,11 @@
package com.velocitypowered.api.event.proxy;
/**
* This event is fired by the proxy after the proxy has stopped accepting connections but before the proxy process
* exits.
* This event is fired by the proxy after the proxy has stopped accepting connections but before the
* proxy process exits.
*/
public final class ProxyShutdownEvent {
@Override
public String toString() {
return "ProxyShutdownEvent";

Datei anzeigen

@ -2,14 +2,14 @@ package com.velocitypowered.api.event.query;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.server.QueryResponse;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.net.InetAddress;
import org.checkerframework.checker.nullness.qual.NonNull;
/**
* This event is fired if proxy is getting queried over GS4 Query protocol
*/
public final class ProxyQueryEvent {
private final QueryType queryType;
private final InetAddress querierAddress;
private QueryResponse response;
@ -22,6 +22,7 @@ public final class ProxyQueryEvent {
/**
* Get query type
*
* @return query type
*/
@NonNull
@ -31,6 +32,7 @@ public final class ProxyQueryEvent {
/**
* Get querier address
*
* @return querier address
*/
@NonNull
@ -40,6 +42,7 @@ public final class ProxyQueryEvent {
/**
* Get query response
*
* @return query response
*/
@NonNull
@ -49,6 +52,7 @@ public final class ProxyQueryEvent {
/**
* Set query response
*
* @param response query response
*/
public void setResponse(@NonNull QueryResponse response) {
@ -69,15 +73,15 @@ public final class ProxyQueryEvent {
*/
public enum QueryType {
/**
* Basic query asks only a subset of information, such as hostname, game type (hardcoded to <pre>MINECRAFT</pre>), map,
* current players, max players, proxy port and proxy hostname
* Basic query asks only a subset of information, such as hostname, game type (hardcoded to
* <pre>MINECRAFT</pre>), map, current players, max players, proxy port and proxy hostname
*/
BASIC,
/**
* Full query asks pretty much everything present on this event (only hardcoded values cannot be modified here).
* Full query asks pretty much everything present on this event (only hardcoded values cannot be
* modified here).
*/
FULL
;
FULL;
}
}

Datei anzeigen

@ -1,11 +1,11 @@
package com.velocitypowered.api.permission;
/**
* Function that calculates the permission settings for a given
* {@link PermissionSubject}.
* Function that calculates the permission settings for a given {@link PermissionSubject}.
*/
@FunctionalInterface
public interface PermissionFunction {
/**
* A permission function that always returns {@link Tristate#TRUE}.
*/

Datei anzeigen

@ -5,6 +5,7 @@ package com.velocitypowered.api.permission;
*/
@FunctionalInterface
public interface PermissionProvider {
/**
* Creates a {@link PermissionFunction} for the subject.
*

Datei anzeigen

@ -4,6 +4,7 @@ package com.velocitypowered.api.permission;
* Represents a object that has a set of queryable permissions.
*/
public interface PermissionSubject {
/**
* Determines whether or not the subject has a particular permission.
*

Datei anzeigen

@ -34,7 +34,8 @@ public enum Tristate {
* Returns a {@link Tristate} from a boolean
*
* @param val the boolean value
* @return {@link #TRUE} or {@link #FALSE}, if the value is <code>true</code> or <code>false</code>, respectively.
* @return {@link #TRUE} or {@link #FALSE}, if the value is <code>true</code> or
* <code>false</code>, respectively.
*/
public static Tristate fromBoolean(boolean val) {
return val ? TRUE : FALSE;
@ -47,8 +48,8 @@ public enum Tristate {
* if the value is null.</p>
*
* @param val the boolean value
* @return {@link #UNDEFINED}, {@link #TRUE} or {@link #FALSE}, if the value
* is <code>null</code>, <code>true</code> or <code>false</code>, respectively.
* @return {@link #UNDEFINED}, {@link #TRUE} or {@link #FALSE}, if the value is <code>null</code>,
* <code>true</code> or <code>false</code>, respectively.
*/
public static Tristate fromNullableBoolean(@Nullable Boolean val) {
if (val == null) {

Datei anzeigen

@ -10,6 +10,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Dependency {
/**
* The plugin ID of the dependency.
*
@ -19,8 +20,7 @@ public @interface Dependency {
String id();
/**
* If this dependency is optional for the plugin to work. By default
* this is {@code false}.
* If this dependency is optional for the plugin to work. By default this is {@code false}.
*
* @return true if the dependency is optional for the plugin to work
*/

Datei anzeigen

@ -1,6 +1,7 @@
package com.velocitypowered.api.plugin;
public class InvalidPluginException extends Exception {
public InvalidPluginException() {
super();
}

Datei anzeigen

@ -11,9 +11,9 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Plugin {
/**
* The ID of the plugin. This ID should be unique as to
* not conflict with other plugins.
* The ID of the plugin. This ID should be unique as to not conflict with other plugins.
*
* The plugin ID must match the {@link PluginDescription#ID_PATTERN}.
*
@ -22,8 +22,7 @@ public @interface Plugin {
String id();
/**
* The human readable name of the plugin as to be used in descriptions and
* similar things.
* The human readable name of the plugin as to be used in descriptions and similar things.
*
* @return The plugin name, or an empty string if unknown
*/

Datei anzeigen

@ -6,6 +6,7 @@ import java.util.Optional;
* A wrapper around a plugin loaded by the proxy.
*/
public interface PluginContainer {
/**
* Returns the plugin's description.
*

Datei anzeigen

@ -3,7 +3,6 @@ package com.velocitypowered.api.plugin;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.velocitypowered.api.plugin.meta.PluginDependency;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@ -14,10 +13,11 @@ import java.util.regex.Pattern;
* Represents metadata for a specific version of a plugin.
*/
public interface PluginDescription {
/**
* The pattern plugin IDs must match. Plugin IDs may only contain
* alphanumeric characters, dashes or underscores, must start with
* an alphabetic character and cannot be longer than 64 characters.
* The pattern plugin IDs must match. Plugin IDs may only contain alphanumeric characters, dashes
* or underscores, must start with an alphabetic character and cannot be longer than 64
* characters.
*/
Pattern ID_PATTERN = Pattern.compile("[a-z][a-z0-9-_]{0,63}");
@ -80,8 +80,7 @@ public interface PluginDescription {
}
/**
* Gets a {@link Collection} of all dependencies of the {@link Plugin} within
* this container.
* Gets a {@link Collection} of all dependencies of the {@link Plugin} within this container.
*
* @return the plugin dependencies, can be empty
* @see Plugin#dependencies()
@ -97,8 +96,7 @@ public interface PluginDescription {
/**
* Returns the source the plugin was loaded from.
*
* @return the source the plugin was loaded from or {@link Optional#empty()}
* if unknown
* @return the source the plugin was loaded from or {@link Optional#empty()} if unknown
*/
default Optional<Path> getSource() {
return Optional.empty();

Datei anzeigen

@ -5,10 +5,12 @@ import java.util.Collection;
import java.util.Optional;
/**
* Manages plugins loaded on the proxy. This manager can retrieve {@link PluginContainer}s from plugin instances
* and inject arbitrary JAR files into the plugin classpath with {@link #addToClasspath(Object, Path)}.
* Manages plugins loaded on the proxy. This manager can retrieve {@link PluginContainer}s from
* plugin instances and inject arbitrary JAR files into the plugin classpath with {@link
* #addToClasspath(Object, Path)}.
*/
public interface PluginManager {
/**
* Gets the plugin container from an instance.
*

Datei anzeigen

@ -1,18 +1,18 @@
package com.velocitypowered.api.plugin.annotation;
import com.google.inject.BindingAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* This annotation requests that Velocity inject a {@link java.nio.file.Path} instance with a plugin-specific data
* directory.
* This annotation requests that Velocity inject a {@link java.nio.file.Path} instance with a
* plugin-specific data directory.
*/
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
public @interface DataDirectory {
}

Datei anzeigen

@ -1,18 +1,18 @@
package com.velocitypowered.api.plugin.meta;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Objects;
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a dependency on another plugin.
*/
public final class PluginDependency {
private final String id;
@Nullable
private final String version;
@ -45,8 +45,7 @@ public final class PluginDependency {
}
/**
* Returns whether the dependency is optional for the plugin to work
* correctly.
* Returns whether the dependency is optional for the plugin to work correctly.
*
* @return true if dependency is optional
*/
@ -56,8 +55,12 @@ public final class PluginDependency {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PluginDependency that = (PluginDependency) o;
return optional == that.optional &&
Objects.equals(id, that.id) &&

Datei anzeigen

@ -1,39 +1,44 @@
package com.velocitypowered.api.proxy;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import net.kyori.text.Component;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import net.kyori.text.Component;
/**
* Provides a fluent interface to compose and send a connection request to another server behind the proxy. A connection
* request is created using {@link Player#createConnectionRequest(RegisteredServer)}.
* Provides a fluent interface to compose and send a connection request to another server behind the
* proxy. A connection request is created using {@link Player#createConnectionRequest(RegisteredServer)}.
*/
public interface ConnectionRequestBuilder {
/**
* Returns the server that this connection request represents.
*
* @return the server this request will connect to
*/
RegisteredServer getServer();
/**
* Initiates the connection to the remote server and emits a result on the {@link CompletableFuture} after the user
* has logged on. No messages will be communicated to the client: the user is responsible for all error handling.
* Initiates the connection to the remote server and emits a result on the {@link
* CompletableFuture} after the user has logged on. No messages will be communicated to the
* client: the user is responsible for all error handling.
*
* @return a {@link CompletableFuture} representing the status of this connection
*/
CompletableFuture<Result> connect();
/**
* Initiates the connection to the remote server and emits a result on the {@link CompletableFuture} after the user
* has logged on. Velocity's own built-in handling will be used to provide errors to the client.
* Initiates the connection to the remote server and emits a result on the {@link
* CompletableFuture} after the user has logged on. Velocity's own built-in handling will be used
* to provide errors to the client.
*
* @return a {@link CompletableFuture} representing the status of this connection
*/
CompletableFuture<Boolean> connectWithIndication();
/**
* Initiates the connection to the remote server without waiting for a result. Velocity will use generic error
* handling code to notify the user.
* Initiates the connection to the remote server without waiting for a result. Velocity will use
* generic error handling code to notify the user.
*/
void fireAndForget();
@ -41,8 +46,10 @@ public interface ConnectionRequestBuilder {
* Represents the result of a connection request.
*/
interface Result {
/**
* Determines whether or not the connection request was successful.
*
* @return whether or not the request succeeded
*/
default boolean isSuccessful() {
@ -51,12 +58,14 @@ public interface ConnectionRequestBuilder {
/**
* Returns the status associated with this result.
*
* @return the status for this result
*/
Status getStatus();
/**
* Returns an (optional) textual reason for the failure to connect to the server.
*
* @return the reason why the user could not connect to the server
*/
Optional<Component> getReason();

Datei anzeigen

@ -7,26 +7,31 @@ import java.util.Optional;
* Represents an incoming connection to the proxy.
*/
public interface InboundConnection {
/**
* Returns the player's IP address.
*
* @return the player's IP
*/
InetSocketAddress getRemoteAddress();
/**
* Returns the hostname that the user entered into the client, if applicable.
*
* @return the hostname from the client
*/
Optional<InetSocketAddress> getVirtualHost();
/**
* Determine whether or not the player remains online.
*
* @return whether or not the player active
*/
boolean isActive();
/**
* Returns the current protocol version this connection uses.
*
* @return the protocol version the connection uses
*/
int getProtocolVersion();

Datei anzeigen

@ -4,61 +4,68 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
import com.velocitypowered.api.proxy.player.PlayerSettings;
import com.velocitypowered.api.proxy.player.TabList;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.proxy.player.TabList;
import com.velocitypowered.api.util.MessagePosition;
import com.velocitypowered.api.util.ModInfo;
import com.velocitypowered.api.util.title.Title;
import java.util.List;
import net.kyori.text.Component;
import java.util.Optional;
import java.util.UUID;
import net.kyori.text.Component;
/**
* Represents a player who is connected to the proxy.
*/
public interface Player extends CommandSource, InboundConnection, ChannelMessageSource, ChannelMessageSink {
public interface Player extends CommandSource, InboundConnection, ChannelMessageSource,
ChannelMessageSink {
/**
* Returns the player's current username.
*
* @return the username
*/
String getUsername();
/**
* Returns the player's UUID.
*
* @return the UUID
*/
UUID getUniqueId();
/**
* Returns the server that the player is currently connected to.
*
* @return an {@link Optional} the server that the player is connected to, which may be empty
*/
Optional<ServerConnection> getCurrentServer();
/**
* Returns the player settings
*
* @return the settings
*/
PlayerSettings getPlayerSettings();
/**
* Returns the player's mod info if they have a modded client.
*
* @return an {@link Optional} the mod info. which may be empty
*/
Optional<ModInfo> getModInfo();
/**
* Returns the current player's ping
*
* @return the player's ping or -1 if ping information is currently unknown
*/
long getPing();
/**
* Sends a chat message to the player's client.
*
* @param component the chat message to send
*/
default void sendMessage(Component component) {
@ -67,6 +74,7 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
/**
* Sends a chat message to the player's client in the specified position.
*
* @param component the chat message to send
* @param position the position for the message
*/
@ -74,6 +82,7 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
/**
* Creates a new connection request so that the player can connect to another server.
*
* @param server the server to connect to
* @return a new connection request
*/
@ -97,6 +106,7 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
/**
* Sets the tab list header and footer for the player.
*
* @param header the header component
* @param footer the footer component
* @deprecated Use {@link TabList#setHeaderAndFooter(Component, Component)}.
@ -106,6 +116,7 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
/**
* Clears the tab list header and footer for the player.
*
* @deprecated Use {@link TabList#clearHeaderAndFooter()}.
*/
@Deprecated
@ -113,26 +124,29 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
/**
* Returns the player's tab list.
*
* @return this player's tab list
*/
TabList getTabList();
/**
* Disconnects the player with the specified reason. Once this method is called, further calls to other {@link Player}
* methods will become undefined.
* Disconnects the player with the specified reason. Once this method is called, further calls to
* other {@link Player} methods will become undefined.
*
* @param reason component with the reason
*/
void disconnect(Component reason);
/**
* Sends the specified title to the client.
*
* @param title the title to send
*/
void sendTitle(Title title);
/**
* Sends chat input onto the players current server as if they typed it
* into the client chat box.
* Sends chat input onto the players current server as if they typed it into the client chat box.
*
* @param input the chat input to send
*/
void spoofChatInput(String input);

Datei anzeigen

@ -10,19 +10,21 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import com.velocitypowered.api.scheduler.Scheduler;
import com.velocitypowered.api.util.ProxyVersion;
import net.kyori.text.Component;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
import net.kyori.text.Component;
/**
* Provides an interface to a Minecraft server proxy.
*/
public interface ProxyServer {
/**
* Retrieves the player currently connected to this proxy by their Minecraft username. The search is case-insensitive.
* Retrieves the player currently connected to this proxy by their Minecraft username. The search
* is case-insensitive.
*
* @param username the username to search for
* @return an {@link Optional} with the player, which may be empty
*/
@ -30,6 +32,7 @@ public interface ProxyServer {
/**
* Retrieves the player currently connected to this proxy by their Minecraft UUID.
*
* @param uuid the UUID
* @return an {@link Optional} with the player, which may be empty
*/
@ -37,25 +40,30 @@ public interface ProxyServer {
/**
* Broadcasts a message to all players currently online.
*
* @param component the message to send
*/
void broadcast(Component component);
/**
* Retrieves all players currently connected to this proxy. This call may or may not be a snapshot of all players
* online.
* Retrieves all players currently connected to this proxy. This call may or may not be a snapshot
* of all players online.
*
* @return the players online on this proxy
*/
Collection<Player> getAllPlayers();
/**
* Returns the number of players currently connected to this proxy.
*
* @return the players on this proxy
*/
int getPlayerCount();
/**
* Retrieves a registered {@link RegisteredServer} instance by its name. The search is case-insensitive.
* Retrieves a registered {@link RegisteredServer} instance by its name. The search is
* case-insensitive.
*
* @param name the name of the server
* @return the registered server, which may be empty
*/
@ -63,12 +71,14 @@ public interface ProxyServer {
/**
* Retrieves all {@link RegisteredServer}s registered with this proxy.
*
* @return the servers registered with this proxy
*/
Collection<RegisteredServer> getAllServers();
/**
* Registers a server with this proxy. A server with this name should not already exist.
*
* @param server the server to register
* @return the newly registered server
*/
@ -76,14 +86,17 @@ public interface ProxyServer {
/**
* Unregisters this server from the proxy.
*
* @param server the server to unregister
*/
void unregisterServer(ServerInfo server);
/**
* Returns an instance of {@link CommandSource} that can be used to determine if the command is being invoked by
* the console or a console-like executor. Plugins that execute commands are strongly urged to implement their own
* {@link CommandSource} instead of using the console invoker.
* Returns an instance of {@link CommandSource} that can be used to determine if the command is
* being invoked by the console or a console-like executor. Plugins that execute commands are
* strongly urged to implement their own {@link CommandSource} instead of using the console
* invoker.
*
* @return the console command invoker
*/
CommandSource getConsoleCommandSource();
@ -104,37 +117,43 @@ public interface ProxyServer {
/**
* Gets the {@link CommandManager} instance.
*
* @return the command manager
*/
CommandManager getCommandManager();
/**
* Gets the {@link Scheduler} instance.
*
* @return the scheduler instance
*/
Scheduler getScheduler();
/**
* Gets the {@link ChannelRegistrar} instance.
*
* @return the channel registrar
*/
ChannelRegistrar getChannelRegistrar();
/**
* Gets the address that this proxy is bound to. This does not necessarily indicate the external IP address of the
* proxy.
* Gets the address that this proxy is bound to. This does not necessarily indicate the external
* IP address of the proxy.
*
* @return the address the proxy is bound to
*/
InetSocketAddress getBoundAddress();
/**
* Gets the {@link ProxyConfig} instance.
*
* @return the proxy config
* */
*/
ProxyConfig getConfiguration();
/**
* Returns the version of the proxy.
*
* @return the proxy version
*/
ProxyVersion getVersion();

Datei anzeigen

@ -9,20 +9,24 @@ import com.velocitypowered.api.proxy.server.ServerInfo;
* Represents a connection to a backend server from the proxy for a client.
*/
public interface ServerConnection extends ChannelMessageSource, ChannelMessageSink {
/**
* Returns the server that this connection is connected to.
*
* @return the server this connection is connected to
*/
RegisteredServer getServer();
/**
* Returns the server info for this connection.
*
* @return the server info for this connection
*/
ServerInfo getServerInfo();
/**
* Returns the player that this connection is associated with.
*
* @return the player for this connection
*/
Player getPlayer();

Datei anzeigen

@ -1,115 +1,132 @@
package com.velocitypowered.api.proxy.config;
import com.velocitypowered.api.util.Favicon;
import net.kyori.text.Component;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import net.kyori.text.Component;
/**
* Provides an interface to a proxy configuration
*/
public interface ProxyConfig {
/**
* Whether GameSpy 4 queries are accepted by the proxy
*
* @return queries enabled
*/
boolean isQueryEnabled();
/**
* Get the port GameSpy 4 queries are accepted on
*
* @return the query port
*/
int getQueryPort();
/**
* Get the map name reported to GameSpy 4 query services
*
* @return the map name
*/
String getQueryMap();
/**
* Whether GameSpy 4 queries should show plugins installed on
* Velocity by default
* Whether GameSpy 4 queries should show plugins installed on Velocity by default
*
* @return show plugins in query
*/
boolean shouldQueryShowPlugins();
/**
* Get the MOTD component shown in the tab list
*
* @return the motd component
*/
Component getMotdComponent();
/**
* Get the maximum players shown in the tab list
*
* @return max players
*/
int getShowMaxPlayers();
/**
* Get whether the proxy is online mode. This determines if players are authenticated with Mojang servers.
* Get whether the proxy is online mode. This determines if players are authenticated with Mojang
* servers.
*
* @return online mode enabled
*/
boolean isOnlineMode();
/**
* Get a Map of all servers registered on this proxy
*
* @return registered servers map
*/
Map<String, String> getServers();
/**
* Get the order of servers that players will be connected to
*
* @return connection order list
*/
List<String> getAttemptConnectionOrder();
/**
* Get forced servers mapped to given virtual host
*
* @return list of server names
*/
Map<String, List<String>> getForcedHosts();
/**
* Get the minimum compression threshold for packets
*
* @return the compression threshold
*/
int getCompressionThreshold();
/**
* Get the level of compression that packets will be compressed to
*
* @return the compression level
*/
int getCompressionLevel();
/**
* Get the limit for how long a player must wait to log back in
*
* @return the login rate limit (in milliseconds)
*/
int getLoginRatelimit();
/**
* Get the proxy favicon shown in the tablist
*
* @return optional favicon
*/
Optional<Favicon> getFavicon();
/**
* Get whether this proxy displays that it supports Forge/FML
*
* @return forge announce enabled
*/
boolean isAnnounceForge();
/**
* Get how long this proxy will wait until performing a read timeout
*
* @return connection timeout (in milliseconds)
*/
int getConnectTimeout();
/**
* Get how long this proxy will wait until performing a read timeout
*
* @return read timeout (in milliseconds)
*/
int getReadTimeout();

Datei anzeigen

@ -4,8 +4,10 @@ package com.velocitypowered.api.proxy.messages;
* Represents a kind of channel identifier.
*/
public interface ChannelIdentifier {
/**
* Returns the textual representation of this identifier.
*
* @return the textual representation of the identifier
*/
String getId();

Datei anzeigen

@ -4,8 +4,10 @@ package com.velocitypowered.api.proxy.messages;
* Represents something that can send plugin messages.
*/
public interface ChannelMessageSink {
/**
* Sends a plugin message to this target.
*
* @param identifier the channel identifier to send the message on
* @param data the data to send
* @return whether or not the message could be sent

Datei anzeigen

@ -4,4 +4,5 @@ package com.velocitypowered.api.proxy.messages;
* A marker interface that indicates a source of plugin messages.
*/
public interface ChannelMessageSource {
}

Datei anzeigen

@ -1,17 +1,21 @@
package com.velocitypowered.api.proxy.messages;
/**
* Represents an interface to register and unregister {@link ChannelIdentifier}s for the proxy to listen on.
* Represents an interface to register and unregister {@link ChannelIdentifier}s for the proxy to
* listen on.
*/
public interface ChannelRegistrar {
/**
* Registers the specified message identifiers to listen on for the
*
* @param identifiers the channel identifiers to register
*/
void register(ChannelIdentifier... identifiers);
/**
* Unregisters the handler for the specified channel.
*
* @param identifiers the identifiers to unregister
*/
void unregister(ChannelIdentifier... identifiers);

Datei anzeigen

@ -2,15 +2,16 @@ package com.velocitypowered.api.proxy.messages;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
/**
* Reperesents a legacy channel identifier (for Minecraft 1.12 and below). For modern 1.13 plugin messages, please see
* {@link MinecraftChannelIdentifier}. This class is immutable and safe for multi-threaded use.
* Reperesents a legacy channel identifier (for Minecraft 1.12 and below). For modern 1.13 plugin
* messages, please see {@link MinecraftChannelIdentifier}. This class is immutable and safe for
* multi-threaded use.
*/
public final class LegacyChannelIdentifier implements ChannelIdentifier {
private final String name;
public LegacyChannelIdentifier(String name) {
@ -29,8 +30,12 @@ public final class LegacyChannelIdentifier implements ChannelIdentifier {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LegacyChannelIdentifier that = (LegacyChannelIdentifier) o;
return Objects.equals(name, that.name);
}

Datei anzeigen

@ -2,15 +2,16 @@ package com.velocitypowered.api.proxy.messages;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
import java.util.regex.Pattern;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a Minecraft 1.13+ channel identifier. This class is immutable and safe for multi-threaded use.
* Represents a Minecraft 1.13+ channel identifier. This class is immutable and safe for
* multi-threaded use.
*/
public final class MinecraftChannelIdentifier implements ChannelIdentifier {
private static final Pattern VALID_IDENTIFIER_REGEX = Pattern.compile("[a-z0-9\\-_]+");
private final String namespace;
@ -22,8 +23,9 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
}
/**
* Creates an identifier in the default namespace ({@code minecraft}). Plugins are strongly encouraged to provide
* their own namespace.
* Creates an identifier in the default namespace ({@code minecraft}). Plugins are strongly
* encouraged to provide their own namespace.
*
* @param name the name in the default namespace to use
* @return a new channel identifier
*/
@ -33,6 +35,7 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
/**
* Creates an identifier in the specified namespace.
*
* @param namespace the namespace to use
* @param name the channel name inside the specified namespace
* @return a new channel identifier
@ -40,8 +43,10 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
public static MinecraftChannelIdentifier create(String namespace, String name) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(namespace), "namespace is null or empty");
Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "namespace is null or empty");
Preconditions.checkArgument(VALID_IDENTIFIER_REGEX.matcher(namespace).matches(), "namespace is not valid");
Preconditions.checkArgument(VALID_IDENTIFIER_REGEX.matcher(name).matches(), "name is not valid");
Preconditions.checkArgument(VALID_IDENTIFIER_REGEX.matcher(namespace).matches(),
"namespace is not valid");
Preconditions
.checkArgument(VALID_IDENTIFIER_REGEX.matcher(name).matches(), "name is not valid");
return new MinecraftChannelIdentifier(namespace, name);
}
@ -60,8 +65,12 @@ public final class MinecraftChannelIdentifier implements ChannelIdentifier {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MinecraftChannelIdentifier that = (MinecraftChannelIdentifier) o;
return Objects.equals(namespace, that.namespace) &&
Objects.equals(name, that.name);

Datei anzeigen

@ -1,4 +1,5 @@
/**
* Provides an interface to receive, handle, and send plugin messages on the proxy from clients and servers.
* Provides an interface to receive, handle, and send plugin messages on the proxy from clients and
* servers.
*/
package com.velocitypowered.api.proxy.messages;

Datei anzeigen

@ -6,39 +6,46 @@ import java.util.Locale;
* Represents the client settings for the player.
*/
public interface PlayerSettings {
/**
* Returns the locale of the Minecraft client.
*
* @return the client locale
*/
Locale getLocale();
/**
* Returns the client's view distance. This does not guarantee the client will see this many chunks, since your
* servers are responsible for sending the chunks.
* Returns the client's view distance. This does not guarantee the client will see this many
* chunks, since your servers are responsible for sending the chunks.
*
* @return the client view distance
*/
byte getViewDistance();
/**
* Returns the chat setting for the client.
*
* @return the chat setting
*/
ChatMode getChatMode();
/**
* Returns whether or not the client has chat colors disabled.
*
* @return whether or not the client has chat colors disabled
*/
boolean hasChatColors();
/**
* Returns the parts of player skins the client will show.
*
* @return the skin parts for the client
*/
SkinParts getSkinParts();
/**
* Returns the primary hand of the client.
*
* @return the primary hand of the client
*/
MainHand getMainHand();

Datei anzeigen

@ -1,6 +1,7 @@
package com.velocitypowered.api.proxy.player;
public final class SkinParts {
private final byte bitmask;
public SkinParts(byte skinBitmask) {

Datei anzeigen

@ -2,19 +2,20 @@ package com.velocitypowered.api.proxy.player;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.util.GameProfile;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents the tab list of a {@link Player}.
*/
public interface TabList {
/**
* Sets the tab list header and footer for the player.
*
* @param header the header component
* @param footer the footer component
*/
@ -27,26 +28,30 @@ public interface TabList {
/**
* Adds a {@link TabListEntry} to the {@link Player}'s tab list.
*
* @param entry to add to the tab list
*/
void addEntry(TabListEntry entry);
/**
* Removes the {@link TabListEntry} from the tab list with the {@link GameProfile}
* identified with the specified {@link UUID}.
* Removes the {@link TabListEntry} from the tab list with the {@link GameProfile} identified with
* the specified {@link UUID}.
*
* @param uuid of the
* @return {@link Optional} containing the removed {@link TabListEntry} if present,
* otherwise {@link Optional#empty()}
* @return {@link Optional} containing the removed {@link TabListEntry} if present, otherwise
* {@link Optional#empty()}
*/
Optional<TabListEntry> removeEntry(UUID uuid);
/**
* Returns an immutable {@link Collection} of the {@link TabListEntry}s in the tab list.
*
* @return immutable {@link Collection} of tab list entries
*/
Collection<TabListEntry> getEntries();
// Necessary because the TabListEntry implementation isn't in the api
@Deprecated
TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, int gameMode);
TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
int gameMode);
}

Datei anzeigen

@ -1,25 +1,27 @@
package com.velocitypowered.api.proxy.player;
import com.velocitypowered.api.util.GameProfile;
import java.util.Optional;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Optional;
/**
* Represents a single entry in a {@link TabList}.
*/
public interface TabListEntry {
/**
* Returns the parent {@link TabList} of this {@code this} {@link TabListEntry}.
*
* @return parent {@link TabList}
*/
TabList getTabList();
/**
* Returns the {@link GameProfile} of the entry, which uniquely identifies the entry
* with the containing {@link java.util.UUID}, as well as deciding what is shown
* as the player head in the tab list.
* Returns the {@link GameProfile} of the entry, which uniquely identifies the entry with the
* containing {@link java.util.UUID}, as well as deciding what is shown as the player head in the
* tab list.
*
* @return {@link GameProfile} of the entry
*/
GameProfile getProfile();
@ -27,13 +29,15 @@ public interface TabListEntry {
/**
* Returns {@link Optional} text {@link Component}, which if present is the text displayed for
* {@code this} entry in the {@link TabList}, otherwise {@link GameProfile#getName()} is shown.
*
* @return {@link Optional} text {@link Component} of name displayed in the tab list
*/
Optional<Component> getDisplayName();
/**
* Sets the text {@link Component} to be displayed for {@code this} {@link TabListEntry}.
* If {@code null}, {@link GameProfile#getName()} will be shown.
* Sets the text {@link Component} to be displayed for {@code this} {@link TabListEntry}. If
* {@code null}, {@link GameProfile#getName()} will be shown.
*
* @param displayName to show in the {@link TabList} for {@code this} entry
* @return {@code this}, for chaining
*/
@ -51,15 +55,17 @@ public interface TabListEntry {
* <li>A latency move than 1 second will display 1 bar</li>
* <li></li>
* </ul>
*
* @return latency set for {@code this} entry
*/
int getLatency();
/**
* Sets the latency for {@code this} entry to the specified value
* @see #getLatency()
*
* @param latency to changed to
* @return {@code this}, for chaining
* @see #getLatency()
*/
TabListEntry setLatency(int latency);
@ -72,20 +78,23 @@ public interface TabListEntry {
* <li>Adventure</li>
* <li>Spectator</li>
* </ol>
*
* @return the game mode
*/
int getGameMode();
/**
* Sets the game mode for {@code this} entry to the specified value
* @see #getGameMode()
*
* @param gameMode to change to
* @return {@code this}, for chaining
* @see #getGameMode()
*/
TabListEntry setGameMode(int gameMode);
/**
* Returns a {@link Builder} to create a {@link TabListEntry}.
*
* @return {@link TabListEntry} builder
*/
static Builder builder() {
@ -94,20 +103,24 @@ public interface TabListEntry {
/**
* Represents a builder which creates {@link TabListEntry}s.
*
* @see TabListEntry
*/
class Builder {
private @Nullable TabList tabList;
private @Nullable GameProfile profile;
private @Nullable Component displayName;
private int latency = 0;
private int gameMode = 0;
private Builder() {}
private Builder() {
}
/**
* Sets the parent {@link TabList} for this entry,
* the entry will only be able to be added to that specific {@link TabList}.
* Sets the parent {@link TabList} for this entry, the entry will only be able to be added to
* that specific {@link TabList}.
*
* @param tabList to set
* @return {@code this}, for chaining
*/
@ -118,9 +131,10 @@ public interface TabListEntry {
/**
* Sets the {@link GameProfile} of the {@link TabListEntry}.
* @see TabListEntry#getProfile()
*
* @param profile to set
* @return {@code this}, for chaining
* @see TabListEntry#getProfile()
*/
public Builder profile(GameProfile profile) {
this.profile = profile;
@ -129,9 +143,10 @@ public interface TabListEntry {
/**
* Sets the displayed name of the {@link TabListEntry}
* @see TabListEntry#getDisplayName()
*
* @param displayName to set
* @return {@code this}, for chaining
* @see TabListEntry#getDisplayName()
*/
public Builder displayName(@Nullable Component displayName) {
this.displayName = displayName;
@ -140,9 +155,10 @@ public interface TabListEntry {
/**
* Sets the latency of the {@link TabListEntry}
* @see TabListEntry#getLatency()
*
* @param latency to set
* @return {@code this}, for chaining
* @see TabListEntry#getLatency()
*/
public Builder latency(int latency) {
this.latency = latency;
@ -151,9 +167,10 @@ public interface TabListEntry {
/**
* Sets the game mode of the {@link TabListEntry}
* @see TabListEntry#getGameMode()
*
* @param gameMode to set
* @return {@code this}, for chaining
* @see TabListEntry#getGameMode()
*/
public Builder gameMode(int gameMode) {
this.gameMode = gameMode;
@ -162,6 +179,7 @@ public interface TabListEntry {
/**
* Constructs the {@link TabListEntry} specified by {@code this} {@link Builder}.
*
* @return the constructed {@link TabListEntry}
*/
public TabListEntry build() {

Datei anzeigen

@ -3,18 +3,18 @@ package com.velocitypowered.api.proxy.server;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.proxy.config.ProxyConfig;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* GS4 query response. This class is immutable.
*/
public final class QueryResponse {
private final String hostname;
private final String gameVersion;
private final String map;
@ -26,7 +26,9 @@ public final class QueryResponse {
private final String proxyVersion;
private final Collection<PluginInformation> plugins;
private QueryResponse(String hostname, String gameVersion, String map, int currentPlayers, int maxPlayers, String proxyHost, int proxyPort, Collection<String> players, String proxyVersion, Collection<PluginInformation> plugins) {
private QueryResponse(String hostname, String gameVersion, String map, int currentPlayers,
int maxPlayers, String proxyHost, int proxyPort, Collection<String> players,
String proxyVersion, Collection<PluginInformation> plugins) {
this.hostname = hostname;
this.gameVersion = gameVersion;
this.map = map;
@ -40,7 +42,9 @@ public final class QueryResponse {
}
/**
* Get hostname which will be used to reply to the query. By default it is {@link ProxyConfig#getMotdComponent()} in plain text without colour codes.
* Get hostname which will be used to reply to the query. By default it is {@link
* ProxyConfig#getMotdComponent()} in plain text without colour codes.
*
* @return hostname
*/
public String getHostname() {
@ -48,7 +52,9 @@ public final class QueryResponse {
}
/**
* Get game version which will be used to reply to the query. By default supported Minecraft versions range is sent.
* Get game version which will be used to reply to the query. By default supported Minecraft
* versions range is sent.
*
* @return game version
*/
public String getGameVersion() {
@ -56,7 +62,9 @@ public final class QueryResponse {
}
/**
* Get map name which will be used to reply to the query. By default {@link ProxyConfig#getQueryMap()} is sent.
* Get map name which will be used to reply to the query. By default {@link
* ProxyConfig#getQueryMap()} is sent.
*
* @return map name
*/
public String getMap() {
@ -65,6 +73,7 @@ public final class QueryResponse {
/**
* Get current online player count which will be used to reply to the query.
*
* @return online player count
*/
public int getCurrentPlayers() {
@ -73,6 +82,7 @@ public final class QueryResponse {
/**
* Get max player count which will be used to reply to the query.
*
* @return max player count
*/
public int getMaxPlayers() {
@ -81,6 +91,7 @@ public final class QueryResponse {
/**
* Get proxy (public facing) hostname
*
* @return proxy hostname
*/
public String getProxyHost() {
@ -89,6 +100,7 @@ public final class QueryResponse {
/**
* Get proxy (public facing) port
*
* @return proxy port
*/
public int getProxyPort() {
@ -97,6 +109,7 @@ public final class QueryResponse {
/**
* Get collection of players which will be used to reply to the query.
*
* @return collection of players
*/
public Collection<String> getPlayers() {
@ -105,6 +118,7 @@ public final class QueryResponse {
/**
* Get server software (name and version) which will be used to reply to the query.
*
* @return server software
*/
public String getProxyVersion() {
@ -113,6 +127,7 @@ public final class QueryResponse {
/**
* Get list of plugins which will be used to reply to the query.
*
* @return collection of plugins
*/
public Collection<PluginInformation> getPlugins() {
@ -122,6 +137,7 @@ public final class QueryResponse {
/**
* Creates a new {@link Builder} instance from data represented by this response
*
* @return {@link QueryResponse} builder
*/
public Builder toBuilder() {
@ -140,6 +156,7 @@ public final class QueryResponse {
/**
* Creates a new {@link Builder} instance
*
* @return {@link QueryResponse} builder
*/
public static Builder builder() {
@ -150,6 +167,7 @@ public final class QueryResponse {
* A builder for {@link QueryResponse} objects.
*/
public static final class Builder {
@MonotonicNonNull
private String hostname;
@ -172,7 +190,8 @@ public final class QueryResponse {
private List<String> players = new ArrayList<>();
private List<PluginInformation> plugins = new ArrayList<>();
private Builder() {}
private Builder() {
}
public Builder hostname(String hostname) {
this.hostname = Preconditions.checkNotNull(hostname, "hostname");
@ -207,7 +226,8 @@ public final class QueryResponse {
}
public Builder proxyPort(int proxyPort) {
Preconditions.checkArgument(proxyPort >= 1 && proxyPort <= 65535, "proxyPort must be between 1-65535");
Preconditions
.checkArgument(proxyPort >= 1 && proxyPort <= 65535, "proxyPort must be between 1-65535");
this.proxyPort = proxyPort;
return this;
}
@ -249,6 +269,7 @@ public final class QueryResponse {
/**
* Builds new {@link QueryResponse} with supplied data
*
* @return response
*/
public QueryResponse build() {
@ -271,6 +292,7 @@ public final class QueryResponse {
* Plugin information
*/
public static class PluginInformation {
private String name;
private String version;

Datei anzeigen

@ -2,7 +2,6 @@ package com.velocitypowered.api.proxy.server;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
@ -10,20 +9,24 @@ import java.util.concurrent.CompletableFuture;
* Represents a server that has been registered with the proxy.
*/
public interface RegisteredServer extends ChannelMessageSink {
/**
* Returns the {@link ServerInfo} for this server.
*
* @return the server info
*/
ServerInfo getServerInfo();
/**
* Returns a list of all the players currently connected to this server on this proxy.
*
* @return the players on this proxy
*/
Collection<Player> getPlayersConnected();
/**
* Attempts to ping the remote server and return the server list ping result.
*
* @return the server ping result from the server
*/
CompletableFuture<ServerPing> ping();

Datei anzeigen

@ -1,20 +1,22 @@
package com.velocitypowered.api.proxy.server;
import com.google.common.base.Preconditions;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.net.InetSocketAddress;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* ServerInfo represents a server that a player can connect to. This object is immutable and safe for concurrent access.
* ServerInfo represents a server that a player can connect to. This object is immutable and safe
* for concurrent access.
*/
public final class ServerInfo {
private final String name;
private final InetSocketAddress address;
/**
* Creates a new ServerInfo object.
*
* @param name the name for the server
* @param address the address of the server to connect to
*/
@ -41,8 +43,12 @@ public final class ServerInfo {
@Override
public final boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ServerInfo that = (ServerInfo) o;
return Objects.equals(name, that.name) &&
Objects.equals(address, that.address);

Datei anzeigen

@ -4,26 +4,32 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.api.util.ModInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.*;
/**
* Represents a 1.7 and above server list ping response. This class is immutable.
*/
public final class ServerPing {
private final Version version;
private final @Nullable Players players;
private final Component description;
private final @Nullable Favicon favicon;
private final @Nullable ModInfo modinfo;
public ServerPing(Version version, @Nullable Players players, Component description, @Nullable Favicon favicon) {
public ServerPing(Version version, @Nullable Players players, Component description,
@Nullable Favicon favicon) {
this(version, players, description, favicon, ModInfo.DEFAULT);
}
public ServerPing(Version version, @Nullable Players players, Component description, @Nullable Favicon favicon, @Nullable ModInfo modinfo) {
public ServerPing(Version version, @Nullable Players players, Component description,
@Nullable Favicon favicon, @Nullable ModInfo modinfo) {
this.version = Preconditions.checkNotNull(version, "version");
this.players = players;
this.description = Preconditions.checkNotNull(description, "description");
@ -89,6 +95,7 @@ public final class ServerPing {
* A builder for {@link ServerPing} objects.
*/
public static final class Builder {
private Version version = new Version(0, "Unknown");
private int onlinePlayers;
private int maximumPlayers;
@ -171,7 +178,8 @@ public final class ServerPing {
if (this.description == null) {
throw new IllegalStateException("no server description supplied");
}
return new ServerPing(version, nullOutPlayers ? null : new Players(onlinePlayers, maximumPlayers, samplePlayers),
return new ServerPing(version,
nullOutPlayers ? null : new Players(onlinePlayers, maximumPlayers, samplePlayers),
description, favicon, nullOutModinfo ? null : new ModInfo(modType, mods));
}
@ -225,6 +233,7 @@ public final class ServerPing {
}
public static final class Version {
private final int protocol;
private final String name;
@ -251,6 +260,7 @@ public final class ServerPing {
}
public static final class Players {
private final int online;
private final int max;
private final List<SamplePlayer> sample;
@ -284,6 +294,7 @@ public final class ServerPing {
}
public static final class SamplePlayer {
private final String name;
private final UUID id;

Datei anzeigen

@ -4,21 +4,24 @@ package com.velocitypowered.api.scheduler;
* Represents a task that is scheduled to run on the proxy.
*/
public interface ScheduledTask {
/**
* Returns the plugin that scheduled this task.
*
* @return the plugin that scheduled this task
*/
Object plugin();
/**
* Returns the current status of this task.
*
* @return the current status of this task
*/
TaskStatus status();
/**
* Cancels this task. If the task is already running, the thread in which it is running will be interrupted.
* If the task is not currently running, Velocity will terminate it safely.
* Cancels this task. If the task is already running, the thread in which it is running will be
* interrupted. If the task is not currently running, Velocity will terminate it safely.
*/
void cancel();
}

Datei anzeigen

@ -1,15 +1,16 @@
package com.velocitypowered.api.scheduler;
import org.checkerframework.common.value.qual.IntRange;
import java.util.concurrent.TimeUnit;
import org.checkerframework.common.value.qual.IntRange;
/**
* Represents a scheduler to execute tasks on the proxy.
*/
public interface Scheduler {
/**
* Initializes a new {@link TaskBuilder} for creating a task on the proxy.
*
* @param plugin the plugin to request the task for
* @param runnable the task to run when scheduled
* @return the task builder
@ -20,8 +21,10 @@ public interface Scheduler {
* Represents a fluent interface to schedule tasks on the proxy.
*/
interface TaskBuilder {
/**
* Specifies that the task should delay its execution by the specified amount of time.
*
* @param time the time to delay by
* @param unit the unit of time for {@code time}
* @return this builder, for chaining
@ -29,7 +32,9 @@ public interface Scheduler {
TaskBuilder delay(@IntRange(from = 0) long time, TimeUnit unit);
/**
* Specifies that the task should continue running after waiting for the specified amount, until it is cancelled.
* Specifies that the task should continue running after waiting for the specified amount, until
* it is cancelled.
*
* @param time the time to delay by
* @param unit the unit of time for {@code time}
* @return this builder, for chaining
@ -38,18 +43,21 @@ public interface Scheduler {
/**
* Clears the delay on this task.
*
* @return this builder, for chaining
*/
TaskBuilder clearDelay();
/**
* Clears the repeat interval on this task.
*
* @return this builder, for chaining
*/
TaskBuilder clearRepeat();
/**
* Schedules this task for execution.
*
* @return the scheduled task
*/
ScheduledTask schedule();

Datei anzeigen

@ -1,9 +1,6 @@
package com.velocitypowered.api.util;
import com.google.common.base.Preconditions;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -12,17 +9,22 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.Objects;
import javax.imageio.ImageIO;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a Minecraft server favicon. A Minecraft server favicon is a 64x64 image that can be displayed to a remote
* client that sends a Server List Ping packet, and is automatically displayed in the Minecraft client.
* Represents a Minecraft server favicon. A Minecraft server favicon is a 64x64 image that can be
* displayed to a remote client that sends a Server List Ping packet, and is automatically displayed
* in the Minecraft client.
*/
public final class Favicon {
private final String base64Url;
/**
* Directly create a favicon using its Base64 URL directly. You are generally better served by the create() series
* of functions.
* Directly create a favicon using its Base64 URL directly. You are generally better served by the
* create() series of functions.
*
* @param base64Url the url for use with this favicon
*/
public Favicon(String base64Url) {
@ -31,6 +33,7 @@ public final class Favicon {
/**
* Returns the Base64-encoded URI for this image.
*
* @return a URL representing this favicon
*/
public String getBase64Url() {
@ -39,8 +42,12 @@ public final class Favicon {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Favicon favicon = (Favicon) o;
return Objects.equals(base64Url, favicon.base64Url);
}
@ -59,12 +66,14 @@ public final class Favicon {
/**
* Creates a new {@code Favicon} from the specified {@code image}.
*
* @param image the image to use for the favicon
* @return the created {@link Favicon} instance
*/
public static Favicon create(BufferedImage image) {
Preconditions.checkNotNull(image, "image");
Preconditions.checkArgument(image.getWidth() == 64 && image.getHeight() == 64, "Image does not have" +
Preconditions
.checkArgument(image.getWidth() == 64 && image.getHeight() == 64, "Image does not have" +
" 64x64 dimensions (found %sx%s)", image.getWidth(), image.getHeight());
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
@ -72,11 +81,13 @@ public final class Favicon {
} catch (IOException e) {
throw new AssertionError(e);
}
return new Favicon("data:image/png;base64," + Base64.getEncoder().encodeToString(os.toByteArray()));
return new Favicon(
"data:image/png;base64," + Base64.getEncoder().encodeToString(os.toByteArray()));
}
/**
* Creates a new {@code Favicon} by reading the image from the specified {@code path}.
*
* @param path the path to the image to create a favicon for
* @return the created {@link Favicon} instance
* @throws IOException if the file could not be read from the path

Datei anzeigen

@ -2,7 +2,6 @@ package com.velocitypowered.api.util;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.UUID;
@ -10,6 +9,7 @@ import java.util.UUID;
* Represents a Mojang game profile. This class is immutable.
*/
public final class GameProfile {
private final String id;
private final String name;
private final List<Property> properties;
@ -38,6 +38,7 @@ public final class GameProfile {
/**
* Creates a game profile suitable for use in offline-mode.
*
* @param username the username to use
* @return the new offline-mode game profile
*/
@ -57,6 +58,7 @@ public final class GameProfile {
}
public static final class Property {
private final String name;
private final String value;
private final String signature;

Datei anzeigen

@ -5,7 +5,8 @@ package com.velocitypowered.api.util;
*/
public enum MessagePosition {
/**
* The chat message will appear in the client's HUD. These messages can be filtered out by the client.
* The chat message will appear in the client's HUD. These messages can be filtered out by the
* client.
*/
CHAT,
/**
@ -13,8 +14,8 @@ public enum MessagePosition {
*/
SYSTEM,
/**
* The chat message will appear above the player's main HUD. This text format doesn't support many component features,
* such as hover events.
* The chat message will appear above the player's main HUD. This text format doesn't support many
* component features, such as hover events.
*/
ACTION_BAR
}

Datei anzeigen

@ -2,10 +2,10 @@ package com.velocitypowered.api.util;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.List;
public final class ModInfo {
public static final ModInfo DEFAULT = new ModInfo("FML", ImmutableList.of());
private final String type;
@ -33,6 +33,7 @@ public final class ModInfo {
}
public static final class Mod {
private final String id;
private final String version;

Datei anzeigen

@ -1,14 +1,14 @@
package com.velocitypowered.api.util;
import com.google.common.base.Preconditions;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Provides a version object for the proxy.
*/
public final class ProxyVersion {
private final String name;
private final String vendor;
private final String version;
@ -33,8 +33,12 @@ public final class ProxyVersion {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ProxyVersion that = (ProxyVersion) o;
return Objects.equals(name, that.name) &&
Objects.equals(vendor, that.vendor) &&

Datei anzeigen

@ -2,7 +2,6 @@ package com.velocitypowered.api.util;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.UUID;
@ -11,12 +10,14 @@ import java.util.UUID;
* Provides a small, useful selection of utilities for working with Minecraft UUIDs.
*/
public final class UuidUtils {
private UuidUtils() {
throw new AssertionError();
}
/**
* Converts from an undashed Mojang-style UUID into a Java {@link UUID} object.
*
* @param string the string to convert
* @return the UUID object
*/
@ -31,6 +32,7 @@ public final class UuidUtils {
/**
* Converts from a Java {@link UUID} object into an undashed Mojang-style UUID.
*
* @param uuid the UUID to convert
* @return the undashed UUID
*/
@ -42,6 +44,7 @@ public final class UuidUtils {
/**
* Generates a UUID for use for offline mode.
*
* @param username the username to use
* @return the offline mode UUID
*/

Datei anzeigen

@ -1,16 +1,16 @@
package com.velocitypowered.api.util.title;
import com.google.common.base.Preconditions;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Objects;
import java.util.Optional;
import net.kyori.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a "full" title, including all components. This class is immutable.
*/
public final class TextTitle implements Title {
private final @Nullable Component title;
private final @Nullable Component subtitle;
private final int stay;
@ -29,6 +29,7 @@ public final class TextTitle implements Title {
/**
* Returns the main title this title has, if any.
*
* @return the main title of this title
*/
public Optional<Component> getTitle() {
@ -37,6 +38,7 @@ public final class TextTitle implements Title {
/**
* Returns the subtitle this title has, if any.
*
* @return the subtitle
*/
public Optional<Component> getSubtitle() {
@ -45,6 +47,7 @@ public final class TextTitle implements Title {
/**
* Returns the number of ticks this title will stay up.
*
* @return how long the title will stay, in ticks
*/
public int getStay() {
@ -53,6 +56,7 @@ public final class TextTitle implements Title {
/**
* Returns the number of ticks over which this title will fade in.
*
* @return how long the title will fade in, in ticks
*/
public int getFadeIn() {
@ -61,6 +65,7 @@ public final class TextTitle implements Title {
/**
* Returns the number of ticks over which this title will fade out.
*
* @return how long the title will fade out, in ticks
*/
public int getFadeOut() {
@ -68,8 +73,9 @@ public final class TextTitle implements Title {
}
/**
* Returns whether or not a reset packet will be sent before this title is sent. By default, unless explicitly
* disabled, this is enabled by default.
* Returns whether or not a reset packet will be sent before this title is sent. By default,
* unless explicitly disabled, this is enabled by default.
*
* @return whether or not a reset packet will be sent before this title is sent
*/
public boolean isResetBeforeSend() {
@ -77,8 +83,9 @@ public final class TextTitle implements Title {
}
/**
* Determines whether or not this title has times set on it. If none are set, it will update the previous title
* set on the client.
* Determines whether or not this title has times set on it. If none are set, it will update the
* previous title set on the client.
*
* @return whether or not this title has times set on it
*/
public boolean areTimesSet() {
@ -87,6 +94,7 @@ public final class TextTitle implements Title {
/**
* Creates a new builder from the contents of this title so that it may be changed.
*
* @return a builder instance with the contents of this title
*/
public Builder toBuilder() {
@ -95,8 +103,12 @@ public final class TextTitle implements Title {
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TextTitle textTitle = (TextTitle) o;
return stay == textTitle.stay &&
fadeIn == textTitle.fadeIn &&
@ -125,6 +137,7 @@ public final class TextTitle implements Title {
/**
* Creates a new builder for constructing titles.
*
* @return a builder for constructing titles
*/
public static Builder builder() {
@ -132,6 +145,7 @@ public final class TextTitle implements Title {
}
public static class Builder {
private @Nullable Component title;
private @Nullable Component subtitle;
private int stay;
@ -139,7 +153,8 @@ public final class TextTitle implements Title {
private int fadeOut;
private boolean resetBeforeSend = true;
private Builder() {}
private Builder() {
}
private Builder(TextTitle copy) {
this.title = copy.title;

Datei anzeigen

@ -4,4 +4,5 @@ package com.velocitypowered.api.util.title;
* Represents a title that can be sent to a Minecraft client.
*/
public interface Title {
}

Datei anzeigen

@ -4,6 +4,7 @@ package com.velocitypowered.api.util.title;
* Provides special-purpose titles.
*/
public final class Titles {
private Titles() {
throw new AssertionError();
}
@ -23,8 +24,9 @@ public final class Titles {
};
/**
* Returns a title that, when sent to the client, will cause all title data to be reset and any existing title to be
* hidden.
* Returns a title that, when sent to the client, will cause all title data to be reset and any
* existing title to be hidden.
*
* @return the reset title
*/
public static Title reset() {
@ -32,8 +34,9 @@ public final class Titles {
}
/**
* Returns a title that, when sent to the client, will cause any existing title to be hidden. The title may be
* restored by a {@link TextTitle} with no title or subtitle (only a time).
* Returns a title that, when sent to the client, will cause any existing title to be hidden. The
* title may be restored by a {@link TextTitle} with no title or subtitle (only a time).
*
* @return the hide title
*/
public static Title hide() {
@ -42,6 +45,7 @@ public final class Titles {
/**
* Returns a builder for {@link TextTitle}s.
*
* @return a builder for text titles
*/
public static TextTitle.Builder text() {

Datei anzeigen

@ -1,15 +1,16 @@
package com.velocitypowered.api.util;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
class UuidUtilsTest {
private static final UUID EXPECTED_DASHED_UUID = UUID.fromString("6b501978-d3be-4f33-bcf6-6e7808f37a0d");
private static final String ACTUAL_UNDASHED_UUID = EXPECTED_DASHED_UUID.toString().replace("-", "");
private static final UUID EXPECTED_DASHED_UUID = UUID
.fromString("6b501978-d3be-4f33-bcf6-6e7808f37a0d");
private static final String ACTUAL_UNDASHED_UUID = EXPECTED_DASHED_UUID.toString()
.replace("-", "");
private static final UUID ISSUE_109_ZERO_UUID = new UUID(0, 0);
private static final String ISSUE_109_ZERO_UUID_UNDASHED = "00000000000000000000000000000000";
@ -20,48 +21,61 @@ class UuidUtilsTest {
private static final UUID ISSUE_109_ONE_MLSB_UUID = new UUID(1, 1);
private static final String ISSUE_109_ONE_MLSB_UUID_UNDASHED = "00000000000000010000000000000001";
private static final UUID ISSUE_109_LEADING_ZERO_UUID = UUID.fromString("0d470a25-0416-48a1-b7a6-2a27aa5eb251");
private static final UUID ISSUE_109_LEADING_ZERO_UUID = UUID
.fromString("0d470a25-0416-48a1-b7a6-2a27aa5eb251");
private static final String ISSUE_109_LEADING_ZERO_UNDASHED = "0d470a25041648a1b7a62a27aa5eb251";
private static final UUID TEST_OFFLINE_PLAYER_UUID = UUID.fromString("708f6260-183d-3912-bbde-5e279a5e739a");
private static final UUID TEST_OFFLINE_PLAYER_UUID = UUID
.fromString("708f6260-183d-3912-bbde-5e279a5e739a");
private static final String TEST_OFFLINE_PLAYER = "tuxed";
@Test
void generateOfflinePlayerUuid() {
assertEquals(TEST_OFFLINE_PLAYER_UUID, UuidUtils.generateOfflinePlayerUuid(TEST_OFFLINE_PLAYER), "UUIDs do not match");
assertEquals(TEST_OFFLINE_PLAYER_UUID, UuidUtils.generateOfflinePlayerUuid(TEST_OFFLINE_PLAYER),
"UUIDs do not match");
}
@Test
void fromUndashed() {
assertEquals(EXPECTED_DASHED_UUID, UuidUtils.fromUndashed(ACTUAL_UNDASHED_UUID), "UUIDs do not match");
assertEquals(EXPECTED_DASHED_UUID, UuidUtils.fromUndashed(ACTUAL_UNDASHED_UUID),
"UUIDs do not match");
}
@Test
void toUndashed() {
assertEquals(ACTUAL_UNDASHED_UUID, UuidUtils.toUndashed(EXPECTED_DASHED_UUID), "UUIDs do not match");
assertEquals(ACTUAL_UNDASHED_UUID, UuidUtils.toUndashed(EXPECTED_DASHED_UUID),
"UUIDs do not match");
}
@Test
void zeroUuidIssue109() {
assertEquals(ISSUE_109_ZERO_UUID, UuidUtils.fromUndashed(ISSUE_109_ZERO_UUID_UNDASHED), "UUIDs do not match");
assertEquals(ISSUE_109_ZERO_UUID_UNDASHED, UuidUtils.toUndashed(ISSUE_109_ZERO_UUID), "UUIDs do not match");
assertEquals(ISSUE_109_ZERO_UUID, UuidUtils.fromUndashed(ISSUE_109_ZERO_UUID_UNDASHED),
"UUIDs do not match");
assertEquals(ISSUE_109_ZERO_UUID_UNDASHED, UuidUtils.toUndashed(ISSUE_109_ZERO_UUID),
"UUIDs do not match");
}
@Test
void leadingZeroUuidIssue109() {
assertEquals(ISSUE_109_LEADING_ZERO_UUID, UuidUtils.fromUndashed(ISSUE_109_LEADING_ZERO_UNDASHED), "UUIDs do not match");
assertEquals(ISSUE_109_LEADING_ZERO_UNDASHED, UuidUtils.toUndashed(ISSUE_109_LEADING_ZERO_UUID), "UUIDs do not match");
assertEquals(ISSUE_109_LEADING_ZERO_UUID,
UuidUtils.fromUndashed(ISSUE_109_LEADING_ZERO_UNDASHED), "UUIDs do not match");
assertEquals(ISSUE_109_LEADING_ZERO_UNDASHED, UuidUtils.toUndashed(ISSUE_109_LEADING_ZERO_UUID),
"UUIDs do not match");
}
@Test
void oneUuidLsbIssue109() {
assertEquals(ISSUE_109_ONE_LSB_UUID, UuidUtils.fromUndashed(ISSUE_109_ONE_LSB_UUID_UNDASHED), "UUIDs do not match");
assertEquals(ISSUE_109_ONE_LSB_UUID_UNDASHED, UuidUtils.toUndashed(ISSUE_109_ONE_LSB_UUID), "UUIDs do not match");
assertEquals(ISSUE_109_ONE_LSB_UUID, UuidUtils.fromUndashed(ISSUE_109_ONE_LSB_UUID_UNDASHED),
"UUIDs do not match");
assertEquals(ISSUE_109_ONE_LSB_UUID_UNDASHED, UuidUtils.toUndashed(ISSUE_109_ONE_LSB_UUID),
"UUIDs do not match");
}
@Test
void oneUuidMsbAndLsbIssue109() {
assertEquals(ISSUE_109_ONE_MLSB_UUID, UuidUtils.fromUndashed(ISSUE_109_ONE_MLSB_UUID_UNDASHED), "UUIDs do not match");
assertEquals(ISSUE_109_ONE_MLSB_UUID_UNDASHED, UuidUtils.toUndashed(ISSUE_109_ONE_MLSB_UUID), "UUIDs do not match");
assertEquals(ISSUE_109_ONE_MLSB_UUID, UuidUtils.fromUndashed(ISSUE_109_ONE_MLSB_UUID_UNDASHED),
"UUIDs do not match");
assertEquals(ISSUE_109_ONE_MLSB_UUID_UNDASHED, UuidUtils.toUndashed(ISSUE_109_ONE_MLSB_UUID),
"UUIDs do not match");
}
}

Datei anzeigen

@ -0,0 +1,256 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//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
that can be found at https://google.github.io/styleguide/javaguide.html.
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="TreeWalker">
<module name="OuterTypeFilename"/>
<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)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="100"/>
<property name="ignorePattern"
value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="AvoidStarImport"/>
<module name="OneTopLevelClass"/>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens"
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="NeedBraces"/>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
<property name="tokens"
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,
INSTANCE_INIT"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
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."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<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}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
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}''."/>
</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}''."/>
</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}''."/>
</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}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<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}''."/>
</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}''."/>
</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}''."/>
</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}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
<property name="arrayInitIndent" value="2"/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="true"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore">
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad"/>
<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,
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<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"/>
</module>
<module name="JavadocMethod">
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>
</module>
</module>

4
gradle/checkstyle.gradle Normale Datei
Datei anzeigen

@ -0,0 +1,4 @@
checkstyle {
toolVersion '8.14'
configFile new File(project.rootDir, ['config', 'checkstyle', 'checkstyle.xml'].join(File.separator))
}

Datei anzeigen

@ -1,8 +1,10 @@
plugins {
id 'java'
id 'checkstyle'
}
apply from: '../gradle/checkerframework.gradle'
apply from: '../gradle/checkstyle.gradle'
dependencies {
compile "com.google.guava:guava:${guavaVersion}"

Datei anzeigen

@ -1,13 +1,16 @@
package com.velocitypowered.natives;
/**
* This marker interface indicates that this object should be explicitly disposed before the object can no longer be used.
* Not disposing these objects will likely leak native resources and eventually lead to resource exhaustion.
* This marker interface indicates that this object should be explicitly disposed before the object
* can no longer be used. Not disposing these objects will likely leak native resources and
* eventually lead to resource exhaustion.
*/
public interface Disposable {
/**
* Disposes this object. After this call returns, any use of this object becomes invalid. Multiple calls to
* this function should be safe: there should be no side-effects once an object is disposed.
* Disposes this object. After this call returns, any use of this object becomes invalid. Multiple
* calls to this function should be safe: there should be no side-effects once an object is
* disposed.
*/
void dispose();
}

Datei anzeigen

@ -2,12 +2,12 @@ package com.velocitypowered.natives.compression;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public class JavaVelocityCompressor implements VelocityCompressor {
public static final VelocityCompressorFactory FACTORY = JavaVelocityCompressor::new;
private final Deflater deflater;

Datei anzeigen

@ -2,10 +2,10 @@ package com.velocitypowered.natives.compression;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException;
public class NativeVelocityCompressor implements VelocityCompressor {
public static final VelocityCompressorFactory FACTORY = NativeVelocityCompressor::new;
private final NativeZlibInflate inflate = new NativeZlibInflate();
@ -29,7 +29,8 @@ public class NativeVelocityCompressor implements VelocityCompressor {
if (!destination.isWritable()) {
destination.ensureWritable(ZLIB_BUFFER_SIZE);
}
int produced = inflate.process(inflateCtx, source.memoryAddress() + source.readerIndex(), source.readableBytes(),
int produced = inflate.process(inflateCtx, source.memoryAddress() + source.readerIndex(),
source.readableBytes(),
destination.memoryAddress() + destination.writerIndex(), destination.writableBytes());
source.readerIndex(source.readerIndex() + inflate.consumed);
destination.writerIndex(destination.writerIndex() + produced);
@ -50,8 +51,10 @@ public class NativeVelocityCompressor implements VelocityCompressor {
if (!destination.isWritable()) {
destination.ensureWritable(ZLIB_BUFFER_SIZE);
}
int produced = deflate.process(deflateCtx, source.memoryAddress() + source.readerIndex(), source.readableBytes(),
destination.memoryAddress() + destination.writerIndex(), destination.writableBytes(), !source.isReadable());
int produced = deflate.process(deflateCtx, source.memoryAddress() + source.readerIndex(),
source.readableBytes(),
destination.memoryAddress() + destination.writerIndex(), destination.writableBytes(),
!source.isReadable());
source.readerIndex(source.readerIndex() + deflate.consumed);
destination.writerIndex(destination.writerIndex() + produced);
}

Datei anzeigen

@ -4,6 +4,7 @@ package com.velocitypowered.natives.compression;
* Represents a native interface for zlib's deflate functions.
*/
class NativeZlibDeflate {
boolean finished;
int consumed;
@ -11,7 +12,8 @@ class NativeZlibDeflate {
native long free(long ctx);
native int process(long ctx, long sourceAddress, int sourceLength, long destinationAddress, int destinationLength,
native int process(long ctx, long sourceAddress, int sourceLength, long destinationAddress,
int destinationLength,
boolean flush);
native void reset(long ctx);

Datei anzeigen

@ -4,6 +4,7 @@ package com.velocitypowered.natives.compression;
* Represents a native interface for zlib's inflate functions.
*/
class NativeZlibInflate {
boolean finished;
int consumed;
@ -11,7 +12,8 @@ class NativeZlibInflate {
native long free(long ctx);
native int process(long ctx, long sourceAddress, int sourceLength, long destinationAddress, int destinationLength);
native int process(long ctx, long sourceAddress, int sourceLength, long destinationAddress,
int destinationLength);
native void reset(long ctx);

Datei anzeigen

@ -2,13 +2,13 @@ package com.velocitypowered.natives.compression;
import com.velocitypowered.natives.Disposable;
import io.netty.buffer.ByteBuf;
import java.util.zip.DataFormatException;
/**
* Provides an interface to inflate and deflate {@link ByteBuf}s using zlib.
*/
public interface VelocityCompressor extends Disposable {
/**
* The default preferred output buffer size for zlib.
*/

Datei anzeigen

@ -1,5 +1,6 @@
package com.velocitypowered.natives.compression;
public interface VelocityCompressorFactory {
VelocityCompressor create(int level);
}

Datei anzeigen

@ -2,14 +2,14 @@ package com.velocitypowered.natives.encryption;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import java.security.GeneralSecurityException;
public class JavaVelocityCipher implements VelocityCipher {
public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() {
@Override
public VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException {
@ -27,7 +27,8 @@ public class JavaVelocityCipher implements VelocityCipher {
private JavaVelocityCipher(boolean encrypt, SecretKey key) throws GeneralSecurityException {
this.cipher = Cipher.getInstance("AES/CFB8/NoPadding");
this.cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key, new IvParameterSpec(key.getEncoded()));
this.cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key,
new IvParameterSpec(key.getEncoded()));
}
@Override

Datei anzeigen

@ -1,9 +1,11 @@
package com.velocitypowered.natives.encryption;
public class MbedtlsAesImpl {
native long init(byte[] key);
native void process(long ctx, long sourceAddress, int sourceLength, long destinationAddress, boolean encrypt);
native void process(long ctx, long sourceAddress, int sourceLength, long destinationAddress,
boolean encrypt);
native void free(long ptr);
}

Datei anzeigen

@ -1,12 +1,12 @@
package com.velocitypowered.natives.encryption;
import io.netty.buffer.ByteBuf;
import java.security.GeneralSecurityException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import java.security.GeneralSecurityException;
public class NativeVelocityCipher implements VelocityCipher {
public static final VelocityCipherFactory FACTORY = new VelocityCipherFactory() {
@Override
public VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException {

Datei anzeigen

@ -2,9 +2,9 @@ package com.velocitypowered.natives.encryption;
import com.velocitypowered.natives.Disposable;
import io.netty.buffer.ByteBuf;
import javax.crypto.ShortBufferException;
public interface VelocityCipher extends Disposable {
void process(ByteBuf source, ByteBuf destination) throws ShortBufferException;
}

Datei anzeigen

@ -1,9 +1,10 @@
package com.velocitypowered.natives.encryption;
import javax.crypto.SecretKey;
import java.security.GeneralSecurityException;
import javax.crypto.SecretKey;
public interface VelocityCipherFactory {
VelocityCipher forEncryption(SecretKey key) throws GeneralSecurityException;
VelocityCipher forDecryption(SecretKey key) throws GeneralSecurityException;

Datei anzeigen

@ -1,12 +1,12 @@
package com.velocitypowered.natives.util;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class NativeCodeLoader<T> implements Supplier<T> {
private final Variant<T> selected;
NativeCodeLoader(List<Variant<T>> variants) {
@ -34,13 +34,15 @@ public final class NativeCodeLoader<T> implements Supplier<T> {
}
static class Variant<T> {
private Status status;
private final Runnable setup;
private final String name;
private final T object;
Variant(BooleanSupplier possiblyAvailable, Runnable setup, String name, T object) {
this.status = possiblyAvailable.getAsBoolean() ? Status.POSSIBLY_AVAILABLE : Status.NOT_AVAILABLE;
this.status =
possiblyAvailable.getAsBoolean() ? Status.POSSIBLY_AVAILABLE : Status.NOT_AVAILABLE;
this.setup = setup;
this.name = name;
this.object = object;
@ -73,9 +75,11 @@ public final class NativeCodeLoader<T> implements Supplier<T> {
SETUP_FAILURE
}
static final BooleanSupplier MACOS = () -> System.getProperty("os.name", "").equalsIgnoreCase("Mac OS X") &&
static final BooleanSupplier MACOS = () ->
System.getProperty("os.name", "").equalsIgnoreCase("Mac OS X") &&
System.getProperty("os.arch").equals("x86_64");
static final BooleanSupplier LINUX = () -> System.getProperties().getProperty("os.name", "").equalsIgnoreCase("Linux") &&
static final BooleanSupplier LINUX = () ->
System.getProperties().getProperty("os.name", "").equalsIgnoreCase("Linux") &&
System.getProperty("os.arch").equals("amd64");
static final BooleanSupplier ALWAYS = () -> true;
}

Datei anzeigen

@ -6,7 +6,6 @@ import com.velocitypowered.natives.compression.NativeVelocityCompressor;
import com.velocitypowered.natives.compression.VelocityCompressorFactory;
import com.velocitypowered.natives.encryption.JavaVelocityCipher;
import com.velocitypowered.natives.encryption.VelocityCipherFactory;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@ -14,6 +13,7 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
public class Natives {
private Natives() {
throw new AssertionError();
}
@ -50,7 +50,8 @@ public class Natives {
new NativeCodeLoader.Variant<>(NativeCodeLoader.LINUX,
copyAndLoadNative("/linux_x64/velocity-compress.so"), "native (Linux amd64)",
NativeVelocityCompressor.FACTORY),
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {}, "Java", JavaVelocityCompressor.FACTORY)
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {
}, "Java", JavaVelocityCompressor.FACTORY)
)
);
@ -62,7 +63,8 @@ public class Natives {
new NativeCodeLoader.Variant<>(NativeCodeLoader.LINUX,
copyAndLoadNative("/linux_x64/velocity-cipher.so"), "mbed TLS (Linux amd64)",
NativeVelocityCipher.FACTORY),*/
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {}, "Java", JavaVelocityCipher.FACTORY)
new NativeCodeLoader.Variant<>(NativeCodeLoader.ALWAYS, () -> {
}, "Java", JavaVelocityCipher.FACTORY)
)
);
}

Datei anzeigen

@ -1,23 +1,23 @@
package com.velocitypowered.natives.compression;
import com.velocitypowered.natives.util.Natives;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import java.util.Random;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.condition.OS.LINUX;
import static org.junit.jupiter.api.condition.OS.MAC;
import com.velocitypowered.natives.util.Natives;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.util.Random;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
class VelocityCompressorTest {
@BeforeAll
static void checkNatives() {
Natives.compressor.getLoadedVariant();
@ -36,7 +36,8 @@ class VelocityCompressorTest {
@Test
void javaIntegrityCheck() throws DataFormatException {
VelocityCompressor compressor = JavaVelocityCompressor.FACTORY.create(Deflater.DEFAULT_COMPRESSION);
VelocityCompressor compressor = JavaVelocityCompressor.FACTORY
.create(Deflater.DEFAULT_COMPRESSION);
check(compressor);
}

Datei anzeigen

@ -1,21 +1,21 @@
package com.velocitypowered.natives.encryption;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import com.velocitypowered.natives.util.Natives;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import java.security.GeneralSecurityException;
import java.util.Random;
import javax.crypto.spec.SecretKeySpec;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
class VelocityCipherTest {
private static final int ENCRYPT_DATA_SIZE = 1 << 16;
@BeforeAll

Datei anzeigen

@ -2,17 +2,11 @@ plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '2.0.4'
id 'de.sebastianboegl.shadow.transformer.log4j' version '2.1.1'
id 'checkstyle'
}
apply from: '../gradle/checkerframework.gradle'
compileJava {
options.compilerArgs += ['-proc:none']
}
compileTestJava {
options.compilerArgs += ['-proc:none']
}
apply from: '../gradle/checkstyle.gradle'
jar {
manifest {

Datei anzeigen

@ -1,11 +1,11 @@
package com.velocitypowered.proxy;
import java.text.DecimalFormat;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.text.DecimalFormat;
public class Velocity {
private static final Logger logger = LogManager.getLogger(Velocity.class);
static {

Datei anzeigen

@ -24,7 +24,6 @@ import com.velocitypowered.proxy.config.AnnotatedConfig;
import com.velocitypowered.proxy.config.VelocityConfiguration;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.console.VelocityConsole;
import com.velocitypowered.proxy.util.VelocityChannelRegistrar;
import com.velocitypowered.proxy.network.ConnectionManager;
import com.velocitypowered.proxy.network.http.NettyHttpClient;
import com.velocitypowered.proxy.plugin.VelocityEventManager;
@ -36,22 +35,28 @@ import com.velocitypowered.proxy.server.ServerMap;
import com.velocitypowered.proxy.util.AddressUtil;
import com.velocitypowered.proxy.util.EncryptionUtils;
import com.velocitypowered.proxy.util.Ratelimiter;
import com.velocitypowered.proxy.util.VelocityChannelRegistrar;
import io.netty.bootstrap.Bootstrap;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.serializer.GsonComponentSerializer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.*;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyPair;
import java.util.*;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.serializer.GsonComponentSerializer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
public class VelocityServer implements ProxyServer {
@ -118,7 +123,8 @@ public class VelocityServer implements ProxyServer {
return commandManager;
}
@EnsuresNonNull({"serverKeyPair", "servers", "pluginManager", "eventManager", "scheduler", "console", "cm", "configuration"})
@EnsuresNonNull({"serverKeyPair", "servers", "pluginManager", "eventManager", "scheduler",
"console", "cm", "configuration"})
public void start() {
logger.info("Booting up {} {}...", getVersion().getName(), getVersion().getVersion());
@ -142,12 +148,14 @@ public class VelocityServer implements ProxyServer {
configuration = VelocityConfiguration.read(configPath);
if (!configuration.validate()) {
logger.error("Your configuration is invalid. Velocity will refuse to start up until the errors are resolved.");
logger.error(
"Your configuration is invalid. Velocity will refuse to start up until the errors are resolved.");
LogManager.shutdown();
System.exit(1);
}
AnnotatedConfig.saveConfig(configuration.dumpConfig(), configPath); //Resave config to add new values
AnnotatedConfig
.saveConfig(configuration.dumpConfig(), configPath); //Resave config to add new values
} catch (Exception e) {
logger.error("Unable to read/load/save your velocity.toml. The server will shut down.", e);
@ -188,7 +196,8 @@ public class VelocityServer implements ProxyServer {
Files.createDirectory(pluginPath);
} else {
if (!pluginPath.toFile().isDirectory()) {
logger.warn("Plugin location {} is not a directory, continuing without loading plugins", pluginPath);
logger.warn("Plugin location {} is not a directory, continuing without loading plugins",
pluginPath);
return;
}
@ -384,7 +393,8 @@ public class VelocityServer implements ProxyServer {
@Override
public InetSocketAddress getBoundAddress() {
if (configuration == null) {
throw new IllegalStateException("No configuration"); // even though you'll never get the chance... heh, heh
throw new IllegalStateException(
"No configuration"); // even though you'll never get the chance... heh, heh
}
return configuration.getBind();
}

Datei anzeigen

@ -9,17 +9,17 @@ import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import net.kyori.text.TextComponent;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class ServerCommand implements Command {
private final ProxyServer server;
public ServerCommand(ProxyServer server) {
@ -39,18 +39,22 @@ public class ServerCommand implements Command {
String serverName = args[0];
Optional<RegisteredServer> toConnect = server.getServer(serverName);
if (!toConnect.isPresent()) {
player.sendMessage(TextComponent.of("Server " + serverName + " doesn't exist.", TextColor.RED));
player.sendMessage(
TextComponent.of("Server " + serverName + " doesn't exist.", TextColor.RED));
return;
}
player.createConnectionRequest(toConnect.get()).fireAndForget();
} else {
String currentServer = player.getCurrentServer().map(ServerConnection::getServerInfo).map(ServerInfo::getName)
String currentServer = player.getCurrentServer().map(ServerConnection::getServerInfo)
.map(ServerInfo::getName)
.orElse("<unknown>");
player.sendMessage(TextComponent.of("You are currently connected to " + currentServer + ".", TextColor.YELLOW));
player.sendMessage(TextComponent
.of("You are currently connected to " + currentServer + ".", TextColor.YELLOW));
// Assemble the list of servers as components
TextComponent.Builder serverListBuilder = TextComponent.builder("Available servers: ").color(TextColor.YELLOW);
TextComponent.Builder serverListBuilder = TextComponent.builder("Available servers: ")
.color(TextColor.YELLOW);
List<RegisteredServer> infos = ImmutableList.copyOf(server.getAllServers());
for (int i = 0; i < infos.size(); i++) {
RegisteredServer rs = infos.get(i);
@ -62,8 +66,10 @@ public class ServerCommand implements Command {
TextComponent.of("Currently connected to this server\n" + playersText)));
} else {
infoComponent = infoComponent.color(TextColor.GRAY)
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/server " + rs.getServerInfo().getName()))
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to connect to this server\n" + playersText)));
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
"/server " + rs.getServerInfo().getName()))
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
TextComponent.of("Click to connect to this server\n" + playersText)));
}
serverListBuilder.append(infoComponent);
if (i != infos.size() - 1) {

Datei anzeigen

@ -8,6 +8,7 @@ import net.kyori.text.format.TextColor;
import org.checkerframework.checker.nullness.qual.NonNull;
public class ShutdownCommand implements Command {
private final VelocityServer server;
public ShutdownCommand(VelocityServer server) {
@ -17,7 +18,8 @@ public class ShutdownCommand implements Command {
@Override
public void execute(CommandSource source, String @NonNull [] args) {
if (source != server.getConsoleCommandSource()) {
source.sendMessage(TextComponent.of("You are not allowed to use this command.", TextColor.RED));
source
.sendMessage(TextComponent.of("You are not allowed to use this command.", TextColor.RED));
return;
}
server.shutdown();

Datei anzeigen

@ -7,19 +7,19 @@ import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.permission.Tristate;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.util.ProxyVersion;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import net.kyori.text.TextComponent;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
public class VelocityCommand implements Command {
private final Map<String, Command> subcommands;
public VelocityCommand(ProxyServer server) {
@ -86,6 +86,7 @@ public class VelocityCommand implements Command {
}
private static class Info implements Command {
private final ProxyServer server;
private Info(ProxyServer server) {
@ -101,7 +102,9 @@ public class VelocityCommand implements Command {
.color(TextColor.DARK_AQUA)
.append(TextComponent.of(version.getVersion()).decoration(TextDecoration.BOLD, false))
.build();
TextComponent copyright = TextComponent.of("Copyright 2018 " + version.getVendor() + ". " + version.getName() + " is freely licensed under the terms of the " +
TextComponent copyright = TextComponent
.of("Copyright 2018 " + version.getVendor() + ". " + version.getName()
+ " is freely licensed under the terms of the " +
"MIT License.");
source.sendMessage(velocity);
source.sendMessage(copyright);
@ -111,12 +114,14 @@ public class VelocityCommand implements Command {
.content("Visit the ")
.append(TextComponent.builder("Velocity website")
.color(TextColor.GREEN)
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.velocitypowered.com"))
.clickEvent(
new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.velocitypowered.com"))
.build())
.append(TextComponent.of(" or the ").resetStyle())
.append(TextComponent.builder("Velocity GitHub")
.color(TextColor.GREEN)
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://github.com/VelocityPowered/Velocity"))
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
"https://github.com/VelocityPowered/Velocity"))
.build())
.build();
source.sendMessage(velocityWebsite);

Datei anzeigen

@ -5,11 +5,16 @@ import com.google.common.collect.ImmutableList;
import com.velocitypowered.api.command.Command;
import com.velocitypowered.api.command.CommandManager;
import com.velocitypowered.api.command.CommandSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.*;
public class VelocityCommandManager implements CommandManager {
private final Map<String, Command> commands = new HashMap<>();
@Override
@ -98,7 +103,8 @@ public class VelocityCommandManager implements CommandManager {
return command.suggest(source, actualArgs);
} catch (Exception e) {
throw new RuntimeException("Unable to invoke suggestions for command " + alias + " for " + source, e);
throw new RuntimeException(
"Unable to invoke suggestions for command " + alias + " for " + source, e);
}
}
}

Datei anzeigen

@ -1,8 +1,5 @@
package com.velocitypowered.proxy.config;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -19,11 +16,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Simple annotation and fields based TOML configuration serializer
*/
public abstract class AnnotatedConfig {
private static final Logger logger = LogManager.getLogger(AnnotatedConfig.class);
public static Logger getLogger() {
@ -36,6 +36,7 @@ public abstract class AnnotatedConfig {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Table {
String value();
}
@ -45,6 +46,7 @@ public abstract class AnnotatedConfig {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Comment {
String[] value();
}
@ -54,33 +56,40 @@ public abstract class AnnotatedConfig {
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface ConfigKey {
String value();
}
/**
* Indicates that a field is a map and we need to save all map data to
* config
* Indicates that a field is a map and we need to save all map data to config
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface IsMap {}
public @interface IsMap {
}
/**
* Indicates that a field is a string converted to byte[]
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface StringAsBytes {}
public @interface StringAsBytes {
}
/**
* Indicates that a field should be skipped
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Ignore {}
public @interface Ignore {
}
/**
* Dumps this configuration to list of strings using {@link #dumpConfig(Object)}
*
* @return configuration dump
*/
public List<String> dumpConfig() {
@ -91,8 +100,8 @@ public abstract class AnnotatedConfig {
* Creates TOML configuration from supplied <pre>dumpable</pre> object.
*
* @param dumpable object which is going to be dumped
* @throws RuntimeException if reading field value(s) fail
* @return string list of configuration file lines
* @throws RuntimeException if reading field value(s) fail
*/
private static List<String> dumpConfig(Object dumpable) {
List<String> lines = new ArrayList<>();
@ -116,7 +125,8 @@ public abstract class AnnotatedConfig {
// Get a key name for config
ConfigKey key = field.getAnnotation(ConfigKey.class);
String name = safeKey(key == null ? field.getName() : key.value()); // Use field name if @ConfigKey annotation is not present
String name = safeKey(key == null ? field.getName()
: key.value()); // Use field name if @ConfigKey annotation is not present
// Check if field is table.
Table table = field.getAnnotation(Table.class);
@ -130,7 +140,8 @@ public abstract class AnnotatedConfig {
@SuppressWarnings("unchecked")
Map<String, ?> map = (Map<String, ?>) field.get(dumpable);
for (Entry<String, ?> entry : map.entrySet()) {
lines.add(safeKey(entry.getKey()) + " = " + serialize(entry.getValue())); // Save map data
lines.add(
safeKey(entry.getKey()) + " = " + serialize(entry.getValue())); // Save map data
}
lines.add(""); // Add empty line
continue;
@ -194,7 +205,8 @@ public abstract class AnnotatedConfig {
}
private static String safeKey(String key) {
if(key.contains(".") && !(key.indexOf('"') == 0 && key.lastIndexOf('"') == (key.length() - 1))) {
if (key.contains(".") && !(key.indexOf('"') == 0 && key.lastIndexOf('"') == (key.length()
- 1))) {
return '"' + key + '"';
}
return key;

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