
基本信息
我的世界Java版本
平台
运行环境
分类

创作者
详情信息
Octant(卦限)
本地、自愿、可撤回的 Minecraft 玩家行为洞察模组:把一段存档里的游玩过程,变成本机生成的 单文件 HTML 报告,让整合包作者看到「玩家到底玩到了什么、卡在哪、怎么打的」。
| 支持组合 | Forge / NeoForge / Fabric × Minecraft 1.20.1 / 1.21.1(六个组合都已构建通过,见 §4) |
| 运行时依赖 | 零第三方库(报告是自绘内联 SVG + 内嵌字体子集) |
| 网络 | 运行期零联网;并由构建期守卫扫源码强制(禁止 java.net.* 等联网 API,命中即构建失败) |
| 隐私默认 | 默认不采集(fail-closed:同意文件缺失或读不出来,一律按"不采集"处理) |
| 许可 | MIT |
| 本仓库内容 | 只有源码与构建脚本:不含测试数据、不含构建产物、不含样例报告 |
1. 它是什么
给整合包作者用的诊断工具。玩家在自己电脑上,把自己在某个存档里的游玩过程导出成一份报告; 报告里的每一句话都由本机算出来,玩家可以随时撤回授权、也可以随时删掉全部本地数据。
报告回答四个问题:
- 你玩到了什么 —— 进度推进的节奏、内容触达面、哪些内容一次没碰
- 卡在哪 —— 长时间没有推进的阶段、反复失败的环节
- 你怎么打的 —— 交战时长与结局、受到的伤害来自哪
- 数值平衡 —— 各条数值门槛的实际通过情况(含"样本不足 ⇒ 未判定")
外加一节隐私条款(本地随手可查)和一节默认折叠的机器附录(每个数字的来源、算法规格、 抑制明细与可机读片段)。
2. 它不做什么(边界,建议先读这一段)
- 不上传任何东西。产物只写在本机磁盘;模组不做任何网络请求。
- 不自动采集、不自动导出。采集需要玩家显式授权;导出必须由玩家在游戏内主动执行命令。 代码里没有定时器、没有自动触发点——"不得自动导出"是写不出来的,不是靠自觉。
- 不做服务器管理、不做多人监控。它是给玩家自己看自己这段时间的工具。
- 不证明别人的体验。一份报告只描述这一份存档、这一台机器上被观测到的行为; 样本不足的地方它写「未判定」,而不是猜一个数。
3. 隐私设计(可核对,不是承诺)
| 机制 | 怎么做到的 | 在哪里能核对 |
|---|---|---|
| 默认不采集 | 同意门(ConsentGate)默认关闭;同意文件缺失/损坏一律拒绝 |
common/privacy/…;游戏内 /octant status |
| 运行期零联网 | 构建期守卫逐文件扫源码,命中联网 API 即失败 | pipeline/build.gradle 的 assertNoNetworkApis |
| 只由玩家触发 | 导出只挂在命令与 ESC 菜单按钮上,无定时器 | /octant export;ESC 菜单按钮 |
| 单文件、零外链 | 样式与字体子集内联,报告可离线打开、可整份转发 | 报告的 <style> 与字体资产;自检还会断言"无远程外链" |
| 可随时撤回 | /octant revoke 立即停止采集;清除操作覆盖事件、账本与盐并给出删除收据 |
/octant revoke;清除操作 |
| 标识最小化 | 玩家键 = 盐派生的假名;对手键 = 会话内序号 <entityType>#<n>(禁止用实体 UUID 或自定义名派生) |
OpponentKeyAllocator;docs/design/data-contracts.md §2.4 |
| 未登记字段不落盘 | 脱敏管道对字段表里没有的键一律清空取值并记违规(fail-closed) | FieldRegistry + docs/privacy/schema/(两侧一致性由测试强制) |
| 抑制而不是编数 | 样本不足的指标写「未判定(样本不足)」并给原因码,绝不画成 0 | 报告的抑制明细与机器附录 |
本地数据落点(玩家可自行检查、可自行删除):
<存档>/octant/events/raw/ 已采集的原始事件(本机,永不导出)
<存档>/octant/meta/salt.bin 每存档假名盐(永不导出)
<存档>/octant/state/ 会话与截断账本
<gameDir>/config/octant/ 同意状态、同意履历账本
<gameDir>/octant/exports/ 导出产物(报告在这里)
从旧版本(
mcinsight名称时期)升级时,上述目录会一次性自动迁移,授权状态不会丢失。 代码里的mcinsight字样因此不是漏改的残留:它是遗留目录名与清理规则的判据 (OctantPaths.LEGACY_NAME、DataEraser删mcinsight*.log),改名会直接破坏迁移。
4. 支持的平台与安装
六个组合都已完成构建与产物校验(verifyModJar 逐条目断言)。选择与你的实例对应的一行:
| 组合 | 加载器版本(构建时钉住) | Java | 产物 |
|---|---|---|---|
| Forge × 1.20.1 | Forge 47.4.23(官方 mappings) | 17 | forge/1.20.1/build/libs/octant-0.1.0.jar |
| Forge × 1.21.1 | Forge 52.1.16 | 21 | forge/1.21.1/build/libs/octant-0.1.0.jar |
| NeoForge × 1.20.1 | NeoForge 线 47.1.106(net.neoforged:forge,legacy) |
17 | neoforge/1.20.1/build/libs/octant-0.1.0.jar |
| NeoForge × 1.21.1 | NeoForge 21.1.251 | 21 | neoforge/1.21.1/build/libs/octant-0.1.0.jar |
| Fabric × 1.20.1 | Loader 0.19.5 / Fabric API 0.92.12+1.20.1 | 17 | fabric/1.20.1/build/libs/octant-0.1.0.jar |
| Fabric × 1.21.1 | Loader 0.19.5 / Fabric API 0.116.17+1.21.1 | 21 | fabric/1.21.1/build/libs/octant-0.1.0.jar |
安装:从下载与你的实例对应的 jar(发行文件名已带平台与 MC 版本),
放进实例的 mods/ 目录。若自己从源码构建,六个模块产出的 jar 同名(octant-0.1.0.jar),
自用时建议先改名成 octant-forge-1.20.1.jar 这类能区分的名字。
纯客户端即可 / 纯服务端也可:本模组不注册网络通道、不改协议(displayTest = "IGNORE_ALL_VERSION"),
装了它的客户端可以连没装的服务器,反之亦然。
5. 使用
入口:ESC 菜单底部的 「Octant 报告」 按钮(点开即是导出面板)。也可以直接用命令:
| 命令 | 作用 |
|---|---|
/octant status |
查看同意状态、采集计数、产物落点(只读) |
/octant grant |
明确授权采集与本地导出(会告知未做哪些事、随时可撤回) |
/octant revoke |
撤回授权(立即停止采集) |
/octant export |
现在导出一次报告包(唯一会产出产物的动作) |
/octant verify |
无头自检:验证引擎随 jar 可运行 |
导出后的产物:
<gameDir>/octant/exports/<exportId>/
├── report.html ← 直接双击打开就是最终报告(单文件、离线可用)
├── report.md 纯文本版
├── analysis.json 指标与结论(机器可读)
├── metrics.json / conclusions.json
├── events.anonymized.jsonl 脱敏后的事件流
├── redaction_report.json 脱敏明细
├── PRIVACY-README.txt 这份产物里有什么、没有什么
└── manifest.json 溯源与版本声明
6. 报告长什么样
正文四节 + 隐私条款 + 默认折叠的机器附录;整份报告是单文件、无远程引用的 HTML。 图都是自绘的内联 SVG:
- 累积推进图:各内容组的推进脊线 + 累积线,鼠标悬停看具体数值
- 玩家画像:七轴雷达,四层同心网格 + 轴点悬停;没有分值的轴不画进多边形, 并在图下与表格里标「未判定(样本不足)」——把"没测出来"画成 0 是本项目明令禁止的
- 卡点 / 死亡 / 经济与门槛等条形图,每条都带"样本依据"与抑制原因
报告里的每条小提示都来自一个可核对的提示库(pipeline/src/main/resources/content/tips.tsv,
含出处与适用条件),语气尽量像"有人在旁边提一句",而不是教你做事。
7. 从源码构建
模块形态:common(平台无关采集模型与契约)、pipeline(二次处理与三形态导出)、
capture-core(六个组合共用的平台无关采集核心,一行不含 net.minecraft 引用,由
assertNoMinecraftRefs 守卫)、<加载器>/<MC 版本>(平台适配层)。
平台模块默认不参与构建(避免解析 Minecraft 依赖拖慢纯 Java 单测),需要 -Poctant.platforms=true 打开。
两个 wrapper,不是一个——这不是洁癖,是插件版本约束逼出来的:
| wrapper | Gradle | 用于 |
|---|---|---|
./gradlew(本仓库另有串行化的 gradlew-locked.bat) |
8.9 | Forge × 1.20.1、NeoForge × 2、Fabric × 2 |
tools/gradle96/gradlew |
9.6.1 | Forge × 1.21.1 |
原因(均为实测坐标,不是推断):ForgeGradle 6 硬拒 Gradle ≥ 9;ForgeGradle 7(1.21.1 用的那条线)
要求 Gradle ≥ 9.3;Fabric Loom 1.7.4 在 Gradle 9 上会 LoomGradleExtensionImpl 失败,只能 8.x。
于是 1.21.1 的 Forge 单独走第二个 wrapper;两个 wrapper 共用同一把仓库级锁,不会互相踩。
# ① 五个组合(Gradle 8.9)
./gradlew -Poctant.platforms=true \
:forge:mc1201:verifyModJar :fabric:mc1201:verifyModJar :fabric:mc1211:verifyModJar \
:neoforge:mc1201:verifyModJar :neoforge:mc1211:verifyModJar
# ② Forge × 1.21.1(Gradle 9.6.1,独立开关)
tools/gradle96/gradlew -Poctant.platforms=true -Poctant.platforms.forge1211=true :forge:mc1211:verifyModJar
# ③ 纯 Java 测试(不需要 -Poctant.platforms,离线可跑)
./gradlew :common:test :capture-core:test :pipeline:test
verifyModJar 的意义:逐条目断言 jar 里必须有(平台元数据、图标、content/tips.tsv、
字体资产、平台入口类、capture/* 共享核心类),并且必须没有(PDF/图表库)。六个组合实测
产物均为 5.7 MB 左右 / 404–411 个条目,每个 jar 都含共享核心的 26 个类与 2 个字体子集。
测试基线(在本仓库的干净克隆里重测过)::common:test 248 用例 / 0 失败、
:capture-core:test 30 用例 / 0 失败、:pipeline:test 103 用例 / 6 失败
(那 6 项即 §8 第 4 条列的遗留红项)。
本仓库不发布测试数据(
samples/等),因此依赖导出物抽样的守卫 (:checkContractConformance的"实测项")会报未判定并返回退出码 3——这是三值语义的正确表现 (缺失 ≠ 通过),不是构建失败。
8. 兼容性与已知问题
兼容性:见 §4 的六个组合。其余组合(例如 1.20.1 之外的老版本、Quilt 等)未验证,不在承诺范围内。
已知问题(如实列出,没修完的不写成修完了):
- 事件覆盖 10/24 种。已接线:会话开始/心跳/结束、进度获得、玩家死亡、生物群系、物品行为、
容器快照、战斗开始/结束。其余 14 种(任务、机器、卡点段等)在代码里被显式登记为"未接线"
(
ObservationAdapter.unwiredTypes(),并由测试断言两侧恰好覆盖契约全集),而不是假装覆盖。 - 导出落点与"游戏目录"语义不符:实现把存档目录的上一级当作
gameDir(worldDir.getParent()),于是产物落在<实例>/saves/octant/exports/, 严格语义应为<实例>/octant/exports。显示路径与实际落点已统一到同一来源,但根因未改。 - 报告界面目前只有中文。
:pipeline有 6 项判据为红(PDF 时代遗留口径、pinned 指纹,以及两处真实但不影响产物的 文案/字体问题)。已用真实产物实测:这 6 项不改变 HTML 产物的任何读者可见内容。- NeoForge × 1.21.1 的元数据有两处只有文档依据、缺一手产物证据:清单文件名
neoforge.mods.toml与依赖字段type(而非mandatory)。两者写错的后果是"构建全绿、游戏里什么都不发生", 因此这一条只能由一次真实游戏加载来关闭;本次交付未做该加载,故如实登记为未验证。 - 本版尚未上架 CurseForge / Modrinth;目前以 GitHub 发行与本地构建分发。
9. 许可与第三方
- 本模组:MIT(含一段范围说明:不覆盖 Mojang 资源;不自动覆盖第三方依赖)。
- 随 jar 附带的报告字体:SIL OFL-1.1,许可文本随包(
…/font/OFL-1.1-LICENSE.txt)。 - 模组 jar 不含任何第三方运行时库(PDF / 图表库已从产品路径移出,仅存在于离线导出工具侧)。
- Mojang 资源:不随附任何。
- 第三方清单与许可文本:
THIRD-PARTY-NOTICES.md、docs/verification/licenses/。
10. 进一步阅读
docs/design/data-contracts.md—— 数据契约(构建期守卫会实时从它解析闭集)docs/privacy/schema/—— 导出物 JSON Schema 与抑制原因码THIRD-PARTY-NOTICES.md·LICENSE
本仓库是源码发布:内部的设计/验证台账、测试数据与构建产物都未随源码发布, 因此源码注释里会出现
docs/…的引用,指向的是那些未发布的内部文档。


