三脚架相机槽位

基本信息

属性 值
类型 特殊机制(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 是实例字段,因此换图/重连后所有机位必定消失。

相关条目