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
|
// Use string uuid as key
|
||||||
public static Set<String> deadPlayerWhileLogging = ConcurrentHashMap.newKeySet();
|
public static Set<String> deadPlayerWhileLogging = ConcurrentHashMap.newKeySet();
|
||||||
public static Set<String> syncNotCompletedPlayer = 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) {
|
public static void doPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||||
ServerPlayer serverPlayer = (ServerPlayer) event.getEntity();
|
ServerPlayer serverPlayer = (ServerPlayer) event.getEntity();
|
||||||
|
|
@ -466,6 +468,9 @@ public class VanillaSync {
|
||||||
boolean enable = rs2.getBoolean("enable");
|
boolean enable = rs2.getBoolean("enable");
|
||||||
if (enable && System.currentTimeMillis() < lastUpdate + 300000L) {
|
if (enable && System.currentTimeMillis() < lastUpdate + 300000L) {
|
||||||
// Other server is alive → KICK using ServerPlayer.connection which works reliably
|
// 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);
|
PlayerSync.LOGGER.warn("Kicking player {} - already online on server {}", player_uuid, lastServer);
|
||||||
player.connection.disconnect(Component.translatableWithFallback(
|
player.connection.disconnect(Component.translatableWithFallback(
|
||||||
"playersync.already_online",
|
"playersync.already_online",
|
||||||
|
|
@ -739,7 +744,15 @@ public class VanillaSync {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) {
|
public static void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) {
|
||||||
String player_uuid = event.getEntity().getUUID().toString();
|
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);
|
PlayerSync.LOGGER.warn("A dead or dying player was kicked, uuid: {}", player_uuid);
|
||||||
try {
|
try {
|
||||||
JDBCsetUp.executePreparedUpdate("UPDATE player_data SET online=0 WHERE uuid=?", player_uuid);
|
JDBCsetUp.executePreparedUpdate("UPDATE player_data SET online=0 WHERE uuid=?", player_uuid);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user