diff --git a/src/main/java/Sdf1_login/LoginManager.java b/src/main/java/Sdf1_login/LoginManager.java index 8477707..200ef01 100644 --- a/src/main/java/Sdf1_login/LoginManager.java +++ b/src/main/java/Sdf1_login/LoginManager.java @@ -66,6 +66,10 @@ public class LoginManager { plugin.getDb().createUser( name, hash, salt); plugin.getLoggedIn().add(name); + // ★ 记录Java手动登录:5分钟内重连可直接放行(检查点1) + if (plugin.webManager != null) { + plugin.webManager.recordJavaLogin(name); + } p.setAllowFlight(false); p.setFlying(false); plugin.getDb().setLoggedIn(name, true); @@ -162,6 +166,10 @@ public class LoginManager { name, hash); if (matchMain) { plugin.getLoggedIn().add(name); + // ★ 记录Java手动登录:5分钟内重连可直接放行(检查点1) + if (plugin.webManager != null) { + plugin.webManager.recordJavaLogin(name); + } plugin.getDb().setLoggedIn( name, true); plugin.getDb().setLoggedIn( @@ -207,6 +215,10 @@ public class LoginManager { name, hash); if (matchTemp) { plugin.getLoggedIn().add(name); + // ★ 记录Java手动登录:5分钟内重连可直接放行(检查点1) + if (plugin.webManager != null) { + plugin.webManager.recordJavaLogin(name); + } plugin.getDb().setLoggedIn(name, true); p.setAllowFlight(false); p.setFlying(false); diff --git a/src/main/java/Sdf1_login/Main.java b/src/main/java/Sdf1_login/Main.java index 85bf235..53b3058 100644 --- a/src/main/java/Sdf1_login/Main.java +++ b/src/main/java/Sdf1_login/Main.java @@ -1166,6 +1166,10 @@ public class Main extends JavaPlugin } loggedIn.add(name); + // ★ 记录Java手动登录:5分钟内重连可直接放行(检查点1) + if (webManager != null) { + webManager.recordJavaLogin(name); + } p.setAllowFlight(false); p.setFlying(false); @@ -1741,14 +1745,15 @@ public class Main extends JavaPlugin // ===== 快速重连三层检查(严格按流程图) ===== - // ★ 检查点1:检查玩家是否有Java手动登录记录( loggedIn 集合) - // 注意:loggedIn在onQuit时会被清除,因此快速重连时检查点1通常失败 - // 这是正常行为 — 快速重连走检查点2(isWebLoginVerified)通过IP+内存验证 - if (loggedIn.contains(name)) { - getLogger().info("[Web登录] 检查点1通过: 玩家 " + name + " 有Java手动登录记录,放行"); - // 继续走正常登录流程(不中断) + // ★ 检查点1:检查玩家是否有Java手动登录记录 + // 优先检查loggedIn(当前在线),再检查javaLoginRecords(5分钟内重连有效) + boolean hasJavaLogin = loggedIn.contains(name) || (webManager != null && webManager.isJavaLoginRecorded(name)); + if (hasJavaLogin) { + getLogger().info("[Web登录] 检查点1通过: 玩家 " + name + " 有Java登录记录,自动登录"); + autoLogin(p, "java_reconnect"); + return; // 检查点1通过 → 直接放行 } else { - getLogger().info("[Web登录] 检查点1失败: 玩家 " + name + " 无Java手动登录记录(正常,已在onQuit清除)"); + getLogger().info("[Web登录] 检查点1失败: 玩家 " + name + " 无Java登录记录"); } // 辅助操作:生成Web Token + 同步PHP注册数据 diff --git a/src/main/java/Sdf1_login/WebManager.java b/src/main/java/Sdf1_login/WebManager.java index b8d7c2b..1740145 100644 --- a/src/main/java/Sdf1_login/WebManager.java +++ b/src/main/java/Sdf1_login/WebManager.java @@ -55,6 +55,11 @@ public class WebManager { private final ConcurrentHashMap verifiedWebLogins = new ConcurrentHashMap<>(); private static final long VERIFIED_LOGIN_EXPIRE_MS = 300000; // 5分钟过期 + // ★ Java手动登录记录:playerName -> 登录时间戳(毫秒) + // 玩家通过/l命令或autoLogin成功后记录,onQuit不清除,5分钟内重连可直接放行(检查点1) + private final ConcurrentHashMap javaLoginRecords = new ConcurrentHashMap<>(); + private static final long JAVA_LOGIN_RECORD_EXPIRE_MS = 300000; // 5分钟过期 + // ★ 合并定时器错峰调度(v17:3个定时器替代6个) private static final int TIMER_A = 0; // 注册登录 0~5秒 private static final int TIMER_B = 1; // 交易 0~10秒 @@ -2999,6 +3004,40 @@ public class WebManager { verifiedWebLogins.remove(playerName); } + // ==================== Java手动登录记录(检查点1持久化) ==================== + + /** + * 记录玩家Java手动登录成功(/l命令或autoLogin调用后) + * onQuit不清除,5分钟内重连可直接放行(检查点1) + */ + public void recordJavaLogin(String playerName) { + javaLoginRecords.put(playerName, System.currentTimeMillis()); + plugin.getLogger().info("[Web登录] 记录Java登录: " + playerName + "(5分钟内重连可直接放行)"); + } + + /** + * 检查玩家是否有Java手动登录记录(检查点1用) + * 5分钟内有效,超时自动清除 + */ + public boolean isJavaLoginRecorded(String playerName) { + Long loginTime = javaLoginRecords.get(playerName); + if (loginTime != null) { + if (System.currentTimeMillis() - loginTime > JAVA_LOGIN_RECORD_EXPIRE_MS) { + javaLoginRecords.remove(playerName); + return false; + } + return true; + } + return false; + } + + /** + * 清除玩家的Java登录记录(玩家成功再次登录后调用,避免过期残留) + */ + public void clearJavaLoginRecord(String playerName) { + javaLoginRecords.remove(playerName); + } + /** * 同步在线玩家列表到PHP端(用于Web登录状态检查) * 注意:推送所有在线玩家(包括未登录的),PHP端通过 web_login_verified 判断是否已认证 @@ -3838,11 +3877,17 @@ public class WebManager { // 成功 → 重置 loginPollFailCount = 0; - if (!json.contains("\"success\":true")) return; + if (!json.contains("\"success\":true")) { + plugin.getLogger().info("[Web登录确认轮询] PHP响应非success: " + json.substring(0, Math.min(200, json.length()))); + return; + } // 简单解析玩家名列表 int dataStart = json.indexOf("\"data\":"); - if (dataStart < 0) return; + if (dataStart < 0) { + plugin.getLogger().info("[Web登录确认轮询] PHP响应无data字段: " + json.substring(0, Math.min(200, json.length()))); + return; + } String dataStr = json.substring(dataStart + 7); int arrEnd = findMatchingBracket(dataStr, 0); if (arrEnd < 0) return; @@ -3916,15 +3961,38 @@ public class WebManager { (now - entry.getValue()) > VERIFIED_LOGIN_EXPIRE_MS ); } + // ★ 清理过期的Java登录记录(检查点1用) + if (javaLoginRecords.size() > 0) { + long now = System.currentTimeMillis(); + javaLoginRecords.entrySet().removeIf(entry -> + (now - entry.getValue()) > JAVA_LOGIN_RECORD_EXPIRE_MS + ); + } String urlStr = webBaseUrl + "/api/sync.php?action=check_pending_web_logins&secret=" + java.net.URLEncoder.encode(secretKey, "UTF-8"); String json = doGet(urlStr); - if (json == null) return; - if (!json.contains("\"success\":true")) return; + if (json == null) { + loginPollFailCount++; + long now = System.currentTimeMillis(); + if (now - lastLoginPollLogTime > POLL_LOG_INTERVAL) { + plugin.getLogger().warning("[Web密码验证轮询] GET失败 (连续失败" + loginPollFailCount + "次)"); + lastLoginPollLogTime = now; + } + return; + } + // 成功 → 重置 + loginPollFailCount = 0; + if (!json.contains("\"success\":true")) { + plugin.getLogger().info("[Web密码验证轮询] PHP响应非success: " + json.substring(0, Math.min(200, json.length()))); + return; + } // 解析请求列表 int dataStart = json.indexOf("\"data\":"); - if (dataStart < 0) return; + if (dataStart < 0) { + plugin.getLogger().info("[Web密码验证轮询] PHP响应无data字段: " + json.substring(0, Math.min(200, json.length()))); + return; + } String dataStr = json.substring(dataStart + 7); int arrEnd = findMatchingBracket(dataStr, 0); if (arrEnd < 0) return;