一. 什么是方块实体

方块实体就是用于存储与单个方块相关联的数据,比如箱子里存的东西,熔炉里烧的东西
这里我们实现一个能够点击后计数的方块,这个计数应该被存储起来,并且退出游戏后读档保持原来的数值。

二.创建一个类实现方块实体(BlockEntity)的基类,等于BlockEntity里的Block

public class ExampleBlock03 extends BaseEntityBlock {
    public ExampleBlock03(BlockBehaviour.Properties properties) {
        super(properties);  //调用父类构造函数
    }
}

实现构造方法,父类未实现的方法先放着

三.创建类继承方块实体

public class ExampleBlockEntity extends BlockEntity{
    public ExampleBlockEntity(BlockPos pos, BlockState state) {
        super(Registry.EXAMPLE_ENTITY.get(), pos, state);
    }
}

四.注册一个方块实体的延迟注册器,并注册一个方块实体

这里需要提前注册一个Block:Example_Block_03
然后注册BlockEntity

public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES =
            DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, TestMod.MODID);
public static final Supplier<BlockEntityType<ExampleBlockEntity>> EXAMPLE_ENTITY=
            BLOCK_ENTITIES.register("example_entity", () ->
                    BlockEntityType.Builder.of(
                            ExampleBlockEntity::new,
                            Registry.EXAMPLE_BLOCK_03.get()
                    ).build(null));

别忘了添加到主线

BLOCK_ENTITIES.register(bus);

五.接下来我们补充ExampleBlockEntity

public void increase() {
    counter++;
    setChanged();
}

public int getCounter() {
    return counter;
}
    
@Override
public void saveAdditional(CompoundTag tag) {
    super.saveAdditional(tag);
    tag.putInt("Counter", counter);
 }

 @Override
 public void load(CompoundTag tag) {
     super.load(tag);
     counter = tag.getInt("Counter");
 }

六.然后补充ExampleBlock03

public static final MapCodec<ExampleBlock03> CODEC =simpleCodec(ExampleBlock03::new);

@Override
    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
        return new ExampleBlockEntity(pos, state);  
    }

@Override
    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
        //服务端执行逻辑,获取实例
        if (!level.isClientSide && level.getBlockEntity(pos) instanceof ExampleBlockEntity entity) {
            entity.increase(); // 增加计数器
            player.sendSystemMessage(Component.literal("Counter: " + entity.getCounter())); // 发送消息
        }
        return InteractionResult.SUCCESS;
    }

@Override
    public RenderShape getRenderShape(BlockState state) {
        return RenderShape.MODEL;
    }

@Override
    protected MapCodec<? extends BaseEntityBlock> codec() {
        return CODEC;
    }

附完整代码

ExampleBlockEntity

import com.XXXYJade17.TestMod.Registry;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity;

public class ExampleBlockEntity extends BlockEntity {
    private int counter=0;

    public ExampleBlockEntity(BlockPos pos, BlockState state) {
        super(Registry.EXAMPLE_ENTITY.get(), pos, state);
    }
    public void increase() {
        counter++;
        setChanged();
    }

    public int getCounter() {
        return counter;
    }

    @Override
    public void saveAdditional(CompoundTag tag) {
        super.saveAdditional(tag);
        tag.putInt("Counter", counter);
    }

    @Override
    public void load(CompoundTag tag) {
        super.load(tag);
        counter = tag.getInt("Counter");
    }
}

ExampleBlcok03

import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;

public class ExampleBlock03 extends BaseEntityBlock {
    public static final MapCodec<ExampleBlock03> CODEC =simpleCodec(ExampleBlock03::new);

    public ExampleBlock03(BlockBehaviour.Properties properties) {
        super(properties);  //调用父类构造函数
    }

    @Override
    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
        return new ExampleBlockEntity(pos, state);  //创建实例
    }

    @Override
    public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
        //服务端执行逻辑,获取实例
        if (!level.isClientSide && level.getBlockEntity(pos) instanceof ExampleBlockEntity entity) {
            entity.increase(); // 增加计数器
            player.sendSystemMessage(Component.literal("Counter: " + entity.getCounter())); // 发送消息
        }
        return InteractionResult.SUCCESS;
    }

    //定义渲染
    @Override
    public RenderShape getRenderShape(BlockState state) {
        return RenderShape.MODEL;
    }

    //方块定义数据编解码器(用于数据保存与加载)
    @Override
    protected MapCodec<? extends BaseEntityBlock> codec() {
        return CODEC;
    }
}

Registry

import com.XXXYJade17.TestMod.BlockEntity.ExampleBlock03;
import com.XXXYJade17.TestMod.BlockEntity.ExampleBlockEntity;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.SwordItem;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
import static com.XXXYJade17.TestMod.PropertyRegistry.FOOD_PROPERTIES;

public class Registry {
    //延迟注册器
    public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(Registries.BLOCK, TestMod.MODID);
    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(Registries.ITEM, TestMod.MODID);
    public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES =
            DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, TestMod.MODID);
    //BLOCK
    public static final Supplier<Block> EXAMPLE_BLOCK_01 = BLOCKS.register("example_block_01",
            () -> new Block(BlockBehaviour.Properties.of()
                    .strength(3.0f, 6.0f)
                    .requiresCorrectToolForDrops()));
    public static final DeferredHolder<Block, Block> EXAMPLE_BLOCK_02 = BLOCKS.register("example_block_02",
            () -> new Block(BlockBehaviour.Properties.of()));
    public static final Supplier<Block> EXAMPLE_BLOCK_03 = BLOCKS.register("example_block_03",
            () -> new ExampleBlock03(BlockBehaviour.Properties.of()));
    //BLOCK_ITEM
    public static final Supplier<Item> EXAMPLE_BLOCK_01_ITEM = ITEMS.register("example_block_01",
            () -> new BlockItem(EXAMPLE_BLOCK_01.get(), new Item.Properties()));
    public static final DeferredHolder<Item,Item> EXAMPLE_BLOCK_02_ITEM = ITEMS.register("example_block_02",
            () -> new BlockItem(EXAMPLE_BLOCK_02.get(), new Item.Properties()));
    public static final Supplier<Item> EXAMPLE_BLOCK_03_ITEM = ITEMS.register("example_block_03",
            () -> new BlockItem(EXAMPLE_BLOCK_03.get(), new Item.Properties()));
    //ITEM
    public static final Supplier<Item>  EXAMPLE_ITEM_01= ITEMS.register("example_item_01",
            () -> new Item(new Item.Properties()));
    public static final DeferredHolder<Item, Item> EXAMPLE_ITEM_02 = ITEMS.register("example_item_02",
            () -> new Item(new Item.Properties().food(FOOD_PROPERTIES)));
    public static final Supplier<Item> EXAMPLE_SWORD=ITEMS.register("example_sword",
            () ->new SwordItem(ExampleTier.Example,100,0.1f,new Item.Properties()));
    public static final Supplier<Item> EXAMPLE_HELMET=ITEMS.register("example_helmet",
            ()->new ArmorItem(ExampleArmorMaterial.Example,ArmorItem.Type.HELMET,new Item.Properties()));
    public static final Supplier<Item> EXAMPLE_CHESTPLATE=ITEMS.register("example_chestplate",
            ()->new ArmorItem(ExampleArmorMaterial.Example,ArmorItem.Type.HELMET,new Item.Properties()));
    public static final Supplier<Item> EXAMPLE_LEGGINGS=ITEMS.register("example_leggings",
            ()->new ArmorItem(ExampleArmorMaterial.Example,ArmorItem.Type.HELMET,new Item.Properties()));
    public static final Supplier<Item> EXAMPLE_BOOTS=ITEMS.register("example_boots",
            ()->new ArmorItem(ExampleArmorMaterial.Example,ArmorItem.Type.HELMET,new Item.Properties()));
    //BLOCK STATE
    public static final Supplier<Block> STATE_EXAMPLE_BLOCK = BLOCKS.register("state_example_block",
            () -> new StateExampleBlock(BlockBehaviour.Properties.of()));
    public static final Supplier<Item> STATE_EXAMPLE_BLOCK_ITEM = ITEMS.register("state_example_block",
            () -> new BlockItem(STATE_EXAMPLE_BLOCK.get(), new Item.Properties()));
    //BLOCK ENTITY
    public static final Supplier<BlockEntityType<ExampleBlockEntity>> EXAMPLE_ENTITY=
            BLOCK_ENTITIES.register("example_entity", () ->
                    BlockEntityType.Builder.of(
                            ExampleBlockEntity::new,
                            Registry.EXAMPLE_BLOCK_03.get()
                    ).build(null));
    //注册方法
    public static void register(IEventBus bus){
        BLOCKS.register(bus);
        ITEMS.register(bus);
        BLOCK_ENTITIES.register(bus);
        ModCreativeTab.register(bus);
    }
}