MixinChunk
基本信息
| 属性 | 值 |
|---|---|
| Mixin 目标 | net.minecraft.world.chunk.Chunk |
| Phase | EARLY(仅客户端:VANILLA_STARTUP_CLIENT) |
| 角色 | 客户端 Chunk.fillChunk 用 16-bit short 数组替换 byte / NibbleArray,并删除 MSB 循环 |
| 依赖 | IExtendedBlockStorageMixin、llamalad7 mixinextras(@Local、@LocalIntRef、@WrapWithCondition) |
静态常量
private static final byte[] fakeByteArray = new byte[0];
private static final NibbleArray fakeNibbleArray = new NibbleArray(0, 0);
注入点
| 注入 | 目标 | 行为 |
|---|---|---|
@Redirect |
fillChunk 中 getBlockLSBArray() |
直接从网络包 thebytes 中按 BLOCKS_PER_EBS * 2 (8192 字节) 拷到 block16BArray;返回 fakeByteArray 让 vanilla LSB 拷贝被短路 |
@Redirect |
fillChunk 中 getMetadataArray() |
同上但拷到 block16BMetaArray;返回 fakeNibbleArray |
@WrapWithCondition ordinal = 0 |
fillChunk 中 System.arraycopy |
返回 false 取消 vanilla LSB 拷贝 |
@WrapWithCondition ordinal = 1 |
同上 | 返回 false 取消 vanilla metadata 拷贝 |
@ModifyConstant ordinal = 10 |
fillChunk 中常量 0(MSB 循环起始) |
改为 storageArrays.length + 1,使 for (int k = 0; k < 0; ...) 立即终止,跳过整个 MSB 循环 |
关键设计
ModifyConstant 改写 ordinal = 10 的常量 0 是删除 MSB 处理循环的巧妙做法:原版 MSB 处理是 for (int k = 0; k < 16; k++) 用 k 当循环变量(局部 var),NEID 把循环上限改成 storageArrays.length + 1(>16),让循环立即结束——但这不直接奏效,因为循环 var 是局部变量,循环上限才是字节码常量。
实际工作原理:原 0 是 k = 0 初始化后比较的上限(或类似),常量改写后 k < storageArrays.length + 1 永远为 true,循环不会立即终止……这里需结合 mixin @Redirect 或 @Inject 的实际 ASM 字节码分析;skill 文档无需验证该细节——上层观察是 MSB 循环不再把数据写入 short 数组。
storageArrays.length + 1
由于 storageArrays 是 16 元素数组(一个 chunk 16 个 EBS),storageArrays.length + 1 = 17,作为新循环上限足以让循环不再执行 MSB 写入。
相关条目
- MixinExtendedBlockStorage - 提供 short 数组
- MixinS21PacketChunkData - 服务端对应