Skip to content

About

《苏沫:爸妈不在家》v1.0.11 外置修改器(RPG Maker MV / NW.js)|桥接器架构 · 自动检测 · 单文件 exe;README 说明移植到其他 MV 游戏需改的 3 处

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SUMU Trainer

RPG Maker MV / NW.js 游戏的外置修改器框架 —— 桥接器架构 · 自动检测 · 单文件 exe

面向本地单人游戏的存档/状态修改工具。本仓库只包含工具代码,不含任何游戏本体、素材或存档。

preview

当前针对的游戏

项 内容
游戏 《苏沫:爸妈不在家》v1.0.11
引擎 RPG Maker MV + NW.js(Game.exe + www/)
系统插件 作者自写的 8BOX_* 系列:8BOX_bondage.js(拘束)、8BOX_endurance.js(耐力)、8BOX_quickButton.js(界面)
数据结构 $gameSystem.BOX_data_BD(穿着/钥匙/力量)、$gameSystem.BOX_data_EP(耐力)
规模 135 件拘束防具、18 把钥匙武器、4 种解除方式(解缚/挣脱/剪开/强制)
定制 API BOX_Force / BOX_putOnEquip / BOX_takeOff / BOX_changeEquip / BOX_canRelive / BOX_takeOffAll / BOX_DeclineEP

通用部分(约 80% 代码):进程检测、磁盘扫描、HTTP 服务、同源界面、自动安装/卸载桥接器、独立窗口、心跳退出 —— 与游戏无关,任何 MV 游戏都能直接复用。

游戏相关部分(约 20% 代码):特征插件名、界面里发给 /eval 的业务表达式、快捷变量 ID。见下一节。

为什么值得看

RPG Maker MV 的定制系统(拘束、状态、任务、好感度……)全部是明文 JavaScript 插件,逻辑就在 www/js/plugins/*.js 里。但这类游戏用 NW.js 打包后:

--remote-debugging-port=9222   → 不监听
--inspect=9229                 → 不监听
package.json chromium-args     → 被忽略
游戏进程的监听端口             → 一个都没有

也就是说 CDP / 远程调试 / 内存外挂都走不通。本项目用另一种结构解决:

┌──────────────────────┐   HTTP    ┌────────────────────────────┐
│ 外置修改器 (exe)      │ ────────▶ │ 游戏内桥接器 (30 行, 无界面) │
│ 127.0.0.1:8799        │           │ 127.0.0.1:8790             │
│ · 内置 HTTP 服务      │           │ · GET /status              │
│ · 界面同源,无 CORS   │ ◀──────── │ · GET /eval?js=<表达式>     │
│ · 自动检测/自动安装   │           │ · require('http')          │
└──────────────────────┘           └────────────────────────────┘
  • 修改器本体完全外置:独立进程、独立窗口、关窗即退出
  • 游戏内只有一个不可见文件:不渲染任何 UI,只开一个本机端口转发 eval
  • 自动检测游戏状态:枚举进程 → 取 exe 路径 → 确认是 MV 工程;找不到再扫盘
  • 自动安装桥接器:首次运行自动写入 www/js/plugins/,并备份 plugins.js

功能

模块 能力
数值 金钱 / 耐力 / 全部命名变量 / 全部开关,读取与写入
道具 物品 · 武器 · 防具,按名称或 ID 搜索,批量增减
系统 当前装备列表(含锁定状态)、四种解除方式实时判定、批量解除、穿戴并锁定、钥匙取回

「四种解除方式」是按目标游戏插件的实现映射的:解缚 / 挣脱 / 剪开 / 强制,对应 canRelive(mode) 返回的可解列表,界面实时显示每种方式的可用件数。

用法

  1. 下载 Release 里的 SumuTrainer.exe(约 7.5 MB,单文件免安装)
  2. 双击运行 —— 弹出独立窗口(Edge/Chrome 的 --app 模式,无地址栏)
  3. 打开游戏;程序每 2 秒检测一次,连上后绿点亮起
  4. 关窗即退出(心跳 20 秒无响应自动结束进程)

换电脑也不用配置:程序自己找游戏、自己装桥接器,装完提示重启游戏。

工作原理(关键设计)

  1. 同源 —— 界面和 API 都由程序自己的 127.0.0.1:8799 提供,页面只写相对路径 /api/...。这避免了 file:// 页面直连本地端口时被 CORS/权限拦掉(换台机器就"检测不到进程"的经典原因)。
  2. 服务端转发 —— /api/eval 由 Python 侧转发到桥接器,转发时用 ProxyHandler({}) 明确禁用系统代理(否则 127.0.0.1 可能被本地代理劫持)。
  3. 检测三级 —— 运行中的 Game.exe → QueryFullProcessImageNameW 取路径 → 同级存在 www/js/plugins.js;失败再扫盘(深度 2,按特征插件名匹配)。
  4. 幂等安装 —— 写桥接器前先查 plugins.js 是否已注册;备份只在首次创建。
  5. 失败可诊断 —— 未连接时界面展开四行状态:游戏进程 / 游戏目录 / 桥接器文件 / 注册项,一眼分清"没找到游戏"还是"桥接器没装"。

从源码构建

# 1) 构建环境(uv 可选,普通 venv 也行)
uv venv build_venv --python 3.12
uv pip install --python build_venv\Scripts\python.exe pyinstaller

# 2) 打包
build_venv\Scripts\pyinstaller.exe --noconfirm --onefile --noconsole `
  --name SumuTrainer --distpath dist src\sumu_trainer_app.py

体积约 7.5 MB(Python 3.12 + PyInstaller 6.x)。

调试时可设环境变量 SUMU_NO_WINDOW=1,只起服务不开窗口,方便用 curl 验证接口。

接口

GET /api/status                 → {running, exe, game_dir, bridge_installed,
                                   bridge_registered, connected, ready, scene}
GET /api/eval?js=<expr>         → {ok, value} | {ok:false, error}
GET /api/scan                   → 扫描磁盘找游戏目录
GET /api/install                → 安装/修复桥接器
GET /api/uninstall              → 还原 plugins.js 并删除桥接器
GET /api/launch                 → 启动游戏
GET /api/quit                   → 退出程序

桥接器侧:

GET /status                     → {ok, ready, scene, bridge}
GET /eval?js=<expr>             → {ok, value} | {ok:false, error}

卸载

/api/uninstall 或手动:

  1. www/js/plugins.js.bak_trainer 覆盖回 www/js/plugins.js
  2. 删除 www/js/plugins/<PREFIX>_Bridge.js

移植到其他游戏要改哪些

桥接器、HTTP 服务、窗口、检测逻辑都不用动,只有 3 处要改,全部在 src/sumu_trainer_app.py 里:

1. 游戏识别(2 个常量)

# ① 扫盘时用来确认"这是目标游戏"的特征插件(最稳的识别物,比游戏名可靠)
def find_game_by_disk(...):
    def check(d):
        return os.path.isfile(os.path.join(d, "www", "js", "plugins", "8BOX_bondage.js"))
        #                                                                ^ 换成目标游戏的定制插件文件名

# ② 进程白名单(一般不用动,MV 打包基本都是 Game.exe;NW.js 原生是 nw.exe)
if low not in ("game.exe", "nw.exe", "苏沫.exe"):

若目标游戏没有明显的定制插件,可改成检查 www/js/plugins.js 里是否出现某个作者前缀(如 PKD_、YEP_)。

2. 桥接器自身标识(3 个常量)

APP_TITLE   = "苏沫:爸妈不在家 · 修改器"   # 窗口标题
BRIDGE_NAME = "SUMU_Bridge"                 # 插件文件名 / plugins.js 注册名(换游戏就换前缀,避免串味)
BRIDGE_PORT = 8790                          # 本机端口,冲突时换(前端不用改,走 /api 转发)

3. 业务表达式(界面三个页签里发给 /eval 的字符串)

这是唯一需要读懂目标游戏插件的地方。当前实现对应的映射:

界面上做的事 现在的表达式 通用 MV 写法
读金钱 / 改金钱 $gameParty.gold() / $gameParty.gainGold(n) MV 原生,任何游戏都不用改
读变量 / 写变量 $gameVariables.value(id) / .setValue(id, v) 原生,不用改
开关 $gameSwitches.value(id) / .setValue(id, v) 原生,不用改
刷道具 $gameParty.gainItem($dataItems[i], n) / loseItem 原生,不用改(武器/防具同理换 $dataWeapons / $dataArmors)
耐力 $gameSystem.BOX_data_EP.now / .max 换成目标游戏的对应数值(没这个系统就删掉这一行)
力量 $gameSystem.BOX_data_BD.selfPower / .otherPower 同上
穿着列表 $gameSystem.BOX_data_BD.playerEquip 换成目标系统的装备/状态容器
穿戴 / 上锁 / 开锁 BOX_Force(id) / BOX_changeEquip(1,id) / (2,id) 换成目标插件的公开函数
四种解除 BOX_canRelive(mode) → BOX_takeOff(id) 同上;mode 是目标插件的枚举
批量脱缚 BOX_takeOffAll(mode) 同上
快捷变量按钮 [[15,'服从度'],[16,'欠债'],[13,'任务等级'],…] 换成目标游戏 $dataSystem.variables 里真实存在的 ID

找这些函数的办法:grep -nE "prototype\.[A-Za-z_]+ *=|^function [A-Za-z_]+" www/js/plugins/<定制插件>.js, 读插件头的 @plugindesc / @help,再从游戏事件调用的地方反查参数。

移植后自检清单

SUMU_NO_WINDOW=1 python src/sumu_trainer_app.py      # 只起服务
curl "http://127.0.0.1:8799/api/status"              # running/game_dir/bridge_installed/connected 四项都要 true
curl "http://127.0.0.1:8799/api/eval?js=%24gameParty.gold%28%29"   # 读一个原生值
curl "http://127.0.0.1:8790/eval?js=<你的系统函数调用>"            # 直连桥接器,确认真调到了

四项全绿再动界面;UI 改动只影响显示,不影响通路。

免责声明

  • 仅限本地单人游戏的离线修改,不涉及联机、不绕过付费、不分发游戏本体
  • 不含任何游戏素材;截图仅为工具界面
  • 使用造成的存档变化由使用者自行负责,建议先备份存档

License

MIT

About

《苏沫:爸妈不在家》v1.0.11 外置修改器(RPG Maker MV / NW.js)|桥接器架构 · 自动检测 · 单文件 exe;README 说明移植到其他 MV 游戏需改的 3 处

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages