Fix duplicate login kick bypass - logout was resetting online flag
ROOT CAUSE: When Server B kicks a player for being already online on Server A, the onPlayerLogout handler on Server B fires and sets online=0 in the DB. The player then immediately reconnects to Server B, the DB says online=0, and the kick check passes - player is now on BOTH servers simultaneously. FIX: New kickedForDuplicateLogin set tracks players being kicked for duplicate login. onPlayerLogout checks this set FIRST and skips the online=0 update entirely. The player's DB record correctly stays online=1 with last_server=A, preventing reconnect bypass. Flow: 1. Player on Server A (online=1, last_server=A) 2. Player tries Server B → kick check → online=1, A alive → KICK 3. kickedForDuplicateLogin.add(uuid) BEFORE disconnect 4. onPlayerLogout fires → sees kickedForDuplicateLogin → skips online=0 5. Player retries Server B → online=1 still → KICKED AGAIN Vyrriox
This commit is contained in:
parent
0a88694166
commit
b1563cc9ae
|
|
@ -217,6 +217,8 @@ public class VanillaSync {
|
|||
// Use string uuid as key
|
||||
public static Set<String> deadPlayerWhileLogging = ConcurrentHashMap.newKeySet();
|
||||
public static Set<String> syncNotCompletedPlayer = ConcurrentHashMap.newKeySet();
|
||||
// Players kicked for being already online on another server - their logout must NOT set online=0
|
||||
public static Set<String> kickedForDuplicateLogin = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
ServerPlayer serverPlayer = (ServerPlayer) event.getEntity();
|
||||
|
|
@ -466,6 +468,9 @@ public class VanillaSync {
|
|||
boolean enable = rs2.getBoolean("enable");
|
||||
if (enable && System.currentTimeMillis() < lastUpdate + 300000L) {
|
||||
// Other server is alive → KICK using ServerPlayer.connection which works reliably
|
||||
// CRITICAL: Mark as kicked BEFORE disconnect so onPlayerLogout does NOT set online=0.
|
||||
// Without this, the logout handler resets online=0, allowing immediate reconnect bypass.
|
||||
kickedForDuplicateLogin.add(player_uuid);
|
||||
PlayerSync.LOGGER.warn("Kicking player {} - already online on server {}", player_uuid, lastServer);
|
||||
player.connection.disconnect(Component.translatableWithFallback(
|
||||
"playersync.already_online",
|
||||
|
|
@ -739,7 +744,15 @@ public class VanillaSync {
|
|||
@SubscribeEvent
|
||||
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||
String player_uuid = event.getEntity().getUUID().toString();
|
||||
if (deadPlayerWhileLogging.contains(player_uuid)) {
|
||||
// FIX: Players kicked for duplicate login must NOT set online=0.
|
||||
// They are still online on the OTHER server. Setting online=0 here would allow
|
||||
// them to bypass the kick by immediately reconnecting (DB says offline while
|
||||
// they're still on the other server).
|
||||
if (kickedForDuplicateLogin.contains(player_uuid)) {
|
||||
PlayerSync.LOGGER.info("Player {} was kicked for duplicate login, NOT marking offline (still on other server)", player_uuid);
|
||||
kickedForDuplicateLogin.remove(player_uuid);
|
||||
return;
|
||||
} else if (deadPlayerWhileLogging.contains(player_uuid)) {
|
||||
PlayerSync.LOGGER.warn("A dead or dying player was kicked, uuid: {}", player_uuid);
|
||||
try {
|
||||
JDBCsetUp.executePreparedUpdate("UPDATE player_data SET online=0 WHERE uuid=?", player_uuid);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user