Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-12-23 23:00:35 +01:00
Introduce RegisteredServer API
This interface roughly maps the BungeeCord ServerInfo API. Accordingly, this is a breaking API change, as many of the server-related events and methods working with server info instances now provide/expect the RegisteredServer interface instead.
Dieser Commit ist enthalten in:
Ursprung
88b7407aaf
Commit
e1b2dc0d43
@ -3,6 +3,7 @@ package com.velocitypowered.api.event.player;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@ -13,12 +14,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
*/
|
||||
public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEvent.ServerKickResult> {
|
||||
private final Player player;
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
private final Component originalReason;
|
||||
private final boolean duringLogin;
|
||||
private ServerKickResult result;
|
||||
|
||||
public KickedFromServerEvent(Player player, ServerInfo server, Component originalReason, boolean duringLogin, Component fancyReason) {
|
||||
public KickedFromServerEvent(Player player, RegisteredServer server, Component originalReason, boolean duringLogin, Component fancyReason) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
this.originalReason = Preconditions.checkNotNull(originalReason, "originalReason");
|
||||
@ -40,7 +41,7 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
return player;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@ -91,9 +92,9 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
* when this result is used.
|
||||
*/
|
||||
public static class RedirectPlayer implements ServerKickResult {
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
|
||||
private RedirectPlayer(ServerInfo server) {
|
||||
private RedirectPlayer(RegisteredServer server) {
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
}
|
||||
|
||||
@ -102,7 +103,7 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
return false;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@ -111,7 +112,7 @@ public class KickedFromServerEvent implements ResultedEvent<KickedFromServerEven
|
||||
* @param server the server to send the player to
|
||||
* @return the redirect result
|
||||
*/
|
||||
public static RedirectPlayer create(ServerInfo server) {
|
||||
public static RedirectPlayer create(RegisteredServer server) {
|
||||
return new RedirectPlayer(server);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.velocitypowered.api.event.player;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
|
||||
/**
|
||||
* This event is fired once the player has successfully connected to the target server and the connection to the previous
|
||||
@ -10,9 +10,9 @@ import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
*/
|
||||
public class ServerConnectedEvent {
|
||||
private final Player player;
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
|
||||
public ServerConnectedEvent(Player player, ServerInfo server) {
|
||||
public ServerConnectedEvent(Player player, RegisteredServer server) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
this.server = Preconditions.checkNotNull(server, "server");
|
||||
}
|
||||
@ -21,7 +21,7 @@ public class ServerConnectedEvent {
|
||||
return player;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.velocitypowered.api.event.player;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
@ -14,10 +15,10 @@ import java.util.Optional;
|
||||
*/
|
||||
public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEvent.ServerResult> {
|
||||
private final Player player;
|
||||
private final ServerInfo originalServer;
|
||||
private final RegisteredServer originalServer;
|
||||
private ServerResult result;
|
||||
|
||||
public ServerPreConnectEvent(Player player, ServerInfo originalServer) {
|
||||
public ServerPreConnectEvent(Player player, RegisteredServer originalServer) {
|
||||
this.player = Preconditions.checkNotNull(player, "player");
|
||||
this.originalServer = Preconditions.checkNotNull(originalServer, "originalServer");
|
||||
this.result = ServerResult.allowed(originalServer);
|
||||
@ -37,7 +38,7 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
this.result = Preconditions.checkNotNull(result, "result");
|
||||
}
|
||||
|
||||
public ServerInfo getOriginalServer() {
|
||||
public RegisteredServer getOriginalServer() {
|
||||
return originalServer;
|
||||
}
|
||||
|
||||
@ -57,9 +58,9 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
private static final ServerResult DENIED = new ServerResult(false, null);
|
||||
|
||||
private final boolean allowed;
|
||||
private final ServerInfo server;
|
||||
private final RegisteredServer server;
|
||||
|
||||
private ServerResult(boolean allowed, @Nullable ServerInfo server) {
|
||||
private ServerResult(boolean allowed, @Nullable RegisteredServer server) {
|
||||
this.allowed = allowed;
|
||||
this.server = server;
|
||||
}
|
||||
@ -69,7 +70,7 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public Optional<ServerInfo> getServer() {
|
||||
public Optional<RegisteredServer> getServer() {
|
||||
return Optional.ofNullable(server);
|
||||
}
|
||||
|
||||
@ -78,14 +79,14 @@ public class ServerPreConnectEvent implements ResultedEvent<ServerPreConnectEven
|
||||
if (!allowed) {
|
||||
return "denied";
|
||||
}
|
||||
return "allowed: connect to " + server.getName();
|
||||
return "allowed: connect to " + server.getServerInfo().getName();
|
||||
}
|
||||
|
||||
public static ServerResult denied() {
|
||||
return DENIED;
|
||||
}
|
||||
|
||||
public static ServerResult allowed(ServerInfo server) {
|
||||
public static ServerResult allowed(RegisteredServer server) {
|
||||
Preconditions.checkNotNull(server, "server");
|
||||
return new ServerResult(true, server);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@ -9,21 +10,21 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Provides a fluent interface to compose and send a connection request to another server behind the proxy. A connection
|
||||
* request is created using {@link Player#createConnectionRequest(ServerInfo)}.
|
||||
* request is created using {@link Player#createConnectionRequest(RegisteredServer)}.
|
||||
*/
|
||||
public interface ConnectionRequestBuilder {
|
||||
/**
|
||||
* Returns the server that this connection request represents.
|
||||
* @return the server this request will connect to
|
||||
*/
|
||||
@NonNull ServerInfo getServer();
|
||||
RegisteredServer getServer();
|
||||
|
||||
/**
|
||||
* Initiates the connection to the remote server and emits a result on the {@link CompletableFuture} after the user
|
||||
* has logged on. No messages will be communicated to the client: the user is responsible for all error handling.
|
||||
* @return a {@link CompletableFuture} representing the status of this connection
|
||||
*/
|
||||
@NonNull CompletableFuture<Result> connect();
|
||||
CompletableFuture<Result> connect();
|
||||
|
||||
/**
|
||||
* Initiates the connection to the remote server without waiting for a result. Velocity will use generic error
|
||||
|
@ -4,6 +4,7 @@ import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.util.MessagePosition;
|
||||
import net.kyori.text.Component;
|
||||
@ -59,10 +60,10 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage
|
||||
|
||||
/**
|
||||
* Creates a new connection request so that the player can connect to another server.
|
||||
* @param info the server to connect to
|
||||
* @param server the server to connect to
|
||||
* @return a new connection request
|
||||
*/
|
||||
ConnectionRequestBuilder createConnectionRequest(@NonNull ServerInfo info);
|
||||
ConnectionRequestBuilder createConnectionRequest(@NonNull RegisteredServer server);
|
||||
|
||||
/**
|
||||
* Sets the tab list header and footer for the player.
|
||||
|
@ -5,6 +5,7 @@ import com.velocitypowered.api.command.CommandManager;
|
||||
import com.velocitypowered.api.event.EventManager;
|
||||
import com.velocitypowered.api.plugin.PluginManager;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelRegistrar;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.scheduler.Scheduler;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
|
||||
@ -45,23 +46,24 @@ public interface ProxyServer {
|
||||
int getPlayerCount();
|
||||
|
||||
/**
|
||||
* Retrieves a registered {@link ServerInfo} instance by its name. The search is case-insensitive.
|
||||
* Retrieves a registered {@link RegisteredServer} instance by its name. The search is case-insensitive.
|
||||
* @param name the name of the server
|
||||
* @return the registered server, which may be empty
|
||||
*/
|
||||
Optional<ServerInfo> getServerInfo(String name);
|
||||
Optional<RegisteredServer> getServerInfo(String name);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link ServerInfo}s registered with this proxy.
|
||||
* Retrieves all {@link RegisteredServer}s registered with this proxy.
|
||||
* @return the servers registered with this proxy
|
||||
*/
|
||||
Collection<ServerInfo> getAllServers();
|
||||
Collection<RegisteredServer> getAllServers();
|
||||
|
||||
/**
|
||||
* Registers a server with this proxy. A server with this name should not already exist.
|
||||
* @param server the server to register
|
||||
* @return the newly registered server
|
||||
*/
|
||||
void registerServer(ServerInfo server);
|
||||
RegisteredServer registerServer(ServerInfo server);
|
||||
|
||||
/**
|
||||
* Unregisters this server from the proxy.
|
||||
|
@ -2,6 +2,7 @@ package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
|
||||
/**
|
||||
@ -12,6 +13,12 @@ public interface ServerConnection extends ChannelMessageSource, ChannelMessageSi
|
||||
* Returns the server that this connection is connected to.
|
||||
* @return the server this connection is connected to
|
||||
*/
|
||||
RegisteredServer getServer();
|
||||
|
||||
/**
|
||||
* Returns the server info for this connection.
|
||||
* @return the server info for this connection
|
||||
*/
|
||||
ServerInfo getServerInfo();
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,7 @@ public interface ChannelMessageSink {
|
||||
* Sends a plugin message to this target.
|
||||
* @param identifier the channel identifier to send the message on
|
||||
* @param data the data to send
|
||||
* @return whether or not the message could be sent
|
||||
*/
|
||||
void sendPluginMessage(ChannelIdentifier identifier, byte[] data);
|
||||
boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data);
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package com.velocitypowered.api.proxy.server;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Represents a server that has been registered with the proxy.
|
||||
*/
|
||||
public interface RegisteredServer extends ChannelMessageSink {
|
||||
/**
|
||||
* Returns the {@link ServerInfo} for this server.
|
||||
* @return the server info
|
||||
*/
|
||||
ServerInfo getServerInfo();
|
||||
|
||||
/**
|
||||
* Returns a list of all the players currently connected to this server on this proxy.
|
||||
* @return the players on this proxy
|
||||
*/
|
||||
Collection<Player> getPlayersConnected();
|
||||
|
||||
/**
|
||||
* Attempts to ping the remote server and return the server list ping result.
|
||||
* @return the server ping result from the server
|
||||
*/
|
||||
CompletableFuture<ServerPing> ping();
|
||||
}
|
@ -10,6 +10,7 @@ import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import com.velocitypowered.api.plugin.PluginManager;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
@ -30,7 +31,7 @@ import com.velocitypowered.proxy.scheduler.VelocityScheduler;
|
||||
import com.velocitypowered.proxy.util.AddressUtil;
|
||||
import com.velocitypowered.proxy.util.EncryptionUtils;
|
||||
import com.velocitypowered.proxy.util.Ratelimiter;
|
||||
import com.velocitypowered.proxy.util.ServerMap;
|
||||
import com.velocitypowered.proxy.server.ServerMap;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import net.kyori.text.Component;
|
||||
import net.kyori.text.TextComponent;
|
||||
@ -61,7 +62,7 @@ public class VelocityServer implements ProxyServer {
|
||||
private VelocityConfiguration configuration;
|
||||
private NettyHttpClient httpClient;
|
||||
private KeyPair serverKeyPair;
|
||||
private final ServerMap servers = new ServerMap();
|
||||
private final ServerMap servers = new ServerMap(this);
|
||||
private final VelocityCommandManager commandManager = new VelocityCommandManager();
|
||||
private final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);
|
||||
private boolean shutdown = false;
|
||||
@ -263,19 +264,19 @@ public class VelocityServer implements ProxyServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ServerInfo> getServerInfo(String name) {
|
||||
public Optional<RegisteredServer> getServerInfo(String name) {
|
||||
Preconditions.checkNotNull(name, "name");
|
||||
return servers.getServer(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ServerInfo> getAllServers() {
|
||||
public Collection<RegisteredServer> getAllServers() {
|
||||
return servers.getAllServers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerServer(ServerInfo server) {
|
||||
servers.register(server);
|
||||
public RegisteredServer registerServer(ServerInfo server) {
|
||||
return servers.register(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,7 @@ import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import net.kyori.text.TextComponent;
|
||||
import net.kyori.text.event.ClickEvent;
|
||||
@ -34,7 +35,7 @@ public class ServerCommand implements Command {
|
||||
if (args.length == 1) {
|
||||
// Trying to connect to a server.
|
||||
String serverName = args[0];
|
||||
Optional<ServerInfo> toConnect = server.getServerInfo(serverName);
|
||||
Optional<RegisteredServer> toConnect = server.getServerInfo(serverName);
|
||||
if (!toConnect.isPresent()) {
|
||||
player.sendMessage(TextComponent.of("Server " + serverName + " doesn't exist.", TextColor.RED));
|
||||
return;
|
||||
@ -48,17 +49,19 @@ public class ServerCommand implements Command {
|
||||
|
||||
// Assemble the list of servers as components
|
||||
TextComponent.Builder serverListBuilder = TextComponent.builder("Available servers: ").color(TextColor.YELLOW);
|
||||
List<ServerInfo> infos = ImmutableList.copyOf(server.getAllServers());
|
||||
List<RegisteredServer> infos = ImmutableList.copyOf(server.getAllServers());
|
||||
for (int i = 0; i < infos.size(); i++) {
|
||||
ServerInfo serverInfo = infos.get(i);
|
||||
TextComponent infoComponent = TextComponent.of(serverInfo.getName());
|
||||
if (serverInfo.getName().equals(currentServer)) {
|
||||
RegisteredServer rs = infos.get(i);
|
||||
TextComponent infoComponent = TextComponent.of(rs.getServerInfo().getName());
|
||||
String playersText = rs.getPlayersConnected().size() + " player(s) online";
|
||||
if (rs.getServerInfo().getName().equals(currentServer)) {
|
||||
infoComponent = infoComponent.color(TextColor.GREEN)
|
||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Currently connected to this server")));
|
||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
|
||||
TextComponent.of("Currently connected to this server\n" + playersText)));
|
||||
} else {
|
||||
infoComponent = infoComponent.color(TextColor.GRAY)
|
||||
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/server " + serverInfo.getName()))
|
||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to connect to this server")));
|
||||
.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/server " + rs.getServerInfo().getName()))
|
||||
.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to connect to this server\n" + playersText)));
|
||||
}
|
||||
serverListBuilder.append(infoComponent);
|
||||
if (i != infos.size() - 1) {
|
||||
@ -74,11 +77,11 @@ public class ServerCommand implements Command {
|
||||
public List<String> suggest(CommandSource source, String[] currentArgs) {
|
||||
if (currentArgs.length == 0) {
|
||||
return server.getAllServers().stream()
|
||||
.map(ServerInfo::getName)
|
||||
.map(rs -> rs.getServerInfo().getName())
|
||||
.collect(Collectors.toList());
|
||||
} else if (currentArgs.length == 1) {
|
||||
return server.getAllServers().stream()
|
||||
.map(ServerInfo::getName)
|
||||
.map(rs -> rs.getServerInfo().getName())
|
||||
.filter(name -> name.regionMatches(true, 0, currentArgs[0], 0, currentArgs[0].length()))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
|
@ -25,7 +25,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
@Override
|
||||
public void activated() {
|
||||
server.getEventManager().fireAndForget(new ServerConnectedEvent(connection.getPlayer(), connection.getServerInfo()));
|
||||
server.getEventManager().fireAndForget(new ServerConnectedEvent(connection.getPlayer(), connection.getServer()));
|
||||
connection.getServer().addPlayer(connection.getPlayer());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,7 +47,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
} else if (packet instanceof Disconnect) {
|
||||
Disconnect original = (Disconnect) packet;
|
||||
connection.disconnect();
|
||||
connection.getPlayer().handleConnectionException(connection.getServerInfo(), original);
|
||||
connection.getPlayer().handleConnectionException(connection.getServer(), original);
|
||||
} else if (packet instanceof JoinGame) {
|
||||
playerHandler.handleBackendJoinGame((JoinGame) packet);
|
||||
} else if (packet instanceof BossBar) {
|
||||
@ -112,7 +113,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
@Override
|
||||
public void exception(Throwable throwable) {
|
||||
connection.getPlayer().handleConnectionException(connection.getServerInfo(), throwable);
|
||||
connection.getPlayer().handleConnectionException(connection.getServer(), throwable);
|
||||
}
|
||||
|
||||
public VelocityServer getServer() {
|
||||
@ -121,10 +122,11 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
if (connection.isGracefulDisconnect()) {
|
||||
return;
|
||||
connection.getServer().removePlayer(connection.getPlayer());
|
||||
if (!connection.isGracefulDisconnect()) {
|
||||
connection.getPlayer().handleConnectionException(connection.getServer(), Disconnect.create(
|
||||
ConnectionMessages.UNEXPECTED_DISCONNECT));
|
||||
}
|
||||
connection.getPlayer().handleConnectionException(connection.getServerInfo(), Disconnect.create(ConnectionMessages.UNEXPECTED_DISCONNECT));
|
||||
}
|
||||
|
||||
private boolean canForwardPluginMessage(PluginMessage message) {
|
||||
|
@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.proxy.ConnectionRequestBuilder;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
@ -19,6 +20,7 @@ import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import io.netty.util.AttributeKey;
|
||||
@ -38,7 +40,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
static final AttributeKey<CompletableFuture<ConnectionRequestBuilder.Result>> CONNECTION_NOTIFIER =
|
||||
AttributeKey.newInstance("connection-notification-result");
|
||||
|
||||
private final ServerInfo serverInfo;
|
||||
private final VelocityRegisteredServer registeredServer;
|
||||
private final ConnectedPlayer proxyPlayer;
|
||||
private final VelocityServer server;
|
||||
private MinecraftConnection minecraftConnection;
|
||||
@ -46,8 +48,8 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
private boolean hasCompletedJoin = false;
|
||||
private boolean gracefulDisconnect = false;
|
||||
|
||||
public VelocityServerConnection(ServerInfo target, ConnectedPlayer proxyPlayer, VelocityServer server) {
|
||||
this.serverInfo = target;
|
||||
public VelocityServerConnection(VelocityRegisteredServer registeredServer, ConnectedPlayer proxyPlayer, VelocityServer server) {
|
||||
this.registeredServer = registeredServer;
|
||||
this.proxyPlayer = proxyPlayer;
|
||||
this.server = server;
|
||||
}
|
||||
@ -72,7 +74,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
ch.pipeline().addLast(HANDLER, connection);
|
||||
}
|
||||
})
|
||||
.connect(serverInfo.getAddress())
|
||||
.connect(registeredServer.getServerInfo().getAddress())
|
||||
.addListener(new ChannelFutureListener() {
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
@ -94,7 +96,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
// BungeeCord IP forwarding is simply a special injection after the "address" in the handshake,
|
||||
// separated by \0 (the null byte). In order, you send the original host, the player's IP, their
|
||||
// UUID (undashed), and if you are in online-mode, their login properties (retrieved from Mojang).
|
||||
return serverInfo.getAddress().getHostString() + "\0" +
|
||||
return registeredServer.getServerInfo().getAddress().getHostString() + "\0" +
|
||||
proxyPlayer.getRemoteAddress().getHostString() + "\0" +
|
||||
proxyPlayer.getProfile().getId() + "\0" +
|
||||
GSON.toJson(proxyPlayer.getProfile().getProperties());
|
||||
@ -112,9 +114,9 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
} else if (proxyPlayer.getConnection().isLegacyForge()) {
|
||||
handshake.setServerAddress(handshake.getServerAddress() + "\0FML\0");
|
||||
} else {
|
||||
handshake.setServerAddress(serverInfo.getAddress().getHostString());
|
||||
handshake.setServerAddress(registeredServer.getServerInfo().getAddress().getHostString());
|
||||
}
|
||||
handshake.setPort(serverInfo.getAddress().getPort());
|
||||
handshake.setPort(registeredServer.getServerInfo().getAddress().getPort());
|
||||
minecraftConnection.write(handshake);
|
||||
|
||||
int protocolVersion = proxyPlayer.getConnection().getProtocolVersion();
|
||||
@ -136,8 +138,14 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
return minecraftConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelocityRegisteredServer getServer() {
|
||||
return registeredServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerInfo getServerInfo() {
|
||||
return serverInfo;
|
||||
return registeredServer.getServerInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -155,17 +163,18 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[server connection] " + proxyPlayer.getProfile().getName() + " -> " + serverInfo.getName();
|
||||
return "[server connection] " + proxyPlayer.getProfile().getName() + " -> " + registeredServer.getServerInfo().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||
Preconditions.checkNotNull(identifier, "identifier");
|
||||
Preconditions.checkNotNull(data, "data");
|
||||
PluginMessage message = new PluginMessage();
|
||||
message.setChannel(identifier.getId());
|
||||
message.setData(data);
|
||||
minecraftConnection.write(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isLegacyForge() {
|
||||
|
@ -11,6 +11,7 @@ import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
import com.velocitypowered.api.proxy.ConnectionRequestBuilder;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.util.MessagePosition;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
@ -24,6 +25,7 @@ import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||
import com.velocitypowered.proxy.protocol.packet.ClientSettings;
|
||||
import com.velocitypowered.proxy.protocol.packet.PluginMessage;
|
||||
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
|
||||
import com.velocitypowered.proxy.util.ThrowableUtils;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.proxy.protocol.packet.Disconnect;
|
||||
@ -159,8 +161,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionRequestBuilder createConnectionRequest(@NonNull ServerInfo info) {
|
||||
return new ConnectionRequestBuilderImpl(info);
|
||||
public ConnectionRequestBuilder createConnectionRequest(@NonNull RegisteredServer server) {
|
||||
return new ConnectionRequestBuilderImpl(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -184,57 +186,57 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
return connectedServer;
|
||||
}
|
||||
|
||||
public void handleConnectionException(ServerInfo info, Throwable throwable) {
|
||||
public void handleConnectionException(RegisteredServer server, Throwable throwable) {
|
||||
String error = ThrowableUtils.briefDescription(throwable);
|
||||
String userMessage;
|
||||
if (connectedServer != null && connectedServer.getServerInfo().equals(info)) {
|
||||
userMessage = "Exception in server " + info.getName();
|
||||
if (connectedServer != null && connectedServer.getServerInfo().equals(server.getServerInfo())) {
|
||||
userMessage = "Exception in server " + server.getServerInfo().getName();
|
||||
} else {
|
||||
logger.error("{}: unable to connect to server {}", this, info.getName(), throwable);
|
||||
userMessage = "Exception connecting to server " + info.getName();
|
||||
logger.error("{}: unable to connect to server {}", this, server.getServerInfo().getName(), throwable);
|
||||
userMessage = "Exception connecting to server " + server.getServerInfo().getName();
|
||||
}
|
||||
handleConnectionException(info, null, TextComponent.builder()
|
||||
handleConnectionException(server, null, TextComponent.builder()
|
||||
.content(userMessage + ": ")
|
||||
.color(TextColor.RED)
|
||||
.append(TextComponent.of(error, TextColor.WHITE))
|
||||
.build());
|
||||
}
|
||||
|
||||
public void handleConnectionException(ServerInfo info, Disconnect disconnect) {
|
||||
public void handleConnectionException(RegisteredServer server, Disconnect disconnect) {
|
||||
Component disconnectReason = ComponentSerializers.JSON.deserialize(disconnect.getReason());
|
||||
String plainTextReason = PASS_THRU_TRANSLATE.serialize(disconnectReason);
|
||||
if (connectedServer != null && connectedServer.getServerInfo().equals(info)) {
|
||||
logger.error("{}: kicked from server {}: {}", this, info.getName(), plainTextReason);
|
||||
handleConnectionException(info, disconnectReason, TextComponent.builder()
|
||||
.content("Kicked from " + info.getName() + ": ")
|
||||
if (connectedServer != null && connectedServer.getServerInfo().equals(server.getServerInfo())) {
|
||||
logger.error("{}: kicked from server {}: {}", this, server.getServerInfo().getName(), plainTextReason);
|
||||
handleConnectionException(server, disconnectReason, TextComponent.builder()
|
||||
.content("Kicked from " + server.getServerInfo().getName() + ": ")
|
||||
.color(TextColor.RED)
|
||||
.append(disconnectReason)
|
||||
.build());
|
||||
} else {
|
||||
logger.error("{}: disconnected while connecting to {}: {}", this, info.getName(), plainTextReason);
|
||||
handleConnectionException(info, disconnectReason, TextComponent.builder()
|
||||
.content("Unable to connect to " + info.getName() + ": ")
|
||||
logger.error("{}: disconnected while connecting to {}: {}", this, server.getServerInfo().getName(), plainTextReason);
|
||||
handleConnectionException(server, disconnectReason, TextComponent.builder()
|
||||
.content("Unable to connect to " + server.getServerInfo().getName() + ": ")
|
||||
.color(TextColor.RED)
|
||||
.append(disconnectReason)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConnectionException(ServerInfo info, @Nullable Component kickReason, Component friendlyReason) {
|
||||
boolean alreadyConnected = connectedServer != null && connectedServer.getServerInfo().equals(info);;
|
||||
private void handleConnectionException(RegisteredServer rs, @Nullable Component kickReason, Component friendlyReason) {
|
||||
boolean alreadyConnected = connectedServer != null && connectedServer.getServerInfo().equals(rs.getServerInfo());
|
||||
connectionInFlight = null;
|
||||
if (connectedServer == null) {
|
||||
// The player isn't yet connected to a server.
|
||||
Optional<ServerInfo> nextServer = getNextServerToTry();
|
||||
Optional<RegisteredServer> nextServer = getNextServerToTry();
|
||||
if (nextServer.isPresent()) {
|
||||
createConnectionRequest(nextServer.get()).fireAndForget();
|
||||
} else {
|
||||
connection.closeWith(Disconnect.create(friendlyReason));
|
||||
}
|
||||
} else if (connectedServer.getServerInfo().equals(info)) {
|
||||
} else if (connectedServer.getServerInfo().equals(rs.getServerInfo())) {
|
||||
// Already connected to the server being disconnected from.
|
||||
if (kickReason != null) {
|
||||
server.getEventManager().fire(new KickedFromServerEvent(this, info, kickReason, !alreadyConnected, friendlyReason))
|
||||
server.getEventManager().fire(new KickedFromServerEvent(this, rs, kickReason, !alreadyConnected, friendlyReason))
|
||||
.thenAcceptAsync(event -> {
|
||||
if (event.getResult() instanceof KickedFromServerEvent.DisconnectPlayer) {
|
||||
KickedFromServerEvent.DisconnectPlayer res = (KickedFromServerEvent.DisconnectPlayer) event.getResult();
|
||||
@ -255,7 +257,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
}
|
||||
}
|
||||
|
||||
Optional<ServerInfo> getNextServerToTry() {
|
||||
Optional<RegisteredServer> getNextServerToTry() {
|
||||
List<String> serversToTry = server.getConfiguration().getAttemptConnectionOrder();
|
||||
if (tryIndex >= serversToTry.size()) {
|
||||
return Optional.empty();
|
||||
@ -289,7 +291,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
);
|
||||
}
|
||||
|
||||
return new VelocityServerConnection(newEvent.getResult().getServer().get(), this, server).connect();
|
||||
RegisteredServer rs = newEvent.getResult().getServer().get();
|
||||
Preconditions.checkState(rs instanceof VelocityRegisteredServer, "Not a valid Velocity server.");
|
||||
return new VelocityServerConnection((VelocityRegisteredServer) rs, this, server).connect();
|
||||
});
|
||||
}
|
||||
|
||||
@ -335,25 +339,26 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||
Preconditions.checkNotNull(identifier, "identifier");
|
||||
Preconditions.checkNotNull(data, "data");
|
||||
PluginMessage message = new PluginMessage();
|
||||
message.setChannel(identifier.getId());
|
||||
message.setData(data);
|
||||
connection.write(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
private class ConnectionRequestBuilderImpl implements ConnectionRequestBuilder {
|
||||
private final ServerInfo info;
|
||||
private final RegisteredServer server;
|
||||
|
||||
ConnectionRequestBuilderImpl(ServerInfo info) {
|
||||
this.info = Preconditions.checkNotNull(info, "info");
|
||||
ConnectionRequestBuilderImpl(RegisteredServer server) {
|
||||
this.server = Preconditions.checkNotNull(server, "info");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerInfo getServer() {
|
||||
return info;
|
||||
public RegisteredServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -366,7 +371,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
connect()
|
||||
.whenCompleteAsync((status, throwable) -> {
|
||||
if (throwable != null) {
|
||||
handleConnectionException(info, throwable);
|
||||
handleConnectionException(server, throwable);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -381,7 +386,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
// Ignored; the plugin probably already handled this.
|
||||
break;
|
||||
case SERVER_DISCONNECTED:
|
||||
handleConnectionException(info, Disconnect.create(status.getReason().orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR)));
|
||||
handleConnectionException(server, Disconnect.create(status.getReason().orElse(ConnectionMessages.INTERNAL_SERVER_CONNECTION_ERROR)));
|
||||
break;
|
||||
}
|
||||
}, connection.getChannel().eventLoop());
|
||||
|
@ -8,6 +8,7 @@ import com.velocitypowered.api.event.connection.PreLoginEvent.PreLoginComponentR
|
||||
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
|
||||
import com.velocitypowered.api.event.player.GameProfileRequestEvent;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.proxy.config.PlayerInfoForwarding;
|
||||
import com.velocitypowered.proxy.connection.VelocityConstants;
|
||||
@ -220,7 +221,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
}
|
||||
|
||||
private void handleProxyLogin(ConnectedPlayer player) {
|
||||
Optional<ServerInfo> toTry = player.getNextServerToTry();
|
||||
Optional<RegisteredServer> toTry = player.getNextServerToTry();
|
||||
if (!toTry.isPresent()) {
|
||||
player.close(TextComponent.of("No available servers", TextColor.RED));
|
||||
return;
|
||||
@ -246,9 +247,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
|
||||
logger.info("{} has connected", player);
|
||||
inbound.setSessionHandler(new InitialConnectSessionHandler(player));
|
||||
server.getEventManager().fire(new PostLoginEvent(player)).thenRun(() -> {
|
||||
player.createConnectionRequest(toTry.get()).fireAndForget();
|
||||
});
|
||||
server.getEventManager().fire(new PostLoginEvent(player)).thenRun(() -> player.createConnectionRequest(toTry.get()).fireAndForget());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
68
proxy/src/main/java/com/velocitypowered/proxy/server/ServerMap.java
Normale Datei
68
proxy/src/main/java/com/velocitypowered/proxy/server/ServerMap.java
Normale Datei
@ -0,0 +1,68 @@
|
||||
package com.velocitypowered.proxy.server;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class ServerMap {
|
||||
private final VelocityServer server;
|
||||
private final Map<String, RegisteredServer> servers = new HashMap<>();
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public ServerMap(VelocityServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public Optional<RegisteredServer> getServer(String name) {
|
||||
Preconditions.checkNotNull(name, "server");
|
||||
String lowerName = name.toLowerCase(Locale.US);
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return Optional.ofNullable(servers.get(lowerName));
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<RegisteredServer> getAllServers() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return ImmutableList.copyOf(servers.values());
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public RegisteredServer register(ServerInfo serverInfo) {
|
||||
Preconditions.checkNotNull(serverInfo, "serverInfo");
|
||||
String lowerName = serverInfo.getName().toLowerCase(Locale.US);
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
VelocityRegisteredServer rs = new VelocityRegisteredServer(server, serverInfo);
|
||||
Preconditions.checkArgument(servers.putIfAbsent(lowerName, rs) == null, "Server with name %s already registered", serverInfo.getName());
|
||||
return rs;
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(ServerInfo serverInfo) {
|
||||
Preconditions.checkNotNull(serverInfo, "serverInfo");
|
||||
String lowerName = serverInfo.getName().toLowerCase(Locale.US);
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
RegisteredServer rs = servers.get(lowerName);
|
||||
Preconditions.checkArgument(rs != null, "Server with name %s is not registered!", serverInfo.getName());
|
||||
Preconditions.checkArgument(rs.getServerInfo().equals(serverInfo), "Trying to remove server %s with differing information", serverInfo.getName());
|
||||
servers.remove(lowerName);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.velocitypowered.proxy.server;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class VelocityRegisteredServer implements RegisteredServer {
|
||||
private final VelocityServer server;
|
||||
private final ServerInfo serverInfo;
|
||||
private final Set<ConnectedPlayer> players = new HashSet<>();
|
||||
private final ReadWriteLock playersLock = new ReentrantReadWriteLock();
|
||||
|
||||
public VelocityRegisteredServer(VelocityServer server, ServerInfo serverInfo) {
|
||||
this.server = server;
|
||||
this.serverInfo = serverInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerInfo getServerInfo() {
|
||||
return serverInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Player> getPlayersConnected() {
|
||||
playersLock.readLock().lock();
|
||||
try {
|
||||
return ImmutableList.copyOf(players);
|
||||
} finally {
|
||||
playersLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<ServerPing> ping() {
|
||||
CompletableFuture<ServerPing> p = new CompletableFuture<>();
|
||||
p.completeExceptionally(new UnsupportedOperationException("Not currently implemented."));
|
||||
return p;
|
||||
}
|
||||
|
||||
public void addPlayer(ConnectedPlayer player) {
|
||||
playersLock.writeLock().lock();
|
||||
try {
|
||||
players.add(player);
|
||||
} finally {
|
||||
playersLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(ConnectedPlayer player) {
|
||||
playersLock.writeLock().lock();
|
||||
try {
|
||||
players.remove(player);
|
||||
} finally {
|
||||
playersLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
|
||||
ServerConnection backendConnection = null;
|
||||
playersLock.readLock().lock();
|
||||
try {
|
||||
for (ConnectedPlayer player : players) {
|
||||
if (player.getConnectedServer() != null && player.getConnectedServer().getServerInfo().equals(serverInfo)) {
|
||||
backendConnection = player.getConnectedServer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (backendConnection == null) {
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
playersLock.readLock().unlock();
|
||||
}
|
||||
|
||||
return backendConnection.sendPluginMessage(identifier, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "registered server: " + serverInfo;
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package com.velocitypowered.proxy.util;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class ServerMap {
|
||||
private final Map<String, ServerInfo> servers = new HashMap<>();
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public Optional<ServerInfo> getServer(String server) {
|
||||
Preconditions.checkNotNull(server, "server");
|
||||
String lowerName = server.toLowerCase(Locale.US);
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return Optional.ofNullable(servers.get(lowerName));
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ServerInfo> getAllServers() {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return ImmutableList.copyOf(servers.values());
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void register(ServerInfo server) {
|
||||
Preconditions.checkNotNull(server, "server");
|
||||
String lowerName = server.getName().toLowerCase(Locale.US);
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
Preconditions.checkArgument(servers.putIfAbsent(lowerName, server) == null, "Server with name %s already registered", server.getName());
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(ServerInfo server) {
|
||||
Preconditions.checkNotNull(server, "server");
|
||||
String lowerName = server.getName().toLowerCase(Locale.US);
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
Preconditions.checkArgument(servers.remove(lowerName, server), "Server with this name is not registered!");
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package com.velocitypowered.proxy.util;
|
||||
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.proxy.server.ServerMap;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.InetAddress;
|
||||
@ -14,18 +16,18 @@ class ServerMapTest {
|
||||
|
||||
@Test
|
||||
void respectsCaseInsensitivity() {
|
||||
ServerMap map = new ServerMap();
|
||||
ServerMap map = new ServerMap(null);
|
||||
ServerInfo info = new ServerInfo("TestServer", TEST_ADDRESS);
|
||||
map.register(info);
|
||||
RegisteredServer connection = map.register(info);
|
||||
|
||||
assertEquals(Optional.of(info), map.getServer("TestServer"));
|
||||
assertEquals(Optional.of(info), map.getServer("testserver"));
|
||||
assertEquals(Optional.of(info), map.getServer("TESTSERVER"));
|
||||
assertEquals(Optional.of(connection), map.getServer("TestServer"));
|
||||
assertEquals(Optional.of(connection), map.getServer("testserver"));
|
||||
assertEquals(Optional.of(connection), map.getServer("TESTSERVER"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsRepeatedRegisterAttempts() {
|
||||
ServerMap map = new ServerMap();
|
||||
ServerMap map = new ServerMap(null);
|
||||
ServerInfo info = new ServerInfo("TestServer", TEST_ADDRESS);
|
||||
map.register(info);
|
||||
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren