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

Forge开发中调用setBlock()放置自定义方块报错的问题咨询

Minecraft 模组开发方块放置错误解决

问题情况

用代码 level.setBlock(pos, Blocks.DIRT.defaultBlockState(), 1); 能正常放置原版方块,但放置自定义方块 ModBlocks.lock 时弹出错误:

The method setBlock(BlockPos, BlockState, int) in the type Level is not applicable for the arguments (BlockPos, RegistryObject, int)

我一开始误以为自定义方块不能用 defaultBlockState(),想直接实现 level.setBlock(pos, ModBlocks.lock, 1) 的效果,相关代码如下:

ModBlocks.java

package com.redmecanics.villagedestroyer.block;

import java.util.function.Supplier;

import com.redmecanics.villagedestroyer.VillageDestroyer;
import com.redmecanics.villagedestroyer.item.ModCreativeModeTab;
import com.redmecanics.villagedestroyer.item.ModItems;

import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Material;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

public class ModBlocks {
    public static final BooleanProperty defState = BooleanProperty.create("defaultBlockState");
    
    public static final DeferredRegister<Block> BLOCKS =
            DeferredRegister.create(ForgeRegistries.BLOCKS, VillageDestroyer.MOD_ID);

    public static final RegistryObject<Block> aluminium_block = registerBlock("aluminium_block",
            () -> new Block(BlockBehaviour.Properties.of(Material.METAL)
                    .strength(3f).requiresCorrectToolForDrops()), ModCreativeModeTab.villagedestroyer_tab);

    public static final RegistryObject<Block> aluminium_ore = registerBlock("aluminium_ore",
            () -> new Block(BlockBehaviour.Properties.of(Material.STONE)
                    .strength(3f).requiresCorrectToolForDrops()), ModCreativeModeTab.villagedestroyer_tab);
    
    public static final RegistryObject<Block> deepslate_aluminium_ore = registerBlock("deepslate_aluminium_ore",
            () -> new Block(BlockBehaviour.Properties.of(Material.STONE)
                    .strength(3f).requiresCorrectToolForDrops()), ModCreativeModeTab.villagedestroyer_tab);
    
    public static final RegistryObject<Block> lock = registerBlock("lock",
            () -> new Block(BlockBehaviour.Properties.of(Material.METAL)
                    .strength(-1f)), ModCreativeModeTab.villagedestroyer_tab);


    private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block, CreativeModeTab tab) {
        RegistryObject<T> toReturn = BLOCKS.register(name, block);
        registerBlockItem(name, toReturn, tab);
        return toReturn;
    }

    private static <T extends Block> RegistryObject<Item> registerBlockItem(String name, RegistryObject<T> block,
                                                                            CreativeModeTab tab) {
        return ModItems.ITEMS.register(name, () -> new BlockItem(block.get(), new Item.Properties().tab(tab)));
    }

    public static void register(IEventBus eventBus) {
        BLOCKS.register(eventBus);
    }
}

KeyItem.java

package com.redmecanics.villagedestroyer.item.custom;

import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;

public class KeyItem extends Item {
    public KeyItem(Properties properties) {
        super(properties);
    }

    @Override
    public InteractionResult useOn(UseOnContext ctx) {
        Level level = ctx.getLevel();
        BlockPos pos = ctx.getClickedPos();
        Block btc = level.getBlockState(pos).getBlock();
        
        if (!level.isClientSide) {
            if (btc == Blocks.OAK_DOOR) {
                level.removeBlock(pos, true);
                level.setBlock(pos, ModBlocks.lock, 1);
                System.out.println("door locked");
            }
        }
        
        return super.useOn(ctx);
    }
}

错误原因

ModBlocks.lock 是 RegistryObject<Block> 类型,而 level.setBlock() 要求第二个参数是 BlockState,不是注册对象本身。自定义方块和原版方块完全一样,都能调用 defaultBlockState(),只是得先从注册对象里拿到实际的Block实例。

修复方法

修改KeyItem.java里的错误代码:

// 原错误代码
level.setBlock(pos, ModBlocks.lock, 1);

// 修复后代码
level.setBlock(pos, ModBlocks.lock.get().defaultBlockState(), 1);
  • ModBlocks.lock.get():从RegistryObject中取出实际注册的Block对象
  • .defaultBlockState():获取该方块的默认状态,用法和原版方块完全一致

另外,你的ModBlocks里定义的defState变量是多余的,方块的默认状态不需要自己手动定义,Block类本身就自带defaultBlockState()方法,直接用就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:17:08