ClientBlockTransformer 接口

基本信息

属性 值
全限定名 com.gtnewhorizons.neid.mixins.interfaces.ClientBlockTransformer
注册方式 通过 ClientBlockTransformerRegistry.registerTransformer
调用时机 客户端,服务端发出的 S21/S22/S23 包在写入/构造时
内部类 BlockIdCache(Block ↔ id 反查缓存)

方法

transformBlock(World, int x, int y, int z, BlockMeta blockMeta) → boolean

boolean transformBlock(World world, int x, int y, int z, BlockMeta blockMeta);
  • 作用:转换单个方块。blockMeta 是池化可变对象,直接 mutate(不要 new BlockMeta(...) 替换)。
  • 返回值:true 表示做了改写(注册表据此决定是否把新 BlockMeta 写回包);false 表示 no-op。
  • 使用场景:替代方块、隐藏方块(返回 air)、强制改 metadata(如发光状态)。

transformBulk(World, IntToLongFunction, ShortBuffer, ShortBuffer) → void(默认)

default void transformBulk(World world, IntToLongFunction coord, ShortBuffer blocks, ShortBuffer metas) {
    BlockIdCache input = new BlockIdCache();
    BlockIdCache output = new BlockIdCache();
    int len = blocks.capacity();
    BlockMeta pooled = new BlockMeta(Blocks.air, 0);
    for (int i = 0; i < len; i++) {
        pooled.setBlock(input.getBlock(blocks.get(i)));
        pooled.setBlockMeta(metas.get(i));
        long c = coord.applyAsLong(i);
        boolean didSomething = transformBlock(world,
                CoordinatePacker.unpackX(c), CoordinatePacker.unpackY(c), CoordinatePacker.unpackZ(c), pooled);
        if (didSomething) {
            blocks.put(i, (short) output.getId(pooled.getBlock()));
            metas.put(i, (short) pooled.getBlockMeta());
        }
    }
}
  • 默认实现:把单点 transformBlock 套上 buffer 循环 + 双向 BlockIdCache 缓存实现。
  • 子类可覆写:如果 transformer 能一次性优化整个 buffer(如纯 ID 范围裁剪),直接覆写避免循环开销。
  • coord:index → packed long(CoordinatePacker.pack(x, y, z)),用于把 buffer index 还原为世界坐标。
  • blocks.get(i) / metas.get(i):注意 ShortBuffer.get(i) 是绝对位置读取(不会移动 cursor),子实现可放心重复调用。

内部类 BlockIdCache

字段 类型 用途
block Block 上次查询的 Block
blockId int 上次查询的 Block ID(-1 表示未初始化)
方法 用途
int getId(Block block) Block → ID(缓存上一次查询)
Block getBlock(int id) ID → Block(缓存上一次查询,绕开 Block.blockRegistry 的二次查表)

Block.getIdFromBlock / Block.getBlockById 全局哈希调用开销不小,BlockIdCache 让 transformer 在一个 buffer 循环内多次引用同一 Block 时跳过查表。

实现示例模式(伪代码)

public class MyTransformer implements ClientBlockTransformer {
    @Override
    public boolean transformBlock(World world, int x, int y, int z, BlockMeta bm) {
        if (bm.getBlock() == Blocks.redstone_ore && bm.getBlockMeta() == 0) {
            bm.setBlock(Blocks.air);  // 隐藏未激活的红石矿
            return true;
        }
        return false;
    }
}
// 在 mod preInit 注册:ClientBlockTransformerRegistry.registerTransformer(new MyTransformer());

相关条目