三脚架相机槽位
基本信息
| 属性 | 值 |
|---|---|
| 类型 | 特殊机制(9 个可长期驻留的机位) |
| 枚举 | com.caedis.freecam.camera.tripod.TripodSlot(NONE + ONE…NINE) |
| 容器 | com.caedis.freecam.camera.tripod.TripodRegistry(EnumMap<TripodSlot, CameraEntity>) |
| 数量 | MIN = 1,MAX = values().length - 1 = 9 |
| 选位按键 | 按住 切换自由相机(F4)时按数字键 1~9 |
| 起源 | 源码注释标注改编自 hashalite/Freecam 的 TripodSlot |
选键到槽位的映射
TripodSlot.ofKeyCode(int keyCode)(TripodSlot.java:39):
int number = keyCode - Keyboard.KEY_1 + 1;
return inRange(number) ? values()[number] : TripodSlot.NONE;
即直接把 lwjgl 的 KEY_1…KEY_9 线性映射到 values()[1]…values()[9](values()[0] 是 NONE),
落在范围外一律返回 NONE。
在 ClientEventHandler.onKeyInput 中,slot.ordinal() - 1 再被用作
gameSettings.keyBindsHotbar[] 的下标,把同一次按键同时用于选中机位与清空原版物品栏切换。
| 槽位 | 数字键 | 原版物品栏下标 | HUD 显示 |
|---|---|---|---|
NONE |
— | — | None |
ONE |
1 |
0 | #1 |
TWO |
2 |
1 | #2 |
THREE |
3 |
2 | #3 |
FOUR |
4 |
3 | #4 |
FIVE |
5 |
4 | #5 |
SIX |
6 |
5 | #6 |
SEVEN |
7 |
6 | #7 |
EIGHT |
8 |
7 | #8 |
NINE |
9 |
8 | #9 |
toString() 被覆写:NONE 返回 "None",其余返回 String.format("#%d", ordinal())。
valueOf(int number) 带范围检查,非法值抛 IndexOutOfBoundsException 并在消息里带上允许区间;
inRange(int) 是配套的公开判定方法。
槽位生命周期
TripodRegistry(TripodRegistry.java)只有两个方法:
| 方法 | 行为 |
|---|---|
getOrCreate(slot) |
命中则复用;未命中则以当前玩家位置与朝向新建 脱离实体,下发 setCollisionMode(GeneralConfig.collisionMode) 后存入 EnumMap |
clear() |
cameras.clear(),丢弃全部机位 |
调用点分布在 自由相机状态机 的三处:
enableTripod(slot)—— 未激活时开启某机位;switchTripod(slot)—— 已激活时换到另一机位;resetTripods()—— 供 重置相机 调用。
三种进入路径的差异
toggleTripod(TripodSlot slot)(FreecamController.java:82)先查 已被禁用,
被禁用时只输出 msg.freecam.disable 并返回。随后分支:
| 情形 | 动作 | 说明 |
|---|---|---|
已激活 且 activeSlot == slot |
disable() + 输出 msg.freecam.tripod.close |
相当于"收起这个机位" |
已激活,activeSlot != slot |
switchTripod(slot) |
换机位,速度归零,HUD 输出 open |
| 未激活 | enableTripod(slot) |
启用该机位,HUD 输出 open |
enable() 与 enableTripod() 的实质差别
这是本系统最容易被忽略的一点,两者不等价:
| 字段 | enable()(普通自由相机) |
enableTripod(slot)(三脚架) |
|---|---|---|
| 相机来源 | 每次 new CameraEntity(...),用完丢弃 |
tripodRegistry.getOrCreate(slot),长期保留 |
| 强制第三人称 | 无条件 thirdPersonView = 0 |
仅当 previousPerspective == -1 时才置 0 |
applyPerspectiveOffset() |
调用 | 不调用 |
activeSlot |
TripodSlot.NONE |
slot |
因此 进入视角 的偏移只对普通自由相机生效,选三脚架机位时会被跳过; 而"强制第一人称"在已处于 freecam 中途切换机位时会被跳过,避免把已经归零的视角状态二次改写。
清空
resetTripods()(FreecamController.java:230)调用 tripodRegistry.clear() 并输出 msg.freecam.tripod.reset。
它不会关闭当前正在使用的机位——被清掉的 CameraEntity 引用仍由 FreecamController.cameraEntity 持有,
只是下次再选该槽位时会重新创建一个。真正的原因是 FreecamController.reset()(连上服务器时调用)
换掉了整个单例,TripodRegistry 是实例字段,因此换图/重连后所有机位必定消失。