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
相关产品推荐
相关产品推荐

