Appearance
侦测方块
文档版本:基于 2026-06-01 代码分析
概述
侦测方块系统是逃走中MOD的一个子玩法:在地图中放置侦测方块,游戏开始后这些方块成为"监控点"。当存活的逃走者进入侦测方块的范围内时,该逃走者会被标记为"被侦测到",播放响铃警报暴露其位置。
系统包含完整的生命周期:方块注册 → 快照锁定 → 激活侦测 → 破坏(扩大范围)→ 警报联动。通过破坏侦测方块可动态扩大侦测范围(+3格/个)。
核心概念
范围计算公式
当前范围 = base_range + destroyedCount × 3base_range:基础侦测范围,通过/nfa rfm detect range <1-512>配置,默认 50 格destroyedCount:本局通过destroy指令破坏的侦测方块数量- 每破坏一个侦测方块,范围增加 3 格
距离计算:使用二维欧几里得距离(忽略 Y 轴):
distance² = (playerX - blockX-0.5)² + (playerZ - blockZ-0.5)²若 distance² <= range²,则玩家进入侦测范围。
架构设计
完整生命周期
mermaid
flowchart TD
A[方块放置] -->|"serverTick 每20tick"| B[registerPlacedBlock<br/>加入 registeredBlocks]
B --> C{指令: detect start}
C -->|"activateSnapshot()"| D[快照 registeredBlocks → activeBlocks<br/>enabled=true, destroyedCount=0]
D --> E["tick 每5tick 循环检测"]
E --> F{玩家在范围内?}
F -->|"是 且 首次进入"| G["startDetectAlarm()<br/>警报播放"]
F -->|否| H["stopDetectAlarm()<br/>停止警报"]
I[指令: detect destroy pos] -->|"destroyActiveBlock()"| J[从 activeBlocks 移除<br/>destroyedCount++<br/>范围+3]
K[指令: detect stop] -->|"deactivate()"| L[enabled=false<br/>清空activeBlocks<br/>reset destroyedCount]侦测与警报联动
mermaid
sequenceDiagram
participant Tick as RfmDetectBlockManager.tick()
participant Active as activeBlocks(快照方块)
participant Player as 在线逃走者
participant Alarm as RfmAlarmManager
Tick->>Active: 遍历所有活跃方块
Tick->>Player: 遍历所有存活参战逃走者
loop 检查每个玩家
Tick->>Tick: 计算二维距离² vs range²
alt 在范围内 且 不在报警集合中
Tick->>Alarm: startDetectAlarm(uuid)
Note over Alarm: 创建 detectManaged 任务<br/>永不超时,立即播放
else 在范围内 但已在报警
Tick->>Tick: 跳过(已在报警)
else 不在范围内 且在报警集合中
Tick->>Alarm: stopDetectAlarm(uuid)
end
end关键文件
| 文件 | 说明 |
|---|---|
com/chenxi/chenxi_rfm/common/block/DetectBlock.java | 侦测方块类 |
com/chenxi/chenxi_rfm/common/block/DetectBlockEntity.java | 方块实体(serverTick 注册) |
com/chenxi/chenxi_rfm/server/rfm/RfmDetectBlockManager.java | 侦测管理核心(tick/注册/快照/破坏) |
com/chenxi/chenxi_rfm/server/config/rfm/PersistentRfmDetectSavedData.java | 持久化存储 |
com/chenxi/chenxi_rfm/server/rfm/RfmAlarmManager.java | 警报联动(startDetectAlarm/stopDetectAlarm) |
com/chenxi/chenxi_rfm/server/config/rfm/RfmServerConfigStore.java | base_range 配置 |
com/chenxi/chenxi_rfm/server/command/rfm/RfmDetectCommand.java | /nfa rfm detect 入口 |
com/chenxi/chenxi_rfm/server/command/rfm/RfmDetectStartCommand.java | detect start |
com/chenxi/chenxi_rfm/server/command/rfm/RfmDetectStopCommand.java | detect stop |
com/chenxi/chenxi_rfm/server/command/rfm/RfmDetectRangeCommand.java | detect range |
com/chenxi/chenxi_rfm/server/command/rfm/RfmDetectStatusCommand.java | detect status |
com/chenxi/chenxi_rfm/server/command/rfm/RfmDetectDestroyCommand.java | detect destroy |
关键流程
方块注册
DetectBlockEntity.serverTick()每秒执行一次- 调用
RfmDetectBlockManager.registerPlacedBlock(level, pos) - 将位置(维度 + x/y/z)加入
PersistentRfmDetectSavedData.registeredBlocks - 同一位置重复注册无害(
LinkedHashSet.add幂等)
快照锁定(start)
/nfa rfm detect start 调用 activateSnapshot():
- 清空
activeBlocks - 将
registeredBlocks全部复制到activeBlocks destroyedCount = 0enabled = !activeBlocks.isEmpty()
关键:start 之后新放置的侦测方块不会自动加入快照(需要重新 start)。
破坏检测(destroy)
/nfa rfm detect destroy <pos>:
- 验证方块是
DetectBlock - 验证方块在
activeBlocks中 - 双重确认方块仍在原位
- 从
activeBlocks和registeredBlocks中移除 destroyedCount++- 世界中方块设为
Blocks.AIR - 若
activeBlocks变为空 →enabled=false, destroyedCount=0
自然破坏 vs 指令破坏
| 方式 | 触发 | destroyedCount | 范围增加 |
|---|---|---|---|
指令 destroy | 管理员执行 | +1 | +3格 |
| 自然挖掉 | onRemove() | 不变 | 不变 |
自然挖掉仅从 registeredBlocks 和 activeBlocks 移除,不计入破坏数。
数据持久化
PersistentRfmDetectSavedData
文件:<world>/data/nfa_rfm/rfm_detect.dat
| 字段 | 类型 | 说明 |
|---|---|---|
registeredBlocks | LinkedHashSet<DetectBlockRecord> | 所有已登记的侦测方块 |
activeBlocks | LinkedHashSet<DetectBlockRecord> | 快照(start时的副本) |
enabled | boolean | 是否启用 |
destroyedCount | int | 已破坏数量 |
DetectBlockRecord:(String dimension, int x, int y, int z) record。
注意事项 / 限制
- Y轴忽略:侦测范围为二维(XZ平面),Y轴高度不影响检测结果。
- 仅侦测存活的参战逃走者:被淘汰、弃权、叛节者不在侦测范围内。
- 警报不自动停止:侦测触发的警报(
detectManaged)永不超时(endAtMillis = Long.MAX_VALUE),仅当玩家离开范围时才停止。 - 快照在 start 时固定:start 之后新放置的方块不参与侦测,需重新 start。
- enabled=false 时清空报警:tick 中若
!enabled,会调用stopAlarmsForAllActivePlayers()。