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。

相关条目