一. 什么是方块实体
方块实体就是用于存储与单个方块相关联的数据,比如箱子里存的东西,熔炉里烧的东西
这里我们实现一个能够点击后计数的方块,这个计数应该被存储起来,并且退出游戏后读档保持原来的数值。
二.创建一个类实现方块实体(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");
}
- increase : 实现计数器加一
- getCount : 返回计数器的值
- saveAdditional : 保存数据
- load : 加载上次存储的数据
六.然后补充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;
}
- CODEC 和 codec : 用来编码解码你要存储的信息
- newBlockEntity : 创建Entity实例
- use : 实现点击+1的逻辑
- getRenderShape : 定义渲染类型,没有这玩意儿你的方块会变透明
附完整代码
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);
}
}