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:
Ursprung
e12f970684
Commit
d2b8271eb4
@ -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
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren