# 块功能介绍 **这份文档讲清一件事:插件把代码和文档切成「块」来管理 —— 块是什么、能干什么、怎么用。** 不涉及具体实现。想动手改东西,看 `OPERATIONS.md`;想按块导入别人的改动,看 `MIGRATION.md`。 > 本文的数字与表格由 `tools/gen-blocks-doc.py` 从 `blocks.json` 现算,**不是手抄的**。 > 改了代码之后重跑一次即可,不会出现「文档说 900 块、实际 1259 块」这种脱节。 --- ## 一、块是什么 **一个块 = 一个函数、一个类、一个文档章节,或一段独立配置。** 块的名字是三段式,用冒号隔开: ``` 文件路径 : 块类型 : 块名 lib/parse.js:function:attributeCluster OPERATIONS.md:h2:四、静默失败的排查顺序 ``` **为什么不用文件做单位**:文件里改一行,整份文件的哈希就变了 —— 只能告诉你「这个文件变了」, 说不出「变了哪一处、是谁改的」。块的作用就是把粒度降到能回答这两个问题。 --- ## 二、块能干什么 | 用途 | 一句话 | 用什么 | |---|---|---| | 按块比对 | 「别人那版比我多了哪些块」 | `rimworld_plugin_compare` / `tools/compare-plugin.mjs` | | 按块导入 | 只要别人某一个函数,不用整包替换 | `tools/import-blocks.mjs` | | 署名追踪 | 每个块记着谁写的、什么时候、第几版 | `blocks.json` + `tools/stamp-blocks.mjs` | 三条的共同点:**换位置、改缩进、重排顺序都不会被当成改动** —— 比对单位是块,不是行。 --- ## 三、一眼看全貌 | 指标 | 数值 | |---|---| | 块总数 | **1,405** | | 涉及文件 | **134** 个 | | 有版本号的块 | 646 | | 无版本号的块 | 759(早于登记表引入,属正常) | 按类型(前三类占了大多数): | 类型 | 数量 | 是什么 | |---|---|---| | `const` | 641 | 常量声明 | | `function` | 287 | 函数 / 方法 | | `h2` | 150 | 二级标题(文档) | | `head` | 104 | Python 函数 / 脚本头 | | `h3` | 95 | 三级标题(文档) | | `def` | 46 | Python 函数定义 | | `let` | 42 | 局部变量声明 | | `h1` | 18 | 一级标题(文档) | --- ## 四、按区域认识块群 | 区域 | 块数 | 里面是什么 | |---|---|---| | `tools/`(其余脚本) | 804 | 一次性调查脚本:审计、定位、归属可视化、程序集检查、数据分析 | | 文档(12 份) | 266 | 章节级块;改一段话也会被记为一次改动 | | `lib/`(6 个模块) | 166 | 定位 RimCrow / 解析日志 / 判断归属 / 渲染报告 / Player.log / mod 配置 | | 根目录其它文件 | 90 | `index.js` / `client.js` / 配置与图标 | | `tools/dev/`(6 个开发脚本) | 47 | 开发期调试用:聚类调试、日志条目打印、环境诊断 | | `plugins/`(3 个模块) | 32 | 工具注册表、安装状态、功能报告 | > 完整到文件的分布见文末附录。 --- ## 五、版本号怎么读 ``` 1.6.1.Jzc1098.330 └─┬─┘ └─┬──┘ └┬┘ 基础版本 作者代号 递增序号 ``` - **基础版本**来自 `package.json`;升版本时全部块的基础版本一起变 - **作者代号**是 `--author` 自动生成的稳定短码,中文名也行 - **递增序号**只增不减,用来判断「这块后来有没有人动过」 **版本号只是记录,从不参与比较。** 它不会告诉你哪份更新 —— 两份副本可以有相同版本号但内容不同。 改过别人的函数时,登记表**同时记两个**:原作者不变,另记「最后修改者是你」。导入不会顶掉原作者。 --- ## 六、怎么用(三个实操场景) ### 1. 别人那版有什么我没有 ``` node tools/compare-plugin.mjs --other <别人的插件目录> ``` 报告分节:汇总 / A 有 B 没有 / 两边都有但不同 / 疑似同功能 / **按导入安全性排序的可学清单** / 依赖待查。 ### 2. 我只想要他那一个函数 ``` node tools/import-blocks.mjs <别人的目录> --blocks "lib/parse.js:function:xxx" ``` 默认**只生成暂存目录,不写入你的插件**;看完确认了才落盘,署名原样保留。 ### 3. 这块是谁写的 ``` node -e "const b=require('./blocks.json');console.log((b.blocks||b)['lib/parse.js:function:attributeCluster'])" ``` 或在 DSH 里问一句「`rimworld_plugin_guide` 报一下块清单」。 --- ## 七、块的边界(如实说明) | 现象 | 真相 | |---|---| | 块数变多/变少 | **不等于功能变多/变少** —— 重排、加注释、改文档标题都会改块数 | | 某个块突然消失 | 多半是**重切分改名**:函数拆成两个,旧块没了、新块出现 | | 出现了陌生块 | 可能是别人导入的,也可能是你自己刚写但还没盖章 | | 块指向的文件不在了 | **孤儿块**,见下一节 | --- ## 八、登记表的卫生 **什么时候盖章**:改完东西、发版之前。先 `--dry-run` 看一眼它会动哪些块,再真正执行。 ``` node tools/stamp-blocks.mjs --dry-run # 只看,不写 node tools/stamp-blocks.mjs # 写 blocks.json ``` ### 孤儿块(已知现状) 文件删了或移走了,它的块会**留在登记表里**。当前实测: | 指标 | 数值 | |---|---| | 来源已不存在的块 | **0** | | 涉及的文件 | 0 个 | **为什么不自动清**:清掉就找不回来了(对照旧版本时还有用)。清理是 `tools/bump-version.mjs` 的工作, 或者你确认不需要后手工删。**知道它们存在**比让它们悄悄堆着要好。 --- ## 九、一页速查 ``` node tools/stamp-blocks.mjs --dry-run # 我改了哪些块(不写盘) node tools/stamp-blocks.mjs --author "你的名字" # 盖章并署名 node tools/compare-plugin.mjs --other <目录> # 按块比对另一份副本 node tools/import-blocks.mjs <目录> --blocks "…" # 只导入某一块 node tools/selftest-blocks.mjs # 块机制自测 python tools/gen-blocks-doc.py # 重新生成本文 ``` --- ## 附录:每个文件的块数 按块数从多到少。共 134 个文件、1,405 个块。 | 文件 | 块数 | |---|---:| | `COMBAT_EXTENDED.md` | 47 | | `插件清单.md` | 36 | | `lib/workspace-archive.js` | 34 | | `tools/verify-harmony-targets.mjs` | 30 | | `OPERATIONS.md` | 29 | | `index.js` | 29 | | `RELEASE.md` | 22 | | `lib/parse.js` | 22 | | `tools/ce-audit.mjs` | 22 | | `安装说明.md` | 22 | | `tools/lib-blocks.mjs` | 21 | | `tools/sync-manifest.mjs` | 21 | | `lib/detect.js` | 20 | | `modconfig-test.mjs` | 19 | | `tools/find-string-targets.mjs` | 19 | | `tools/selftest-patchaudit.mjs` | 19 | | `lib/report.js` | 18 | | `plugins/registry.js` | 18 | | `tools/compare-plugin.mjs` | 18 | | `tools/stamp-blocks.mjs` | 18 | | `tools/bump-version.mjs` | 17 | | `tools/compact-report-prototype.mjs` | 17 | | `tools/explain-tally.mjs` | 17 | | `tools/read-session.mjs` | 17 | | `tools/selftest-aboutcheck.mjs` | 17 | | `PORTING.md` | 16 | | `tools/probe-cluster-attribution.mjs` | 16 | | `tools/selftest-modwatch.mjs` | 16 | | `块功能介绍.md` | 16 | | `MIGRATION.md` | 15 | | `tools/audit-patches.mjs` | 15 | | `tools/dev/debug-json.mjs` | 15 | | `tools/trace-cluster.mjs` | 15 | | `HISTORY.md` | 14 | | `lib/config.js` | 14 | | `lib/modconfig.js` | 14 | | `mock-host.mjs` | 14 | | `tools/check-about.mjs` | 14 | | `tools/dump-clusters.mjs` | 14 | | `tools/probe-findactive.mjs` | 14 | | `tools/selftest-sig.mjs` | 14 | | `tools/trace-candidates.mjs` | 14 | | `tools/selftest-workspace-archive.mjs` | 13 | | `tools/tally-damage-report.mjs` | 13 | | `使用参考.md` | 13 | | `lib/modwatch.js` | 12 | | `lib/playerlog.js` | 12 | | `tools/dev/diag.mjs` | 12 | | `tools/find-textures-by-size.mjs` | 12 | | `tools/probe-structure.mjs` | 12 | | `tools/selftest-plugin.mjs` | 12 | | `CONTRIBUTING.md` | 11 | | `attribution-test.mjs` | 11 | | `tools/ce-melee-anchor.mjs` | 11 | | `tools/find-def-across-mods.mjs` | 11 | | `tools/find-mod-by-name.mjs` | 11 | | `tools/selftest-config.mjs` | 11 | | `tools/ammo-consumers.mjs` | 10 | | `tools/check-all.mjs` | 10 | | `tools/diff-modlists.mjs` | 10 | | `tools/import-blocks.mjs` | 10 | | `tools/probe-nameshape.mjs` | 10 | | `tools/selftest-mod-write-guard.mjs` | 10 | | `tools/weapon-cost.mjs` | 10 | | `SOLVED-block-split.md` | 9 | | `UI-SURFACE.md` | 9 | | `lib/patchaudit.js` | 9 | | `tools/check-about-schema.mjs` | 9 | | `tools/check-packagerefs.mjs` | 9 | | `tools/compare-weapons.mjs` | 9 | | `tools/def-chain.mjs` | 9 | | `tools/find-melee-weapons.mjs` | 9 | | `tools/new-warnings.mjs` | 9 | | `tools/probe-method-il.py` | 9 | | `lib/sig.js` | 8 | | `plugins/state.js` | 8 | | `tools/attribute-recipes.mjs` | 8 | | `tools/build-public.py` | 8 | | `tools/compare-sessions.mjs` | 8 | | `tools/dev/debug-attrib.mjs` | 8 | | `tools/dump-melee-tools.mjs` | 8 | | `tools/find-vanilla-def.mjs` | 8 | | `tools/probe-variants.mjs` | 8 | | `templates/NEW-BLOCK.md` | 7 | | `tools/find-def-refs.mjs` | 7 | | `tools/probe-missing-recipes.mjs` | 7 | | `tools/probe-ve.mjs` | 7 | | `tools/session-timeline.mjs` | 7 | | `tools/trace-component-health.mjs` | 7 | | `plugins/feature-report.js` | 6 | | `tools/build-package.py` | 6 | | `tools/decode-sigs.py` | 6 | | `tools/dev/debug-entries.mjs` | 6 | | `tools/dump-assembly.py` | 6 | | `tools/find-scribe-references.mjs` | 6 | | `tools/list-mod-assemblies.mjs` | 6 | | `selftest.mjs` | 5 | | `tools/find-bad-about.mjs` | 5 | | `tools/find-type-provider.mjs` | 5 | | `tools/probe-180mm.mjs` | 5 | | `tools/probe-diff.mjs` | 5 | | `tools/probe-tables.py` | 5 | | `tools/selftest-blocks.mjs` | 5 | | `fallback-test.mjs` | 4 | | `tools/dev/missing.mjs` | 4 | | `tools/gen-blocks-doc.py` | 4 | | `tools/probe-meta.py` | 4 | | `tools/run-selftests.mjs` | 4 | | `lib/aboutcheck.js` | 3 | | `tools/check-package-json.py` | 3 | | `tools/probe-pe.py` | 3 | | `tools/write-plugin-manifest.py` | 3 | | `tools/bump-version.py` | 2 | | `tools/dev/debug-playerlog.mjs` | 2 | | `tools/lib_tools.py` | 2 | | `tools/rename-author.py` | 2 | | `client.js` | 1 | | `cordis.patch.yml` | 1 | | `icon.svg` | 1 | | `locale/en.json` | 1 | | `locale/zh.json` | 1 | | `package.json` | 1 | | `pnpm-lock.yaml` | 1 | | `templates/blocks.example.json` | 1 | | `tools/__pycache__/build-package.cpython-312.pyc` | 1 | | `tools/__pycache__/build-public.cpython-312.pyc` | 1 | | `tools/__pycache__/lib_tools.cpython-312.pyc` | 1 | | `tools/__pycache__/rename-author.cpython-312.pyc` | 1 | | `tools/check-compress-fix.ps1` | 1 | | `tools/probe-patch-file.ps1` | 1 | | `tools/probe-strings.py` | 1 | | `tools/tools.json` | 1 | | `tools/verify-155mm-recipe-fix.ps1` | 1 | | `tools/verify-recipe-fixes.ps1` | 1 | ## 十、工具清单(4 个) > 本节由 `tools/lib_tools.py` 按 `index.js` 的注册生成,用途来自 `tools/tools.json`。 | 工具 | 一句话用途 | |---|---| | `rimworld_log_scan` | 读日志:聚类错误/警告、按堆栈归属 mod、给出可回溯证据(analyze / detect / grep / mods,只读) | | `rimworld_plugin_guide` | 插件自述:工具与命令清单、块清单、作者表、版本变化 | | `rimworld_plugin_compare` | 按块比对另一份插件副本,报告差异与按导入安全性排序的可学清单 | | `rimworld_workspace_archive` | 工作区备份:按天快照(保留最新 3 份)、导出迁移包、写归档记录与 INDEX |