Pape-ResSolver 将规范化后的 Pape 资源转换为适合服务端使用、可读且保留来源信息的配置数据。程序依赖资源清单,不把包 ID 写死,因此可以跨资源版本复用。
它生成四类产物:
- 对
LuaCfg.*配置 Lua 做静态求值,依据_k字段表导出 JSONL 和 SQLite; - 为逻辑 Lua 建立来源名、依赖、RPC、配置引用和内容哈希索引;
- 整理 MessagePack、文本、X3 和其他配置资源,生成服务端可读取的 JSONL;
- 根据 ResGet 的多语言资源清单生成独立的
languages.sqlite。
Lua 读取器不会执行游戏代码,只处理现有 Lua 5.3 反编译器输出的受限数据构造语法。无法静态表示的表达式会被明确记录,不会被猜测成普通数值。
需要 Python 3.11 及以上版本。部分 Lua 反编译流程还需要 Java 17 及以上版本。
python -m pape_res_solver extract `
D:\path\to\normalized-resources `
--output .\out\resource-version `
--export-scripts useful `
--materialize-tables hardlink开发时可以只提取指定表:
python -m pape_res_solver extract D:\path\to\normalized-resources `
--output .\out\gacha `
--table CardBaseInfo --table Item --table GachaAll `
--table GachaGroup --table GachaRule --table GachaDrop典型输出结构:
out/<version>/
catalog.json
resources.sqlite
languages.sqlite
tables/*.jsonl
schemas/*.json
scripts/catalog.jsonl
scripts/**/*.lua
server_tables/msgpack/*.jsonl
server_tables/config/*.jsonl
artifacts/tables/**
reports/parse_failures.json
reports/unresolved_values.json
reports/references.json
reports/lua_index.json
reports/artifacts.json
每条配置目录记录来源包、条目序号、源码路径、内容哈希、行数和 schema 指纹。JSONL 保持为干净的配置对象,来源信息保存在 catalog 和 SQLite 元数据中。
资源清单中的正式名称是唯一依据,程序不会根据包 ID 或条目序号猜表名。如果下一版本把 LuaCfg.Item 移到其他包,输出仍然是 tables/Item.jsonl,新的来源会写入 catalog.json。
当前 Android Lua 字节码使用 32 位 size_t。转换器只调整二进制 chunk 的字符串长度字段,以便本地 64 位 Lua 5.3 运行时读取,同时保留 Lua 整数和 SETLIST 顺序。Vector2、Vector3、Quaternion、Color 等 Unity 构造器会转换为带标签的 JSON 对象。配置 chunk 无权访问文件、网络、进程、包或 debug API。
resources.sqlite 包含 config_tables、config_rows、config_references、lua_scripts、lua_dependencies、resource_packages、resource_files 和 decoded_table_rows 等稳定表。
select json_extract(data_json, '$.FragmentID')
from config_rows
where table_name = 'CardBaseInfo' and row_key = '121130';也可以直接查询:
python -m pape_res_solver query .\out\1.7.1546 CardBaseInfo 121130
python -m pape_res_solver find-id .\out\1.7.1546 121130
python -m pape_res_solver text .\out\1.7.1546 377066
python -m pape_res_solver verify .\out\1.7.1546languages.sqlite 根据 ResGet 的 multilanguage/manifest.json 原子重建,不向 resources.sqlite 或 BOOI 紧凑库写入文本镜像。主要表包括 language_resource_sets、language_packages、localized_text 和 language_metadata。
资源集 ID 是跨版本语言查找的稳定键:
select text from localized_text
where resource_set_id = 1000000000001 and text_id = 377066;Solver 默认增量提取。未变化的 Lua、MessagePack、X3 和文本输出会复用;删除的包会同步清理。需要完整重建时使用 --no-incremental 或 --clean。
使用维护好的 booi 预设可以生成 BOOI 运行时数据库:
python -m pape_res_solver trim `
.\out\1.7.1546\resources.sqlite `
.\out\1.7.1546\booi-res.sqlite `
--preset booi `
--resource-version 1.7.1546也可以显式指定表:
python -m pape_res_solver trim resources.sqlite booi-res.sqlite `
--table Task --table Item --table ItemType `
--table CardBaseInfo --table CardRare `
--table GachaAll --table GachaGroup --table GachaRule --table GachaDrop输出会先写入临时文件,完成完整性检查后再原子替换。使用 --force 才会覆盖已有输出。X3 战斗配置会提升为稳定的 X3<TableName>,例如 X3WeaponLogicConfigs、X3WeaponSkinConfigs 和 X3ActorCfgs。
解析阶段还会处理两个已知客户端二进制资源:
config/DBCfg/DirtyWords.db会还原为server_tables/config/DirtyWords.sqlite,并导出DirtyWords.jsonl;config/XFileZip/210201614.bin会导出为XFileZip_210201614.jsonl。
两个解析器都会校验记录数量,并把结果写入 reports/artifacts.json。尚未识别的 MultiLanguagePackageManiFest.bin 会继续列在未解析报告中。
python -m pape_res_solver patch-app-key `
D:\path\to\XFileZip\2530387745.zip `
.\patched\2530387745.zip `
--old-app-key old-app-key-here `
--new-app-key new-app-key-here `
--nx-output .\patched\2530387745.nx新旧 key 必须拥有相同的 ASCII 字节长度。程序默认要求恰好匹配一次,会保留未修改内容,并在输出后重新读取验证。不同资源版本的包 ID 可能不同,也可以直接传入 XFileZip 目录或规范化资源根目录让程序按内容查找。
支持 _k 通过中间变量赋值的反编译结果。对 _useBinary 主表,按客户端 CfgHelper 的 LuaCfg.LuaSplitFils.{table}.cfg_{table}_{key} 规则查找片段并按主表 schema 合并;缺片、哈希冲突和 ID 不一致会报告提取失败。目录记录片段数量及依赖指纹,分片变化会使主表增量缓存失效。
Solver 会从 Lua 的 LuaCfgMgr 调用点提取正式注册名,并使用精确的 XLua CRC,或游戏字段访问与配置 schema 的唯一互证,恢复被裁剪或热修表的名称。
无法形成唯一证据的候选会保留为未解析项,写入 reports/config_name_resolution.json,不会生成 Recovered.* 猜测表。
hardlink(默认):同卷时使用硬链接,失败后复制;copy:生成独立副本;none:只生成 catalog 和汇总产物。
--clean 只删除带有 Pape-ResSolver 输出标记的目录,不会递归删除任意未标记目录。
资源输入和生成目录不会提交到 Git。它们应放在 resources/、source/、input/、out/ 或仓库外。仓库只发布工具源码、测试和文档,遵循 MIT License;第三方组件和数据边界见 NOTICE。
先运行只读诊断,无需重跑下载、反编译或配置提取:
python -m pape_res_solver diagnose-lua D:\resources\normalized `
--output D:\resources\solved --limit 10输入必须是包含 lua_source/manifest.json 的 normalized 根目录,不是
lua_source/、by_package/ 或 Solver 输出目录。--output 可省略;提供时
只读取已有的 scripts/catalog.jsonl,不会创建或修改输出。诊断输出到标准
输出,列出实际输入根目录、manifest 路径、Python/模块位置、源码数量和最多
10 条路径样例;--limit 支持 0–100。发现缺失、路径不匹配、过期的缺失记录
或上游不完整时退出码为 2。它检查文件状态,不验证 Lua 内容或依赖语义。
totals.missing_sources > 0:当前 manifest 指向的文件确实无法找到。 对比样例中的source_path、resolved_path与实际文件位置。totals.missing_with_conventional_source > 0:manifest 目标缺失,但同包、 同序号的标准lua_source/by_package/<package_id>/<index>.lua文件存在。 应核对资源地区、版本和清单来源;诊断不会自动改路径或认定文件内容匹配。catalog.missing_now_present > 0:旧目录记为缺失的条目现在已有源码。same_bytecode_hash可帮助区分补齐源码与换了一套输入。upstream.totals中的failed、package_failures、missing_index_targets或source_decompile_complete=false表明 ResGet 报告反编译不完整。
旧版增量索引仅依据字节码及条目信息复用结果,补齐 .lua 后仍可能保留
source_missing=true 和空依赖。更新 Solver 后可用以下命令明确重建:
python -m pape_res_solver extract D:\resources\normalized --output D:\resources\solved `
--no-incremental --export-scripts none --materialize-tables none
python -m pape_res_solver verify D:\resources\solved--no-incremental 会重建 Solver 配置和索引,不重新下载或反编译。
仅当上游有失败或源码确实缺失时,才需回到 ResGet 检查反编译报告并重试。
存储性能影响处理耗时,不能单独解释已有源码仍被旧索引标记为缺失;
应先核对路径和缓存,再做磁盘性能对照测试。
extract 会在逻辑 Lua 源码缺失或上游反编译不完整时返回退出码 2,
但保留可用的数据库和报告供排查。配置表失败数与 lua_missing_sources
分别统计;verify 检查上游反编译状态、源码缺失和依赖行数,不能把
“SQLite 文件存在”当作完整成功。
Lua 索引增量缓存包含分析器版本、源路径、源文件大小与纳秒修改时间;
补齐源码、重建源码或升级分析器后会重新扫描,数据库依赖行丢失也会重建。
源文件状态按包目录扫描,避免 Windows 上为每个条目重复查询文件属性。
若手工修改源码且刻意保留原大小和修改时间,使用 --no-incremental。
依赖扫描支持直接调用和保守的直线寄存器别名传播,不执行游戏逻辑。 动态计算的模块名、跨分支或跨函数传递不保证可解析;没有可识别的静态 依赖可以合法地产生零行,不能仅凭零行判断资源损坏。
对普通磁盘,推荐先使用:
python -m pape_res_solver extract D:\resources\normalized --output D:\resources\solved `
--export-scripts none --materialize-tables none这仍生成配置 SQLite、语言 SQLite 和 Lua 依赖索引,只省略可选的源码副本
与原始 artifacts 镜像。需要这些副本时使用 useful / hardlink;跨盘硬链接
不可用时会退回复制。索引目录逐行读取、JSONL 哈希和行数单遍计算,减少
峰值内存和重复磁盘读。资源清单的条目查找使用预建字典,避免逐表全表扫描。