红警作战中心 · Red Alert Command Center
在 DeepSeek Harness 面板里打原版红警
复用本机 redalert-mac(红警作战中心.app)的游戏库与 Wine 运行时:
点「开始作战」,原版红警 2 / 尤里的复仇 / 共和国之辉 的游戏窗口会被自动摆进面板区域并置前,
原版画面、原版操作、原生帧率。

怎么做到"面板里玩原版"
浏览器本身不能嵌原生游戏窗口,所以插件用 macOS 辅助功能 API 做"窗口进位":
- Host 半边(
server/launcher.mjs)读取本机 redalert-mac 的游戏库,用 Wine 启动你已部署的原版 EXE (窗口模式、无边框,按面板大小设置渲染分辨率)。 - 面板里的
game-slot区域由浏览器测量出屏幕坐标,发给 Host。 - Host 用
AXUIElement把原版游戏窗口精确移动到该区域,再用 System Events 把游戏置前—— 于是你看到的就是"面板里在跑原版红警",鼠标键盘就是原版输入,没有视频串流、没有编码延迟。 - 面板尺寸变化 / 侧栏切换时自动重新对齐;点「切回游戏」重新置前;点「停止作战」把窗口移开并结束游戏。
游戏本体、原版 MIX 资源、Wine prefix 都在你自己的
~/Library/Application Support/RedAlertMac/里, 插件不含、也不下载任何游戏资源。

功能
- 作战档案:读取 redalert-mac 的真实档案(红警 2 / 尤里的复仇 / 共和国之辉),显示 EXE、 显示模式/分辨率、游玩时长、上次游玩、部署状态;运行环境(Wine 版本)、数据目录、启动器 App 状态一屏可见。
- 开始作战:自动准备 cnc-ddraw 兼容补丁 / ddraw.ini / 视频 INI / Wine prefix / 注册表, 启动原版游戏并嵌进面板;首次启动 5~20 秒(有 loading 提示)。
- 嵌入运行:工具栏「切回游戏 / 停止作战」,原版窗口按面板 slot 居中、16:9;窗口不抢系统光标时自动降级为 「点一下游戏画面即可操作」。
- 日志:每次启动写入
Logs/plugin-<档案id>.log,面板里可直接查看 tail;游戏退出后回写本局游玩时长到library.json(与原生启动器共享)。 - 未安装引导:没有启动器/游戏库/Wine 时给出三步引导与 Releases 链接,不会白屏。
- 中英双语、深/浅主题、左侧栏入口(order 50)。
环境要求
- macOS 13+(Apple Silicon + Rosetta),已安装 Xcode Command Line Tools(首次使用编译窗口定位 helper,
swiftc)。 - 已安装 红警作战中心.app,并至少部署过一个版本。
- 本机已有 Wine 运行时(redalert-mac 在「运行环境」里安装的
Wine 11.21)。 - 系统权限(首次用到会提示):
- 辅助功能(Accessibility):移动游戏窗口、把窗口置前;
- 自动化(System Events):把 Wine 游戏进程切到前台。
- 你拥有可合法使用的原版游戏文件(插件不提供)。
安装
plugin_manager install_bundle target=<本仓库绝对路径>
装好后刷新页面(⌘R);若点「开始作战」报 "embed 接口 404 / 找不到窗口",说明 Host 侧模块还是旧版本: 退出并重新打开 DeepSeek Harness(会话会自动恢复),再点侧栏红星即可。
使用
- 左侧栏点「红警作战中心」→ 默认进入作战档案页,能看到你本机的三个游戏档案。
- 点目标档案的「开始作战」→ loading(首次 5~20 秒)→ 原版游戏窗口出现在面板里,直接开打。
- 点侧栏/聊天区会切回 DSH,游戏继续在后台运行;回到面板点「切回游戏」即可继续。
- 点「停止作战」结束游戏并回到档案页。
结构
dsh-redalert/
├─ package.json # bundle 清单 + dsh.client(web / immediately / inject layout+sidebar)
├─ cordis.patch.yml # insert 一行插件条目(id: redalert)
├─ index.js # Host 半边:launcher / launch / stop / log / open / embed 路由
├─ server/
│ ├─ launcher.mjs # 游戏库、Wine 环境、显示配置补丁、启动/停止、窗口发现、窗口嵌入(AX)
│ └─ capture/racapture.swift # 窗口定位(辅助功能) + 输入回传 helper(首次使用时编译到 .build/)
├─ client.js # 构建产物(tools/build.mjs 拼 src/*.js)
├─ src/
│ ├─ 70-styles.js # 通用主题/基础样式(ra- 前缀)
│ ├─ 80-ui.js # 图标(红星徽 PanelIcon)与通用组件
│ ├─ 85-launcher.js # 作战档案 / 环境条 / 日志 / 未安装引导
│ ├─ 87-viewer.js # 面板内嵌入(测量 slot、RA.Embed、RootPage 切换)
│ ├─ 90-apply.js # slot 注册、locale、样式、RootPage 装配
│ └─ 00-core.js 10-defs.js 20-sim.js 30-art.js 40-render.js 50-audio.js 60-engine.js
│ # 早期网页复刻引擎(保留代码,未接入界面)
├─ locale/{zh,en}.json # 插件管理页标题与描述
├─ assets/icon.svg # 原创图标(红星徽)
├─ docs/CONTRACT.md # 开发契约
├─ tools/build.mjs # 构建 client.js
└─ selftest/ # headless Chrome 离线验收(mock Host,不启动真实游戏)
开发与自测
NODE="/Applications/DeepSeek Harness.app/Contents/Resources/runtime/primary-runtime/dependencies/node/bin/node"
"$NODE" tools/build.mjs # 生成 client.js
"$NODE" --check client.js # 语法检查
cd selftest && "$NODE" run.mjs # headless Chrome 验收(mock 启动器/嵌入 API)
真实链路自测(会真的启动原版游戏并把窗口嵌到指定矩形,结束时自动关闭):
"$NODE" -e "import('./server/launcher.mjs').then(async m=>{
const v = await m.launcherView(); console.log(v.profiles.map(p=>p.name));
await m.startEmbed(v.profiles[0].id, {x:200,y:120,w:1200,h:800});
await new Promise(r=>setTimeout(r,2000));
console.log(await m.setEmbedRect({x:200,y:120,w:1200,h:800}, true));
await new Promise(r=>setTimeout(r,3000));
await m.stopEmbed();
})"
已知边界
- 原版窗口会改写该档案的
ddraw.ini与视频 INI(备份在游戏目录.redalert-backup/), 以无边框、面板尺寸的窗口模式运行;部署/导入/其他分辨率设置仍在原生启动器 App 里做。 - 游戏窗口是独立原生窗口,只是被精确摆到面板区域并置前;它不是浏览器 DOM 的一部分 (macOS 不允许网页嵌入原生窗口)。DSH 窗口位置/尺寸变化时插件会自动重新对齐。
- 首次使用需要给 Harness 辅助功能 + 自动化权限;没给时「开始作战」会报错并提示去系统设置授权。
- 只启动你本机已部署的游戏;插件不提供游戏文件、不联网下载。
License
原创客户端代码采用 MIT License,见 LICENSE。 原创性/第三方声明见 NOTICE.md。
Command & Conquer、Red Alert 相关名称与设定版权归 EA 及其权利人所有; 本项目与 EA 无关,也不分发任何原版游戏资源——插件只是启动并嵌入你自己已拥有的游戏。
No comments yet. Be the first to write one.