fix: 修正服务器反复传送刷屏日志、识别外站账号绑定流程、重连指数退避
部署到 Debian 服务器时暴露的三个真实缺陷: 1. 「被服务器传送」日志洪水 账号未完成服务器验证时服务端每 tick 强推一次位置,实测 3 分钟刷出 748 行日志, 几十分钟就会冲光 2000 条的日志环形缓冲并把 WebSocket 打满。 现改为首次立即记录、其余按 30 秒窗口聚合成一条,断开连接时刷出未汇总计数。 2. 外站账号绑定流程无法识别 原先只认 /login 与 /register,遇到简幻通这类要求 /auth <UID> <验证码> 或扫码绑定的 服务器时,表现只是「连上→被传送→120 秒后被踢→重连」的静默死循环。 现新增 NEED_AUTH_PATTERN 识别并输出可操作的中文告警(每连接一次), 新增 server.authCommand 模板供有固定验证码的服务器自动过验证。 3. 重连无退避 连续被踢时每 10 秒硬撞服务器。现按指数退避拉长(server.reconnectMaxDelayMs, 默认上限 120 秒),成功进入世界后清零;抽出 computeReconnectDelay 便于测试。 顺带补充 README 的「部署到服务器」章节(Node ≥ 22 要求、私有运行时、pm2、日志分文件、排障表)。 测试从 242 增至 252,全部通过。
这个提交包含在:
@@ -199,6 +199,14 @@ function defaultConfig() {
|
||||
loginCommand: 'login {password}',
|
||||
/** 注册指令模板,`{password}` 会被替换;留空则不发送 */
|
||||
registerCommand: '',
|
||||
/**
|
||||
* 账号绑定 / 二次验证指令模板(`{password}` 会被替换),留空则不发送。
|
||||
*
|
||||
* 用于「简幻通」这类外站账号体系:新账号必须先用 `/auth <UID> <验证码>` 或扫码绑定。
|
||||
* 扫码类验证无法自动完成,此时保持留空即可——程序会在日志里明确提示需要人工验证一次;
|
||||
* 若该服务器提供固定验证码,把 `auth {password}` 之类填进来就能自动过。
|
||||
*/
|
||||
authCommand: '',
|
||||
/**
|
||||
* 登录结果确认超时(毫秒)。
|
||||
* 部分离线服登录成功后不回明确提示,超时后按「已登录」放行,
|
||||
@@ -210,7 +218,14 @@ function defaultConfig() {
|
||||
/** 断线后是否自动重连 */
|
||||
autoReconnect: true,
|
||||
/** 重连间隔(毫秒) */
|
||||
reconnectDelayMs: 10000
|
||||
reconnectDelayMs: 10000,
|
||||
/**
|
||||
* 重连间隔上限(毫秒)。
|
||||
*
|
||||
* 连续重连失败(例如账号未完成服务器验证被反复踢出)时按指数退避拉长间隔,
|
||||
* 避免每 10 秒一次地硬撞服务器;成功进入世界后计数清零、间隔回到 reconnectDelayMs。
|
||||
*/
|
||||
reconnectMaxDelayMs: 120000
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -311,7 +326,9 @@ function validateConfig(config) {
|
||||
|
||||
config.server.commandCooldownMs = clampInt(config.server.commandCooldownMs, 0, 60000, 1200);
|
||||
config.server.reconnectDelayMs = clampInt(config.server.reconnectDelayMs, 1000, 600000, 10000);
|
||||
config.server.reconnectMaxDelayMs = clampInt(config.server.reconnectMaxDelayMs, config.server.reconnectDelayMs, 3600000, 120000);
|
||||
config.server.loginConfirmTimeoutMs = clampInt(config.server.loginConfirmTimeoutMs, 0, 300000, 10000);
|
||||
if (typeof config.server.authCommand !== 'string') config.server.authCommand = '';
|
||||
|
||||
if (config.waterMode !== WATER_MODE.SWIM && config.waterMode !== WATER_MODE.BOAT) {
|
||||
config.waterMode = WATER_MODE.AVOID;
|
||||
|
||||
在新工单中引用
屏蔽一个用户