Skip to content

Repository files navigation

RiichiCity / Mahjong-JP 本地装扮解锁工具

这是一个面向 Mahjong-JP.exe 的本地研究工具,用本地代理在客户端侧补全角色、皮肤、称号、装扮、加载 CG 等“已拥有”数据,并通过可选 MITM WebSocket 补丁让对局内角色与装扮保持一致。

项目当前按授权 CTF / 本地研究环境设计,不依赖原后端源码,不需要把伪造的完整拥有列表提交给远端服务器。实际保存的角色、称号、装扮方案等状态默认写入本地配置。

功能

  • 解锁全部角色与皮肤。
  • 解锁全部装扮:立直棒、牌背、桌布、特效、立直特效、BGM、场景、牌面、头像框、桌边框、个人头像、画廊背景、牌桌手、对局按钮样式等。
  • 解锁非连续 ID 的特殊装扮:会合并服务器返回、内置目录、游戏资源文件名、lua_config 物品名配置中发现的 ID。
  • 解锁称号、头像、头像框、加载 CG。
  • 支持星标角色、自定义昵称、本地大厅方案。
  • 支持本地保存装扮方案。
  • 支持对局 WebSocket 数据补丁,避免大厅已换装但进入对局仍显示默认角色/默认装扮。

项目结构

LocalUnlockTool/
├─ one_click_launcher.py             # 一键启动器:环境检查、证书安装、Proxifier 规则自动配置、代理链启动
├─ riichicity_unlock_proxy.py        # 本地 HTTP/HTTPS 代理与解锁逻辑
├─ start_unlock_proxy.ps1            # 源码版启动脚本
├─ start_unlock_proxy_exe.ps1        # 编译版启动脚本
├─ requirements.txt                  # 运行依赖
├─ requirements-build.txt            # 构建依赖
├─ config/
│  ├─ decor_catalog.json             # 装扮目录
│  ├─ RiichiCity_OneClick.ppx         # 备用 Proxifier profile;启动器会自动生成/更新
│  ├─ unlock_state.example.json      # 公开模板;首次运行会复制为 unlock_state.json
│  └─ user_settings.example.json     # 公开模板;首次运行会复制为 user_settings.json
├─ mitm/
│  ├─ riichicity_mitm_capture.py      # mitmdump 插件,用于 WebSocket 对局数据补丁
│  └─ start_mitm_capture.ps1          # MITM 启动脚本
└─ scripts/
   ├─ decrypt_check_data.py           # AES 加解密辅助脚本
   ├─ test_local_endpoints.ps1        # 本地接口自测
   ├─ build_one_click_launcher.ps1    # 只编译一键启动器
   └─ build_release.ps1               # PyInstaller 编译与 Release zip 打包

不会提交到公开仓库的运行数据:

  • logs/
  • mitm/logs/
  • %USERPROFILE%\.mitmproxy/,默认共享的 mitmproxy CA 与私钥目录(不得提交)
  • mitm/backups/
  • config/user_settings.json
  • config/unlock_state.json
  • 截图、抓包、Proxifier 备份、pyc、构建产物

装扮 ID 类型

普通装扮 ID 通常由“前两位类型 + 后三位序号”组成。特殊装扮不一定连续,因此程序额外扫描资源与配置补齐。

ID NAME_ENG NAME_CHN
13 RiichiStick 立直棒
14 CardBack 牌背
15 Tablecloth 桌布
16 SpecialEffect 特效
17 LiZhiEffect 立直特效
18 HallBGM 大厅 BGM
19 RankBGM 段位战 BGM
20 LZBGM 立直 BGM
24 SceneEffect 场景特效
25 HallBg 大厅背景
26 CardFace 牌面
30 AvatarFrame 头像框
36 TableEdge 牌桌边框
37 PersonalHead 个人头像
38 Gallery 画廊背景
39 TableHand 牌桌手
40 TableButtonStyle 牌桌按钮样式

当前代码也兼容 22、27、28、31、32、33、34、35、42 等特殊或扩展装扮类型。

使用方式一:使用 Release 编译版

  1. 从 GitHub Releases 下载 RiichiCityLocalUnlockTool-<version>-win-x64.zip
  2. 解压到一个固定目录,例如:
F:\一番街Q\LocalUnlockTool

不要把文件散放到桌面根目录。

  1. 推荐直接运行一键启动器:
.\RiichiCityOneClickUnlock.exe

启动器会自动检查依赖、生成并安装 MITM CA 证书、自动设置本机已安装 Proxifier 的代理配置规则、启动 49020 MITM 和 49010 本地解锁代理。窗口保持打开即可;关闭窗口即停止代理链。

一键启动器默认不会自动启动游戏。等窗口显示“本地解锁代理已监听”后,通过 Steam 或桌面入口手动启动游戏即可。

Release 包里两个 EXE 的区别

Release 包里会看到两个编译程序,普通用户只需要启动 RiichiCityOneClickUnlock.exe

文件 作用 是否需要手动启动
RiichiCityOneClickUnlock.exe 一键启动器。负责检查/修复环境、生成和检测 MITM CA 证书、自动配置 Proxifier、启动 MITM、启动本地解锁代理。 需要。正常只启动这个。
RiichiCityLocalUnlockProxy.exe 本地解锁代理核心服务。负责监听 127.0.0.1:49010,处理游戏请求,返回/补丁本地解锁数据。 不需要。会被一键启动器自动拉起。

不要同时手动启动这两个 EXE。手动启动 RiichiCityLocalUnlockProxy.exe 只适合排错或高级调试,否则可能造成 49010 端口占用、代理链重复、日志混乱。

MITM CA 默认固定保存在 %USERPROFILE%\.mitmproxy,只需要安装一次。后续启动器会检测当前用户 Root 证书库里是否已有同一证书指纹,已安装则直接跳过。更换或删除工具目录不会再生成新 CA;只有删除共享 CA 目录或显式指定新的 --mitm-conf-dir 时才会重新生成。

工具不会内置、复制或安装 Proxifier 程序本体。它只会定位你本机已有的 Proxifier.exe,写入 %APPDATA%\Proxifier4\Profiles\RiichiCity_OneClick.ppx,并设置当前 profile 为 RiichiCity_OneClick。如果 Proxifier 弹出“切换/导入/加载 profile”的确认框,启动器会默认自动点击“确定/是/OK/Yes”。写入前会把原 profile 备份到:

config\proxifier_backups\

如果你使用的是绿色版或自定义路径 Proxifier,可以显式指定:

.\RiichiCityOneClickUnlock.exe --proxifier-exe "E:\Proxifier\Proxifier.exe"

如需调试确认框行为,可以禁用自动确认:

.\RiichiCityOneClickUnlock.exe --no-proxifier-auto-confirm

如果你确实想让工具在代理链就绪后自动启动游戏,可以显式传入:

.\RiichiCityOneClickUnlock.exe --launch-game

默认要求上游代理 127.0.0.1:7897 可用。如果你的环境不需要上游代理,可以运行:

.\RiichiCityOneClickUnlock.exe --remote-proxy-port 0

如果 Proxifier 没有自动应用配置,请先确认 Proxifier 已安装/已启动;仍失败时再手动导入备用 profile:

config\RiichiCity_OneClick.ppx
  1. 手动方式:如果只需要大厅/背包界面解锁,启动本地代理:
powershell -ExecutionPolicy Bypass -File .\start_unlock_proxy_exe.ps1 -ListenPort 49010 -RemoteProxyPort 7897
  1. 如果需要进入对局后角色与装扮也生效,先启动 MITM:
powershell -ExecutionPolicy Bypass -File .\mitm\start_mitm_capture.ps1 -ListenPort 49020 -UpstreamProxy http://127.0.0.1:7897

默认复用当前用户的 %USERPROFILE%\.mitmproxy CA 目录。需要把其中的 mitmproxy-ca-cert.cer 安装到 Windows 的“受信任的根证书颁发机构”。可通过 --mitm-conf-dir 或环境变量 RIICHICITY_MITM_CONF_DIR 指定独立目录。

然后启动编译版代理并开启 MITM 路由:

powershell -ExecutionPolicy Bypass -File .\start_unlock_proxy_exe.ps1 -ListenPort 49010 -RemoteProxyPort 7897 -UseMitm
  1. Proxifier 增加规则:
Program : Mahjong-JP.exe
Proxy   : HTTP 127.0.0.1:49010
Action  : 走本地代理
  1. 确认上游代理可用。如果你的网络环境依赖 Clash Verge / mihomo,默认要求 127.0.0.1:7897 正在监听。
  2. 通过 Steam 正常启动游戏。

使用方式二:源码运行

安装依赖:

cd /d F:\一番街Q\LocalUnlockTool
python -m pip install -r .\requirements.txt

只跑本地解锁代理:

powershell -ExecutionPolicy Bypass -File .\start_unlock_proxy.ps1 -ListenPort 49010 -RemoteProxyPort 7897

跑完整链路,包含对局 WebSocket 补丁:

powershell -ExecutionPolicy Bypass -File .\mitm\start_mitm_capture.ps1 -ListenPort 49020 -UpstreamProxy http://127.0.0.1:7897
powershell -ExecutionPolicy Bypass -File .\start_unlock_proxy.ps1 -ListenPort 49010 -RemoteProxyPort 7897 -UseMitm

配置说明

首次运行时程序会自动从 example 生成本地运行配置:

config/unlock_state.json
config/user_settings.json

常用配置在 config/user_settings.json

  • current.roleID:当前角色 ID
  • current.skinID:当前皮肤 ID
  • current.titleID:当前称号 ID
  • current.headID:当前头像 ID
  • current.profileFrameID:当前头像框 ID
  • current.nickname:本地自定义昵称
  • current.equip:当前装扮,key 为装扮类型 ID,value 为物品 ID
  • star_chars:星标角色列表
  • homepage:本地大厅展示方案
  • equipsuit:本地装扮方案列表

如果游戏安装路径不是默认路径,可以通过环境变量指定资源扫描目录:

$env:RIICHICITY_GAME_ASSET_ROOTS = "D:\SteamLibrary\steamapps\common\RiichiCity\Mahjong-JP_Data\StreamingAssets;D:\SteamLibrary\steamapps\common\RiichiCity\Mahjong-JP_Data\_Data\Mahjong"

如果 lua_config 路径不在默认目录,也可以指定:

$env:RIICHICITY_LUA_CONFIG_PATHS = "D:\SteamLibrary\steamapps\common\RiichiCity\Mahjong-JP_Data\StreamingAssets\Base\lua_config"

教程:确认是否真的生效

  1. 启动上游代理,例如 127.0.0.1:7897
  2. 启动 mitm/start_mitm_capture.ps1
  3. 启动 start_unlock_proxy.ps1 -UseMitmstart_unlock_proxy_exe.ps1 -UseMitm
  4. Proxifier 把 Mahjong-JP.exe 指向 HTTP 127.0.0.1:49010
  5. 进入游戏大厅,打开背包检查装扮是否显示已获得。
  6. 更换角色、皮肤、称号、牌背、桌布、桌边框、特效、BGM 等。
  7. 创建房间或进入对局,确认对局内不是默认角色/默认装扮。
  8. 观察代理日志:
logs/
mitm/logs/

正常进入对局且 WebSocket 补丁命中时,mitmdump 日志里应能看到类似:

[rc:ws:self]
[rc:ws:patch]

本地接口自测

启动本地代理后运行:

powershell -ExecutionPolicy Bypass -File .\scripts\test_local_endpoints.ps1 -Port 49010

典型结果会显示已补全的数量,例如:

userItemList : 1369
getTitleList : 227
userEquip    : 15
roleList     : 63

数量会随游戏版本和本地资源扫描结果变化。重点不是固定数字,而是关键接口能返回非空数据且未报错。

编译 Release 包

源码目录下安装构建依赖:

python -m pip install -r .\requirements-build.txt

构建 zip:

powershell -ExecutionPolicy Bypass -File .\scripts\build_release.ps1 -Version v0.1.7

只构建一键启动器:

powershell -ExecutionPolicy Bypass -File .\scripts\build_one_click_launcher.ps1

输出位置:

release\RiichiCityLocalUnlockTool-v0.1.7-win-x64.zip

常见报错与处理

装饰品方案显示为空

userItemList 只代表“已拥有饰品列表”,装饰品方案走的是另一个接口:/backpack/userEquipSuitV2

如果本地 config/user_settings.json 里的 equipsuit 为空,或者某个方案的 items 为空,客户端就会显示空方案。当前版本会在启动后自动迁移:

  • 首次运行会根据当前穿戴生成一个“本地默认方案”;
  • 旧配置里已有空方案时,会自动把当前角色、皮肤、称号、头像框、牌背、桌布、立直棒等穿戴项补进 items
  • 新建/编辑方案时,如果客户端没有传方案明细,会自动用当前穿戴生成快照。

如果仍显示为空,关闭工具后删除:

Remove-Item .\config\user_settings.json

再重新启动 RiichiCityOneClickUnlock.exe,工具会重新生成本地方案。

称号列表为空或无法更换

称号主要走 /users/getTitleList,部分自定义/方案 UI 还会读取同一份本地穿戴状态。

当前版本会对称号接口做兼容补齐:

  • data 保持为称号数组;
  • 同时补充 listtitleListtotal,兼容不同客户端读取方式;
  • 每个称号同时带 titleIDtitleIdTitleID
  • 按客户端枚举语义返回 titleState/state/State1=已拥有2=正在使用3=锁定
  • 每个称号补充 type 分类字段,避免称号面板因为缺分类而把数据全部过滤掉;
  • 自动补齐当前客户端 title_config 中存在但旧本地列表缺失的特殊称号;
  • 每个称号强制标记为已拥有、未过期、可装备;
  • 保存称号时兼容 titleIDtitleIdtitle_ididitemID 等字段。

如果游戏里仍显示没有任何称号,优先看:

Get-ChildItem .\logs\*users_getTitleList*.json | Sort-Object LastWriteTime -Descending | Select-Object -First 3

确认日志里的响应解密后 data 数量不是 0,并且每条非默认称号都有 type 字段。当前版本内置的称号配置正常返回约 227 条,数量会随游戏版本变化。

提示“您的网络不可用,请检查网络连接”

优先检查:

  1. Proxifier 是否把 Mahjong-JP.exe 指向 127.0.0.1:49010
  2. 本地代理是否正在监听:
netstat -ano | findstr ":49010"
  1. 如果使用上游代理,确认 127.0.0.1:7897 正在监听:
netstat -ano | findstr ":7897"
  1. 如果开启 -UseMitm,确认 127.0.0.1:49020 正在监听:
netstat -ano | findstr ":49020"
  1. mitmproxy 证书是否已安装到受信任根证书。

提示“版本信息获取失败”

通常是启动阶段 HTTP/HTTPS 链路没有通:

  • 先关闭 -UseMitm 只启动普通代理,确认能进大厅。
  • 检查 RemoteProxyPort 是否与你的实际上游代理一致。
  • 如果不需要上游代理,把 -RemoteProxyPort 0 传给启动脚本。
  • 查看 logs/*users_checkVersion*.json 是否有响应。

Steam 登录不可用

确认游戏是从 Steam 正常启动,而不是直接双击 Mahjong-JP.exe。如果直启,Steam 登录态可能不可用。

大厅能换装,但进入对局后仍是默认角色/默认装扮

这是 WebSocket 对局数据没有被补丁,重点检查:

  • 是否启动 mitm/start_mitm_capture.ps1
  • 本地代理是否带 -UseMitm
  • mitm/conf/mitmproxy-ca-cert.cer 是否已安装并信任。
  • mitm/logs/mitmdump*.stdout.log 是否出现 [rc:ws:patch]
  • Proxifier 规则是否没有绕过 aga-alb.mahjong-jp.net

提示“存在已过期的装饰品无法保存/使用”

当前逻辑会把本地补齐的装扮设置为:

isOwn = true
isCanGet = true
isLock = false
isExpired = false
expiredAt = 0
expirationTime = 0

如果仍然提示过期:

  1. 重启游戏,清掉客户端旧缓存。
  2. 删除本地运行状态后重新生成:
Remove-Item .\config\user_settings.json
  1. 重新启动代理并进入背包刷新。
  2. 如果只在“自定义饰品方案保存/使用”里触发,保留对应 logs/*equipSuit*.json 再分析接口字段。

背包里有小部分特殊道具仍显示未获得

优先检查游戏资源扫描:

  • 确认游戏安装目录存在。
  • 设置 RIICHICITY_GAME_ASSET_ROOTS
  • 设置 RIICHICITY_LUA_CONFIG_PATHS
  • 重启代理后再打开背包。

程序会从服务器原始返回、decor_catalog.json、资源文件名、lua_config item_name_xxx 合并 ID。特殊 ID 不连续时,lua_config 是最关键的补齐来源。

端口被占用

查看占用进程:

netstat -ano | findstr ":49010"
netstat -ano | findstr ":49020"

换端口启动:

powershell -ExecutionPolicy Bypass -File .\start_unlock_proxy.ps1 -ListenPort 49110

同时记得修改 Proxifier 规则。

中文路径或 PowerShell 编码问题

建议使用 python -X utf8。本项目脚本已经默认使用 UTF-8 运行主程序。路径中有中文时,尽量在 PowerShell 里使用 -LiteralPath 或先 cd 到项目目录。

可编辑配置(参考 MajsoulMax)

首次启动会把 config/settings.example.yaml 复制为 config/settings.yaml。修改后需要重启一键启动器;命令行参数优先于 YAML。

常用项:

  • features:分别开关角色、皮肤、称号、装扮、头像、头像框和主页方案。
  • appearance:填写角色/皮肤/称号等 ID 可强制本地显示;保持 null 则跟随游戏内保存值。
  • decorations.allowed_item_types:只显示指定的可装备装扮类型,空列表表示全部。
  • decorations.blocked_item_ids:隐藏指定装扮 ID。
  • network.remote_proxy_port0 表示直连,不需要上游代理。
  • network.mitm_ca_dir:默认统一使用 %USERPROFILE%\.mitmproxy
  • logging:控制流量索引、正文保存和日志预览长度。

普通道具、礼物、觉醒材料和活动消耗品的数量始终保留服务器原值。这是安全约束,不提供可关闭的配置项。

指定其他配置文件:

.\RiichiCityOneClickUnlock.exe --config .\config\my-settings.yaml

配置解析错误、未知字段、代理异常与方案应用记录分别写入:

logs/one_click_launcher.*.log
logs/errors.jsonl
logs/events.jsonl
mitm/logs/patch_errors.jsonl
mitm/logs/flows.jsonl

收集完整诊断包:

powershell -ExecutionPolicy Bypass -File .\scripts\collect_diagnostics.ps1

AES 辅助脚本

旧项目中恢复到的 AES 参数:

key = idpwepjzsjbg18sdf25as4bsefls944a
iv  = DkHu8vuy/ye7cd7k

解密 Base64 字段:

python -X utf8 .\scripts\decrypt_check_data.py --decrypt-base64 --text "<base64>"

加密 JSON:

python -X utf8 .\scripts\decrypt_check_data.py --encrypt-json --text '{"code":0,"data":{}}'

已知限制

  • 游戏版本更新后,接口字段、WebSocket 命令或资源命名可能变化,需要重新抓包和补字段。
  • 对局内生效依赖 MITM WebSocket 补丁;只跑普通 HTTP 代理时,背包/大厅可能生效,但对局内可能回到服务器原始状态。
  • mitm/conf/ 里的 CA 私钥是本机运行产物,不能提交到公开仓库。

About

RiichiCity Mahjong-JP local decoration unlock proxy

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages