Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
Allow to enable online mode for player connection (#51)
Dieser Commit ist enthalten in:
Ursprung
e6e3ccaa95
Commit
a3c4522ca0
3
.gitignore
vendored
3
.gitignore
vendored
@ -92,6 +92,9 @@ modules.xml
|
||||
**/.settings/
|
||||
**/bin/
|
||||
|
||||
# NetBeans Gradle#
|
||||
.nb-gradle/
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.velocitypowered.api.event;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@ -72,7 +73,7 @@ public interface ResultedEvent<R extends ResultedEvent.Result> {
|
||||
private final boolean allowed;
|
||||
private final @Nullable Component reason;
|
||||
|
||||
private ComponentResult(boolean allowed, @Nullable Component reason) {
|
||||
protected ComponentResult(boolean allowed, @Nullable Component reason) {
|
||||
this.allowed = allowed;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
@ -2,22 +2,28 @@ package com.velocitypowered.api.event.connection;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.event.ResultedEvent.ComponentResult;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* This event is fired when a player has initiated a connection with the proxy but before the proxy authenticates the
|
||||
* player with Mojang or before the player's proxy connection is fully established (for offline mode).
|
||||
*/
|
||||
public class PreLoginEvent implements ResultedEvent<ResultedEvent.ComponentResult> {
|
||||
public class PreLoginEvent implements ResultedEvent<PreLoginEvent.PreLoginComponentResult> {
|
||||
private final InboundConnection connection;
|
||||
private final String username;
|
||||
private ComponentResult result;
|
||||
private PreLoginComponentResult result;
|
||||
|
||||
public PreLoginEvent(InboundConnection connection, String username) {
|
||||
this.connection = Preconditions.checkNotNull(connection, "connection");
|
||||
this.username = Preconditions.checkNotNull(username, "username");
|
||||
this.result = ComponentResult.allowed();
|
||||
this.result = PreLoginComponentResult.allowed();
|
||||
}
|
||||
|
||||
public InboundConnection getConnection() {
|
||||
@ -29,12 +35,12 @@ public class PreLoginEvent implements ResultedEvent<ResultedEvent.ComponentResul
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentResult getResult() {
|
||||
public PreLoginComponentResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResult(@NonNull ComponentResult result) {
|
||||
public void setResult(@NonNull PreLoginComponentResult result) {
|
||||
this.result = Preconditions.checkNotNull(result, "result");
|
||||
}
|
||||
|
||||
@ -46,4 +52,56 @@ public class PreLoginEvent implements ResultedEvent<ResultedEvent.ComponentResul
|
||||
", result=" + result +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an "allowed/allowed with online mode/denied" result with a reason allowed for denial.
|
||||
*/
|
||||
public static class PreLoginComponentResult extends ComponentResult {
|
||||
|
||||
private static final PreLoginComponentResult ALLOWED = new PreLoginComponentResult((Component) null);
|
||||
private static final PreLoginComponentResult FORCE_ONLINEMODE = new PreLoginComponentResult(true);
|
||||
|
||||
private final boolean onlineMode;
|
||||
/**
|
||||
* Allows to enable a online mode for the player connection, when Velocity running in offline mode
|
||||
* Does not have any sense if velocity running in onlineMode;
|
||||
* @param allowedOnlineMode if true, offline uuid will be used for player connection if Velocity run in offlineMode
|
||||
*/
|
||||
private PreLoginComponentResult(boolean allowedOnlineMode) {
|
||||
super(true, null);
|
||||
this.onlineMode = allowedOnlineMode;
|
||||
}
|
||||
|
||||
private PreLoginComponentResult(@Nullable Component reason) {
|
||||
super(reason == null, reason);
|
||||
// Don't care about this
|
||||
this.onlineMode = false;
|
||||
}
|
||||
|
||||
public boolean isOnlineModeAllowed() {
|
||||
return this.onlineMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isOnlineModeAllowed()) {
|
||||
return "allowed with online mode";
|
||||
}
|
||||
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
public static PreLoginComponentResult allowed() {
|
||||
return ALLOWED;
|
||||
}
|
||||
|
||||
public static PreLoginComponentResult forceOnlineMode() {
|
||||
return FORCE_ONLINEMODE;
|
||||
}
|
||||
|
||||
public static PreLoginComponentResult denied(@NonNull Component reason) {
|
||||
Preconditions.checkNotNull(reason, "reason");
|
||||
return new PreLoginComponentResult(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
package com.velocitypowered.api.event.player.gameprofile;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
|
||||
|
||||
public class GameProfileRequestEvent {
|
||||
private final String username;
|
||||
private final GameProfile originalProfile;
|
||||
private final boolean onlineMode;
|
||||
private GameProfile gameProfile;
|
||||
|
||||
public GameProfileRequestEvent(GameProfile originalProfile, boolean onlinemode) {
|
||||
this.originalProfile = Preconditions.checkNotNull(originalProfile, "profile");
|
||||
this.username = originalProfile.getName();
|
||||
this.onlineMode = onlinemode;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public GameProfile getOriginalProfile() {
|
||||
return originalProfile;
|
||||
}
|
||||
|
||||
public boolean isOnlineMode() {
|
||||
return onlineMode;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return a GameProfile, can be null
|
||||
*/
|
||||
public GameProfile getGameProfile() {
|
||||
return gameProfile;
|
||||
}
|
||||
|
||||
public void setGameProfile(@Nullable GameProfile gameProfile) {
|
||||
this.gameProfile = gameProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GameProfileRequestEvent{"+
|
||||
"username=" + username +
|
||||
", gameProfile=" + gameProfile +
|
||||
"}";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
package com.velocitypowered.api.proxy;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.event.connection.LoginEvent;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSink;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelMessageSource;
|
||||
import com.velocitypowered.api.server.ServerInfo;
|
||||
import com.velocitypowered.api.util.GameProfile.Property;
|
||||
import com.velocitypowered.api.util.MessagePosition;
|
||||
import net.kyori.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -25,7 +25,7 @@ public class GameProfile {
|
||||
public UUID idAsUuid() {
|
||||
return UuidUtils.fromUndashed(id);
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -9,12 +9,14 @@ import com.velocitypowered.api.proxy.ConnectionRequestBuilder;
|
||||
import com.velocitypowered.api.proxy.ServerConnection;
|
||||
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
|
||||
import com.velocitypowered.api.util.MessagePosition;
|
||||
import com.velocitypowered.api.util.UuidUtils;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
|
||||
import com.velocitypowered.proxy.connection.util.ConnectionMessages;
|
||||
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||
import com.velocitypowered.proxy.protocol.packet.Chat;
|
||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
|
||||
@ -45,9 +47,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(ConnectedPlayer.class);
|
||||
|
||||
private final GameProfile profile;
|
||||
private final MinecraftConnection connection;
|
||||
private final InetSocketAddress virtualHost;
|
||||
private final GameProfile profile;
|
||||
private PermissionFunction permissionFunction = null;
|
||||
private int tryIndex = 0;
|
||||
private VelocityServerConnection connectedServer;
|
||||
|
@ -3,11 +3,14 @@ package com.velocitypowered.proxy.connection.client;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.velocitypowered.api.event.connection.LoginEvent;
|
||||
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.gameprofile.GameProfileRequestEvent;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import com.velocitypowered.api.server.ServerInfo;
|
||||
import com.velocitypowered.proxy.connection.VelocityConstants;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.api.util.UuidUtils;
|
||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolConstants;
|
||||
import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||
@ -37,7 +40,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
private static final Logger logger = LogManager.getLogger(LoginSessionHandler.class);
|
||||
private static final String MOJANG_SERVER_AUTH_URL =
|
||||
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s&ip=%s";
|
||||
|
||||
|
||||
private final MinecraftConnection inbound;
|
||||
private final InboundConnection apiInbound;
|
||||
private ServerLogin login;
|
||||
@ -97,15 +100,14 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
// The player disconnected after we authenticated them.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
inbound.enableEncryption(decryptedSharedSecret);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
GameProfile profile = VelocityServer.GSON.fromJson(profileResponse, GameProfile.class);
|
||||
initializePlayer(profile);
|
||||
|
||||
initializePlayer(VelocityServer.GSON.fromJson(profileResponse, GameProfile.class), true);
|
||||
|
||||
}, inbound.getChannel().eventLoop())
|
||||
.exceptionally(exception -> {
|
||||
logger.error("Unable to enable encryption", exception);
|
||||
@ -125,20 +127,24 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
PreLoginEvent event = new PreLoginEvent(apiInbound, login.getUsername());
|
||||
VelocityServer.getServer().getEventManager().fire(event)
|
||||
.thenRunAsync(() -> {
|
||||
if (!event.getResult().isAllowed()) {
|
||||
if (inbound.isClosed()) {
|
||||
// The player was disconnected
|
||||
return;
|
||||
}
|
||||
PreLoginComponentResult result = event.getResult();
|
||||
if (!result.isAllowed()) {
|
||||
// The component is guaranteed to be provided if the connection was denied.
|
||||
inbound.closeWith(Disconnect.create(event.getResult().getReason().get()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (VelocityServer.getServer().getConfiguration().isOnlineMode()) {
|
||||
|
||||
if (VelocityServer.getServer().getConfiguration().isOnlineMode() || result.isOnlineModeAllowed()) {
|
||||
// Request encryption.
|
||||
EncryptionRequest request = generateRequest();
|
||||
this.verify = Arrays.copyOf(request.getVerifyToken(), 4);
|
||||
inbound.write(request);
|
||||
} else {
|
||||
// Offline-mode, don't try to request encryption.
|
||||
initializePlayer(GameProfile.forOfflinePlayer(login.getUsername()));
|
||||
initializePlayer(GameProfile.forOfflinePlayer(login.getUsername()), false);
|
||||
}
|
||||
}, inbound.getChannel().eventLoop());
|
||||
}
|
||||
@ -153,28 +159,38 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
||||
return request;
|
||||
}
|
||||
|
||||
private void initializePlayer(GameProfile profile) {
|
||||
// Initiate a regular connection and move over to it.
|
||||
ConnectedPlayer player = new ConnectedPlayer(profile, inbound, apiInbound.getVirtualHost().orElse(null));
|
||||
private void initializePlayer(GameProfile profile, boolean onlineMode) {
|
||||
|
||||
// load permissions first
|
||||
VelocityServer.getServer().getEventManager().fire(new PermissionsSetupEvent(player, ConnectedPlayer.DEFAULT_PERMISSIONS))
|
||||
.thenCompose(event -> {
|
||||
// wait for permissions to load, then set the players permission function
|
||||
player.setPermissionFunction(event.createFunction(player));
|
||||
// then call & wait for the login event
|
||||
return VelocityServer.getServer().getEventManager().fire(new LoginEvent(player));
|
||||
})
|
||||
// then complete the connection
|
||||
.thenAcceptAsync(event -> {
|
||||
if (!event.getResult().isAllowed()) {
|
||||
// The component is guaranteed to be provided if the connection was denied.
|
||||
inbound.closeWith(Disconnect.create(event.getResult().getReason().get()));
|
||||
return;
|
||||
}
|
||||
GameProfileRequestEvent profileRequestEvent = new GameProfileRequestEvent(profile, onlineMode);
|
||||
|
||||
VelocityServer.getServer().getEventManager().fire(profileRequestEvent).thenCompose(profileEvent -> {
|
||||
// Initiate a regular connection and move over to it.
|
||||
ConnectedPlayer player = new ConnectedPlayer(profileEvent.getGameProfile() == null ? profile : profileEvent.getGameProfile(),
|
||||
inbound, apiInbound.getVirtualHost().orElse(null));
|
||||
|
||||
return VelocityServer.getServer().getEventManager().fire(new PermissionsSetupEvent(player, ConnectedPlayer.DEFAULT_PERMISSIONS))
|
||||
.thenCompose(event -> {
|
||||
// wait for permissions to load, then set the players permission function
|
||||
player.setPermissionFunction(event.createFunction(player));
|
||||
// then call & wait for the login event
|
||||
return VelocityServer.getServer().getEventManager().fire(new LoginEvent(player));
|
||||
})
|
||||
// then complete the connection
|
||||
.thenAcceptAsync(event -> {
|
||||
if (inbound.isClosed()) {
|
||||
// The player was disconnected
|
||||
return;
|
||||
}
|
||||
if (!event.getResult().isAllowed()) {
|
||||
// The component is guaranteed to be provided if the connection was denied.
|
||||
inbound.closeWith(Disconnect.create(event.getResult().getReason().get()));
|
||||
return;
|
||||
}
|
||||
|
||||
handleProxyLogin(player);
|
||||
}, inbound.getChannel().eventLoop());
|
||||
});
|
||||
|
||||
handleProxyLogin(player);
|
||||
}, inbound.getChannel().eventLoop());
|
||||
}
|
||||
|
||||
private void handleProxyLogin(ConnectedPlayer player) {
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren