geforkt von Mirrors/Velocity
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()) {
|
if (servers.getServers().isEmpty()) {
|
||||||
logger.error("You have no servers configured. :(");
|
logger.warn("You don't have any servers configured.");
|
||||||
valid = false;
|
}
|
||||||
} else {
|
|
||||||
if (servers.getAttemptConnectionOrder().isEmpty()) {
|
for (Map.Entry<String, String> entry : servers.getServers().entrySet()) {
|
||||||
logger.error("No fallback servers are configured!");
|
try {
|
||||||
|
AddressUtil.parseAddress(entry.getValue());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
logger.error("Server {} does not have a valid IP address.", entry.getKey(), e);
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : servers.getServers().entrySet()) {
|
for (String s : servers.getAttemptConnectionOrder()) {
|
||||||
try {
|
if (!servers.getServers().containsKey(s)) {
|
||||||
AddressUtil.parseAddress(entry.getValue());
|
logger.error("Fallback server " + s + " is not registered in your configuration!");
|
||||||
} catch (IllegalArgumentException e) {
|
valid = false;
|
||||||
logger.error("Server {} does not have a valid IP address.", entry.getKey(), e);
|
}
|
||||||
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()) {
|
for (String server : entry.getValue()) {
|
||||||
if (!servers.getServers().containsKey(s)) {
|
if (!servers.getServers().containsKey(server)) {
|
||||||
logger.error("Fallback server " + s + " is not registered in your configuration!");
|
logger.error("Server '{}' for forced host '{}' does not exist", server, entry.getKey());
|
||||||
valid = false;
|
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 {
|
try {
|
||||||
|
@ -417,33 +417,22 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectedServer == null) {
|
boolean kickedFromCurrent = connectedServer == null || connectedServer.getServer().equals(rs);
|
||||||
Optional<RegisteredServer> nextServer = getNextServerToTry(rs);
|
ServerKickResult result;
|
||||||
if (nextServer.isPresent()) {
|
if (kickedFromCurrent) {
|
||||||
// There can't be any connection in flight now.
|
Optional<RegisteredServer> next = getNextServerToTry(rs);
|
||||||
resetInFlightConnection();
|
result = next.<ServerKickResult>map(RedirectPlayer::create)
|
||||||
createConnectionRequest(nextServer.get()).fireAndForget();
|
.orElseGet(() -> DisconnectPlayer.create(friendlyReason));
|
||||||
} else {
|
|
||||||
disconnect(friendlyReason);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
boolean kickedFromCurrent = connectedServer.getServer().equals(rs);
|
// If we were kicked by going to another server, the connection should not be in flight
|
||||||
ServerKickResult result;
|
if (connectionInFlight != null && connectionInFlight.getServer().equals(rs)) {
|
||||||
if (kickedFromCurrent) {
|
resetInFlightConnection();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
KickedFromServerEvent originalEvent = new KickedFromServerEvent(this, rs, kickReason,
|
result = Notify.create(friendlyReason);
|
||||||
!kickedFromCurrent, result);
|
|
||||||
handleKickEvent(originalEvent, friendlyReason);
|
|
||||||
}
|
}
|
||||||
|
KickedFromServerEvent originalEvent = new KickedFromServerEvent(this, rs, kickReason,
|
||||||
|
!kickedFromCurrent, result);
|
||||||
|
handleKickEvent(originalEvent, friendlyReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleKickEvent(KickedFromServerEvent originalEvent, Component friendlyReason) {
|
private void handleKickEvent(KickedFromServerEvent originalEvent, Component friendlyReason) {
|
||||||
|
@ -1,24 +1,21 @@
|
|||||||
package com.velocitypowered.proxy.connection.client;
|
package com.velocitypowered.proxy.connection.client;
|
||||||
|
|
||||||
import static com.google.common.net.UrlEscapers.urlFormParameterEscaper;
|
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.api.network.ProtocolVersion.MINECRAFT_1_8;
|
||||||
import static com.velocitypowered.proxy.VelocityServer.GSON;
|
import static com.velocitypowered.proxy.VelocityServer.GSON;
|
||||||
import static com.velocitypowered.proxy.connection.VelocityConstants.EMPTY_BYTE_ARRAY;
|
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.decryptRsa;
|
||||||
import static com.velocitypowered.proxy.util.EncryptionUtils.generateServerId;
|
import static com.velocitypowered.proxy.util.EncryptionUtils.generateServerId;
|
||||||
import static org.asynchttpclient.Dsl.asyncHttpClient;
|
import static org.asynchttpclient.Dsl.asyncHttpClient;
|
||||||
import static org.asynchttpclient.Dsl.config;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
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.LoginEvent;
|
||||||
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||||
import com.velocitypowered.api.event.connection.PreLoginEvent;
|
import com.velocitypowered.api.event.connection.PreLoginEvent;
|
||||||
import com.velocitypowered.api.event.connection.PreLoginEvent.PreLoginComponentResult;
|
import com.velocitypowered.api.event.connection.PreLoginEvent.PreLoginComponentResult;
|
||||||
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
|
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
|
||||||
import com.velocitypowered.api.event.player.GameProfileRequestEvent;
|
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.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.api.util.GameProfile;
|
import com.velocitypowered.api.util.GameProfile;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
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.Disconnect;
|
||||||
import com.velocitypowered.proxy.protocol.packet.EncryptionRequest;
|
import com.velocitypowered.proxy.protocol.packet.EncryptionRequest;
|
||||||
import com.velocitypowered.proxy.protocol.packet.EncryptionResponse;
|
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.ServerLogin;
|
||||||
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
|
import com.velocitypowered.proxy.protocol.packet.ServerLoginSuccess;
|
||||||
import com.velocitypowered.proxy.protocol.packet.SetCompression;
|
import com.velocitypowered.proxy.protocol.packet.SetCompression;
|
||||||
import com.velocitypowered.proxy.util.VelocityMessages;
|
import com.velocitypowered.proxy.util.VelocityMessages;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -50,7 +42,6 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||||||
import net.kyori.text.Component;
|
import net.kyori.text.Component;
|
||||||
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.asynchttpclient.Dsl;
|
|
||||||
import org.asynchttpclient.ListenableFuture;
|
import org.asynchttpclient.ListenableFuture;
|
||||||
import org.asynchttpclient.Response;
|
import org.asynchttpclient.Response;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
@ -231,12 +222,6 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void finishLogin(ConnectedPlayer player) {
|
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();
|
int threshold = server.getConfiguration().getCompressionThreshold();
|
||||||
if (threshold >= 0 && mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) {
|
if (threshold >= 0 && mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) {
|
||||||
mcConnection.write(new SetCompression(threshold));
|
mcConnection.write(new SetCompression(threshold));
|
||||||
@ -269,11 +254,27 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
mcConnection.setSessionHandler(new InitialConnectSessionHandler(player));
|
mcConnection.setSessionHandler(new InitialConnectSessionHandler(player));
|
||||||
server.getEventManager().fire(new PostLoginEvent(player))
|
server.getEventManager().fire(new PostLoginEvent(player))
|
||||||
.thenRun(() -> player.createConnectionRequest(toTry.get()).fireAndForget());
|
.thenRun(() -> connectToInitialServer(player));
|
||||||
}
|
}
|
||||||
}, mcConnection.eventLoop());
|
}, 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
|
@Override
|
||||||
public void handleUnknown(ByteBuf buf) {
|
public void handleUnknown(ByteBuf buf) {
|
||||||
mcConnection.close();
|
mcConnection.close();
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren