You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Forge 1.20.1中如何将手持物品NBT数据转移至放置的方块

解决手持物品NBT转移到放置方块的空指针问题及实现方案

问题分析

你的代码存在几个导致空指针(NullPointerException)的核心问题:

  • 强制类型转换风险:直接将event.getEntity()转为ServerPlayer,若放置方块的实体不是玩家(如发射器),会触发类型转换异常。
  • NBT键空值未处理:itemNBT.get("tag")在物品无自定义NBT时会返回null,直接用Objects.requireNonNull包裹会触发空指针。
  • 方块实体初始化时机:BlockEvent.EntityPlaceEvent触发时,部分方块的实体可能未完全初始化,直接调用getBlockEntity()可能返回null。
  • NBT结构不匹配:方块实体与物品的NBT结构不同,直接将物品的tag键放入方块实体NBT,不符合多数方块实体的预期格式。

修改后的代码

@SubscribeEvent
public static void onBlockPlacedBy(BlockEvent.EntityPlaceEvent event) {
    // 仅处理玩家放置的情况
    if (!(event.getEntity() instanceof ServerPlayer player)) {
        return;
    }

    Block placedBlock = event.getPlacedBlock().getBlock();
    if (!blockList.contains(placedBlock)) {
        return;
    }

    ItemStack heldStack = player.getMainHandItem();
    // 检查手持物品是否存在自定义NBT
    if (!heldStack.hasTag()) {
        return;
    }

    CompoundTag itemCustomTags = heldStack.getTag();
    BlockPos blockPos = event.getPos();
    Level level = event.getLevel();

    // 安全获取已初始化的方块实体
    level.getBlockEntity(blockPos, BlockEntityTypes.ANY).ifPresent(blockEntity -> {
        CompoundTag blockNBT = blockEntity.serializeNBT();
        // 将物品自定义NBT合并到方块实体NBT中
        blockNBT.merge(itemCustomTags);
        blockEntity.deserializeNBT(blockNBT);
        // 标记方块实体变更并同步到客户端
        blockEntity.setChanged();
        level.sendBlockUpdated(blockPos, blockEntity.getBlockState(), blockEntity.getBlockState(), Block.UPDATE_ALL);
    });
}

关键修改说明

  • 安全的实体类型校验:用instanceof模式匹配获取ServerPlayer,避免类型转换错误。
  • 前置NBT检查:通过heldStack.hasTag()判断物品是否有自定义NBT,跳过无数据的情况。
  • 非空安全的方块实体获取:用getBlockEntity(...)的Optional返回值,仅在实体存在时执行操作,避免空指针。
  • 正确的NBT合并方式:使用merge()方法将物品的自定义NBT直接合并到方块实体的NBT中,对齐原版方块(如告示牌、箱子)的NBT继承逻辑。
  • 客户端同步:修改后调用setChanged()和sendBlockUpdated(),确保客户端能同步到最新的方块实体NBT数据。

额外指引

  • 查看Minecraft原版代码中**告示牌(SignBlock)或箱子(ChestBlock)**的放置逻辑,学习原版如何处理物品NBT到方块实体的转移。
  • 参考Forge社区的开源示例Mod,专注于NBT处理的小型Mod能提供成熟的实现思路。
  • 调试时可使用Level#sendSystemMessage()输出NBT内容,确认数据是否正确传递。

内容的提问来源于stack exchange,提问作者ZeNyfh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:44:53