来源: deepseek-v4-flash + Claude Code agentic 只读扫描(自动)
文件: server/src/identity/command.rs:324
级别: major
证据
handle_identity_command 用 now_tick = game_tick.map(|t| t.0 as u64).unwrap_or(0) 做冷却时钟,但 GameTick 每次启动在 movement.rs:460 insert_resource(GameTick::default()) 归零、逐 tick 自增,不持久化;而 last_switch_tick 持久化在 SQLite player_identities 表(persistence/identity.rs:86/142)。服务重启后新 tick 域从 0 起数,mod.rs:123 now_tick.saturating_sub(self.last_switch_tick) >= 24000 必须等新 GameTick 追到旧会话 L+24000 才成立——服务器在线越久锁死越久(在线 1 天→重启后 /identity new/switch 锁 ~1 天),属持久化冷却状态被 tick 域重置破坏。已 grep 确认 GameTick 无任何持久化、last_switch_tick 仅存 DB。
对抗验证: GameTick 是运行时资源,服务重启后再从 0 自增且不持久化;而 last_switch_tick 持久化于 DB。重启后 saturating_sub(now_tick, old_tick) 长时间为 0,必须等新 tick 数超过旧会话 tick 数加 24000 才解除冷却,在线越久锁越久,属真实跨重启缺陷。
重构清理时一并核实;修复或验伪后关闭。
来源: deepseek-v4-flash + Claude Code agentic 只读扫描(自动)
文件:
server/src/identity/command.rs:324级别: major
证据
handle_identity_command 用
now_tick = game_tick.map(|t| t.0 as u64).unwrap_or(0)做冷却时钟,但 GameTick 每次启动在 movement.rs:460insert_resource(GameTick::default())归零、逐 tick 自增,不持久化;而last_switch_tick持久化在 SQLite player_identities 表(persistence/identity.rs:86/142)。服务重启后新 tick 域从 0 起数,mod.rs:123now_tick.saturating_sub(self.last_switch_tick) >= 24000必须等新 GameTick 追到旧会话 L+24000 才成立——服务器在线越久锁死越久(在线 1 天→重启后/identity new/switch锁 ~1 天),属持久化冷却状态被 tick 域重置破坏。已 grep 确认 GameTick 无任何持久化、last_switch_tick 仅存 DB。对抗验证: GameTick 是运行时资源,服务重启后再从 0 自增且不持久化;而 last_switch_tick 持久化于 DB。重启后 saturating_sub(now_tick, old_tick) 长时间为 0,必须等新 tick 数超过旧会话 tick 数加 24000 才解除冷却,在线越久锁越久,属真实跨重启缺陷。
重构清理时一并核实;修复或验伪后关闭。