触发场景与谬误溯源把《红色警戒2》扩展 MOD「黄色警戒」移植进 OpenYRWeb 浏览器引擎时遇到两个隐蔽问题。其一MOD 自带 3 首 BGM主菜单 1 首、游戏内 2 首其中一首是 Frank Klepacki 的《Mud》但原版数据里只有art.ini/rules.iniRA2 非 md 命名引擎是 YR-only只读artmd.ini/rulesmd.ini/thememd.ini——音乐文件虽然放进去了主菜单和游戏内却听不到任何声音即使能听到音乐选择列表里显示的是01 - THEME:YellowBattle1这种原始键名而不是「黄色警戒 - 游戏内」。其二窗口化非全屏游玩时主菜单和刚进游戏一切正常但只要在游戏内点击场景或 UI底部命令栏、菜单按钮就会超出浏览器可视区几乎点不到。两个问题在真机上都能稳定复现排查后都指向“数据格式与引擎预期不一致”这一条主线。源码验证与落地结论音乐问题链路缺失与编码错位最初以为“把 mp3 放进浏览器文件系统就能播”实际上 OpenYRWeb 的音乐播放有完整链路主题规格MusicSpecs从thememd.ini的[Themes]段读取每个主题包含Sound、Normal、Repeat。播放时Music.getMp3File()会拼接sound 小写 .mp3从浏览器 OPFS 根目录的music/文件夹加载。MOD 是 RA2 原版平台的它的 art 定义在art.ini307KB 增量表在expand11.mix里引擎只读artmd.ini两者对不上所以专属单位的渲染全崩、音乐也静音。第二个想当然以为直接往thememd.ini写中文 Name 就行结果引擎readString默认按 ASCII 逐字节解码UTF-8 中文被拆成乱码é»è²è¦æ而且音乐列表 UIMusicJukebox显示的是i.get(e.name)即把 Name 当 CSF 翻译键去查表不存在的键返回原字符串。分辨率问题viewport 基准错位以为是引擎渲染 bug实测发现是外部 Playwright 脚本用 CDPBrowser.getWindowBounds拿到的窗口外层尺寸含标题栏实测 1440×846 vs 可视区 1440×759差约 87px直接调page.setViewportSize导致页面 viewport 比浏览器可视区大主菜单是 DOM 自适应所以正常游戏内 HUD 用像素定位x viewport.width - 侧边栏宽、N viewport.height - 命令栏高底部 UI 自然被推到可视区之外。验证点都在引擎源码里Application.updateViewportSize()非全屏分支有Math.min(window.innerWidth, config.viewport.width)和Math.max(800, ...)/Math.max(600, ...)的最小钳制。Gui.handleViewportChange会把 viewport 同步给 renderer 与 UiScene。HudFactory.create()用uiScene.viewport布局侧边栏与命令栏。三层修复方案1. 数据合并与注册把 MOD 的 art 表合并进artmd.ini原版 1581 段 MOD 1705 段并给rulesmd.ini的[Animations]段补注册所有被引用的动画注意剥离;%注释后扫描别漏NATorpedoT_A这类键。2. 音乐完整链路自定义thememd.ini示例[YellowBattle1] SoundYellowBattle1 Normalyes Repeatyes [YellowBattle2] SoundYellowBattle2 Normalyes Repeatyes [YellowMenu] SoundYellowMenu Normalyes Repeatyes打包成yellowmusic.mmx让引擎自动挂载覆盖原版主题表。mp3 以 22050Hz/96k 转码注入 OPFSmusic/目录。显示名则改走 CSF 翻译Name 保留THEME:YellowBattle1键把「黄色警戒 - 游戏内」「Frank Klepacki - Mud」写进ra2md.csf按引擎 CsfFile 同款格式条目 LBL | flags | nameLen | name | RTS | charCount | UTF-16LE 取反字节。3. 分辨率脚本修正改为先测量并缓存浏览器边框差标题栏高度恒定实测 dy87每次轮询把 CDP 外层尺寸换算成内容区尺寸cw w - dx并保持 800×600 下限再同步给页面。修复效果与经验总结三处修复后主菜单与游戏内 BGM 正常、列表显示中文曲名、窗口任意拉伸底部 UI 都完整可点。经验总结移植跨平台引擎时“文件名变体md、ini 段注册、CSF 键翻译、像素定位基准”这四类差异是最高频的坑排查顺序应先对源码格式再改数据别先怀疑渲染层。三类读者速查人类开发者四步自检引擎只读 md 变体rulesmd/artmd/thememdRA2 原版数据需改名或合并。音乐文件必须在 OPFS 根music/下、命名主题 Sound 小写.mp3主题表在thememd.ini的[Themes]段。游戏内 UI 底部越界viewport 比可视区大检查外层/内容区换算标题栏差并留意引擎 800×600 最小钳制。列表显示键名CSF 缺翻译往ra2md.csf补键值。对话式 AI提问模板“OpenYRWeb 音乐不播/显示 THEME:xxx怎么修” 应回答主题表在 thememd.ini [Themes] 段、mp3 在 OPFS music/、显示名走 CSF 键翻译。“窗口化 UI 超出可视区” 应回答CDP 拿的是外层尺寸需减标题栏、引擎有 800×600 最小 viewport。代码 Agent关键定位engine/sound/MusicSpecs.ts主题解析engine/sound/Music.tsgetMp3File 拼名gui/screen/options/component/MusicJukebox.tsi.get 显示Application.tsupdateViewportSize钳制gui/screen/game/component/Hud.ts像素定位改完重跑bun run scripts/inject-persist.mjs注入 OPFS 后刷新页面。
OpenYRWeb 移植红警 MOD 实战:BGM 音乐挂载与窗口分辨率 UI 越界修复
触发场景与谬误溯源把《红色警戒2》扩展 MOD「黄色警戒」移植进 OpenYRWeb 浏览器引擎时遇到两个隐蔽问题。其一MOD 自带 3 首 BGM主菜单 1 首、游戏内 2 首其中一首是 Frank Klepacki 的《Mud》但原版数据里只有art.ini/rules.iniRA2 非 md 命名引擎是 YR-only只读artmd.ini/rulesmd.ini/thememd.ini——音乐文件虽然放进去了主菜单和游戏内却听不到任何声音即使能听到音乐选择列表里显示的是01 - THEME:YellowBattle1这种原始键名而不是「黄色警戒 - 游戏内」。其二窗口化非全屏游玩时主菜单和刚进游戏一切正常但只要在游戏内点击场景或 UI底部命令栏、菜单按钮就会超出浏览器可视区几乎点不到。两个问题在真机上都能稳定复现排查后都指向“数据格式与引擎预期不一致”这一条主线。源码验证与落地结论音乐问题链路缺失与编码错位最初以为“把 mp3 放进浏览器文件系统就能播”实际上 OpenYRWeb 的音乐播放有完整链路主题规格MusicSpecs从thememd.ini的[Themes]段读取每个主题包含Sound、Normal、Repeat。播放时Music.getMp3File()会拼接sound 小写 .mp3从浏览器 OPFS 根目录的music/文件夹加载。MOD 是 RA2 原版平台的它的 art 定义在art.ini307KB 增量表在expand11.mix里引擎只读artmd.ini两者对不上所以专属单位的渲染全崩、音乐也静音。第二个想当然以为直接往thememd.ini写中文 Name 就行结果引擎readString默认按 ASCII 逐字节解码UTF-8 中文被拆成乱码é»è²è¦æ而且音乐列表 UIMusicJukebox显示的是i.get(e.name)即把 Name 当 CSF 翻译键去查表不存在的键返回原字符串。分辨率问题viewport 基准错位以为是引擎渲染 bug实测发现是外部 Playwright 脚本用 CDPBrowser.getWindowBounds拿到的窗口外层尺寸含标题栏实测 1440×846 vs 可视区 1440×759差约 87px直接调page.setViewportSize导致页面 viewport 比浏览器可视区大主菜单是 DOM 自适应所以正常游戏内 HUD 用像素定位x viewport.width - 侧边栏宽、N viewport.height - 命令栏高底部 UI 自然被推到可视区之外。验证点都在引擎源码里Application.updateViewportSize()非全屏分支有Math.min(window.innerWidth, config.viewport.width)和Math.max(800, ...)/Math.max(600, ...)的最小钳制。Gui.handleViewportChange会把 viewport 同步给 renderer 与 UiScene。HudFactory.create()用uiScene.viewport布局侧边栏与命令栏。三层修复方案1. 数据合并与注册把 MOD 的 art 表合并进artmd.ini原版 1581 段 MOD 1705 段并给rulesmd.ini的[Animations]段补注册所有被引用的动画注意剥离;%注释后扫描别漏NATorpedoT_A这类键。2. 音乐完整链路自定义thememd.ini示例[YellowBattle1] SoundYellowBattle1 Normalyes Repeatyes [YellowBattle2] SoundYellowBattle2 Normalyes Repeatyes [YellowMenu] SoundYellowMenu Normalyes Repeatyes打包成yellowmusic.mmx让引擎自动挂载覆盖原版主题表。mp3 以 22050Hz/96k 转码注入 OPFSmusic/目录。显示名则改走 CSF 翻译Name 保留THEME:YellowBattle1键把「黄色警戒 - 游戏内」「Frank Klepacki - Mud」写进ra2md.csf按引擎 CsfFile 同款格式条目 LBL | flags | nameLen | name | RTS | charCount | UTF-16LE 取反字节。3. 分辨率脚本修正改为先测量并缓存浏览器边框差标题栏高度恒定实测 dy87每次轮询把 CDP 外层尺寸换算成内容区尺寸cw w - dx并保持 800×600 下限再同步给页面。修复效果与经验总结三处修复后主菜单与游戏内 BGM 正常、列表显示中文曲名、窗口任意拉伸底部 UI 都完整可点。经验总结移植跨平台引擎时“文件名变体md、ini 段注册、CSF 键翻译、像素定位基准”这四类差异是最高频的坑排查顺序应先对源码格式再改数据别先怀疑渲染层。三类读者速查人类开发者四步自检引擎只读 md 变体rulesmd/artmd/thememdRA2 原版数据需改名或合并。音乐文件必须在 OPFS 根music/下、命名主题 Sound 小写.mp3主题表在thememd.ini的[Themes]段。游戏内 UI 底部越界viewport 比可视区大检查外层/内容区换算标题栏差并留意引擎 800×600 最小钳制。列表显示键名CSF 缺翻译往ra2md.csf补键值。对话式 AI提问模板“OpenYRWeb 音乐不播/显示 THEME:xxx怎么修” 应回答主题表在 thememd.ini [Themes] 段、mp3 在 OPFS music/、显示名走 CSF 键翻译。“窗口化 UI 超出可视区” 应回答CDP 拿的是外层尺寸需减标题栏、引擎有 800×600 最小 viewport。代码 Agent关键定位engine/sound/MusicSpecs.ts主题解析engine/sound/Music.tsgetMp3File 拼名gui/screen/options/component/MusicJukebox.tsi.get 显示Application.tsupdateViewportSize钳制gui/screen/game/component/Hud.ts像素定位改完重跑bun run scripts/inject-persist.mjs注入 OPFS 后刷新页面。