Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pape-ResSolver

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 顺序。Vector2Vector3QuaternionColor 等 Unity 构造器会转换为带标签的 JSON 对象。配置 chunk 无权访问文件、网络、进程、包或 debug API。

SQLite 数据库

resources.sqlite 包含 config_tablesconfig_rowsconfig_referenceslua_scriptslua_dependenciesresource_packagesresource_filesdecoded_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.1546

多语言数据库

languages.sqlite 根据 ResGet 的 multilanguage/manifest.json 原子重建,不向 resources.sqlite 或 BOOI 紧凑库写入文本镜像。主要表包括 language_resource_setslanguage_packageslocalized_textlanguage_metadata

资源集 ID 是跨版本语言查找的稳定键:

select text from localized_text
where resource_set_id = 1000000000001 and text_id = 377066;

Solver 默认增量提取。未变化的 Lua、MessagePack、X3 和文本输出会复用;删除的包会同步清理。需要完整重建时使用 --no-incremental--clean

BOOI 紧凑 SQLite

使用维护好的 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>,例如 X3WeaponLogicConfigsX3WeaponSkinConfigsX3ActorCfgs

解析阶段还会处理两个已知客户端二进制资源:

  • config/DBCfg/DirtyWords.db 会还原为 server_tables/config/DirtyWords.sqlite,并导出 DirtyWords.jsonl
  • config/XFileZip/210201614.bin 会导出为 XFileZip_210201614.jsonl

两个解析器都会校验记录数量,并把结果写入 reports/artifacts.json。尚未识别的 MultiLanguagePackageManiFest.bin 会继续列在未解析报告中。

客户端 AppKey 修补

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 目录或规范化资源根目录让程序按内容查找。

LuaCfg 表名恢复

支持 _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

Lua 完整性与普通磁盘运行

源码存在但依赖表为空时

先运行只读诊断,无需重跑下载、反编译或配置提取:

python -m pape_res_solver diagnose-lua D:\resources\normalized `
  --output D:\resources\solved --limit 10

输入必须是包含 lua_source/manifest.jsonnormalized 根目录,不是 lua_source/by_package/ 或 Solver 输出目录。--output 可省略;提供时 只读取已有的 scripts/catalog.jsonl,不会创建或修改输出。诊断输出到标准 输出,列出实际输入根目录、manifest 路径、Python/模块位置、源码数量和最多 10 条路径样例;--limit 支持 0–100。发现缺失、路径不匹配、过期的缺失记录 或上游不完整时退出码为 2。它检查文件状态,不验证 Lua 内容或依赖语义。

  • totals.missing_sources > 0:当前 manifest 指向的文件确实无法找到。 对比样例中的 source_pathresolved_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 中的 failedpackage_failuresmissing_index_targetssource_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 哈希和行数单遍计算,减少 峰值内存和重复磁盘读。资源清单的条目查找使用预建字典,避免逐表全表扫描。

About

Version-tolerant Lua 5.3 and table resource normalizer for server-friendly JSONL and SQLite outputs

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages