diff --git a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java index 73d41ecdc..d1056f3eb 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/PlayerChooseInitialServerEvent.java @@ -8,11 +8,17 @@ package com.velocitypowered.api.event.player; import com.google.common.base.Preconditions; +import com.velocitypowered.api.event.ResultedEvent; import com.velocitypowered.api.event.annotation.AwaitingEvent; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.server.RegisteredServer; + import java.util.Optional; + +import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; /** * Fired when a player has finished the login process, and we need to choose the first server @@ -21,20 +27,20 @@ import org.checkerframework.checker.nullness.qual.Nullable; * {@link KickedFromServerEvent} as normal. */ @AwaitingEvent -public class PlayerChooseInitialServerEvent { +public class PlayerChooseInitialServerEvent implements ResultedEvent { private final Player player; - private @Nullable RegisteredServer initialServer; + private @NotNull Result result; /** * Constructs a PlayerChooseInitialServerEvent. * - * @param player the player that was connected + * @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; + this.result = Allowed.of(initialServer); } public Player getPlayer() { @@ -42,7 +48,10 @@ public class PlayerChooseInitialServerEvent { } public Optional getInitialServer() { - return Optional.ofNullable(initialServer); + if (result instanceof Allowed(RegisteredServer initialServer)) { + return Optional.ofNullable(initialServer); + } + return Optional.empty(); } /** @@ -51,14 +60,62 @@ public class PlayerChooseInitialServerEvent { * @param server the initial server the player should connect to */ public void setInitialServer(@Nullable RegisteredServer server) { - this.initialServer = server; + if (server == null) { + this.result = Denied.of(); + return; + } + this.result = Allowed.of(server); } @Override public String toString() { return "PlayerChooseInitialServerEvent{" - + "player=" + player - + ", initialServer=" + initialServer - + '}'; + + "player=" + player + + ", result=" + result + + '}'; + } + + @Override + public @NonNull Result getResult() { + return this.result; + } + + @Override + public void setResult(final Result result) { + this.result = Preconditions.checkNotNull(result, "result"); + } + + public sealed interface Result extends ResultedEvent.Result permits Allowed, Denied { + } + + public record Allowed(@NotNull RegisteredServer initialServer) implements Result { + + public Allowed { + Preconditions.checkNotNull(initialServer, "initialServer"); + } + + public static @NotNull Result of(final RegisteredServer initialServer) { + return new Allowed(initialServer); + } + + @Override + public boolean isAllowed() { + return true; + } + } + + public record Denied(@Nullable Component reason) implements Result { + public static @NotNull Result of(@Nullable Component reason) { + return new Denied(reason); + } + + public static @NotNull Result of() { + return new Denied(null); + } + + @Override + public boolean isAllowed() { + return false; + } } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/AuthSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/AuthSessionHandler.java index 605388ea3..37135cddf 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/AuthSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/AuthSessionHandler.java @@ -262,14 +262,16 @@ public class AuthSessionHandler implements MinecraftSessionHandler { new PlayerChooseInitialServerEvent(player, initialFromConfig.orElse(null)); return server.getEventManager().fire(event).thenRunAsync(() -> { - Optional toTry = event.getInitialServer(); - if (toTry.isEmpty()) { - player.disconnect0( - Component.translatable("velocity.error.no-available-servers", NamedTextColor.RED), - true); + final PlayerChooseInitialServerEvent.Result result = event.getResult(); + if (event.getResult() instanceof PlayerChooseInitialServerEvent.Denied(Component reason)) { + player.disconnect0(Objects.requireNonNullElse(reason, + Component.translatable("velocity.error.no-available-servers", NamedTextColor.RED)), + true); + //noinspection UnnecessaryReturnStatement return; + } else if (result instanceof PlayerChooseInitialServerEvent.Allowed(RegisteredServer initialServer)) { + player.createConnectionRequest(initialServer).fireAndForget(); } - player.createConnectionRequest(toTry.get()).fireAndForget(); }, mcConnection.eventLoop()); }