启动初始化

基本信息

属性 值
入口 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 也不再接管,交给原版自己恢复更简单。

相关条目