MixinS22PacketMultiBlockChange

基本信息

属性 值
Mixin 目标 net.minecraft.network.play.server.S22PacketMultiBlockChange
Phase EARLY
角色 多方块变化包按方块 6 字节写入 + 客户端方块转换钩子
依赖 ClientBlockTransformerRegistry、llamalad7 mixinextras @Local

常量改写(@ModifyConstant)

@init(I[SLnet/minecraft/world/chunk/Chunk;)V(构造时):

vanilla NEID 含义
4(每方块字节数) 6 2 ID + 2 meta + 1 sky + 1 block

NEID 每个方块占 6 字节(vanilla 是 4:1+1+1+1)。sky/block light 在 vanilla 中共享方块字节的高/低 4 位,NEID 改为各占独立字节。

写入重定向(@Redirect)

@init 内 DataOutputStream.writeShort(I)V ordinal = 1(vanilla 写 Metadata 为单字节):

private void neid$writeShortRedirectInConstructor(DataOutputStream dataOutputStream, int i,
        @Local Chunk p_i45181_3_, @Local(ordinal = 3) int l, @Local(ordinal = 4) int i1,
        @Local(ordinal = 5) int j1) throws IOException {
    Block block = p_i45181_3_.getBlock(l, j1, i1);   // 注意参数顺序:(x=l, y=j1, z=i1)
    int meta = p_i45181_3_.getBlockMetadata(l, j1, i1);

    pooled.setBlock(block);
    pooled.setBlockMeta(meta);

    boolean didSomething = ClientBlockTransformerRegistry.transformBlock(
            p_i45181_3_.worldObj,
            l + p_i45181_3_.xPosition * 16,
            j1,
            i1 + p_i45181_3_.zPosition * 16,
            pooled);

    if (didSomething) {
        block = pooled.getBlock();
        meta = pooled.getBlockMeta();
    }

    dataOutputStream.writeShort(Block.getIdFromBlock(block));
    dataOutputStream.writeShort(meta);
}

调用顺序

  1. 调 Chunk.getBlock(x, y, z) 拿服务端方块
  2. 调 ClientBlockTransformerRegistry.transformBlock 让所有注册的 transformer 改写
  3. 如果 didSomething,用 pooled 中的新方块/Metadata
  4. writeShort 写 16-bit ID + 16-bit Metadata

客户端反序列化

MixinNetHandlerPlayClient.handleMultiBlockChange(NetHandlerPlayClient mixin)配套:

  • 用 readShort() 读方块 ID(替换 Block.getBlockById(int) 调用)
  • readShort() & METADATA_MASK 读 Metadata(替换 WorldClient.func_147492_c 第 4 参数)

相关条目