Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Merge branch 'feature/extended-connection-handshake-event' into dev/2.0.0
Dieser Commit ist enthalten in:
Commit
c496d912ea
@ -9,7 +9,6 @@ package com.velocitypowered.api.event;
|
|||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -85,34 +84,30 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
|
|||||||
*/
|
*/
|
||||||
final class ComponentResult implements Result {
|
final class ComponentResult implements Result {
|
||||||
|
|
||||||
private static final ComponentResult ALLOWED = new ComponentResult(true, null);
|
private static final ComponentResult ALLOWED = new ComponentResult(null);
|
||||||
|
|
||||||
private final boolean status;
|
|
||||||
private final @Nullable Component reason;
|
private final @Nullable Component reason;
|
||||||
|
|
||||||
protected ComponentResult(boolean status, @Nullable Component reason) {
|
protected ComponentResult(@Nullable Component reason) {
|
||||||
this.status = status;
|
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAllowed() {
|
public boolean isAllowed() {
|
||||||
return status;
|
return reason == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Component> reason() {
|
public @Nullable Component reason() {
|
||||||
return Optional.ofNullable(reason);
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (status) {
|
if (reason == null) {
|
||||||
return "allowed";
|
return "allowed";
|
||||||
}
|
} else {
|
||||||
if (reason != null) {
|
|
||||||
return "denied: " + PlainComponentSerializer.plain().serialize(reason);
|
return "denied: " + PlainComponentSerializer.plain().serialize(reason);
|
||||||
}
|
}
|
||||||
return "denied";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ComponentResult allowed() {
|
public static ComponentResult allowed() {
|
||||||
@ -121,7 +116,7 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
|
|||||||
|
|
||||||
public static ComponentResult denied(Component reason) {
|
public static ComponentResult denied(Component reason) {
|
||||||
Preconditions.checkNotNull(reason, "reason");
|
Preconditions.checkNotNull(reason, "reason");
|
||||||
return new ComponentResult(false, reason);
|
return new ComponentResult(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -133,12 +128,12 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ComponentResult that = (ComponentResult) o;
|
ComponentResult that = (ComponentResult) o;
|
||||||
return status == that.status && Objects.equals(reason, that.reason);
|
return Objects.equals(reason, that.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(status, reason);
|
return Objects.hash(reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import com.velocitypowered.api.command.CommandSource;
|
|||||||
import com.velocitypowered.api.event.ResultedEvent;
|
import com.velocitypowered.api.event.ResultedEvent;
|
||||||
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
|
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -45,8 +44,8 @@ public interface CommandExecuteEvent extends ResultedEvent<CommandResult> {
|
|||||||
this.command = command;
|
this.command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> modifiedCommand() {
|
public @Nullable String modifiedCommand() {
|
||||||
return Optional.ofNullable(command);
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isForwardToServer() {
|
public boolean isForwardToServer() {
|
||||||
|
@ -34,7 +34,7 @@ public final class GameProfileRequestEventImpl implements GameProfileRequestEven
|
|||||||
boolean onlineMode) {
|
boolean onlineMode) {
|
||||||
this.connection = Preconditions.checkNotNull(connection, "connection");
|
this.connection = Preconditions.checkNotNull(connection, "connection");
|
||||||
this.originalProfile = Preconditions.checkNotNull(originalProfile, "originalProfile");
|
this.originalProfile = Preconditions.checkNotNull(originalProfile, "originalProfile");
|
||||||
this.username = originalProfile.getName();
|
this.username = originalProfile.name();
|
||||||
this.onlineMode = onlineMode;
|
this.onlineMode = onlineMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import com.velocitypowered.api.event.ResultedEvent;
|
|||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ public interface KickedFromServerEvent extends
|
|||||||
*
|
*
|
||||||
* @return the server kicked the player from the server
|
* @return the server kicked the player from the server
|
||||||
*/
|
*/
|
||||||
Optional<Component> serverKickReason();
|
@Nullable Component serverKickReason();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the player got kicked while connecting to another server.
|
* Returns whether or not the player got kicked while connecting to another server.
|
||||||
|
@ -10,7 +10,6 @@ package com.velocitypowered.api.event.player;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -72,8 +71,8 @@ public final class KickedFromServerEventImpl implements KickedFromServerEvent {
|
|||||||
* @return the server kicked the player from the server
|
* @return the server kicked the player from the server
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Optional<Component> serverKickReason() {
|
public @Nullable Component serverKickReason() {
|
||||||
return Optional.ofNullable(originalReason);
|
return originalReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ package com.velocitypowered.api.event.player;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Optional;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fired when a player has finished connecting to the proxy and we need to choose the first server
|
* Fired when a player has finished connecting to the proxy and we need to choose the first server
|
||||||
@ -19,7 +19,7 @@ public interface PlayerChooseInitialServerEvent {
|
|||||||
|
|
||||||
Player player();
|
Player player();
|
||||||
|
|
||||||
Optional<RegisteredServer> initialServer();
|
@Nullable RegisteredServer initialServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the new initial server.
|
* Sets the new initial server.
|
||||||
|
@ -10,7 +10,6 @@ package com.velocitypowered.api.event.player;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,8 +37,8 @@ public class PlayerChooseInitialServerEventImpl implements PlayerChooseInitialSe
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<RegisteredServer> initialServer() {
|
public @Nullable RegisteredServer initialServer() {
|
||||||
return Optional.ofNullable(initialServer);
|
return initialServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +46,7 @@ public class PlayerChooseInitialServerEventImpl implements PlayerChooseInitialSe
|
|||||||
* @param server the initial server the player should connect to
|
* @param server the initial server the player should connect to
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setInitialServer(RegisteredServer server) {
|
public void setInitialServer(@Nullable RegisteredServer server) {
|
||||||
this.initialServer = server;
|
this.initialServer = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ package com.velocitypowered.api.event.player;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Optional;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is fired once the player has successfully connected to the target server and the
|
* This event is fired once the player has successfully connected to the target server and the
|
||||||
@ -21,5 +21,5 @@ public interface ServerConnectedEvent {
|
|||||||
|
|
||||||
RegisteredServer target();
|
RegisteredServer target();
|
||||||
|
|
||||||
Optional<RegisteredServer> previousServer();
|
@Nullable RegisteredServer previousServer();
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ package com.velocitypowered.api.event.player;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,8 +46,8 @@ public final class ServerConnectedEventImpl implements ServerConnectedEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<RegisteredServer> previousServer() {
|
public @Nullable RegisteredServer previousServer() {
|
||||||
return Optional.ofNullable(previousServer);
|
return previousServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -14,7 +14,6 @@ import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder;
|
|||||||
import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder.Status;
|
import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder.Status;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,8 +59,8 @@ public interface ServerPreConnectEvent extends ResultedEvent<ServerPreConnectEve
|
|||||||
return target != null;
|
return target != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<RegisteredServer> target() {
|
public @Nullable RegisteredServer target() {
|
||||||
return Optional.ofNullable(target);
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -13,8 +13,8 @@ import com.velocitypowered.api.plugin.meta.PluginDependency;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents metadata for a specific version of a plugin.
|
* Represents metadata for a specific version of a plugin.
|
||||||
@ -39,41 +39,41 @@ public interface PluginDescription {
|
|||||||
/**
|
/**
|
||||||
* Gets the name of the {@link Plugin} within this container.
|
* Gets the name of the {@link Plugin} within this container.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} with the plugin name, may be empty
|
* @return a String with the plugin name or the plugin ID
|
||||||
* @see Plugin#name()
|
* @see Plugin#name()
|
||||||
*/
|
*/
|
||||||
default Optional<String> name() {
|
default String name() {
|
||||||
return Optional.empty();
|
return id();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the version of the {@link Plugin} within this container.
|
* Gets the version of the {@link Plugin} within this container.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} with the plugin version, may be empty
|
* @return a String with the plugin version, may be null
|
||||||
* @see Plugin#version()
|
* @see Plugin#version()
|
||||||
*/
|
*/
|
||||||
default Optional<String> version() {
|
default @Nullable String version() {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the description of the {@link Plugin} within this container.
|
* Gets the description of the {@link Plugin} within this container.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} with the plugin description, may be empty
|
* @return a String with the plugin description, may be null
|
||||||
* @see Plugin#description()
|
* @see Plugin#description()
|
||||||
*/
|
*/
|
||||||
default Optional<String> description() {
|
default @Nullable String description() {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the url or website of the {@link Plugin} within this container.
|
* Gets the url or website of the {@link Plugin} within this container.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} with the plugin url, may be empty
|
* @return an String with the plugin url, may be null
|
||||||
* @see Plugin#url()
|
* @see Plugin#url()
|
||||||
*/
|
*/
|
||||||
default Optional<String> url() {
|
default @Nullable String url() {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,16 +96,16 @@ public interface PluginDescription {
|
|||||||
return ImmutableSet.of();
|
return ImmutableSet.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
default Optional<PluginDependency> getDependency(String id) {
|
default @Nullable PluginDependency getDependency(String id) {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the file path the plugin was loaded from.
|
* Returns the file path the plugin was loaded from.
|
||||||
*
|
*
|
||||||
* @return the path the plugin was loaded from or {@link Optional#empty()} if unknown
|
* @return the path the plugin was loaded from or {@code null} if unknown
|
||||||
*/
|
*/
|
||||||
default Optional<Path> file() {
|
default @Nullable Path file() {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
package com.velocitypowered.api.plugin;
|
package com.velocitypowered.api.plugin;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages plugins loaded on the proxy. This manager can retrieve {@link PluginContainer}s from
|
* Manages plugins loaded on the proxy. This manager can retrieve {@link PluginContainer}s from
|
||||||
@ -24,7 +26,7 @@ public interface PluginManager {
|
|||||||
* @param instance the instance
|
* @param instance the instance
|
||||||
* @return the container
|
* @return the container
|
||||||
*/
|
*/
|
||||||
Optional<PluginContainer> fromInstance(Object instance);
|
@Nullable PluginContainer fromInstance(Object instance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a {@link PluginContainer} based on its ID.
|
* Retrieves a {@link PluginContainer} based on its ID.
|
||||||
@ -32,7 +34,7 @@ public interface PluginManager {
|
|||||||
* @param id the plugin ID
|
* @param id the plugin ID
|
||||||
* @return the plugin, if available
|
* @return the plugin, if available
|
||||||
*/
|
*/
|
||||||
Optional<PluginContainer> getPlugin(String id);
|
@Nullable PluginContainer getPlugin(String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a {@link Collection} of all {@link PluginContainer}s.
|
* Gets a {@link Collection} of all {@link PluginContainer}s.
|
||||||
@ -57,4 +59,13 @@ public interface PluginManager {
|
|||||||
* @throws UnsupportedOperationException if the operation is not applicable to this plugin
|
* @throws UnsupportedOperationException if the operation is not applicable to this plugin
|
||||||
*/
|
*/
|
||||||
void addToClasspath(Object plugin, Path path);
|
void addToClasspath(Object plugin, Path path);
|
||||||
|
|
||||||
|
default PluginContainer ensurePluginContainer(Object plugin) {
|
||||||
|
requireNonNull(plugin, "plugin");
|
||||||
|
PluginContainer container = fromInstance(plugin);
|
||||||
|
if (container == null) {
|
||||||
|
throw new IllegalArgumentException("Specified plugin is not loaded");
|
||||||
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
import static com.google.common.base.Strings.emptyToNull;
|
import static com.google.common.base.Strings.emptyToNull;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,17 +42,17 @@ public final class PluginDependency {
|
|||||||
*
|
*
|
||||||
* @return the plugin ID
|
* @return the plugin ID
|
||||||
*/
|
*/
|
||||||
public String getId() {
|
public String id() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the version this {@link PluginDependency} should match.
|
* Returns the version this {@link PluginDependency} should match.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} with the plugin version, may be empty
|
* @return a String with the plugin version, may be {@code null}
|
||||||
*/
|
*/
|
||||||
public Optional<String> getVersion() {
|
public @Nullable String version() {
|
||||||
return Optional.ofNullable(version);
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,7 +60,7 @@ public final class PluginDependency {
|
|||||||
*
|
*
|
||||||
* @return true if dependency is optional
|
* @return true if dependency is optional
|
||||||
*/
|
*/
|
||||||
public boolean isOptional() {
|
public boolean optional() {
|
||||||
return optional;
|
return optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,12 +19,11 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
|
|||||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||||
import com.velocitypowered.api.scheduler.Scheduler;
|
import com.velocitypowered.api.scheduler.Scheduler;
|
||||||
import com.velocitypowered.api.util.ProxyVersion;
|
import com.velocitypowered.api.util.ProxyVersion;
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.kyori.adventure.audience.Audience;
|
import net.kyori.adventure.audience.Audience;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an interface to a Minecraft server proxy.
|
* Provides an interface to a Minecraft server proxy.
|
||||||
@ -48,17 +47,17 @@ public interface ProxyServer extends Audience {
|
|||||||
* is case-insensitive.
|
* is case-insensitive.
|
||||||
*
|
*
|
||||||
* @param username the username to search for
|
* @param username the username to search for
|
||||||
* @return an {@link Optional} with the player, which may be empty
|
* @return the player instance, if connected, else {@code null}
|
||||||
*/
|
*/
|
||||||
Optional<Player> getPlayer(String username);
|
@Nullable Player player(String username);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the player currently connected to this proxy by their Minecraft UUID.
|
* Retrieves the player currently connected to this proxy by their Minecraft UUID.
|
||||||
*
|
*
|
||||||
* @param uuid the UUID
|
* @param uuid the UUID
|
||||||
* @return an {@link Optional} with the player, which may be empty
|
* @return the player instance, if connected, else {@code null}
|
||||||
*/
|
*/
|
||||||
Optional<Player> getPlayer(UUID uuid);
|
@Nullable Player player(UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all players currently connected to this proxy. This call may or may not be a snapshot
|
* Retrieves all players currently connected to this proxy. This call may or may not be a snapshot
|
||||||
@ -82,7 +81,7 @@ public interface ProxyServer extends Audience {
|
|||||||
* @param name the name of the server
|
* @param name the name of the server
|
||||||
* @return the registered server, which may be empty
|
* @return the registered server, which may be empty
|
||||||
*/
|
*/
|
||||||
Optional<RegisteredServer> server(String name);
|
@Nullable RegisteredServer server(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all {@link RegisteredServer}s registered with this proxy.
|
* Retrieves all {@link RegisteredServer}s registered with this proxy.
|
||||||
|
@ -11,7 +11,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
|||||||
import com.velocitypowered.api.util.Favicon;
|
import com.velocitypowered.api.util.Favicon;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exposes certain proxy configuration information that plugins may use.
|
* Exposes certain proxy configuration information that plugins may use.
|
||||||
@ -126,7 +126,7 @@ public interface ProxyConfig {
|
|||||||
*
|
*
|
||||||
* @return optional favicon
|
* @return optional favicon
|
||||||
*/
|
*/
|
||||||
Optional<Favicon> getFavicon();
|
@Nullable Favicon getFavicon();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get whether this proxy displays that it supports Forge/FML.
|
* Get whether this proxy displays that it supports Forge/FML.
|
||||||
|
@ -10,7 +10,7 @@ package com.velocitypowered.api.proxy.connection;
|
|||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Optional;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an incoming connection to the proxy.
|
* Represents an incoming connection to the proxy.
|
||||||
@ -29,7 +29,7 @@ public interface InboundConnection {
|
|||||||
*
|
*
|
||||||
* @return the hostname from the client
|
* @return the hostname from the client
|
||||||
*/
|
*/
|
||||||
Optional<InetSocketAddress> connectedHostname();
|
@Nullable InetSocketAddress connectedHostname();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether or not the player remains online.
|
* Determine whether or not the player remains online.
|
||||||
|
@ -19,10 +19,10 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
|
|||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import com.velocitypowered.api.util.ModInfo;
|
import com.velocitypowered.api.util.ModInfo;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.kyori.adventure.identity.Identified;
|
import net.kyori.adventure.identity.Identified;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player who is connected to the proxy.
|
* Represents a player who is connected to the proxy.
|
||||||
@ -47,9 +47,10 @@ public interface Player extends CommandSource, Identified, InboundConnection,
|
|||||||
/**
|
/**
|
||||||
* Returns the server that the player is currently connected to.
|
* 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
|
* @return the server that the player is connected to, which could be {@code null} if no
|
||||||
|
* connection was made yet (or the player is switching servers)
|
||||||
*/
|
*/
|
||||||
Optional<ServerConnection> connectedServer();
|
@Nullable ServerConnection connectedServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the player's client settings.
|
* Returns the player's client settings.
|
||||||
@ -61,9 +62,9 @@ public interface Player extends CommandSource, Identified, InboundConnection,
|
|||||||
/**
|
/**
|
||||||
* Returns the player's mod info if they have a modded client.
|
* Returns the player's mod info if they have a modded client.
|
||||||
*
|
*
|
||||||
* @return an {@link Optional} the mod info. which may be empty
|
* @return an the mod info. which may be {@code null} if no info is available
|
||||||
*/
|
*/
|
||||||
Optional<ModInfo> modInfo();
|
@Nullable ModInfo modInfo();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current player's ping.
|
* Returns the current player's ping.
|
||||||
|
@ -9,9 +9,9 @@ package com.velocitypowered.api.proxy.player;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a fluent interface to send a connection request to another server on the proxy. A
|
* Provides a fluent interface to send a connection request to another server on the proxy. A
|
||||||
@ -76,7 +76,7 @@ public interface ConnectionRequestBuilder {
|
|||||||
*
|
*
|
||||||
* @return the reason why the user could not connect to the server
|
* @return the reason why the user could not connect to the server
|
||||||
*/
|
*/
|
||||||
Optional<Component> failureReason();
|
@Nullable Component failureReason();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the server we actually tried to connect to.
|
* Returns the server we actually tried to connect to.
|
||||||
|
@ -10,7 +10,6 @@ package com.velocitypowered.api.proxy.player;
|
|||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -45,10 +44,9 @@ public interface TabList {
|
|||||||
* the specified {@link UUID}.
|
* the specified {@link UUID}.
|
||||||
*
|
*
|
||||||
* @param uuid of the entry
|
* @param uuid of the entry
|
||||||
* @return {@link Optional} containing the removed {@link TabListEntry} if present, otherwise
|
* @return the removed {@link TabListEntry} if present, otherwise {@code null}
|
||||||
* {@link Optional#empty()}
|
|
||||||
*/
|
*/
|
||||||
Optional<TabListEntry> removeEntry(UUID uuid);
|
@Nullable TabListEntry removeEntry(UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the specified entry exists in the tab list.
|
* Determines if the specified entry exists in the tab list.
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
package com.velocitypowered.api.proxy.player;
|
package com.velocitypowered.api.proxy.player;
|
||||||
|
|
||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -34,18 +33,17 @@ public interface TabListEntry {
|
|||||||
GameProfile gameProfile();
|
GameProfile gameProfile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link Optional} text {@link Component}, which if present is the text
|
* Returns an optional text {@link Component}, which if present is the text
|
||||||
* displayed for {@code this} entry in the {@link TabList}, otherwise
|
* displayed for {@code this} entry in the {@link TabList}, otherwise
|
||||||
* {@link GameProfile#getName()} is shown.
|
* {@link GameProfile#name()} is shown.
|
||||||
*
|
*
|
||||||
* @return {@link Optional} text {@link Component} of name displayed in the tab
|
* @return text {@link Component} of name displayed in the tab list
|
||||||
* list
|
|
||||||
*/
|
*/
|
||||||
Optional<Component> displayName();
|
@Nullable Component displayName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the text {@link Component} to be displayed for {@code this} {@link TabListEntry}. If
|
* Sets the text {@link Component} to be displayed for {@code this} {@link TabListEntry}. If
|
||||||
* {@code null}, {@link GameProfile#getName()} will be shown.
|
* {@code null}, {@link GameProfile#name()} will be shown.
|
||||||
*
|
*
|
||||||
* @param displayName to show in the {@link TabList} for {@code this} entry
|
* @param displayName to show in the {@link TabList} for {@code this} entry
|
||||||
* @return {@code this}, for chaining
|
* @return {@code this}, for chaining
|
||||||
|
@ -18,7 +18,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -423,8 +422,8 @@ public final class QueryResponse {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<String> getVersion() {
|
public @Nullable String getVersion() {
|
||||||
return Optional.ofNullable(version);
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluginInformation of(String name, @Nullable String version) {
|
public static PluginInformation of(String name, @Nullable String version) {
|
||||||
|
@ -16,7 +16,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -60,20 +59,20 @@ public final class ServerPing {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Players> players() {
|
public @Nullable Players players() {
|
||||||
return Optional.ofNullable(players);
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Component description() {
|
public Component description() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Favicon> favicon() {
|
public @Nullable Favicon favicon() {
|
||||||
return Optional.ofNullable(favicon);
|
return favicon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ModInfo> modInfo() {
|
public @Nullable ModInfo modInfo() {
|
||||||
return Optional.ofNullable(modinfo);
|
return modinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -271,12 +270,12 @@ public final class ServerPing {
|
|||||||
return samplePlayers;
|
return samplePlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Component> getDescription() {
|
public @Nullable Component getDescription() {
|
||||||
return Optional.ofNullable(description);
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Favicon> getFavicon() {
|
public @Nullable Favicon getFavicon() {
|
||||||
return Optional.ofNullable(favicon);
|
return favicon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getModType() {
|
public String getModType() {
|
||||||
|
@ -11,11 +11,15 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.kyori.adventure.identity.Identified;
|
||||||
|
import net.kyori.adventure.identity.Identity;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Mojang game profile. This class is immutable.
|
* Represents a Mojang game profile. This class is immutable.
|
||||||
*/
|
*/
|
||||||
public final class GameProfile {
|
public final class GameProfile implements Identified, Identity {
|
||||||
|
|
||||||
private final UUID id;
|
private final UUID id;
|
||||||
private final String undashedId;
|
private final String undashedId;
|
||||||
@ -55,7 +59,7 @@ public final class GameProfile {
|
|||||||
* Returns the undashed, Mojang-style UUID.
|
* Returns the undashed, Mojang-style UUID.
|
||||||
* @return the undashed UUID
|
* @return the undashed UUID
|
||||||
*/
|
*/
|
||||||
public String getUndashedId() {
|
public String undashedId() {
|
||||||
return undashedId;
|
return undashedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +67,8 @@ public final class GameProfile {
|
|||||||
* Returns the UUID associated with this game profile.
|
* Returns the UUID associated with this game profile.
|
||||||
* @return the UUID
|
* @return the UUID
|
||||||
*/
|
*/
|
||||||
public UUID getId() {
|
@Override
|
||||||
|
public @NotNull UUID uuid() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +76,7 @@ public final class GameProfile {
|
|||||||
* Returns the username associated with this profile.
|
* Returns the username associated with this profile.
|
||||||
* @return the username
|
* @return the username
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +84,7 @@ public final class GameProfile {
|
|||||||
* Returns an immutable list of profile properties associated with this profile.
|
* Returns an immutable list of profile properties associated with this profile.
|
||||||
* @return the properties associated with this profile
|
* @return the properties associated with this profile
|
||||||
*/
|
*/
|
||||||
public List<Property> getProperties() {
|
public List<Property> properties() {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +94,7 @@ public final class GameProfile {
|
|||||||
* @param id the new unique id
|
* @param id the new unique id
|
||||||
* @return the new {@code GameProfile}
|
* @return the new {@code GameProfile}
|
||||||
*/
|
*/
|
||||||
public GameProfile withId(UUID id) {
|
public GameProfile withUuid(UUID id) {
|
||||||
return new GameProfile(Preconditions.checkNotNull(id, "id"), UuidUtils.toUndashed(id),
|
return new GameProfile(Preconditions.checkNotNull(id, "id"), UuidUtils.toUndashed(id),
|
||||||
this.name, this.properties);
|
this.name, this.properties);
|
||||||
}
|
}
|
||||||
@ -172,6 +177,11 @@ public final class GameProfile {
|
|||||||
+ '}';
|
+ '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Identity identity() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Mojang profile property. Just like {@link GameProfile}, this class is immutable.
|
* Represents a Mojang profile property. Just like {@link GameProfile}, this class is immutable.
|
||||||
*/
|
*/
|
||||||
@ -193,15 +203,15 @@ public final class GameProfile {
|
|||||||
this.signature = Preconditions.checkNotNull(signature, "signature");
|
this.signature = Preconditions.checkNotNull(signature, "signature");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue() {
|
public String value() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignature() {
|
public String signature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
eventManager.registerInternally(plugin, instance.get());
|
eventManager.registerInternally(plugin, instance.get());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Unable to register plugin listener for {}",
|
logger.error("Unable to register plugin listener for {}",
|
||||||
plugin.description().name().orElse(plugin.description().id()), e);
|
MoreObjects.firstNonNull(plugin.description().name(), plugin.description().id()), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,18 +373,18 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
for (Map.Entry<String, String> entry : newConfiguration.getServers().entrySet()) {
|
for (Map.Entry<String, String> entry : newConfiguration.getServers().entrySet()) {
|
||||||
ServerInfo newInfo =
|
ServerInfo newInfo =
|
||||||
new ServerInfo(entry.getKey(), AddressUtil.parseAddress(entry.getValue()));
|
new ServerInfo(entry.getKey(), AddressUtil.parseAddress(entry.getValue()));
|
||||||
Optional<RegisteredServer> rs = servers.getServer(entry.getKey());
|
RegisteredServer rs = servers.getServer(entry.getKey());
|
||||||
if (!rs.isPresent()) {
|
if (rs == null) {
|
||||||
servers.register(newInfo);
|
servers.register(newInfo);
|
||||||
} else if (!rs.get().serverInfo().equals(newInfo)) {
|
} else if (!rs.serverInfo().equals(newInfo)) {
|
||||||
for (Player player : rs.get().connectedPlayers()) {
|
for (Player player : rs.connectedPlayers()) {
|
||||||
if (!(player instanceof ConnectedPlayer)) {
|
if (!(player instanceof ConnectedPlayer)) {
|
||||||
throw new IllegalStateException("ConnectedPlayer not found for player " + player
|
throw new IllegalStateException("ConnectedPlayer not found for player " + player
|
||||||
+ " in server " + rs.get().serverInfo().name());
|
+ " in server " + rs.serverInfo().name());
|
||||||
}
|
}
|
||||||
evacuate.add((ConnectedPlayer) player);
|
evacuate.add((ConnectedPlayer) player);
|
||||||
}
|
}
|
||||||
servers.unregister(rs.get().serverInfo());
|
servers.unregister(rs.serverInfo());
|
||||||
servers.register(newInfo);
|
servers.register(newInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,9 +393,9 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
if (!evacuate.isEmpty()) {
|
if (!evacuate.isEmpty()) {
|
||||||
CountDownLatch latch = new CountDownLatch(evacuate.size());
|
CountDownLatch latch = new CountDownLatch(evacuate.size());
|
||||||
for (ConnectedPlayer player : evacuate) {
|
for (ConnectedPlayer player : evacuate) {
|
||||||
Optional<RegisteredServer> next = player.getNextServerToTry();
|
RegisteredServer next = player.getNextServerToTry();
|
||||||
if (next.isPresent()) {
|
if (next != null) {
|
||||||
player.createConnectionRequest(next.get()).connectWithIndication()
|
player.createConnectionRequest(next).connectWithIndication()
|
||||||
.whenComplete((success, ex) -> {
|
.whenComplete((success, ex) -> {
|
||||||
if (ex != null || success == null || !success) {
|
if (ex != null || success == null || !success) {
|
||||||
player.disconnect(Component.text("Your server has been changed, but we could "
|
player.disconnect(Component.text("Your server has been changed, but we could "
|
||||||
@ -613,15 +613,15 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Player> getPlayer(String username) {
|
public @Nullable Player player(String username) {
|
||||||
Preconditions.checkNotNull(username, "username");
|
Preconditions.checkNotNull(username, "username");
|
||||||
return Optional.ofNullable(connectionsByName.get(username.toLowerCase(Locale.US)));
|
return connectionsByName.get(username.toLowerCase(Locale.US));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Player> getPlayer(UUID uuid) {
|
public @Nullable Player player(UUID uuid) {
|
||||||
Preconditions.checkNotNull(uuid, "uuid");
|
Preconditions.checkNotNull(uuid, "uuid");
|
||||||
return Optional.ofNullable(connectionsByUuid.get(uuid));
|
return connectionsByUuid.get(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -653,7 +653,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<RegisteredServer> server(String name) {
|
public @Nullable RegisteredServer server(String name) {
|
||||||
return servers.getServer(name);
|
return servers.getServer(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.command;
|
package com.velocitypowered.proxy.command;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
@ -164,7 +165,8 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
if (commandResult.isForwardToServer() || !commandResult.isAllowed()) {
|
if (commandResult.isForwardToServer() || !commandResult.isAllowed()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return executeImmediately0(source, commandResult.modifiedCommand().orElse(event.rawCommand()));
|
return executeImmediately0(source,
|
||||||
|
MoreObjects.firstNonNull(commandResult.modifiedCommand(), event.rawCommand()));
|
||||||
}, eventManager.getAsyncExecutor());
|
}, eventManager.getAsyncExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
|||||||
import com.velocitypowered.api.proxy.connection.Player;
|
import com.velocitypowered.api.proxy.connection.Player;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
@ -92,13 +91,13 @@ public class GlistCommand {
|
|||||||
}
|
}
|
||||||
sendTotalProxyCount(source);
|
sendTotalProxyCount(source);
|
||||||
} else {
|
} else {
|
||||||
Optional<RegisteredServer> registeredServer = server.server(serverName);
|
RegisteredServer registeredServer = server.server(serverName);
|
||||||
if (!registeredServer.isPresent()) {
|
if (registeredServer == null) {
|
||||||
source.sendMessage(Identity.nil(),
|
source.sendMessage(Identity.nil(),
|
||||||
CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
|
CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sendServerPlayers(source, registeredServer.get(), false);
|
sendServerPlayers(source, registeredServer, false);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -62,21 +62,22 @@ public class ServerCommand implements SimpleCommand {
|
|||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
// Trying to connect to a server.
|
// Trying to connect to a server.
|
||||||
String serverName = args[0];
|
String serverName = args[0];
|
||||||
Optional<RegisteredServer> toConnect = server.server(serverName);
|
RegisteredServer toConnect = server.server(serverName);
|
||||||
if (!toConnect.isPresent()) {
|
if (toConnect == null) {
|
||||||
player.sendMessage(Identity.nil(), CommandMessages.SERVER_DOES_NOT_EXIST
|
player.sendMessage(Identity.nil(), CommandMessages.SERVER_DOES_NOT_EXIST
|
||||||
.args(Component.text(serverName)));
|
.args(Component.text(serverName)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.createConnectionRequest(toConnect.get()).fireAndForget();
|
player.createConnectionRequest(toConnect).fireAndForget();
|
||||||
} else {
|
} else {
|
||||||
outputServerInformation(player);
|
outputServerInformation(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void outputServerInformation(Player executor) {
|
private void outputServerInformation(Player executor) {
|
||||||
String currentServer = executor.connectedServer().map(ServerConnection::serverInfo)
|
String currentServer = Optional.ofNullable(executor.connectedServer())
|
||||||
|
.map(ServerConnection::serverInfo)
|
||||||
.map(ServerInfo::name).orElse("<unknown>");
|
.map(ServerInfo::name).orElse("<unknown>");
|
||||||
executor.sendMessage(Identity.nil(), Component.translatable(
|
executor.sendMessage(Identity.nil(), Component.translatable(
|
||||||
"velocity.command.server-current-server",
|
"velocity.command.server-current-server",
|
||||||
|
@ -44,7 +44,6 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@ -295,17 +294,17 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TextComponent componentForPlugin(PluginDescription description) {
|
private TextComponent componentForPlugin(PluginDescription description) {
|
||||||
String pluginInfo = description.name().orElse(description.id())
|
String pluginInfo = description.name();
|
||||||
+ description.version().map(v -> " " + v).orElse("");
|
|
||||||
|
|
||||||
TextComponent.Builder hoverText = Component.text().content(pluginInfo);
|
TextComponent.Builder hoverText = Component.text().content(pluginInfo);
|
||||||
|
|
||||||
description.url().ifPresent(url -> {
|
String pluginUrl = description.url();
|
||||||
|
if (pluginUrl != null) {
|
||||||
hoverText.append(Component.newline());
|
hoverText.append(Component.newline());
|
||||||
hoverText.append(Component.translatable(
|
hoverText.append(Component.translatable(
|
||||||
"velocity.command.plugin-tooltip-website",
|
"velocity.command.plugin-tooltip-website",
|
||||||
Component.text(url)));
|
Component.text(pluginUrl)));
|
||||||
});
|
}
|
||||||
if (!description.authors().isEmpty()) {
|
if (!description.authors().isEmpty()) {
|
||||||
hoverText.append(Component.newline());
|
hoverText.append(Component.newline());
|
||||||
if (description.authors().size() == 1) {
|
if (description.authors().size() == 1) {
|
||||||
@ -319,11 +318,13 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
description.description().ifPresent(pdesc -> {
|
|
||||||
|
String humanDescription = description.description();
|
||||||
|
if (humanDescription != null) {
|
||||||
hoverText.append(Component.newline());
|
hoverText.append(Component.newline());
|
||||||
hoverText.append(Component.newline());
|
hoverText.append(Component.newline());
|
||||||
hoverText.append(Component.text(pdesc));
|
hoverText.append(Component.text(humanDescription));
|
||||||
});
|
}
|
||||||
|
|
||||||
return Component.text(description.id(), NamedTextColor.GRAY)
|
return Component.text(description.id(), NamedTextColor.GRAY)
|
||||||
.hoverEvent(HoverEvent.showText(hoverText.build()));
|
.hoverEvent(HoverEvent.showText(hoverText.build()));
|
||||||
|
@ -44,7 +44,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
@ -315,8 +314,8 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Favicon> getFavicon() {
|
public @Nullable Favicon getFavicon() {
|
||||||
return Optional.ofNullable(favicon);
|
return favicon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -179,7 +179,8 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
|
|||||||
|| sessionHandler instanceof HandshakeSessionHandler
|
|| sessionHandler instanceof HandshakeSessionHandler
|
||||||
|| sessionHandler instanceof StatusSessionHandler;
|
|| sessionHandler instanceof StatusSessionHandler;
|
||||||
boolean isQuietDecoderException = cause instanceof QuietDecoderException;
|
boolean isQuietDecoderException = cause instanceof QuietDecoderException;
|
||||||
boolean willLog = !isQuietDecoderException && !frontlineHandler;
|
boolean willLog = MinecraftDecoder.DEBUG
|
||||||
|
|| (!isQuietDecoderException && !frontlineHandler);
|
||||||
if (willLog) {
|
if (willLog) {
|
||||||
logger.error("{}: exception encountered in {}", association, sessionHandler, cause);
|
logger.error("{}: exception encountered in {}", association, sessionHandler, cause);
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,7 +37,6 @@ import io.netty.buffer.Unpooled;
|
|||||||
import io.netty.channel.unix.DomainSocketAddress;
|
import io.netty.channel.unix.DomainSocketAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
@ -69,18 +68,20 @@ public class BungeeCordMessageResponder {
|
|||||||
|
|
||||||
private void processConnect(ByteBufDataInput in) {
|
private void processConnect(ByteBufDataInput in) {
|
||||||
String serverName = in.readUTF();
|
String serverName = in.readUTF();
|
||||||
proxy.server(serverName).ifPresent(server -> player.createConnectionRequest(server)
|
RegisteredServer server = proxy.server(serverName);
|
||||||
.fireAndForget());
|
if (server != null) {
|
||||||
|
player.createConnectionRequest(server).fireAndForget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processConnectOther(ByteBufDataInput in) {
|
private void processConnectOther(ByteBufDataInput in) {
|
||||||
String playerName = in.readUTF();
|
String playerName = in.readUTF();
|
||||||
String serverName = in.readUTF();
|
String serverName = in.readUTF();
|
||||||
|
|
||||||
Optional<Player> referencedPlayer = proxy.getPlayer(playerName);
|
Player referencedPlayer = proxy.player(playerName);
|
||||||
Optional<RegisteredServer> referencedServer = proxy.server(serverName);
|
RegisteredServer referencedServer = proxy.server(serverName);
|
||||||
if (referencedPlayer.isPresent() && referencedServer.isPresent()) {
|
if (referencedPlayer != null && referencedServer != null) {
|
||||||
referencedPlayer.get().createConnectionRequest(referencedServer.get()).fireAndForget();
|
referencedPlayer.createConnectionRequest(referencedServer).fireAndForget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,12 +112,13 @@ public class BungeeCordMessageResponder {
|
|||||||
out.writeUTF("ALL");
|
out.writeUTF("ALL");
|
||||||
out.writeInt(proxy.countConnectedPlayers());
|
out.writeInt(proxy.countConnectedPlayers());
|
||||||
} else {
|
} else {
|
||||||
proxy.server(target).ifPresent(rs -> {
|
RegisteredServer referencedServer = proxy.server(target);
|
||||||
int playersOnServer = rs.connectedPlayers().size();
|
if (referencedServer != null) {
|
||||||
|
int playersOnServer = referencedServer.connectedPlayers().size();
|
||||||
out.writeUTF("PlayerCount");
|
out.writeUTF("PlayerCount");
|
||||||
out.writeUTF(rs.serverInfo().name());
|
out.writeUTF(referencedServer.serverInfo().name());
|
||||||
out.writeInt(playersOnServer);
|
out.writeInt(playersOnServer);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.isReadable()) {
|
if (buf.isReadable()) {
|
||||||
@ -141,16 +143,17 @@ public class BungeeCordMessageResponder {
|
|||||||
}
|
}
|
||||||
out.writeUTF(joiner.toString());
|
out.writeUTF(joiner.toString());
|
||||||
} else {
|
} else {
|
||||||
proxy.server(target).ifPresent(info -> {
|
RegisteredServer referencedServer = proxy.server(target);
|
||||||
|
if (referencedServer != null) {
|
||||||
out.writeUTF("PlayerList");
|
out.writeUTF("PlayerList");
|
||||||
out.writeUTF(info.serverInfo().name());
|
out.writeUTF(referencedServer.serverInfo().name());
|
||||||
|
|
||||||
StringJoiner joiner = new StringJoiner(", ");
|
StringJoiner joiner = new StringJoiner(", ");
|
||||||
for (Player online : info.connectedPlayers()) {
|
for (Player online : referencedServer.connectedPlayers()) {
|
||||||
joiner.add(online.username());
|
joiner.add(online.username());
|
||||||
}
|
}
|
||||||
out.writeUTF(joiner.toString());
|
out.writeUTF(joiner.toString());
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf.isReadable()) {
|
if (buf.isReadable()) {
|
||||||
@ -191,8 +194,10 @@ public class BungeeCordMessageResponder {
|
|||||||
if (target.equals("ALL")) {
|
if (target.equals("ALL")) {
|
||||||
proxy.sendMessage(Identity.nil(), messageComponent);
|
proxy.sendMessage(Identity.nil(), messageComponent);
|
||||||
} else {
|
} else {
|
||||||
proxy.getPlayer(target).ifPresent(player -> player.sendMessage(Identity.nil(),
|
Player player = proxy.player(target);
|
||||||
messageComponent));
|
if (player != null) {
|
||||||
|
player.sendMessage(Identity.nil(), messageComponent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +222,8 @@ public class BungeeCordMessageResponder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processUuidOther(ByteBufDataInput in) {
|
private void processUuidOther(ByteBufDataInput in) {
|
||||||
proxy.getPlayer(in.readUTF()).ifPresent(player -> {
|
Player player = proxy.player(in.readUTF());
|
||||||
|
if (player != null) {
|
||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
@ -226,11 +232,12 @@ public class BungeeCordMessageResponder {
|
|||||||
out.writeUTF(UuidUtils.toUndashed(player.id()));
|
out.writeUTF(UuidUtils.toUndashed(player.id()));
|
||||||
|
|
||||||
sendResponseOnConnection(buf);
|
sendResponseOnConnection(buf);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processIpOther(ByteBufDataInput in) {
|
private void processIpOther(ByteBufDataInput in) {
|
||||||
proxy.getPlayer(in.readUTF()).ifPresent(player -> {
|
Player player = proxy.player(in.readUTF());
|
||||||
|
if (player != null) {
|
||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
@ -247,11 +254,12 @@ public class BungeeCordMessageResponder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendResponseOnConnection(buf);
|
sendResponseOnConnection(buf);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processServerIp(ByteBufDataInput in) {
|
private void processServerIp(ByteBufDataInput in) {
|
||||||
proxy.server(in.readUTF()).ifPresent(info -> {
|
RegisteredServer info = proxy.server(in.readUTF());
|
||||||
|
if (info != null) {
|
||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
ByteBufDataOutput out = new ByteBufDataOutput(buf);
|
||||||
|
|
||||||
@ -268,21 +276,22 @@ public class BungeeCordMessageResponder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendResponseOnConnection(buf);
|
sendResponseOnConnection(buf);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processKick(ByteBufDataInput in) {
|
private void processKick(ByteBufDataInput in) {
|
||||||
proxy.getPlayer(in.readUTF()).ifPresent(player -> {
|
Player player = proxy.player(in.readUTF());
|
||||||
|
if (player != null) {
|
||||||
String kickReason = in.readUTF();
|
String kickReason = in.readUTF();
|
||||||
player.disconnect(LegacyComponentSerializer.legacySection().deserialize(kickReason));
|
player.disconnect(LegacyComponentSerializer.legacySection().deserialize(kickReason));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processForwardToPlayer(ByteBufDataInput in) {
|
private void processForwardToPlayer(ByteBufDataInput in) {
|
||||||
Optional<Player> player = proxy.getPlayer(in.readUTF());
|
Player player = proxy.player(in.readUTF());
|
||||||
if (player.isPresent()) {
|
if (player != null) {
|
||||||
ByteBuf toForward = in.unwrap().copy();
|
ByteBuf toForward = in.unwrap().copy();
|
||||||
sendServerResponse((ConnectedPlayer) player.get(), toForward);
|
sendServerResponse((ConnectedPlayer) player, toForward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,9 +308,9 @@ public class BungeeCordMessageResponder {
|
|||||||
toForward.release();
|
toForward.release();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Optional<RegisteredServer> server = proxy.server(target);
|
RegisteredServer server = proxy.server(target);
|
||||||
if (server.isPresent()) {
|
if (server != null) {
|
||||||
((VelocityRegisteredServer) server.get()).sendPluginMessage(CHANNEL, toForward);
|
((VelocityRegisteredServer) server).sendPluginMessage(CHANNEL, toForward);
|
||||||
} else {
|
} else {
|
||||||
toForward.release();
|
toForward.release();
|
||||||
}
|
}
|
||||||
|
@ -168,9 +168,9 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
try {
|
try {
|
||||||
ProtocolUtils.writeVarInt(forwarded, VelocityConstants.FORWARDING_VERSION);
|
ProtocolUtils.writeVarInt(forwarded, VelocityConstants.FORWARDING_VERSION);
|
||||||
ProtocolUtils.writeString(forwarded, address);
|
ProtocolUtils.writeString(forwarded, address);
|
||||||
ProtocolUtils.writeUuid(forwarded, profile.getId());
|
ProtocolUtils.writeUuid(forwarded, profile.uuid());
|
||||||
ProtocolUtils.writeString(forwarded, profile.getName());
|
ProtocolUtils.writeString(forwarded, profile.name());
|
||||||
ProtocolUtils.writeProperties(forwarded, profile.getProperties());
|
ProtocolUtils.writeProperties(forwarded, profile.properties());
|
||||||
|
|
||||||
SecretKey key = new SecretKeySpec(hmacSecret, "HmacSHA256");
|
SecretKey key = new SecretKeySpec(hmacSecret, "HmacSHA256");
|
||||||
Mac mac = Mac.getInstance("HmacSHA256");
|
Mac mac = Mac.getInstance("HmacSHA256");
|
||||||
|
@ -119,7 +119,8 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String playerConnectedHostname() {
|
private String playerConnectedHostname() {
|
||||||
return proxyPlayer.connectedHostname().map(InetSocketAddress::getHostString).orElse("");
|
InetSocketAddress vhost = proxyPlayer.connectedHostname();
|
||||||
|
return vhost == null ? "" : vhost.getHostString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createLegacyForwardingAddress(UnaryOperator<List<Property>> propertiesTransform) {
|
private String createLegacyForwardingAddress(UnaryOperator<List<Property>> propertiesTransform) {
|
||||||
@ -135,10 +136,10 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
.append('\0')
|
.append('\0')
|
||||||
.append(((InetSocketAddress) proxyPlayer.remoteAddress()).getHostString())
|
.append(((InetSocketAddress) proxyPlayer.remoteAddress()).getHostString())
|
||||||
.append('\0')
|
.append('\0')
|
||||||
.append(proxyPlayer.gameProfile().getUndashedId())
|
.append(proxyPlayer.gameProfile().undashedId())
|
||||||
.append('\0');
|
.append('\0');
|
||||||
GENERAL_GSON
|
GENERAL_GSON
|
||||||
.toJson(propertiesTransform.apply(proxyPlayer.gameProfile().getProperties()), data);
|
.toJson(propertiesTransform.apply(proxyPlayer.gameProfile().properties()), data);
|
||||||
return data.toString();
|
return data.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +234,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[server connection] " + proxyPlayer.gameProfile().getName() + " -> "
|
return "[server connection] " + proxyPlayer.gameProfile().name() + " -> "
|
||||||
+ registeredServer.serverInfo().name();
|
+ registeredServer.serverInfo().name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_16;
|
|||||||
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
|
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
|
||||||
import static com.velocitypowered.proxy.network.PluginMessageUtil.constructChannelsPacket;
|
import static com.velocitypowered.proxy.network.PluginMessageUtil.constructChannelsPacket;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
|
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
|
||||||
import com.velocitypowered.api.event.connection.PluginMessageEvent;
|
import com.velocitypowered.api.event.connection.PluginMessageEvent;
|
||||||
@ -65,7 +66,6 @@ import java.util.ArrayDeque;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@ -598,7 +598,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MinecraftConnection smc = player.ensureAndGetCurrentServer().ensureConnected();
|
MinecraftConnection smc = player.ensureAndGetCurrentServer().ensureConnected();
|
||||||
String commandToRun = result.modifiedCommand().orElse(originalCommand);
|
String commandToRun = MoreObjects.firstNonNull(result.modifiedCommand(), originalCommand);
|
||||||
if (result.isForwardToServer()) {
|
if (result.isForwardToServer()) {
|
||||||
return CompletableFuture.runAsync(() -> smc.write(new ServerboundChatPacket("/"
|
return CompletableFuture.runAsync(() -> smc.write(new ServerboundChatPacket("/"
|
||||||
+ commandToRun)), smc.eventLoop());
|
+ commandToRun)), smc.eventLoop());
|
||||||
|
@ -81,7 +81,6 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionException;
|
import java.util.concurrent.CompletionException;
|
||||||
@ -162,17 +161,17 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String username() {
|
public String username() {
|
||||||
return profile.getName();
|
return profile.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID id() {
|
public UUID id() {
|
||||||
return profile.getId();
|
return profile.uuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ServerConnection> connectedServer() {
|
public @Nullable ServerConnection connectedServer() {
|
||||||
return Optional.ofNullable(connectedServer);
|
return connectedServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,8 +221,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ModInfo> modInfo() {
|
public @Nullable ModInfo modInfo() {
|
||||||
return Optional.ofNullable(modInfo);
|
return modInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setModInfo(ModInfo modInfo) {
|
public void setModInfo(ModInfo modInfo) {
|
||||||
@ -237,8 +236,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<InetSocketAddress> connectedHostname() {
|
public @Nullable InetSocketAddress connectedHostname() {
|
||||||
return Optional.ofNullable(virtualHost);
|
return virtualHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPermissionFunction(PermissionFunction permissionFunction) {
|
void setPermissionFunction(PermissionFunction permissionFunction) {
|
||||||
@ -509,9 +508,12 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
boolean kickedFromCurrent = connectedServer == null || connectedServer.target().equals(rs);
|
boolean kickedFromCurrent = connectedServer == null || connectedServer.target().equals(rs);
|
||||||
ServerKickResult result;
|
ServerKickResult result;
|
||||||
if (kickedFromCurrent) {
|
if (kickedFromCurrent) {
|
||||||
Optional<RegisteredServer> next = getNextServerToTry(rs);
|
RegisteredServer next = getNextServerToTry(rs);
|
||||||
result = next.map(RedirectPlayer::create)
|
if (next == null) {
|
||||||
.orElseGet(() -> DisconnectPlayer.create(friendlyReason));
|
result = DisconnectPlayer.create(friendlyReason);
|
||||||
|
} else {
|
||||||
|
result = RedirectPlayer.create(next);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If we were kicked by going to another server, the connection should not be in flight
|
// If we were kicked by going to another server, the connection should not be in flight
|
||||||
if (connectionInFlight != null && connectionInFlight.target().equals(rs)) {
|
if (connectionInFlight != null && connectionInFlight.target().equals(rs)) {
|
||||||
@ -562,11 +564,12 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
case CONNECTION_IN_PROGRESS:
|
case CONNECTION_IN_PROGRESS:
|
||||||
// Fatal case
|
// Fatal case
|
||||||
case CONNECTION_CANCELLED:
|
case CONNECTION_CANCELLED:
|
||||||
disconnect(status.failureReason().orElse(res.message()));
|
disconnect(status.failureReason() != null ? status.failureReason()
|
||||||
|
: res.message());
|
||||||
break;
|
break;
|
||||||
case SERVER_DISCONNECTED:
|
case SERVER_DISCONNECTED:
|
||||||
Component reason = status.failureReason()
|
Component reason = status.failureReason() != null ? status.failureReason()
|
||||||
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);
|
: ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR;
|
||||||
handleConnectionException(res.getServer(), ClientboundDisconnectPacket.create(reason,
|
handleConnectionException(res.getServer(), ClientboundDisconnectPacket.create(reason,
|
||||||
protocolVersion()), ((Impl) status).isSafe());
|
protocolVersion()), ((Impl) status).isSafe());
|
||||||
break;
|
break;
|
||||||
@ -601,7 +604,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
*
|
*
|
||||||
* @return the next server to try
|
* @return the next server to try
|
||||||
*/
|
*/
|
||||||
public Optional<RegisteredServer> getNextServerToTry() {
|
public @Nullable RegisteredServer getNextServerToTry() {
|
||||||
return this.getNextServerToTry(null);
|
return this.getNextServerToTry(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,11 +616,10 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
*
|
*
|
||||||
* @return the next server to try
|
* @return the next server to try
|
||||||
*/
|
*/
|
||||||
private Optional<RegisteredServer> getNextServerToTry(@Nullable RegisteredServer current) {
|
private @Nullable RegisteredServer getNextServerToTry(@Nullable RegisteredServer current) {
|
||||||
if (serversToTry == null) {
|
if (serversToTry == null) {
|
||||||
String virtualHostStr = connectedHostname().map(InetSocketAddress::getHostString)
|
InetSocketAddress vhost = connectedHostname();
|
||||||
.orElse("")
|
String virtualHostStr = vhost == null ? "" : vhost.getHostString().toLowerCase(Locale.ROOT);
|
||||||
.toLowerCase(Locale.ROOT);
|
|
||||||
serversToTry = server.configuration().getForcedHosts().getOrDefault(virtualHostStr,
|
serversToTry = server.configuration().getForcedHosts().getOrDefault(virtualHostStr,
|
||||||
Collections.emptyList());
|
Collections.emptyList());
|
||||||
}
|
}
|
||||||
@ -637,7 +639,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
tryIndex = i;
|
tryIndex = i;
|
||||||
return server.server(toTryName);
|
return server.server(toTryName);
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasSameName(RegisteredServer server, String name) {
|
private static boolean hasSameName(RegisteredServer server, String name) {
|
||||||
@ -684,15 +686,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
connectedServer.disconnect();
|
connectedServer.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Player> connectedPlayer = server.getPlayer(this.id());
|
Player connectedPlayer = server.player(this.id());
|
||||||
server.unregisterConnection(this);
|
server.unregisterConnection(this);
|
||||||
|
|
||||||
DisconnectEventImpl.LoginStatus status;
|
DisconnectEventImpl.LoginStatus status;
|
||||||
if (connectedPlayer.isPresent()) {
|
if (connectedPlayer != null) {
|
||||||
if (!connectedPlayer.get().connectedServer().isPresent()) {
|
if (connectedPlayer.connectedServer() != null) {
|
||||||
status = LoginStatus.PRE_SERVER_JOIN;
|
status = LoginStatus.PRE_SERVER_JOIN;
|
||||||
} else {
|
} else {
|
||||||
status = connectedPlayer.get() == this ? LoginStatus.SUCCESSFUL_LOGIN
|
status = connectedPlayer == this ? LoginStatus.SUCCESSFUL_LOGIN
|
||||||
: LoginStatus.CONFLICTING_LOGIN;
|
: LoginStatus.CONFLICTING_LOGIN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -716,7 +718,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[connected player] " + profile.getName() + " (" + remoteAddress() + ")";
|
return "[connected player] " + profile.name() + " (" + remoteAddress() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -847,45 +849,44 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
return toConnect;
|
return toConnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<ConnectionRequestBuilder.Status> checkServer(RegisteredServer server) {
|
private ConnectionRequestBuilder.@Nullable Status checkServer(RegisteredServer server) {
|
||||||
Preconditions.checkArgument(server instanceof VelocityRegisteredServer,
|
Preconditions.checkArgument(server instanceof VelocityRegisteredServer,
|
||||||
"Not a valid Velocity server.");
|
"Not a valid Velocity server.");
|
||||||
if (connectionInFlight != null || (connectedServer != null
|
if (connectionInFlight != null || (connectedServer != null
|
||||||
&& !connectedServer.hasCompletedJoin())) {
|
&& !connectedServer.hasCompletedJoin())) {
|
||||||
return Optional.of(ConnectionRequestBuilder.Status.CONNECTION_IN_PROGRESS);
|
return ConnectionRequestBuilder.Status.CONNECTION_IN_PROGRESS;
|
||||||
}
|
}
|
||||||
if (connectedServer != null && connectedServer.target().equals(server)) {
|
if (connectedServer != null && connectedServer.target().equals(server)) {
|
||||||
return Optional.of(ALREADY_CONNECTED);
|
return ALREADY_CONNECTED;
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Optional<Status>> getInitialStatus() {
|
private CompletableFuture<ConnectionRequestBuilder.Status> getInitialStatus() {
|
||||||
return CompletableFuture.supplyAsync(() -> checkServer(toConnect), connection.eventLoop());
|
return CompletableFuture.supplyAsync(() -> checkServer(toConnect), connection.eventLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Impl> internalConnect() {
|
private CompletableFuture<Impl> internalConnect() {
|
||||||
return this.getInitialStatus()
|
return this.getInitialStatus()
|
||||||
.thenCompose(initialCheck -> {
|
.thenCompose(initialCheck -> {
|
||||||
if (initialCheck.isPresent()) {
|
if (initialCheck != null) {
|
||||||
return completedFuture(plainResult(initialCheck.get(), toConnect));
|
return completedFuture(plainResult(initialCheck, toConnect));
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerPreConnectEvent event = new ServerPreConnectEventImpl(ConnectedPlayer.this,
|
ServerPreConnectEvent event = new ServerPreConnectEventImpl(ConnectedPlayer.this,
|
||||||
toConnect);
|
toConnect);
|
||||||
return server.eventManager().fire(event)
|
return server.eventManager().fire(event)
|
||||||
.thenComposeAsync(newEvent -> {
|
.thenComposeAsync(newEvent -> {
|
||||||
Optional<RegisteredServer> newDest = newEvent.result().target();
|
RegisteredServer realDestination = newEvent.result().target();
|
||||||
if (!newDest.isPresent()) {
|
if (realDestination == null) {
|
||||||
return completedFuture(
|
return completedFuture(
|
||||||
plainResult(ConnectionRequestBuilder.Status.CONNECTION_CANCELLED, toConnect)
|
plainResult(ConnectionRequestBuilder.Status.CONNECTION_CANCELLED, toConnect)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisteredServer realDestination = newDest.get();
|
ConnectionRequestBuilder.Status secondCheck = checkServer(realDestination);
|
||||||
Optional<ConnectionRequestBuilder.Status> check = checkServer(realDestination);
|
if (secondCheck != null) {
|
||||||
if (check.isPresent()) {
|
return completedFuture(plainResult(secondCheck, realDestination));
|
||||||
return completedFuture(plainResult(check.get(), realDestination));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VelocityRegisteredServer vrs = (VelocityRegisteredServer) realDestination;
|
VelocityRegisteredServer vrs = (VelocityRegisteredServer) realDestination;
|
||||||
@ -945,8 +946,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
// Ignored; the plugin probably already handled this.
|
// Ignored; the plugin probably already handled this.
|
||||||
break;
|
break;
|
||||||
case SERVER_DISCONNECTED:
|
case SERVER_DISCONNECTED:
|
||||||
Component reason = status.failureReason()
|
Component reason = status.failureReason() != null ? status.failureReason()
|
||||||
.orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR);
|
: ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR;
|
||||||
handleConnectionException(toConnect, ClientboundDisconnectPacket.create(reason,
|
handleConnectionException(toConnect, ClientboundDisconnectPacket.create(reason,
|
||||||
protocolVersion()), status.isSafe());
|
protocolVersion()), status.isSafe());
|
||||||
break;
|
break;
|
||||||
|
@ -40,7 +40,6 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -88,11 +87,11 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
LOGGER.error("{} provided invalid protocol {}", ic, handshake.getNextStatus());
|
LOGGER.error("{} provided invalid protocol {}", ic, handshake.getNextStatus());
|
||||||
connection.close(true);
|
connection.close(true);
|
||||||
} else {
|
} else {
|
||||||
connection.setState(nextState);
|
|
||||||
connection.setProtocolVersion(handshake.getProtocolVersion());
|
connection.setProtocolVersion(handshake.getProtocolVersion());
|
||||||
connection.setAssociation(ic);
|
connection.setAssociation(ic);
|
||||||
|
|
||||||
if (nextState == ProtocolStates.STATUS) {
|
if (nextState == ProtocolStates.STATUS) {
|
||||||
|
connection.setState(nextState);
|
||||||
connection.setSessionHandler(new StatusSessionHandler(server, connection, ic));
|
connection.setSessionHandler(new StatusSessionHandler(server, connection, ic));
|
||||||
} else if (nextState == ProtocolStates.LOGIN) {
|
} else if (nextState == ProtocolStates.LOGIN) {
|
||||||
this.handleLogin(handshake, ic);
|
this.handleLogin(handshake, ic);
|
||||||
@ -134,12 +133,15 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connection.setAutoReading(false);
|
connection.setAutoReading(false);
|
||||||
|
connection.setState(ProtocolStates.LOGIN);
|
||||||
server.eventManager().fire(new ConnectionHandshakeEventImpl(ic, handshake.getServerAddress()))
|
server.eventManager().fire(new ConnectionHandshakeEventImpl(ic, handshake.getServerAddress()))
|
||||||
.thenAcceptAsync(event -> {
|
.thenAcceptAsync(event -> {
|
||||||
connection.setAutoReading(true);
|
if (connection.isClosed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!event.result().isAllowed()) {
|
if (!event.result().isAllowed()) {
|
||||||
ic.disconnectQuietly(event.result().reason().get());
|
ic.disconnectQuietly(event.result().reason());
|
||||||
} else {
|
} else {
|
||||||
// if the handshake is changed, propagate the change
|
// if the handshake is changed, propagate the change
|
||||||
if (!event.currentHostname().equals(event.originalHostname())) {
|
if (!event.currentHostname().equals(event.originalHostname())) {
|
||||||
@ -161,6 +163,7 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connection.setSessionHandler(new LoginSessionHandler(server, connection, ic));
|
connection.setSessionHandler(new LoginSessionHandler(server, connection, ic));
|
||||||
|
connection.setAutoReading(true);
|
||||||
}
|
}
|
||||||
}, connection.eventLoop());
|
}, connection.eventLoop());
|
||||||
}
|
}
|
||||||
@ -234,8 +237,8 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<InetSocketAddress> connectedHostname() {
|
public @Nullable InetSocketAddress connectedHostname() {
|
||||||
return Optional.ofNullable(ping.getVhost());
|
return ping.getVhost();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,8 +27,6 @@ import com.velocitypowered.proxy.network.packet.serverbound.ServerboundHandshake
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import net.kyori.adventure.translation.GlobalTranslator;
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
@ -58,8 +56,8 @@ public final class InitialInboundConnection implements InboundConnection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<InetSocketAddress> connectedHostname() {
|
public @Nullable InetSocketAddress connectedHostname() {
|
||||||
return Optional.of(InetSocketAddress.createUnresolved(cleanedHostname, handshake.getPort()));
|
return InetSocketAddress.createUnresolved(cleanedHostname, handshake.getPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -59,7 +59,6 @@ import java.security.GeneralSecurityException;
|
|||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -194,10 +193,10 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ComponentResult result = event.result();
|
ComponentResult result = event.result();
|
||||||
Optional<Component> disconnectReason = result.reason();
|
Component disconnectReason = result.reason();
|
||||||
if (disconnectReason.isPresent()) {
|
if (disconnectReason != null) {
|
||||||
// The component is guaranteed to be provided if the connection was denied.
|
// The component is guaranteed to be provided if the connection was denied.
|
||||||
inbound.disconnect(disconnectReason.get());
|
inbound.disconnect(disconnectReason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +241,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
// Initiate a regular connection and move over to it.
|
// Initiate a regular connection and move over to it.
|
||||||
ConnectedPlayer player = new ConnectedPlayer(server, profileEvent.gameProfile(),
|
ConnectedPlayer player = new ConnectedPlayer(server, profileEvent.gameProfile(),
|
||||||
mcConnection, inbound.connectedHostname().orElse(null), onlineMode);
|
mcConnection, inbound.connectedHostname(), onlineMode);
|
||||||
this.connectedPlayer = player;
|
this.connectedPlayer = player;
|
||||||
if (!server.canRegisterConnection(player)) {
|
if (!server.canRegisterConnection(player)) {
|
||||||
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy",
|
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy",
|
||||||
@ -302,9 +301,9 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Component> reason = event.result().reason();
|
Component denialReason = event.result().reason();
|
||||||
if (reason.isPresent()) {
|
if (denialReason != null) {
|
||||||
player.disconnect0(reason.get(), true);
|
player.disconnect0(denialReason, true);
|
||||||
} else {
|
} else {
|
||||||
if (!server.registerConnection(player)) {
|
if (!server.registerConnection(player)) {
|
||||||
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy"),
|
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy"),
|
||||||
@ -328,19 +327,19 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> connectToInitialServer(ConnectedPlayer player) {
|
private CompletableFuture<Void> connectToInitialServer(ConnectedPlayer player) {
|
||||||
Optional<RegisteredServer> initialFromConfig = player.getNextServerToTry();
|
RegisteredServer initialFromConfig = player.getNextServerToTry();
|
||||||
PlayerChooseInitialServerEvent event = new PlayerChooseInitialServerEventImpl(player,
|
PlayerChooseInitialServerEvent event = new PlayerChooseInitialServerEventImpl(player,
|
||||||
initialFromConfig.orElse(null));
|
initialFromConfig);
|
||||||
|
|
||||||
return server.eventManager().fire(event)
|
return server.eventManager().fire(event)
|
||||||
.thenRunAsync(() -> {
|
.thenRunAsync(() -> {
|
||||||
Optional<RegisteredServer> toTry = event.initialServer();
|
RegisteredServer toTry = event.initialServer();
|
||||||
if (!toTry.isPresent()) {
|
if (toTry == null) {
|
||||||
player.disconnect0(Component.translatable("velocity.error.no-available-servers",
|
player.disconnect0(Component.translatable("velocity.error.no-available-servers",
|
||||||
NamedTextColor.RED), true);
|
NamedTextColor.RED), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
player.createConnectionRequest(toTry.get()).fireAndForget();
|
player.createConnectionRequest(toTry).fireAndForget();
|
||||||
}, mcConnection.eventLoop());
|
}, mcConnection.eventLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ import java.net.InetSocketAddress;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -82,7 +81,7 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
new ServerPing.Players(server.countConnectedPlayers(), configuration.getShowMaxPlayers(),
|
new ServerPing.Players(server.countConnectedPlayers(), configuration.getShowMaxPlayers(),
|
||||||
ImmutableList.of()),
|
ImmutableList.of()),
|
||||||
configuration.getMotd(),
|
configuration.getMotd(),
|
||||||
configuration.getFavicon().orElse(null),
|
configuration.getFavicon(),
|
||||||
configuration.isAnnounceForge() ? ModInfo.DEFAULT : null
|
configuration.isAnnounceForge() ? ModInfo.DEFAULT : null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -92,11 +91,11 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
ServerPing fallback = constructLocalPing(pingingVersion);
|
ServerPing fallback = constructLocalPing(pingingVersion);
|
||||||
List<CompletableFuture<ServerPing>> pings = new ArrayList<>();
|
List<CompletableFuture<ServerPing>> pings = new ArrayList<>();
|
||||||
for (String s : servers) {
|
for (String s : servers) {
|
||||||
Optional<RegisteredServer> rs = server.server(s);
|
RegisteredServer rs = server.server(s);
|
||||||
if (!rs.isPresent()) {
|
if (rs == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
VelocityRegisteredServer vrs = (VelocityRegisteredServer) rs.get();
|
VelocityRegisteredServer vrs = (VelocityRegisteredServer) rs;
|
||||||
pings.add(vrs.ping(connection.eventLoop(), pingingVersion));
|
pings.add(vrs.ping(connection.eventLoop(), pingingVersion));
|
||||||
}
|
}
|
||||||
if (pings.isEmpty()) {
|
if (pings.isEmpty()) {
|
||||||
@ -124,9 +123,9 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
if (response == fallback) {
|
if (response == fallback) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Optional<ModInfo> modInfo = response.modInfo();
|
ModInfo modInfo = response.modInfo();
|
||||||
if (modInfo.isPresent()) {
|
if (modInfo != null) {
|
||||||
return fallback.asBuilder().mods(modInfo.get()).build();
|
return fallback.asBuilder().mods(modInfo).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fallback;
|
return fallback;
|
||||||
@ -145,10 +144,10 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
return new ServerPing(
|
return new ServerPing(
|
||||||
fallback.version(),
|
fallback.version(),
|
||||||
fallback.players().orElse(null),
|
fallback.players(),
|
||||||
response.description(),
|
response.description(),
|
||||||
fallback.favicon().orElse(null),
|
fallback.favicon(),
|
||||||
response.modInfo().orElse(null)
|
response.modInfo()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return fallback;
|
return fallback;
|
||||||
@ -168,9 +167,8 @@ public class StatusSessionHandler implements MinecraftSessionHandler {
|
|||||||
if (passthrough == PingPassthroughMode.DISABLED) {
|
if (passthrough == PingPassthroughMode.DISABLED) {
|
||||||
return CompletableFuture.completedFuture(constructLocalPing(shownVersion));
|
return CompletableFuture.completedFuture(constructLocalPing(shownVersion));
|
||||||
} else {
|
} else {
|
||||||
String virtualHostStr = inbound.connectedHostname().map(InetSocketAddress::getHostString)
|
InetSocketAddress vhost = inbound.connectedHostname();
|
||||||
.map(str -> str.toLowerCase(Locale.ROOT))
|
String virtualHostStr = vhost == null ? "" : vhost.getHostString().toLowerCase(Locale.ROOT);
|
||||||
.orElse("");
|
|
||||||
List<String> serversToTry = server.configuration().getForcedHosts().getOrDefault(
|
List<String> serversToTry = server.configuration().getForcedHosts().getOrDefault(
|
||||||
virtualHostStr, server.configuration().getAttemptConnectionOrder());
|
virtualHostStr, server.configuration().getAttemptConnectionOrder());
|
||||||
return attemptPingPassthrough(configuration.getPingPassthrough(), serversToTry, shownVersion);
|
return attemptPingPassthrough(configuration.getPingPassthrough(), serversToTry, shownVersion);
|
||||||
|
@ -93,7 +93,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase {
|
|||||||
AbstractPluginMessagePacket<?> message,
|
AbstractPluginMessagePacket<?> message,
|
||||||
MinecraftConnection backendConn) {
|
MinecraftConnection backendConn) {
|
||||||
// Read the mod list if we haven't already.
|
// Read the mod list if we haven't already.
|
||||||
if (!player.modInfo().isPresent()) {
|
if (player.modInfo() == null) {
|
||||||
List<ModInfo.Mod> mods = LegacyForgeUtil.readModList(message);
|
List<ModInfo.Mod> mods = LegacyForgeUtil.readModList(message);
|
||||||
if (!mods.isEmpty()) {
|
if (!mods.isEmpty()) {
|
||||||
player.setModInfo(new ModInfo("FML", mods));
|
player.setModInfo(new ModInfo("FML", mods));
|
||||||
|
@ -21,7 +21,6 @@ import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder;
|
|||||||
import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder.Status;
|
import com.velocitypowered.api.proxy.player.ConnectionRequestBuilder.Status;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
|
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundDisconnectPacket;
|
||||||
import java.util.Optional;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
@ -89,8 +88,8 @@ public class ConnectionRequestResults {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Component> failureReason() {
|
public @Nullable Component failureReason() {
|
||||||
return Optional.ofNullable(component);
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -290,12 +290,6 @@ public class VelocityEventManager implements EventManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PluginContainer ensurePlugin(final Object plugin) {
|
|
||||||
requireNonNull(plugin, "plugin");
|
|
||||||
return pluginManager.fromInstance(plugin)
|
|
||||||
.orElseThrow(() -> new IllegalArgumentException("Specified plugin is not loaded"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void register(final List<HandlerRegistration> registrations) {
|
private void register(final List<HandlerRegistration> registrations) {
|
||||||
lock.writeLock().lock();
|
lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
@ -315,7 +309,7 @@ public class VelocityEventManager implements EventManager {
|
|||||||
@Override
|
@Override
|
||||||
public void register(final Object plugin, final Object listener) {
|
public void register(final Object plugin, final Object listener) {
|
||||||
requireNonNull(listener, "listener");
|
requireNonNull(listener, "listener");
|
||||||
final PluginContainer pluginContainer = ensurePlugin(plugin);
|
final PluginContainer pluginContainer = pluginManager.ensurePluginContainer(plugin);
|
||||||
if (plugin == listener) {
|
if (plugin == listener) {
|
||||||
throw new IllegalArgumentException("The plugin main instance is automatically registered.");
|
throw new IllegalArgumentException("The plugin main instance is automatically registered.");
|
||||||
}
|
}
|
||||||
@ -326,7 +320,7 @@ public class VelocityEventManager implements EventManager {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <E> void register(final Object plugin, final Class<E> eventClass,
|
public <E> void register(final Object plugin, final Class<E> eventClass,
|
||||||
final short order, final EventHandler<E> handler) {
|
final short order, final EventHandler<E> handler) {
|
||||||
final PluginContainer pluginContainer = ensurePlugin(plugin);
|
final PluginContainer pluginContainer = pluginManager.ensurePluginContainer(plugin);
|
||||||
requireNonNull(eventClass, "eventClass");
|
requireNonNull(eventClass, "eventClass");
|
||||||
requireNonNull(handler, "handler");
|
requireNonNull(handler, "handler");
|
||||||
|
|
||||||
@ -360,13 +354,13 @@ public class VelocityEventManager implements EventManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterListeners(final Object plugin) {
|
public void unregisterListeners(final Object plugin) {
|
||||||
final PluginContainer pluginContainer = ensurePlugin(plugin);
|
final PluginContainer pluginContainer = pluginManager.ensurePluginContainer(plugin);
|
||||||
unregisterIf(registration -> registration.plugin == pluginContainer);
|
unregisterIf(registration -> registration.plugin == pluginContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterListener(final Object plugin, final Object handler) {
|
public void unregisterListener(final Object plugin, final Object handler) {
|
||||||
final PluginContainer pluginContainer = ensurePlugin(plugin);
|
final PluginContainer pluginContainer = pluginManager.ensurePluginContainer(plugin);
|
||||||
requireNonNull(handler, "handler");
|
requireNonNull(handler, "handler");
|
||||||
unregisterIf(registration ->
|
unregisterIf(registration ->
|
||||||
registration.plugin == pluginContainer && registration.handler == handler);
|
registration.plugin == pluginContainer && registration.handler == handler);
|
||||||
|
@ -355,9 +355,9 @@ public enum ProtocolUtils {
|
|||||||
public static void writeProperties(ByteBuf buf, List<GameProfile.Property> properties) {
|
public static void writeProperties(ByteBuf buf, List<GameProfile.Property> properties) {
|
||||||
writeVarInt(buf, properties.size());
|
writeVarInt(buf, properties.size());
|
||||||
for (GameProfile.Property property : properties) {
|
for (GameProfile.Property property : properties) {
|
||||||
writeString(buf, property.getName());
|
writeString(buf, property.name());
|
||||||
writeString(buf, property.getValue());
|
writeString(buf, property.value());
|
||||||
String signature = property.getSignature();
|
String signature = property.signature();
|
||||||
if (signature != null && !signature.isEmpty()) {
|
if (signature != null && !signature.isEmpty()) {
|
||||||
buf.writeBoolean(true);
|
buf.writeBoolean(true);
|
||||||
writeString(buf, signature);
|
writeString(buf, signature);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.network;
|
package com.velocitypowered.proxy.network;
|
||||||
|
|
||||||
|
import static com.velocitypowered.proxy.network.HandlerNames.FLOW_HANDLER;
|
||||||
import static com.velocitypowered.proxy.network.HandlerNames.FRAME_DECODER;
|
import static com.velocitypowered.proxy.network.HandlerNames.FRAME_DECODER;
|
||||||
import static com.velocitypowered.proxy.network.HandlerNames.FRAME_ENCODER;
|
import static com.velocitypowered.proxy.network.HandlerNames.FRAME_ENCODER;
|
||||||
import static com.velocitypowered.proxy.network.HandlerNames.LEGACY_PING_DECODER;
|
import static com.velocitypowered.proxy.network.HandlerNames.LEGACY_PING_DECODER;
|
||||||
@ -29,6 +30,7 @@ import com.velocitypowered.proxy.VelocityServer;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
|
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketDirection;
|
import com.velocitypowered.proxy.network.packet.PacketDirection;
|
||||||
|
import com.velocitypowered.proxy.network.pipeline.AutoReadHolderHandler;
|
||||||
import com.velocitypowered.proxy.network.pipeline.LegacyPingDecoder;
|
import com.velocitypowered.proxy.network.pipeline.LegacyPingDecoder;
|
||||||
import com.velocitypowered.proxy.network.pipeline.LegacyPingEncoder;
|
import com.velocitypowered.proxy.network.pipeline.LegacyPingEncoder;
|
||||||
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
|
import com.velocitypowered.proxy.network.pipeline.MinecraftDecoder;
|
||||||
@ -61,7 +63,8 @@ public class ServerChannelInitializer extends ChannelInitializer<Channel> {
|
|||||||
.addLast(LEGACY_PING_ENCODER, LegacyPingEncoder.INSTANCE)
|
.addLast(LEGACY_PING_ENCODER, LegacyPingEncoder.INSTANCE)
|
||||||
.addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE)
|
.addLast(FRAME_ENCODER, MinecraftVarintLengthEncoder.INSTANCE)
|
||||||
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(PacketDirection.SERVERBOUND))
|
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(PacketDirection.SERVERBOUND))
|
||||||
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(PacketDirection.CLIENTBOUND));
|
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(PacketDirection.CLIENTBOUND))
|
||||||
|
.addLast(FLOW_HANDLER, new AutoReadHolderHandler());
|
||||||
|
|
||||||
final MinecraftConnection connection = new MinecraftConnection(ch, this.server);
|
final MinecraftConnection connection = new MinecraftConnection(ch, this.server);
|
||||||
connection.setSessionHandler(new HandshakeSessionHandler(connection, this.server));
|
connection.setSessionHandler(new HandshakeSessionHandler(connection, this.server));
|
||||||
|
@ -20,7 +20,6 @@ package com.velocitypowered.proxy.network.packet;
|
|||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import com.velocitypowered.proxy.network.ProtocolUtils;
|
import com.velocitypowered.proxy.network.ProtocolUtils;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import java.util.function.LongFunction;
|
import java.util.function.LongFunction;
|
||||||
|
|
||||||
public abstract class AbstractKeepAlivePacket implements Packet {
|
public abstract class AbstractKeepAlivePacket implements Packet {
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
package com.velocitypowered.proxy.network.packet;
|
package com.velocitypowered.proxy.network.packet;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import java.util.function.LongFunction;
|
import java.util.function.LongFunction;
|
||||||
|
|
||||||
public abstract class AbstractStatusPingPacket implements Packet {
|
public abstract class AbstractStatusPingPacket implements Packet {
|
||||||
|
@ -22,13 +22,10 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import com.velocitypowered.proxy.network.ProtocolUtils;
|
import com.velocitypowered.proxy.network.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.network.packet.Packet;
|
import com.velocitypowered.proxy.network.packet.Packet;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketDirection;
|
|
||||||
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketReader;
|
import com.velocitypowered.proxy.network.packet.PacketReader;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
public class ClientboundDisconnectPacket implements Packet {
|
public class ClientboundDisconnectPacket implements Packet {
|
||||||
public static final PacketReader<ClientboundDisconnectPacket> DECODER = (buf, version) ->
|
public static final PacketReader<ClientboundDisconnectPacket> DECODER = (buf, version) ->
|
||||||
|
@ -21,13 +21,10 @@ import static com.velocitypowered.proxy.network.ProtocolUtils.writeString;
|
|||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
|
||||||
import com.velocitypowered.proxy.network.ProtocolUtils;
|
|
||||||
import com.velocitypowered.proxy.network.packet.Packet;
|
import com.velocitypowered.proxy.network.packet.Packet;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketReader;
|
import com.velocitypowered.proxy.network.packet.PacketReader;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
|
|
||||||
public class ClientboundHeaderAndFooterPacket implements Packet {
|
public class ClientboundHeaderAndFooterPacket implements Packet {
|
||||||
public static final PacketReader<ClientboundHeaderAndFooterPacket> DECODER = PacketReader.unsupported();
|
public static final PacketReader<ClientboundHeaderAndFooterPacket> DECODER = PacketReader.unsupported();
|
||||||
|
@ -205,12 +205,12 @@ public class ClientboundPlayerListItemPacket implements Packet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Item from(TabListEntry entry) {
|
public static Item from(TabListEntry entry) {
|
||||||
return new Item(entry.gameProfile().getId())
|
return new Item(entry.gameProfile().uuid())
|
||||||
.setName(entry.gameProfile().getName())
|
.setName(entry.gameProfile().name())
|
||||||
.setProperties(entry.gameProfile().getProperties())
|
.setProperties(entry.gameProfile().properties())
|
||||||
.setLatency(entry.ping())
|
.setLatency(entry.ping())
|
||||||
.setGameMode(entry.gameMode())
|
.setGameMode(entry.gameMode())
|
||||||
.setDisplayName(entry.displayName().orElse(null));
|
.setDisplayName(entry.displayName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable UUID getUuid() {
|
public @Nullable UUID getUuid() {
|
||||||
|
@ -18,13 +18,11 @@
|
|||||||
package com.velocitypowered.proxy.network.packet.clientbound;
|
package com.velocitypowered.proxy.network.packet.clientbound;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
|
||||||
import com.velocitypowered.proxy.network.ProtocolUtils;
|
import com.velocitypowered.proxy.network.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.network.packet.Packet;
|
import com.velocitypowered.proxy.network.packet.Packet;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketReader;
|
import com.velocitypowered.proxy.network.packet.PacketReader;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ClientboundResourcePackRequestPacket implements Packet {
|
public class ClientboundResourcePackRequestPacket implements Packet {
|
||||||
|
@ -25,7 +25,6 @@ import com.velocitypowered.proxy.network.packet.Packet;
|
|||||||
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketReader;
|
import com.velocitypowered.proxy.network.packet.PacketReader;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -45,7 +45,10 @@ public class LegacyDisconnectPacket implements LegacyPacket {
|
|||||||
*/
|
*/
|
||||||
public static LegacyDisconnectPacket fromServerPing(ServerPing response,
|
public static LegacyDisconnectPacket fromServerPing(ServerPing response,
|
||||||
LegacyMinecraftPingVersion version) {
|
LegacyMinecraftPingVersion version) {
|
||||||
Players players = response.players().orElse(FAKE_PLAYERS);
|
Players players = response.players();
|
||||||
|
if (players == null) {
|
||||||
|
players = FAKE_PLAYERS;
|
||||||
|
}
|
||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case MINECRAFT_1_3:
|
case MINECRAFT_1_3:
|
||||||
|
@ -24,7 +24,6 @@ import com.velocitypowered.proxy.network.packet.Packet;
|
|||||||
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
import com.velocitypowered.proxy.network.packet.PacketHandler;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketReader;
|
import com.velocitypowered.proxy.network.packet.PacketReader;
|
||||||
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
import com.velocitypowered.proxy.network.packet.PacketWriter;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
|
|
||||||
public class ServerboundHandshakePacket implements Packet {
|
public class ServerboundHandshakePacket implements Packet {
|
||||||
public static final PacketReader<ServerboundHandshakePacket> DECODER = (buf, version) -> {
|
public static final PacketReader<ServerboundHandshakePacket> DECODER = (buf, version) -> {
|
||||||
|
@ -43,7 +43,6 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||||
@ -203,8 +202,8 @@ public class GS4QueryHandler extends SimpleChannelInboundHandler<DatagramPacket>
|
|||||||
List<QueryResponse.PluginInformation> result = new ArrayList<>();
|
List<QueryResponse.PluginInformation> result = new ArrayList<>();
|
||||||
for (PluginContainer plugin : server.pluginManager().plugins()) {
|
for (PluginContainer plugin : server.pluginManager().plugins()) {
|
||||||
PluginDescription description = plugin.description();
|
PluginDescription description = plugin.description();
|
||||||
result.add(QueryResponse.PluginInformation.of(description.name()
|
result.add(QueryResponse.PluginInformation.of(description.name(),
|
||||||
.orElse(description.id()), description.version().orElse(null)));
|
description.version()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -272,8 +271,10 @@ public class GS4QueryHandler extends SimpleChannelInboundHandler<DatagramPacket>
|
|||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
QueryResponse.PluginInformation info = iterator.next();
|
QueryResponse.PluginInformation info = iterator.next();
|
||||||
pluginsString.append(info.getName());
|
pluginsString.append(info.getName());
|
||||||
Optional<String> version = info.getVersion();
|
String version = info.getVersion();
|
||||||
version.ifPresent(s -> pluginsString.append(' ').append(s));
|
if (version != null) {
|
||||||
|
pluginsString.append(' ').append(version);
|
||||||
|
}
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
pluginsString.append(';').append(' ');
|
pluginsString.append(';').append(' ');
|
||||||
}
|
}
|
||||||
|
@ -73,11 +73,11 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
int originalReaderIndex = buf.readerIndex();
|
int originalReaderIndex = buf.readerIndex();
|
||||||
int packetId = ProtocolUtils.readVarInt(buf);
|
int packetId = ProtocolUtils.readVarInt(buf);
|
||||||
Packet packet = null;
|
Packet packet;
|
||||||
try {
|
try {
|
||||||
packet = this.registry.readPacket(packetId, buf, this.version);
|
packet = this.registry.readPacket(packetId, buf, this.version);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw handleDecodeFailure(e, packet, packetId); // TODO: packet is always null
|
throw handleDecodeFailure(e, packetId);
|
||||||
}
|
}
|
||||||
if (packet == null) {
|
if (packet == null) {
|
||||||
buf.readerIndex(originalReaderIndex);
|
buf.readerIndex(originalReaderIndex);
|
||||||
@ -85,7 +85,7 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
if (buf.isReadable()) {
|
if (buf.isReadable()) {
|
||||||
throw handleOverflow(packet, buf.readerIndex(), buf.writerIndex());
|
throw handleOverflow(packetId, buf.readerIndex(), buf.writerIndex());
|
||||||
}
|
}
|
||||||
ctx.fireChannelRead(packet);
|
ctx.fireChannelRead(packet);
|
||||||
} finally {
|
} finally {
|
||||||
@ -94,39 +94,43 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doLengthSanityChecks(ByteBuf buf, Packet packet) throws Exception {
|
// TODO: Reimplement this
|
||||||
|
private void doLengthSanityChecks(ByteBuf buf, int packetId, Packet packet) throws Exception {
|
||||||
int expectedMinLen = packet.expectedMinLength(buf, direction, version);
|
int expectedMinLen = packet.expectedMinLength(buf, direction, version);
|
||||||
int expectedMaxLen = packet.expectedMaxLength(buf, direction, version);
|
int expectedMaxLen = packet.expectedMaxLength(buf, direction, version);
|
||||||
if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) {
|
if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) {
|
||||||
throw handleOverflow(packet, expectedMaxLen, buf.readableBytes());
|
throw handleOverflow(packetId, expectedMaxLen, buf.readableBytes());
|
||||||
}
|
}
|
||||||
if (buf.readableBytes() < expectedMinLen) {
|
if (buf.readableBytes() < expectedMinLen) {
|
||||||
throw handleUnderflow(packet, expectedMaxLen, buf.readableBytes());
|
throw handleUnderflow(packetId, expectedMaxLen, buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Exception handleOverflow(Packet packet, int expected, int actual) {
|
private Exception handleOverflow(int packetId, int expected, int actual) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
return new CorruptedFrameException("Packet sent for " + packet.getClass() + " was too "
|
Class<? extends Packet> packetClass = this.registry.lookupPacket(packetId);
|
||||||
|
return new CorruptedFrameException("Packet sent for " + packetClass + " was too "
|
||||||
+ "big (expected " + expected + " bytes, got " + actual + " bytes)");
|
+ "big (expected " + expected + " bytes, got " + actual + " bytes)");
|
||||||
} else {
|
} else {
|
||||||
return DECODE_FAILED;
|
return DECODE_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Exception handleUnderflow(Packet packet, int expected, int actual) {
|
private Exception handleUnderflow(int packetId, int expected, int actual) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
return new CorruptedFrameException("Packet sent for " + packet.getClass() + " was too "
|
Class<? extends Packet> packetClass = this.registry.lookupPacket(packetId);
|
||||||
|
return new CorruptedFrameException("Packet sent for " + packetClass + " was too "
|
||||||
+ "small (expected " + expected + " bytes, got " + actual + " bytes)");
|
+ "small (expected " + expected + " bytes, got " + actual + " bytes)");
|
||||||
} else {
|
} else {
|
||||||
return DECODE_FAILED;
|
return DECODE_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Exception handleDecodeFailure(Exception cause, Packet packet, int packetId) {
|
private Exception handleDecodeFailure(Exception cause, int packetId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
Class<? extends Packet> packetClass = this.registry.lookupPacket(packetId);
|
||||||
return new CorruptedFrameException(
|
return new CorruptedFrameException(
|
||||||
"Error decoding " + packet.getClass() + " " + getExtraConnectionDetail(packetId), cause);
|
"Error decoding " + packetClass + " " + getExtraConnectionDetail(packetId), cause);
|
||||||
} else {
|
} else {
|
||||||
return DECODE_FAILED;
|
return DECODE_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class DensePacketRegistryMap implements PacketRegistryMap {
|
|||||||
|
|
||||||
private final PacketReader<?>[] readersById;
|
private final PacketReader<?>[] readersById;
|
||||||
private final PacketWriter[] writersByClass;
|
private final PacketWriter[] writersByClass;
|
||||||
private final Class<?>[] classesById;
|
private final Class<?>[] classesByKey;
|
||||||
private final int[] idsByKey;
|
private final int[] idsByKey;
|
||||||
|
|
||||||
public DensePacketRegistryMap(Int2ObjectMap<PacketMapping<?>> mappings) {
|
public DensePacketRegistryMap(Int2ObjectMap<PacketMapping<?>> mappings) {
|
||||||
@ -44,7 +44,7 @@ public class DensePacketRegistryMap implements PacketRegistryMap {
|
|||||||
|
|
||||||
this.readersById = new PacketReader[size];
|
this.readersById = new PacketReader[size];
|
||||||
this.writersByClass = new PacketWriter[size * 2];
|
this.writersByClass = new PacketWriter[size * 2];
|
||||||
this.classesById = new Class[size * 2];
|
this.classesByKey = new Class[size * 2];
|
||||||
this.idsByKey = new int[size * 2];
|
this.idsByKey = new int[size * 2];
|
||||||
|
|
||||||
for (PacketMapping<?> value : mappings.values()) {
|
for (PacketMapping<?> value : mappings.values()) {
|
||||||
@ -56,41 +56,41 @@ public class DensePacketRegistryMap implements PacketRegistryMap {
|
|||||||
private void place(int packetId, Class<?> key, PacketWriter<?> value) {
|
private void place(int packetId, Class<?> key, PacketWriter<?> value) {
|
||||||
int bucket = findEmpty(key);
|
int bucket = findEmpty(key);
|
||||||
this.writersByClass[bucket] = value;
|
this.writersByClass[bucket] = value;
|
||||||
this.classesById[bucket] = key;
|
this.classesByKey[bucket] = key;
|
||||||
this.idsByKey[bucket] = packetId;
|
this.idsByKey[bucket] = packetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findEmpty(Class<?> key) {
|
private int findEmpty(Class<?> key) {
|
||||||
int start = key.hashCode() % this.classesById.length;
|
int start = key.hashCode() % this.classesByKey.length;
|
||||||
int index = start;
|
int index = start;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (this.classesById[index] == null || this.classesById[index].equals(key)) {
|
if (this.classesByKey[index] == null || this.classesByKey[index].equals(key)) {
|
||||||
// It's available, so no chance that this value exists anywhere in the map.
|
// It's available, so no chance that this value exists anywhere in the map.
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((index = (index + 1) % this.classesById.length) == start) {
|
if ((index = (index + 1) % this.classesByKey.length) == start) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int index(Class<?> key) {
|
private int index(Class<?> key) {
|
||||||
int start = key.hashCode() % this.classesById.length;
|
int start = key.hashCode() % this.classesByKey.length;
|
||||||
int index = start;
|
int index = start;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (this.classesById[index] == null) {
|
if (this.classesByKey[index] == null) {
|
||||||
// It's available, so no chance that this value exists anywhere in the map.
|
// It's available, so no chance that this value exists anywhere in the map.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (key.equals(this.classesById[index])) {
|
if (key.equals(this.classesByKey[index])) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conflict, keep probing ...
|
// Conflict, keep probing ...
|
||||||
if ((index = (index + 1) % this.classesById.length) == start) {
|
if ((index = (index + 1) % this.classesByKey.length) == start) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,4 +119,14 @@ public class DensePacketRegistryMap implements PacketRegistryMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Class<? extends Packet> lookupPacket(int id) {
|
||||||
|
for (int bucket = 0; bucket < this.idsByKey.length; bucket++) {
|
||||||
|
if (this.idsByKey[bucket] == id) {
|
||||||
|
return (Class<? extends Packet>) this.classesByKey[bucket];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,4 +42,9 @@ public class EmptyPacketRegistryMap implements PacketRegistryMap {
|
|||||||
packet.getClass().getName(), version
|
packet.getClass().getName(), version
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Class<? extends Packet> lookupPacket(int id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,4 +26,6 @@ public interface PacketRegistryMap {
|
|||||||
@Nullable Packet readPacket(final int id, ByteBuf buf, ProtocolVersion version);
|
@Nullable Packet readPacket(final int id, ByteBuf buf, ProtocolVersion version);
|
||||||
|
|
||||||
<P extends Packet> void writePacket(P packet, ByteBuf buf, ProtocolVersion version);
|
<P extends Packet> void writePacket(P packet, ByteBuf buf, ProtocolVersion version);
|
||||||
|
|
||||||
|
@Nullable Class<? extends Packet> lookupPacket(final int id);
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -81,4 +82,14 @@ public class RegularPacketRegistryMap implements PacketRegistryMap {
|
|||||||
ProtocolUtils.writeVarInt(buf, packetId);
|
ProtocolUtils.writeVarInt(buf, packetId);
|
||||||
writer.write(buf, packet, version);
|
writer.write(buf, packet, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Class<? extends Packet> lookupPacket(int id) {
|
||||||
|
for (Entry<Class<?>> entry : this.classesById.object2IntEntrySet()) {
|
||||||
|
if (entry.getIntValue() == id) {
|
||||||
|
return (Class<? extends Packet>) entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,6 +462,17 @@ class PlayPacketRegistry implements ProtocolRegistry {
|
|||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
encoder.write(buf, packet, version);
|
encoder.write(buf, packet, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Class<? extends Packet> lookupPacket(int id) {
|
||||||
|
for (Object2IntMap.Entry<Class<? extends Packet>> entry : this.packetClassToId
|
||||||
|
.object2IntEntrySet()) {
|
||||||
|
if (entry.getIntValue() == id) {
|
||||||
|
return entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +51,9 @@ public final class GameProfileSerializer implements JsonSerializer<GameProfile>,
|
|||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(GameProfile src, Type typeOfSrc, JsonSerializationContext context) {
|
public JsonElement serialize(GameProfile src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
JsonObject obj = new JsonObject();
|
JsonObject obj = new JsonObject();
|
||||||
obj.add("id", new JsonPrimitive(src.getUndashedId()));
|
obj.add("id", new JsonPrimitive(src.undashedId()));
|
||||||
obj.add("name", new JsonPrimitive(src.getName()));
|
obj.add("name", new JsonPrimitive(src.name()));
|
||||||
obj.add("properties", context.serialize(src.getProperties(), propertyList));
|
obj.add("properties", context.serialize(src.properties(), propertyList));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.name.Names;
|
import com.google.inject.name.Names;
|
||||||
@ -52,6 +53,7 @@ import java.util.Optional;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public class VelocityPluginManager implements PluginManager {
|
public class VelocityPluginManager implements PluginManager {
|
||||||
|
|
||||||
@ -110,9 +112,9 @@ public class VelocityPluginManager implements PluginManager {
|
|||||||
for (PluginDescription candidate : sortedPlugins) {
|
for (PluginDescription candidate : sortedPlugins) {
|
||||||
// Verify dependencies
|
// Verify dependencies
|
||||||
for (PluginDependency dependency : candidate.dependencies()) {
|
for (PluginDependency dependency : candidate.dependencies()) {
|
||||||
if (!dependency.isOptional() && !loadedPluginsById.contains(dependency.getId())) {
|
if (!dependency.optional() && !loadedPluginsById.contains(dependency.id())) {
|
||||||
logger.error("Can't load plugin {} due to missing dependency {}", candidate.id(),
|
logger.error("Can't load plugin {} due to missing dependency {}", candidate.id(),
|
||||||
dependency.getId());
|
dependency.id());
|
||||||
continue pluginLoad;
|
continue pluginLoad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,27 +156,27 @@ public class VelocityPluginManager implements PluginManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Loaded plugin {} {} by {}", description.id(), description.version()
|
logger.info("Loaded plugin {} {} by {}", description.id(), MoreObjects.firstNonNull(
|
||||||
.orElse("<UNKNOWN>"), Joiner.on(", ").join(description.authors()));
|
description.version(), "<UNKNOWN>"), Joiner.on(", ").join(description.authors()));
|
||||||
registerPlugin(container);
|
registerPlugin(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PluginContainer> fromInstance(Object instance) {
|
public @Nullable PluginContainer fromInstance(Object instance) {
|
||||||
checkNotNull(instance, "instance");
|
checkNotNull(instance, "instance");
|
||||||
|
|
||||||
if (instance instanceof PluginContainer) {
|
if (instance instanceof PluginContainer) {
|
||||||
return Optional.of((PluginContainer) instance);
|
return (PluginContainer) instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.ofNullable(pluginInstances.get(instance));
|
return pluginInstances.get(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PluginContainer> getPlugin(String id) {
|
public @Nullable PluginContainer getPlugin(String id) {
|
||||||
checkNotNull(id, "id");
|
checkNotNull(id, "id");
|
||||||
return Optional.ofNullable(plugins.get(id));
|
return plugins.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -191,9 +193,12 @@ public class VelocityPluginManager implements PluginManager {
|
|||||||
public void addToClasspath(Object plugin, Path path) {
|
public void addToClasspath(Object plugin, Path path) {
|
||||||
checkNotNull(plugin, "instance");
|
checkNotNull(plugin, "instance");
|
||||||
checkNotNull(path, "path");
|
checkNotNull(path, "path");
|
||||||
Optional<PluginContainer> optContainer = fromInstance(plugin);
|
PluginContainer optContainer = fromInstance(plugin);
|
||||||
checkArgument(optContainer.isPresent(), "plugin is not loaded");
|
if (optContainer == null) {
|
||||||
Optional<?> optInstance = optContainer.get().instance();
|
throw new IllegalArgumentException("plugin is not loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<?> optInstance = optContainer.instance();
|
||||||
checkArgument(optInstance.isPresent(), "plugin has no instance");
|
checkArgument(optInstance.isPresent(), "plugin has no instance");
|
||||||
|
|
||||||
ClassLoader pluginClassloader = optInstance.get().getClass().getClassLoader();
|
ClassLoader pluginClassloader = optInstance.get().getClass().getClassLoader();
|
||||||
|
@ -28,7 +28,6 @@ import java.nio.file.Path;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public class VelocityPluginDescription implements PluginDescription {
|
public class VelocityPluginDescription implements PluginDescription {
|
||||||
@ -62,7 +61,7 @@ public class VelocityPluginDescription implements PluginDescription {
|
|||||||
this.description = Strings.emptyToNull(description);
|
this.description = Strings.emptyToNull(description);
|
||||||
this.url = Strings.emptyToNull(url);
|
this.url = Strings.emptyToNull(url);
|
||||||
this.authors = authors == null ? ImmutableList.of() : ImmutableList.copyOf(authors);
|
this.authors = authors == null ? ImmutableList.of() : ImmutableList.copyOf(authors);
|
||||||
this.dependencies = Maps.uniqueIndex(dependencies, d -> d == null ? null : d.getId());
|
this.dependencies = Maps.uniqueIndex(dependencies, d -> d == null ? null : d.id());
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,23 +71,23 @@ public class VelocityPluginDescription implements PluginDescription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> name() {
|
public String name() {
|
||||||
return Optional.ofNullable(name);
|
return name == null ? id : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> version() {
|
public @Nullable String version() {
|
||||||
return Optional.ofNullable(version);
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> description() {
|
public @Nullable String description() {
|
||||||
return Optional.ofNullable(description);
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> url() {
|
public @Nullable String url() {
|
||||||
return Optional.ofNullable(url);
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -102,13 +101,13 @@ public class VelocityPluginDescription implements PluginDescription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PluginDependency> getDependency(String id) {
|
public @Nullable PluginDependency getDependency(String id) {
|
||||||
return Optional.ofNullable(dependencies.get(id));
|
return dependencies.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Path> file() {
|
public @Nullable Path file() {
|
||||||
return Optional.ofNullable(source);
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,7 +78,10 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
|
throw new IllegalArgumentException("Description provided isn't of the Java plugin loader");
|
||||||
}
|
}
|
||||||
|
|
||||||
URL pluginJarUrl = source.file().get().toUri().toURL();
|
Path jarFilePath = source.file();
|
||||||
|
assert jarFilePath != null;
|
||||||
|
|
||||||
|
URL pluginJarUrl = jarFilePath.toUri().toURL();
|
||||||
PluginClassLoader loader = AccessController.doPrivileged(
|
PluginClassLoader loader = AccessController.doPrivileged(
|
||||||
(PrivilegedAction<PluginClassLoader>) () -> new PluginClassLoader(new URL[]{pluginJarUrl}));
|
(PrivilegedAction<PluginClassLoader>) () -> new PluginClassLoader(new URL[]{pluginJarUrl}));
|
||||||
loader.addToClassloaders();
|
loader.addToClassloaders();
|
||||||
@ -97,9 +100,9 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JavaVelocityPluginDescription javaDescription = (JavaVelocityPluginDescription) description;
|
JavaVelocityPluginDescription javaDescription = (JavaVelocityPluginDescription) description;
|
||||||
Optional<Path> source = javaDescription.file();
|
Path source = javaDescription.file();
|
||||||
|
|
||||||
if (!source.isPresent()) {
|
if (source == null) {
|
||||||
throw new IllegalArgumentException("No path in plugin description");
|
throw new IllegalArgumentException("No path in plugin description");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,13 +187,13 @@ public class JavaPluginLoader implements PluginLoader {
|
|||||||
Class mainClass) {
|
Class mainClass) {
|
||||||
return new JavaVelocityPluginDescription(
|
return new JavaVelocityPluginDescription(
|
||||||
description.id(),
|
description.id(),
|
||||||
description.name().orElse(null),
|
description.name(),
|
||||||
description.version().orElse(null),
|
description.version(),
|
||||||
description.description().orElse(null),
|
description.description(),
|
||||||
description.url().orElse(null),
|
description.url(),
|
||||||
description.authors(),
|
description.authors(),
|
||||||
description.dependencies(),
|
description.dependencies(),
|
||||||
description.file().orElse(null),
|
description.file(),
|
||||||
mainClass
|
mainClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ public class PluginDependencyUtils {
|
|||||||
graph.addNode(description);
|
graph.addNode(description);
|
||||||
|
|
||||||
for (PluginDependency dependency : description.dependencies()) {
|
for (PluginDependency dependency : description.dependencies()) {
|
||||||
PluginDescription in = candidateMap.get(dependency.getId());
|
PluginDescription in = candidateMap.get(dependency.id());
|
||||||
|
|
||||||
if (in != null) {
|
if (in != null) {
|
||||||
graph.putEdge(description, in);
|
graph.putEdge(description, in);
|
||||||
|
@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
import com.velocitypowered.api.plugin.PluginManager;
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
import com.velocitypowered.api.scheduler.ScheduledTask;
|
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||||
import com.velocitypowered.api.scheduler.Scheduler;
|
import com.velocitypowered.api.scheduler.Scheduler;
|
||||||
@ -66,7 +67,7 @@ public class VelocityScheduler implements Scheduler {
|
|||||||
public TaskBuilder buildTask(Object plugin, Runnable runnable) {
|
public TaskBuilder buildTask(Object plugin, Runnable runnable) {
|
||||||
checkNotNull(plugin, "plugin");
|
checkNotNull(plugin, "plugin");
|
||||||
checkNotNull(runnable, "runnable");
|
checkNotNull(runnable, "runnable");
|
||||||
checkArgument(pluginManager.fromInstance(plugin).isPresent(), "plugin is not registered");
|
checkArgument(pluginManager.fromInstance(plugin) != null, "plugin is not registered");
|
||||||
return new TaskBuilderImpl(plugin, runnable);
|
return new TaskBuilderImpl(plugin, runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,12 +206,10 @@ public class VelocityScheduler implements Scheduler {
|
|||||||
if (e instanceof InterruptedException) {
|
if (e instanceof InterruptedException) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
} else {
|
} else {
|
||||||
String friendlyPluginName = pluginManager.fromInstance(plugin)
|
PluginDescription description = pluginManager.ensurePluginContainer(plugin)
|
||||||
.map(container -> container.description().name()
|
.description();
|
||||||
.orElse(container.description().id()))
|
Log.logger.error("Exception in task {} by plugin {}", runnable,
|
||||||
.orElse("UNKNOWN");
|
description.name(), e);
|
||||||
Log.logger.error("Exception in task {} by plugin {}", runnable, friendlyPluginName,
|
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (repeat == 0) {
|
if (repeat == 0) {
|
||||||
|
@ -25,7 +25,6 @@ import com.velocitypowered.proxy.VelocityServer;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -44,10 +43,10 @@ public class ServerMap {
|
|||||||
* @param name the name to look up
|
* @param name the name to look up
|
||||||
* @return the server, if it exists
|
* @return the server, if it exists
|
||||||
*/
|
*/
|
||||||
public Optional<RegisteredServer> getServer(String name) {
|
public @Nullable RegisteredServer getServer(String name) {
|
||||||
Preconditions.checkNotNull(name, "server");
|
Preconditions.checkNotNull(name, "server");
|
||||||
String lowerName = name.toLowerCase(Locale.US);
|
String lowerName = name.toLowerCase(Locale.US);
|
||||||
return Optional.ofNullable(servers.get(lowerName));
|
return servers.get(lowerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<RegisteredServer> getAllServers() {
|
public Collection<RegisteredServer> getAllServers() {
|
||||||
|
@ -31,7 +31,6 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@ -75,18 +74,18 @@ public class VelocityTabList implements TabList {
|
|||||||
Preconditions.checkNotNull(entry, "entry");
|
Preconditions.checkNotNull(entry, "entry");
|
||||||
Preconditions.checkArgument(entry.parent().equals(this),
|
Preconditions.checkArgument(entry.parent().equals(this),
|
||||||
"The provided entry was not created by this tab list");
|
"The provided entry was not created by this tab list");
|
||||||
Preconditions.checkArgument(!entries.containsKey(entry.gameProfile().getId()),
|
Preconditions.checkArgument(!entries.containsKey(entry.gameProfile().uuid()),
|
||||||
"this TabList already contains an entry with the same uuid");
|
"this TabList already contains an entry with the same uuid");
|
||||||
Preconditions.checkArgument(entry instanceof VelocityTabListEntry,
|
Preconditions.checkArgument(entry instanceof VelocityTabListEntry,
|
||||||
"Not a Velocity tab list entry");
|
"Not a Velocity tab list entry");
|
||||||
|
|
||||||
connection.write(new ClientboundPlayerListItemPacket(ClientboundPlayerListItemPacket.ADD_PLAYER,
|
connection.write(new ClientboundPlayerListItemPacket(ClientboundPlayerListItemPacket.ADD_PLAYER,
|
||||||
Collections.singletonList(ClientboundPlayerListItemPacket.Item.from(entry))));
|
Collections.singletonList(ClientboundPlayerListItemPacket.Item.from(entry))));
|
||||||
entries.put(entry.gameProfile().getId(), (VelocityTabListEntry) entry);
|
entries.put(entry.gameProfile().uuid(), (VelocityTabListEntry) entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<TabListEntry> removeEntry(UUID uuid) {
|
public @Nullable TabListEntry removeEntry(UUID uuid) {
|
||||||
Preconditions.checkNotNull(uuid, "uuid");
|
Preconditions.checkNotNull(uuid, "uuid");
|
||||||
|
|
||||||
TabListEntry entry = entries.remove(uuid);
|
TabListEntry entry = entries.remove(uuid);
|
||||||
@ -97,7 +96,7 @@ public class VelocityTabList implements TabList {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.ofNullable(entry);
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -202,7 +201,7 @@ public class VelocityTabList implements TabList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateEntry(int action, TabListEntry entry) {
|
void updateEntry(int action, TabListEntry entry) {
|
||||||
if (entries.containsKey(entry.gameProfile().getId())) {
|
if (entries.containsKey(entry.gameProfile().uuid())) {
|
||||||
connection.write(new ClientboundPlayerListItemPacket(action,
|
connection.write(new ClientboundPlayerListItemPacket(action,
|
||||||
Collections.singletonList(ClientboundPlayerListItemPacket.Item.from(entry))));
|
Collections.singletonList(ClientboundPlayerListItemPacket.Item.from(entry))));
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import com.velocitypowered.api.proxy.player.TabList;
|
|||||||
import com.velocitypowered.api.proxy.player.TabListEntry;
|
import com.velocitypowered.api.proxy.player.TabListEntry;
|
||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket;
|
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket;
|
||||||
import java.util.Optional;
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
@ -53,8 +52,8 @@ public class VelocityTabListEntry implements TabListEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Component> displayName() {
|
public @Nullable Component displayName() {
|
||||||
return Optional.ofNullable(displayName);
|
return displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,7 +31,7 @@ public class VelocityTabListEntryLegacy extends VelocityTabListEntry {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TabListEntry setDisplayName(@Nullable Component displayName) {
|
public TabListEntry setDisplayName(@Nullable Component displayName) {
|
||||||
parent().removeEntry(gameProfile().getId()); // We have to remove first if updating
|
parent().removeEntry(gameProfile().uuid()); // We have to remove first if updating
|
||||||
return super.setDisplayName(displayName);
|
return super.setDisplayName(displayName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerLis
|
|||||||
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket.Item;
|
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundPlayerListItemPacket.Item;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
@ -50,13 +49,15 @@ public class VelocityTabListLegacy extends VelocityTabList {
|
|||||||
@Override
|
@Override
|
||||||
public void addEntry(TabListEntry entry) {
|
public void addEntry(TabListEntry entry) {
|
||||||
super.addEntry(entry);
|
super.addEntry(entry);
|
||||||
nameMapping.put(entry.gameProfile().getName(), entry.gameProfile().getId());
|
nameMapping.put(entry.gameProfile().name(), entry.gameProfile().uuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<TabListEntry> removeEntry(UUID uuid) {
|
public @Nullable TabListEntry removeEntry(UUID uuid) {
|
||||||
Optional<TabListEntry> entry = super.removeEntry(uuid);
|
TabListEntry entry = super.removeEntry(uuid);
|
||||||
entry.map(TabListEntry::gameProfile).map(GameProfile::getName).ifPresent(nameMapping::remove);
|
if (entry != null) {
|
||||||
|
nameMapping.remove(entry.gameProfile().name());
|
||||||
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +109,7 @@ public class VelocityTabListLegacy extends VelocityTabList {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void updateEntry(int action, TabListEntry entry) {
|
void updateEntry(int action, TabListEntry entry) {
|
||||||
if (entries.containsKey(entry.gameProfile().getId())) {
|
if (entries.containsKey(entry.gameProfile().uuid())) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ClientboundPlayerListItemPacket.UPDATE_LATENCY:
|
case ClientboundPlayerListItemPacket.UPDATE_LATENCY:
|
||||||
case ClientboundPlayerListItemPacket.UPDATE_DISPLAY_NAME: // Add here because we
|
case ClientboundPlayerListItemPacket.UPDATE_DISPLAY_NAME: // Add here because we
|
||||||
|
@ -59,11 +59,11 @@ public enum InformationUtils {
|
|||||||
PluginDescription desc = plugin.description();
|
PluginDescription desc = plugin.description();
|
||||||
JsonObject current = new JsonObject();
|
JsonObject current = new JsonObject();
|
||||||
current.addProperty("id", desc.id());
|
current.addProperty("id", desc.id());
|
||||||
if (desc.name().isPresent()) {
|
current.addProperty("name", desc.name());
|
||||||
current.addProperty("name", desc.name().get());
|
|
||||||
}
|
String version = desc.version();
|
||||||
if (desc.version().isPresent()) {
|
if (version != null) {
|
||||||
current.addProperty("version", desc.version().get());
|
current.addProperty("version", version);
|
||||||
}
|
}
|
||||||
if (!desc.authors().isEmpty()) {
|
if (!desc.authors().isEmpty()) {
|
||||||
JsonArray authorsArray = new JsonArray();
|
JsonArray authorsArray = new JsonArray();
|
||||||
@ -72,16 +72,19 @@ public enum InformationUtils {
|
|||||||
}
|
}
|
||||||
current.add("authors", authorsArray);
|
current.add("authors", authorsArray);
|
||||||
}
|
}
|
||||||
if (desc.description().isPresent()) {
|
|
||||||
current.addProperty("description", desc.description().get());
|
String humanDesc = desc.description();
|
||||||
|
if (humanDesc != null) {
|
||||||
|
current.addProperty("description", humanDesc);
|
||||||
}
|
}
|
||||||
if (desc.url().isPresent()) {
|
String url = desc.url();
|
||||||
current.addProperty("url", desc.url().get());
|
if (url != null) {
|
||||||
|
current.addProperty("url", url);
|
||||||
}
|
}
|
||||||
if (!desc.dependencies().isEmpty()) {
|
if (!desc.dependencies().isEmpty()) {
|
||||||
JsonArray dependencies = new JsonArray();
|
JsonArray dependencies = new JsonArray();
|
||||||
for (PluginDependency dependency : desc.dependencies()) {
|
for (PluginDependency dependency : desc.dependencies()) {
|
||||||
dependencies.add(dependency.getId());
|
dependencies.add(dependency.id());
|
||||||
}
|
}
|
||||||
current.add("dependencies", dependencies);
|
current.add("dependencies", dependencies);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package com.velocitypowered.proxy.util.bossbar;
|
|||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
import com.velocitypowered.api.proxy.connection.Player;
|
|
||||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||||
import com.velocitypowered.proxy.network.ProtocolUtils;
|
import com.velocitypowered.proxy.network.ProtocolUtils;
|
||||||
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket;
|
import com.velocitypowered.proxy.network.packet.clientbound.ClientboundBossBarPacket;
|
||||||
|
@ -22,20 +22,20 @@ import com.velocitypowered.api.plugin.PluginContainer;
|
|||||||
import com.velocitypowered.api.plugin.PluginManager;
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public class MockPluginManager implements PluginManager {
|
public class MockPluginManager implements PluginManager {
|
||||||
|
|
||||||
public static final PluginManager INSTANCE = new MockPluginManager();
|
public static final PluginManager INSTANCE = new MockPluginManager();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PluginContainer> fromInstance(final Object instance) {
|
public @Nullable PluginContainer fromInstance(final Object instance) {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PluginContainer> getPlugin(final String id) {
|
public @Nullable PluginContainer getPlugin(final String id) {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,6 +25,7 @@ import java.nio.file.Path;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public class FakePluginManager implements PluginManager {
|
public class FakePluginManager implements PluginManager {
|
||||||
|
|
||||||
@ -35,25 +36,25 @@ public class FakePluginManager implements PluginManager {
|
|||||||
private static final PluginContainer PC_B = new FakePluginContainer("b", PLUGIN_B);
|
private static final PluginContainer PC_B = new FakePluginContainer("b", PLUGIN_B);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull Optional<PluginContainer> fromInstance(@NonNull Object instance) {
|
public @Nullable PluginContainer fromInstance(@NonNull Object instance) {
|
||||||
if (instance == PLUGIN_A) {
|
if (instance == PLUGIN_A) {
|
||||||
return Optional.of(PC_A);
|
return PC_A;
|
||||||
} else if (instance == PLUGIN_B) {
|
} else if (instance == PLUGIN_B) {
|
||||||
return Optional.of(PC_B);
|
return PC_B;
|
||||||
} else {
|
} else {
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull Optional<PluginContainer> getPlugin(@NonNull String id) {
|
public @Nullable PluginContainer getPlugin(@NonNull String id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case "a":
|
case "a":
|
||||||
return Optional.of(PC_A);
|
return PC_A;
|
||||||
case "b":
|
case "b":
|
||||||
return Optional.of(PC_B);
|
return PC_B;
|
||||||
default:
|
default:
|
||||||
return Optional.empty();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import com.velocitypowered.api.proxy.server.ServerInfo;
|
|||||||
import com.velocitypowered.proxy.server.ServerMap;
|
import com.velocitypowered.proxy.server.ServerMap;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Optional;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class ServerMapTest {
|
class ServerMapTest {
|
||||||
@ -39,9 +38,9 @@ class ServerMapTest {
|
|||||||
ServerInfo info = new ServerInfo("TestServer", TEST_ADDRESS);
|
ServerInfo info = new ServerInfo("TestServer", TEST_ADDRESS);
|
||||||
RegisteredServer connection = map.register(info);
|
RegisteredServer connection = map.register(info);
|
||||||
|
|
||||||
assertEquals(Optional.of(connection), map.getServer("TestServer"));
|
assertEquals(connection, map.getServer("TestServer"));
|
||||||
assertEquals(Optional.of(connection), map.getServer("testserver"));
|
assertEquals(connection, map.getServer("testserver"));
|
||||||
assertEquals(Optional.of(connection), map.getServer("TESTSERVER"));
|
assertEquals(connection, map.getServer("TESTSERVER"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren