You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Minecraft Forge 1.12.2自定义物品右键无法放置水问题求助

解决Minecraft 1.12.2 Forge自定义物品无法放置水的问题

嘿,我在1.12.2 Forge开发自定义物品时碰到过一模一样的问题——消耗动画跑起来了,但水就是出不来。大概率是几个常见的逻辑疏漏,咱们一步步排查修复:

1. 必须在服务器端处理方块放置

Minecraft的客户端和服务器是分离的,如果你在客户端代码里修改世界(比如放水),只会在本地看到临时视觉效果,服务器不会同步这个变化,刷新后就没了。所以一定要先判断当前环境,只在服务器执行方块修改:

@Override
public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
    // 跳过客户端逻辑,只在服务器处理世界修改
    if (worldIn.isRemote) {
        return EnumActionResult.SUCCESS;
    }

    ItemStack stack = player.getHeldItem(hand);
    BlockPos placePos = pos.offset(facing);

    // 检查目标位置是否能放置水
    if (worldIn.isAirBlock(placePos) && Blocks.WATER.canPlaceBlockAt(worldIn, placePos)) {
        // 放置水方块
        worldIn.setBlockState(placePos, Blocks.WATER.getDefaultState());
        
        // 消耗物品(创造模式不消耗)
        if (!player.capabilities.isCreativeMode) {
            stack.shrink(1);
        }

        return EnumActionResult.SUCCESS;
    }

    return EnumActionResult.FAIL;
}

2. 正确处理右键事件的返回值

如果你的物品逻辑是在onItemRightClick(空右键,不点击方块)里实现的,一定要确保返回的ActionResult<ItemStack>标记为成功,不然游戏会认为这次交互没完成,可能导致后续逻辑不触发:

@Override
public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) {
    ItemStack stack = playerIn.getHeldItem(handIn);
    if (!worldIn.isRemote) {
        // 获取玩家前方的放置位置(可根据需求调整距离)
        BlockPos placePos = playerIn.getPosition().offset(playerIn.getHorizontalFacing(), 1);
        if (worldIn.isAirBlock(placePos) && Blocks.WATER.canPlaceBlockAt(worldIn, placePos)) {
            worldIn.setBlockState(placePos, Blocks.WATER.getDefaultState());
            if (!playerIn.capabilities.isCreativeMode) {
                stack.shrink(1);
            }
        }
    }
    // 返回成功,让游戏确认这次交互有效
    return new ActionResult<>(EnumActionResult.SUCCESS, stack);
}

3. 检查放置位置的合法性

水方块不是随便能放的,要确保两个核心条件:

  • 目标位置是空气方块(worldIn.isAirBlock(placePos)
  • 目标位置满足水的放置规则(Blocks.WATER.canPlaceBlockAt(worldIn, placePos)),比如不能放在下界岩上(1.12.2里会直接变成黑曜石),也不能放在半砖之类的非完整方块上

4. 验证物品消耗的同步逻辑

虽然你说消耗动画正常,但还是要注意:物品栈的修改必须在服务器端执行,客户端会自动同步服务器的物品状态,不要在客户端手动调用stack.shrink(1),否则会出现“客户端显示消耗、服务器实际没变化”的不同步问题。

按上面的步骤调整代码,应该就能解决问题了——我之前就是因为漏了!worldIn.isRemote的判断,折腾了好半天呢。

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

火山引擎 最新活动