FpsReducer(降帧)
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.gtnewhorizons.angelica.rendering.FpsReducer |
| 路径 | src/main/java/com/gtnewhorizons/angelica/rendering/FpsReducer.java |
| 行数 | 186 |
| mixin | early/angelica/fpsreducer/ 4 个 |
| 初始化 | ClientProxy.java:189 FpsReducer.init() —— 无条件调用 |
FpsReducer 是 ClientProxy.init 中少数几个不受配置开关直接控制的功能(对比 Zoom 受 enableZoom、Iris 受 enableIris 门控)。它自身在 evaluateFrame() 里读 s.enabled 决定是否生效。
状态机
核心是一个独立的状态机对象:
// :28
private static final ReducerStateMachine MACHINE = new ReducerStateMachine(System::nanoTime);
以 System::nanoTime 为时钟源。状态经 MACHINE.state() 读取,可见的状态至少包括 State.MINIMIZED(:108)。
配置来源:不是 AngelicaConfig
FpsReducer 的配置不走 gtnhlib @Config,而是读 Sodium 的配置对象:
// :53-54
final SodiumGameOptions.ReducerSettings s = ClientProxy.options().reducer;
ClientProxy.options()(ClientProxy.java:114-119)懒加载 SodiumGameOptions.load(ConfigMigrator.handleConfigMigration("angelica-options.json")),即配置文件 angelica-options.json。
ReducerSettings 上用到的字段:
| 字段 | 用途 | 行 |
|---|---|---|
enabled |
总开关 | :54、:57 |
idleTimeoutMinutes |
空闲判定超时(分钟),计算时 × 60_000_000_000L 转纳秒 |
:57 |
unfocusedFpsLimit |
失焦时的 FPS 上限 | :104 |
idleFpsLimit |
空闲时的 FPS 上限 | :104 |
limitMenuFrameRate |
菜单内是否限制帧率 | :106 |
idleTimeoutMinutes × 60_000_000_000L 是分钟转纳秒的正确写法(1 分钟 = 6×10¹⁰ 纳秒)。
三层封顶
effectiveCap(userLimit, inMenu)(:99-107)是核心合并逻辑:
if (benchmarkActive) {
return ReducerStateMachine.benchmarkCap(SystemProperties.FLYBY_PACING, userLimit);
}
final SodiumGameOptions.ReducerSettings s = ClientProxy.options().reducer;
final int stateCap = ReducerStateMachine.stateCap(MACHINE.state(), s.unfocusedFpsLimit, s.idleFpsLimit);
return ReducerStateMachine.mergeCap(userLimit, stateCap, inMenu, s.limitMenuFrameRate);
| 层 | 函数 | 说明 |
|---|---|---|
| 1 | benchmarkCap(FLYBY_PACING, userLimit) |
Flyby 录影基准测试期间的特殊封顶;FLYBY_PACING 来自系统属性 -Dangelica.flyby.pacing |
| 2 | stateCap(state, unfocusedFpsLimit, idleFpsLimit) |
按状态机当前状态取对应上限 |
| 3 | mergeCap(userLimit, stateCap, inMenu, limitMenuFrameRate) |
与用户设定合并,菜单内按开关处理 |
完全跳过渲染
skipRender()(:108-110):
return MACHINE.state() == State.MINIMIZED;
最小化状态下整帧跳过渲染(不只是限帧)。
onRenderSkipped()(:112-123)负责补偿副作用:
| 行 | 逻辑 |
|---|---|
:113-117 |
窗口重新获得焦点则刷新 lastActiveMillis 并返回 |
:118 |
世界未加载、已开界面、或 pauseOnLostFocus 为 false 时返回 |
:119 |
触摸屏设备且右键按住时返回(触屏下右键等同点击) |
:120-122 |
失焦超过 500 ms 则 mc.displayInGameMenu() |
音量联动
降帧时同时压低音量,appliedVolumePercent(:35)与 volumePercent(:40,volatile)记录当前百分比,初值均为 100。
scaleVolume(user)(:125-127)→ ReducerStateMachine.masterVolume(user, volumePercent);applyVolume(percent)(:129-135)通过 mc.getSoundHandler().setSoundLevel(SoundCategory.MASTER, ...) 写入。
按键
2 个按键,在 init() 内创建(不是静态字段):
| 按键 | 语言键 | 行 |
|---|---|---|
forceKey |
angelica.keybind.fps_reducer_force |
:45(创建)、:47(注册) |
disableKey |
angelica.keybind.fps_reducer_disable |
:46、:48 |
默认键码均为 0(未绑定),分类 key.categories.angelica。
相关条目
- Zoom - 另一个受配置开关门控的输入类功能
- KeyBinding 注册总表 - 2 个 FpsReducer 按键
- Proxy -
options()与init()调用点 - SystemProperties -
angelica.flyby.pacing - Angelica mixin 分组 - 4 个
fpsreducermixin - Sodium(内嵌库) -
SodiumGameOptions.ReducerSettings的定义方