|
|
330867c6df
|
版本隔离守卫(新套件立即抓出两处真实回流)
## 修掉渲染联测的嵌套实例目录
`test_render_bridge.py` 把实例写成 `<store>/instances/test-mcfold`。
而权威口径(mcview/lib/versions.cjs:59/61)是:
contentRoot = BASE/store/<key> 共享只读(jar/libraries/assets)
instanceDir = BASE/instances/<name> 实例独占(mods/config/options/saves)
⇒ 那是「一个版本的内容根里长出了实例态」。而版本隔离要防的崩因正是
「多实例共用 mods」—— 内层目录会把它重新引回来,而那条路径看起来完全合法。
改为 `BASE/instances/test-mcfold`。
## 新增 tests/test_version_isolation.py(4 项,默认套件里跑)
★ 它**不需要 JVM**(纯路径断言),所以必须落在默认测试里 ——
放进 `--with-render` 才跑的套件等于没守卫(大多数人不会加那个参数)。
✓ 三层同级(store/ · instances/ · runtime/ 是 BASE 下的兄弟)
✓ 内容根干净(无 instances/ 嵌套、无 mods/config/options.txt/saves)
✓ 测试实例归位(落在 instances/ 层,不在任何内容根下)
✓ 内容根无实例配置(查内容,不只查存在)
## ★ 守卫首次运行就抓出第二处(我此前漏掉的)
```
✗ 内容根被实例化:
- store/vanilla-1.21.1/instances/(内容根里嵌套了实例层)
```
内容是 `instances/default/{options.txt,downloads/log.json}`(生成态,
正式 `instances/default` 已存在)⇒ 已删。两个内容根现已干净。
⇒ 这条说明:**「我检查过了」不等于「有一条会自己跑的检查」** ——
我上一轮手工核实过 1.20.1 那处并修掉,却没发现 1.21.1 那处;
守卫一运行,两处一次全暴露。
## 验证
./run_tests.sh → 66 项
./run_tests.sh --with-render → **80 项全绿**
|
2026-09-26 07:23:54 +08:00 |
|
|
|
8b1fc9289d
|
Fabric 加载器路线跑通并落地验证(launcher="fabric",6/6 绿)
上个会话把 `launcher="fabric"` 写进了后端,却**没有留下任何可重跑的验证** ——
「经加载器能起来」这件事只活在对话里。本次把它变成可复算的。
## 机制(路线 C,不是 LOADERS.md 原来写的 A/B)
A/B 都假设「游戏由 Loader 起」。但 `Knot.init()` 是 public 的:它做完
「发现 mod → 建 KnotClassLoader → 应用 mixin → invokeEntrypoints(preLaunch)」
后**返回**,不进入官方主循环(那在 GameProvider.launch())。
⇒ `knot.loadIntoTarget("McfoldRenderServer")` 把我们的服务端注入同一个
KnotClassLoader —— **mod 生态与我们的控制权同时拿到,不必把服务改写成 mod**。
## 主要改动
### ① `RenderBackend._fabric_classpath()` —— 组装从用户手里移到后端
两个变换是实测必需、且用户不该自己拼的机械操作:
- 剔除 1.20.1 自带的 asm(9.2 与 9.6 两版并存)—— 否则 Knot.<clinit> 抛
"duplicate ASM classes found on classpath"
- 追加 Fabric 的 8 个库(asm×5 / sponge-mixin / intermediary / fabric-loader)
库来源改为内容根 `.mcfold/fabric/`(原在 /tmp/fab,tmpfs 且违反版本隔离)。
实测 67 条 → 去 7 asm + 加 8 fabric = 68 条。
### ② `tests/test_loader_render.py`(新增,6 项)
✓ 启动架构与世代正交(动态子类,不写 N 个类)
✓ 两个架构可枚举
✓ classpath 组装(67→68:去 7 asm,加 8 fabric)
✓ 非 asm 库原样保留(去 asm 是外科手术,不是重写)
✓ **Fabric 加载器真启动并渲染**(KnotClassLoader / chunks=10..25 / colors=4391..4547)
✓ **Fabric 拒绝不兼容 mod** ← 反向对照:缺 fabric-api 的 Explorify 被拒
最后一条是**两条路线的可判差异**:零加载器是「无脑注册」,不知道 mod 要
fabric-api;Fabric 会。没有它,"加载器真的介入了"这句话就没有反面证据。
### ③ `run_tests.sh` —— 慢套件改为列表驱动 + 全跳过不再报绿
- SLOW 列表含 test_render_bridge / test_loader_render(默认不跑)
- ★ 全部跳过的套件**不算绿**:报"跳过 N 项"而非计入通过数 ——
否则"没测"会被读成"测过了"。
## 验证
./run_tests.sh → 62 项(2 个慢套件标 ⊘)
./run_tests.sh --with-render → **76 项全绿**
(62 单元 + test_render_bridge 8 + test_loader_render 6)
## 仍未做
Iris 光影真实加载(加载器已通,未验过一次 shader pack)
forge / neoforge 后端(gen_1_20 / gen_1_21 均待设计)
|
2026-09-26 07:12:41 +08:00 |
|
|
|
35534b1564
|
feat: get_block_info —— 方块信息查询(Java 侧回答,Python 只路由)
新增 cmd=blockinfo(两代后端编译通过、实测):
返回 block 名(含 mod 方块)、stateId、属性、isAir/isSolid、
光照/硬度、贴图缺失的程序化判据、是否来自 mod。
★ 修掉一个真实缺陷(附录 D 的语义区分落到了实处):
未加载区块原先返回 void_air(known=true),实测发现两个 API 都不可用:
- ClientLevel.hasChunk() 反编译实测**恒返回 true**
- ChunkSource.hasChunk() 走 getChunk(...,false),而 ClientChunkCache
覆写后在该参数下返回 emptyChunk(占位,非 null)⇒ 也恒 true
正解:getChunk(..., requireChunk=**false**) 判 null
(反编译:return requireChunk ? emptyChunk : null;)
⇒ 现在未加载明确回 known=false + reason=chunk_not_loaded
实测(1.20.1):
草地 → minecraft:grass_block props={'snowy':'false'} missing=False
原木 → minecraft:oak_log props={'axis':'y'}
空气 → minecraft:air
远处 → known=false reason=chunk_not_loaded ← 与空气区分
实测(1.21.1 + mod):
mts:mtsofficialpack.fancydirt_block mod=True tex=mtsofficialpack:block/fancydirt
createbigcannons:steel_block mod=True tex=createbigcannons:block/steel_block
⇒ mod 方块同样能查到正确贴图名与 fromMod 标记
顺带修 gen_1_21 两处世代差异(ChunkStatus 换包、bridge 编译顺序)。
测试:69 项全绿(新增 test_get_block_info 6 条判据)
|
2026-09-26 00:24:29 +08:00 |
|
|
|
16f2e04fff
|
架构重构:差异全部下移到 Java,Python 只做路由
用户口径:差异放在 Java 层,Python 相当于路由。
下移到 Java(新增 cmd=setblocks):
Python 只发 RLE([[stateId,count],...]),Java 用官方 API 完成
调色板组装 / 位打包 / 官方序列化 / 入 cache / 渲染。
★ 意外收益:走 ClientboundLevelChunkPacketData(chunk).getReadBuffer()
+ replaceWithPacketData(...) 这条官方路径,两代签名完全一致
⇒ 原先的 Storage.chunks 反射注入**整段删掉**。
新增 cmd=capacity:世界尺寸(sectionsCount/minSection/defaultBiome)
由运行时回答,Python 不再硬编码 24/-4(1.16 时代是 16/0)。
Python 侧删除(防回归,见 test_import_surface):
render_bridge.py(旧桥,无世代概念)
render._pack/_long_array/_encode_paletted/_encode_chunk/_varint
anvil.encode_block_section/encode_chunk_payload/save_chunk_to_payload
合计 454→374 行(render.py)、300→177 行(anvil.py)
保留在 Python(都是「不随版本变」的知识):
RLE 压缩(rle_encode/rle_decode,具名可测)
存档读取(region/NBT)
方块名→id 的路由(查询在 Java)
NDJSON 协议
测试:62 项单元 + 6 项渲染联测全绿
新测试反映新架构:RLE 边界、运行时容量、世代分派、新路径渲染
test_anvil 里原有 8 项协议位打包测试已删(那已下移到 Java,
由两代后端各自的编译验证覆盖)
新增 scaffold/ARCHITECTURE.md(分层原则 + 加新世代步骤 + 防回归清单)
|
2026-09-25 19:21:45 +08:00 |
|
|
|
34ed70ab53
|
修复视距不生效 + 接入统一测试
视距(用户报「无法调整视距?」)——根因是三处不同步:
1. options.renderDistance 本地设置(原先只设了这个)
2. options.setServerRenderDistance 服务端下发上限(getEffectiveRenderDistance = min(两者))
3. ClientChunkCache.updateViewRadius storage 半径
第三处最关键:官方只在收到服务端半径包时才调它(ClientPacketListener:2316),
我们不连服 ⇒ Storage.inRange 用旧半径判定,超出区块被**静默丢弃**。
另一个前置:加载半径必须跟随视距。视距 12 只喂 3 圈数据,
画面看起来就像没生效(最容易误判的坑)。
实测(同相机同存档):
视距 4 → 注入 81 渲染 55 色彩 15226
视距 12 → 注入 595 渲染 447 色彩 18477
画面差异显著:RD=12 能看到延伸到地平线的森林与完整海岸线。
(sample-render-distance-{4,12}.png)
测试:新增 tests/test_anvil.py(13 项,存档/NBT/编码)
tests/test_render_bridge.py(3 项,桥协议+合成渲染+真实存档渲染)
run_tests.sh 改为默认跑单元测试、--with-render 跑联测
合计 61 项全绿(原 48 + 13)
|
2026-09-25 17:47:58 +08:00 |
|
|
|
5038c7f679
|
feat(mcfold): P7 实例层(传入文件夹→拉起实例→读mod注册方块表→连服,含端到端验证)+ 统一测试入口
|
2026-09-25 14:36:21 +08:00 |
|
|
|
b0182de8c7
|
feat(mcfold): P6 世界模型(多区块聚合/负坐标定位/unloaded与air语义分明/mod降级统计)
|
2026-09-25 14:33:26 +08:00 |
|
|
|
85ad7e580e
|
feat(mcfold): P5 mod jar 解析(三种加载器+多加载器诊断+方块名提取,含诚实边界标注)
|
2026-09-25 14:32:39 +08:00 |
|
|
|
40c5739cae
|
feat(mcfold): P4 区块解析(位打包/三种调色板分支/注册表显式降级)+ prismarine 真实数据交叉验证
|
2026-09-25 14:25:34 +08:00 |
|
|
|
a4914b932e
|
feat(mcfold): 最小客户端 + 跨实现互操作测试(Python 客户端握手 Node 服务端成功)
|
2026-09-25 14:12:06 +08:00 |
|
|
|
fc5a1aae91
|
feat(mcfold): 声明式 protodef 解释器(原生类型+阶段作用域+switch/mapper/bitfield),真实握手字节验证通过
|
2026-09-25 14:10:40 +08:00 |
|
|
|
22cdee35e3
|
feat(mcfold): P1 按实例文件夹解析版本(inheritsFrom 归一化 + 加载器判定)+ 回归测试
|
2026-09-25 14:06:55 +08:00 |
|