3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-12-24 15:20:35 +01:00

Allow running Velocity without any servers.

This is a niche setup, however if your network is 100% dynamically configured, this is a handy feature to have available.

To support this functionality, a new PlayerChooseInitialServerEvent event was added to allow the initial server to connect to be changed as desired.
Dieser Commit ist enthalten in:
Andrew Steinborn 2019-11-16 23:17:09 -05:00
Ursprung e12f970684
Commit d2b8271eb4
4 geänderte Dateien mit 106 neuen und 71 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,51 @@
package com.velocitypowered.api.event.player;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.proxy.Player;
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
* to connect to.
*/
public class PlayerChooseInitialServerEvent {
private final Player player;
private @Nullable RegisteredServer initialServer;
/**
* Constructs a PlayerChooseInitialServerEvent.
* @param player the player that was connected
* @param initialServer the initial server selected, may be {@code null}
*/
public PlayerChooseInitialServerEvent(Player player, @Nullable RegisteredServer initialServer) {
this.player = Preconditions.checkNotNull(player, "player");
this.initialServer = initialServer;
}
public Player getPlayer() {
return player;
}
public Optional<RegisteredServer> getInitialServer() {
return Optional.ofNullable(initialServer);
}
/**
* Sets the new initial server.
* @param server the initial server the player should connect to
*/
public void setInitialServer(RegisteredServer server) {
this.initialServer = server;
}
@Override
public String toString() {
return "PlayerChooseInitialServerEvent{"
+ "player=" + player
+ ", initialServer=" + initialServer
+ '}';
}
}

Datei anzeigen

@ -192,44 +192,38 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
}
if (servers.getServers().isEmpty()) {
logger.error("You have no servers configured. :(");
valid = false;
} else {
if (servers.getAttemptConnectionOrder().isEmpty()) {
logger.error("No fallback servers are configured!");
logger.warn("You don't have any servers configured.");
}
for (Map.Entry<String, String> entry : servers.getServers().entrySet()) {
try {
AddressUtil.parseAddress(entry.getValue());
} catch (IllegalArgumentException e) {
logger.error("Server {} does not have a valid IP address.", entry.getKey(), e);
valid = false;
}
}
for (Map.Entry<String, String> entry : servers.getServers().entrySet()) {
try {
AddressUtil.parseAddress(entry.getValue());
} catch (IllegalArgumentException e) {
logger.error("Server {} does not have a valid IP address.", entry.getKey(), e);
valid = false;
}
for (String s : servers.getAttemptConnectionOrder()) {
if (!servers.getServers().containsKey(s)) {
logger.error("Fallback server " + s + " is not registered in your configuration!");
valid = false;
}
}
for (Map.Entry<String, List<String>> entry : forcedHosts.getForcedHosts().entrySet()) {
if (entry.getValue().isEmpty()) {
logger.error("Forced host '{}' does not contain any servers", entry.getKey());
valid = false;
continue;
}
for (String s : servers.getAttemptConnectionOrder()) {
if (!servers.getServers().containsKey(s)) {
logger.error("Fallback server " + s + " is not registered in your configuration!");
for (String server : entry.getValue()) {
if (!servers.getServers().containsKey(server)) {
logger.error("Server '{}' for forced host '{}' does not exist", server, entry.getKey());
valid = false;
}
}
for (Map.Entry<String, List<String>> entry : forcedHosts.getForcedHosts().entrySet()) {
if (entry.getValue().isEmpty()) {
logger.error("Forced host '{}' does not contain any servers", entry.getKey());
valid = false;
continue;
}
for (String server : entry.getValue()) {
if (!servers.getServers().containsKey(server)) {
logger.error("Server '{}' for forced host '{}' does not exist", server, entry.getKey());
valid = false;
}
}
}
}
try {

Datei anzeigen

@ -417,33 +417,22 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
return;
}
if (connectedServer == null) {
Optional<RegisteredServer> nextServer = getNextServerToTry(rs);
if (nextServer.isPresent()) {
// There can't be any connection in flight now.
resetInFlightConnection();
createConnectionRequest(nextServer.get()).fireAndForget();
} else {
disconnect(friendlyReason);
}
boolean kickedFromCurrent = connectedServer == null || connectedServer.getServer().equals(rs);
ServerKickResult result;
if (kickedFromCurrent) {
Optional<RegisteredServer> next = getNextServerToTry(rs);
result = next.<ServerKickResult>map(RedirectPlayer::create)
.orElseGet(() -> DisconnectPlayer.create(friendlyReason));
} else {
boolean kickedFromCurrent = connectedServer.getServer().equals(rs);
ServerKickResult result;
if (kickedFromCurrent) {
Optional<RegisteredServer> next = getNextServerToTry(rs);
result = next.<ServerKickResult>map(RedirectPlayer::create)
.orElseGet(() -> DisconnectPlayer.create(friendlyReason));
} else {
// If we were kicked by going to another server, the connection should not be in flight
if (connectionInFlight != null && connectionInFlight.getServer().equals(rs)) {
resetInFlightConnection();
}
result = Notify.create(friendlyReason);
// If we were kicked by going to another server, the connection should not be in flight
if (connectionInFlight != null && connectionInFlight.getServer().equals(rs)) {
resetInFlightConnection();
}
KickedFromServerEvent originalEvent = new KickedFromServerEvent(this, rs, kickReason,
!kickedFromCurrent, result);
handleKickEvent(originalEvent, friendlyReason);
result = Notify.create(friendlyReason);
}
KickedFromServerEvent originalEvent = new KickedFromServerEvent(this, rs, kickReason,
!kickedFromCurrent, result);
handleKickEvent(originalEvent, friendlyReason);
}
private void handleKickEvent(KickedFromServerEvent originalEvent, Component friendlyReason) {

Datei anzeigen

@ -1,24 +1,21 @@
package com.velocitypowered.proxy.connection.client;
import static com.google.common.net.UrlEscapers.urlFormParameterEscaper;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8;
import static com.velocitypowered.proxy.VelocityServer.GSON;
import static com.velocitypowered.proxy.connection.VelocityConstants.EMPTY_BYTE_ARRAY;
import static com.velocitypowered.proxy.connection.VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL;
import static com.velocitypowered.proxy.util.EncryptionUtils.decryptRsa;
import static com.velocitypowered.proxy.util.EncryptionUtils.generateServerId;
import static org.asynchttpclient.Dsl.asyncHttpClient;
import static org.asynchttpclient.Dsl.config;
import com.google.common.base.Preconditions;
import com.google.common.net.UrlEscapers;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.connection.PreLoginEvent;
import com.velocitypowered.api.event.connection.PreLoginEvent.PreLoginComponentResult;
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
import com.velocitypowered.api.event.player.GameProfileRequestEvent;
import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.VelocityServer;
@ -29,17 +26,12 @@ import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.Disconnect;
import com.velocitypowered.proxy.protocol.packet.EncryptionRequest;
import com.velocitypowered.proxy.protocol.packet.EncryptionResponse;
import com.velocitypowered.proxy.protocol.packet.LoginPluginMessage;
import com.velocitypowered.proxy.protocol.packet.LoginPluginResponse;
import com.velocitypowered.proxy.protocol.packet.ServerLogin;
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
import com.velocitypowered.proxy.protocol.packet.SetCompression;
import com.velocitypowered.proxy.util.VelocityMessages;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.util.Arrays;
@ -50,7 +42,6 @@ import java.util.concurrent.ThreadLocalRandom;
import net.kyori.text.Component;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.asynchttpclient.Dsl;
import org.asynchttpclient.ListenableFuture;
import org.asynchttpclient.Response;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -231,12 +222,6 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
}
private void finishLogin(ConnectedPlayer player) {
Optional<RegisteredServer> toTry = player.getNextServerToTry();
if (!toTry.isPresent()) {
player.disconnect(VelocityMessages.NO_AVAILABLE_SERVERS);
return;
}
int threshold = server.getConfiguration().getCompressionThreshold();
if (threshold >= 0 && mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) {
mcConnection.write(new SetCompression(threshold));
@ -269,11 +254,27 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
mcConnection.setSessionHandler(new InitialConnectSessionHandler(player));
server.getEventManager().fire(new PostLoginEvent(player))
.thenRun(() -> player.createConnectionRequest(toTry.get()).fireAndForget());
.thenRun(() -> connectToInitialServer(player));
}
}, mcConnection.eventLoop());
}
private void connectToInitialServer(ConnectedPlayer player) {
Optional<RegisteredServer> initialFromConfig = player.getNextServerToTry();
PlayerChooseInitialServerEvent event = new PlayerChooseInitialServerEvent(player,
initialFromConfig.orElse(null));
server.getEventManager().fire(event)
.thenRunAsync(() -> {
Optional<RegisteredServer> toTry = event.getInitialServer();
if (!toTry.isPresent()) {
player.disconnect(VelocityMessages.NO_AVAILABLE_SERVERS);
return;
}
player.createConnectionRequest(toTry.get()).fireAndForget();
}, mcConnection.eventLoop());
}
@Override
public void handleUnknown(ByteBuf buf) {
mcConnection.close();