TileEntityReplacementManager

基本信息

属性 值
完整类名 com.gtnewhorizons.postea.api.TileEntityReplacementManager
包路径 api
类型 公共 API 注册表(abstract class, 不允许实例化)
调用时机 FMLPostInitializationEvent 或更晚(推荐 FMLLoadCompleteEvent 之后)
关联事件 ChunkEvent.Load

功能

Postea 的核心 API 之一。允许其他 mod 在世界区块加载阶段拦截任意 TileEntity NBT 数据,对其执行以下三种操作之一:

  1. TileEntity → 普通方块:删除 TileEntity,将所在坐标替换为一个 Block,并保留原 metadata。
  2. 纯 NBT 转换:保留 TileEntity 类型,仅修改内部 NBT 字段(修改物品栏、能量值、自定义数据等)。
  3. TileEntity 整体替换:换成另一种 TileEntity 类型,并将旧 NBT 字段映射到新 NBT。

TileEntity 转换器总是在 Block 转换器之前执行。当返回 null 时表示当前 handler 不识别该 TileEntity,Postea 会继续调用后续 handler。

方法

tileEntityTransformer(String, TriFunction<NBTTagCompound, World, Chunk, BlockInfo>)

注册一个 TileEntity 转换回调。

  • tileEntityId:要拦截的 TileEntity 类 ID(字符串,如 "Chest"、"GT_TileEntity_Ores")。
  • transformerFunction:接收 TileEntity 的 NBT、世界、区块,返回 BlockInfo 表示转换结果;返回 null 则跳过。

回调触发条件:世界加载时,对应 TileEntity 类型被反序列化之前。

createTETagAtSamePosition(String newId, NBTTagCompound tag)

生成一个仅保留坐标信息(x/y/z)的 TileEntity NBT 模板。可用于"整体替换 TileEntity 类型"的场景中复用旧坐标,避免手动读取 tag.getInteger("x") 等字段。

参数 说明
newId 新 TileEntity 的类型 ID
tag 旧 TileEntity 的 NBT(不会被修改)

返回值:仅包含 id 与坐标字段的新 NBTCompound。

行为规则

规则 说明
多个 handler 顺序 按注册顺序依次执行,任一返回非 null BlockInfo 即终止
返回 null 表示本 handler 不处理,Postea 继续调用后续 handler
区块加载期间世界未就绪 world.getBlock 在转换时会抛异常——必须使用 BlockAccessCompat 替代
执行位置 TileEntity transformers → Block transformers → Simple transformations
执行时机 每个区块加载时(去重后);dev 环境下每次进出区块都会重新执行,便于调试

数据结构 BlockInfo(utility/BlockInfo)

转换回调的返回值类型。

字段 类型 说明
block Block 替换后的方块
metadata int 替换方块的 metadata
tileTransformer Function<NBTTagCompound, NBTTagCompound> NBT 转换回调;null 表示删除 TileEntity

提供两个构造函数:

构造签名 行为
BlockInfo(Block, int) 删除 TileEntity,替换为普通方块
BlockInfo(Block, int, Function<NBTTagCompound, NBTTagCompound>) 替换方块并转换 NBT

使用模式

模式 1:TileEntity → 普通方块

将 GregTech 旧版矿石 TileEntity 全部抹除,按维度染成不同颜色的羊毛:

TileEntityReplacementManager.tileEntityTransformer("GT_TileEntity_Ores", (tag, world, chunk) -> {
    if (world.provider.dimensionId == -1) return new BlockInfo(Blocks.wool, 1);  // 下界
    if (world.provider.dimensionId == 1)  return new BlockInfo(Blocks.wool, 2);  // 末地
    return new BlockInfo(Blocks.wool, 3);                                       // 主世界
});

模式 2:纯 NBT 转换(保留 TileEntity)

修改箱子内的物品 ID(13 槽位 → 钻石,其余 → 石头),不改变箱子本身:

TileEntityReplacementManager.tileEntityTransformer("Chest", (tag, world, chunk) -> {
    NBTTagList slots = tag.getTagList("Items", 10);
    for (int i = 0; i < slots.tagCount(); i++) {
        NBTTagCompound slot = slots.getCompoundTagAt(i);
        if (IDExtenderCompat.getItemStackID(slot) != reedsId) continue;
        if (slot.getByte("Slot") == 13) {
            IDExtenderCompat.setItemStackID(slot, diamondId);
        } else {
            IDExtenderCompat.setItemStackID(slot, stoneId);
        }
    }
    return null;  // 不替换方块
});

模式 3:TileEntity 整体替换(带 NBT 映射)

将 Furnace 替换为 Chest,搬运原物品栏;若原方块是点燃的熔炉则追加一个 fire charge:

TileEntityReplacementManager.tileEntityTransformer("Furnace", (tag, world, chunk) -> {
    int[] idMeta = BlockAccessCompat.getBlockIDAndMetaAtTE(tag, chunk);
    int blockId = idMeta[0], meta = idMeta[1];
    return new BlockInfo(Blocks.chest, meta, oldTag -> transformFurnaceNBT(oldTag, blockId));
});

第三方 mod 集成

  • 依赖:required-after:gtnhlib@[0.6.21,)。
  • 跨 mod 调用:所有其他 API(BlockReplacementManager、ItemStackReplacementManager、BlockAccessCompat、IDExtenderCompat)都通过本类定义的转换流程协同工作。

相关条目