启动初始化
基本信息
| 属性 | 值 |
|---|---|
| 入口 | ClientProxy 构造器 + CommonProxy#performStartupChecks(postInit) |
| 延迟策略入口 | DrawScreenEventHandler#setInitialFullscreen |
| 延迟冷却常量 | Reference.DRAW_SCREEN_EVENT_COOLDOWN = 40 |
| 初始冷却 | 35(比阈值少 5 tick) |
| 延迟效果 | 载入后 5 tick(20 TPS 下 0.25 秒)才真正切全屏 |
第一步:构造器里先禁掉原版全屏
public ClientProxy() {
Minecraft mc = Minecraft.getMinecraft();
_startupRequestedSetting = mc.gameSettings.fullScreen;
mc.gameSettings.fullScreen = false;
}
@SidedProxy 会在 preInit 之前实例化客户端代理,所以原版全屏选项在
Minecraft 打开窗口之前就被清成 false,玩家原本的全屏偏好被记在
_startupRequestedSetting 里,稍后由本 mod 以"无边框"形式补上。
这样避免了"先真全屏启动、再切无边框"造成的 GL 上下文问题—— 源码注释称之为 “truly a hack”。
第二步:postInit 的三条分支
if (!config.isFullscreenWindowedEnabled()) {
Minecraft.getMinecraft().gameSettings.fullScreen = _startupRequestedSetting;
return;
}
总开关关掉时,把原版设置原样还原并退出——mod 此时完全不介入。
开启时再按 enableMaximumCompatibility(默认 true)二分:
兼容模式(默认):延迟到 GUI 绘制阶段
dsHandler.setInitialFullscreen(_startupRequestedSetting, config.getFullscreenMonitor());
只登记意图,不在此处改窗口。真正执行推迟到
全屏切换流程 的 toggleFullScreen。
源码说明这是与 OptiFine 等改 GL 的 mod 正确协作的方式。
非兼容模式:包住启动画面直接切
SplashProgress.pause();
toggleFullScreen(_startupRequestedSetting, config.getFullscreenMonitor());
SplashProgress.resume();
pause() / resume() 之间执行窗口变更。catch (NoClassDefFoundError e)
兜底 Forge 版本过老缺 SplashProgress 的情况:打一条
“are you using an old version of Forge?” 警告后再调一次 toggleFullScreen。
延迟的具体实现
DrawScreenEventHandler 订阅 GuiScreenEvent.DrawScreenEvent,
类注释说明这么做的原因是"想让全屏是全局的"。
setInitialFullscreen 把 _cooldown 设成 35:
_cooldown = 35;
_initialFullscreen = true;
_initialGoFullScreen = goFullScreen;
_initialDesiredMonitor = desiredMonitor;
每帧末尾 _cooldown < 40 就自增。首次进入处理函数时
_cooldown = 35 < 40,不满足 _cooldown >= Reference.DRAW_SCREEN_EVENT_COOLDOWN,
于是 5 帧后(0.25 秒)达到 40,才真正调用 toggleFullScreen。
冷却同时充当去抖
同一个 _cooldown 变量还兼任按键去抖:
else if (_cooldown >= 40 && _lastState != newState && newState)。
每次成功切换后立刻 _cooldown = 0,因此两次切换至少间隔 40 帧(2 秒)。
_lastState 在函数末尾无条件更新为 newState(DrawScreenEventHandler.java:78)。
| 字段 | 初值 | 作用 |
|---|---|---|
_lastState |
false |
上一次按住状态,用于取"按下沿" |
_initialFullscreen |
false |
待执行的延迟请求标志 |
_initialGoFullScreen |
false |
延迟请求的目标状态 |
_initialDesiredMonitor |
0 |
延迟请求的目标屏号 |
_cooldown |
40 |
冷却 / 去抖计数 |
_isProcessing |
false |
声明但从未被读取或赋值 |
_isProcessing 是死字段:全类只在声明处出现。
退出全屏时的例外路径
registerKeyBindings() 在把原版键位还回去时,如果当前处于全屏态,
不走 toggleFullScreen 而是直接 mc.toggleFullscreen()——
因为此时配置已关闭、handler 也不再接管,交给原版自己恢复更简单。
相关条目
- 全屏切换流程 - 延迟与去抖最终调用到这里
- 显示器选择与边界计算 - 延迟执行时用的屏号解析
- 全屏键位接管 - 关闭总开关时如何归还原版键
- 配置项 -
enableMaximumCompatibility的取舍说明