04-entity · diff
git:20260711.586c86f to git:20260818.b1ccba0
25 added, 78 removed. Audit A to A.
# 04 — 实体开发
> 适用版本:Fabric 1.14.4
---
## 约束
### 核心原则
- - 实体必须在 `Registry.register(Registry.ENTITY_TYPE, id, type)` 中注册
- - 实体渲染器在客户端单独注册(`EntityRendererRegistry`)
- - 实体类继承 `Entity` 或其子类
- - 实体必须有 `EntityType.Builder`
- - 实体 ID 必须在 `fabric.mod.json` 的 `entrypoints` 中正确配置
+ - 实体必须在 `Registry.register(Registry.ENTITY_TYPE, id, type)` 中注册(1.14.x 没有 `Registries`)
+ - 属性在实体类里重写 `initAttributes()`。没有 `FabricDefaultAttributeRegistry`
+ - Yarn 枚举是 `EntityCategory`,不是后来的 `SpawnGroup` / Mojmap `MobCategory`
+ - 不要用 Forge `RegistryObject`
+ - 渲染器只在 `ClientModInitializer` 注册
---
## Decision Flow
- ### Decision: 选择实体类型
-
```
- IF 静态实体(不移动、不交互)
- → EntityType.Builder.create(EntityCategory.MISC)
-
- IF 有行为实体(动物、怪物)
- → EntityType.Builder.create(EntityCategory.CREATURE)
- → 重写 registerAttributes() 和 init() 方法
-
- IF 需要在服务端和客户端分别初始化
- → 拆分 FabricMod 为 client/server entrypoints
+ IF 静态实体
+ → EntityType.Builder.create(..., EntityCategory.MISC)
- IF 仅客户端渲染(如护甲、held item)
- → 不需要注册实体,使用 LayerRenderer 或 FeatureRenderer
+ IF 有行为实体
+ → EntityType.Builder.create(..., EntityCategory.CREATURE)
+ → 重写 initAttributes()
```
- ---
-
## 基本实体注册
```java
- // 1. 创建实体类
- public class MyPigEntity extends CowEntity {
+ public class MyPigEntity extends PigEntity {
public MyPigEntity(EntityType<? extends MyPigEntity> type, World world) {
super(type, world);
}
+
+ @Override
+ protected void initAttributes() {
+ super.initAttributes();
+ this.getAttributeInstance(EntityAttributes.MAX_HEALTH).setBaseValue(20.0);
+ }
}
- // 2. 在 onInitialize() 中注册
- public static final RegistryObject<EntityType<MyPigEntity>> MY_PIG = Registry.register(
+ public static final EntityType<MyPigEntity> MY_PIG = Registry.register(
Registry.ENTITY_TYPE,
new Identifier(MOD_ID, "my_pig"),
- EntityType.Builder.<MyPigEntity>create(
- MyPigEntity::new,
- EntityCategory.CREATURE
- )
- .size(0.9f, 1.4f) // 宽, 高
- .build(new Identifier(MOD_ID, "my_pig").toString())
+ EntityType.Builder.<MyPigEntity>create(MyPigEntity::new, EntityCategory.CREATURE)
+ .size(0.9f, 1.4f)
+ .build(null)
);
```
- ## Entity Attributes(属性)
-
- ```java
- // 在 onInitialize() 中设置属性
- @Override
- public void onInitialize() {
- // 注册属性
- ((LivingEntityAttributeRegistry) (Object) this).register(MY_PIG,
- LivingEntityAttributes.GENERIC_MAX_HEALTH,
- 20.0
- );
- ((LivingEntityAttributeRegistry) (Object) this).register(MY_PIG,
- LivingEntityAttributes.GENERIC_MOVEMENT_SPEED,
- 0.25
- );
- ((LivingEntityAttributeRegistry) (Object) this).register(MY_PIG,
- LivingEntityAttributes.GENERIC_ATTACK_DAMAGE,
- 3.0
- );
-
- // 注册实体...
- Registry.register(Registry.ENTITY_TYPE, new Identifier(MOD_ID, "my_pig"), MY_PIG.get());
- }
- ```
-
- ## Spawn Restriction(生成限制)
-
- ```java
- // 使用 World spawn biomes 配置(1.14.4 方式)
- // 在 EntityType 构造后,Minecraft 会自动处理基本生成
- ```
-
## 实体渲染器(客户端)
```java
- // 单独的客户端入口点(推荐)
public class ExampleModClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
- EntityRendererRegistry.register(MY_PIG.get(), (dispatcher, context) ->
+ EntityRendererRegistry.register(MY_PIG, (dispatcher, context) ->
new LivingEntityRenderer<MyPigEntity>(dispatcher, new MyPigEntityModel(), 0.5f)
);
}
}
```
## fabric.mod.json 配置
```json
{
"entrypoints": {
"main": ["com.example.examplemod.ExampleMod"],
"client": ["com.example.examplemod.ExampleModClient"]
}
}
```
## 常见错误
- - ❌忘记在 `fabric.mod.json` 中添加客户端 entrypoint — 实体无渲染
- - ❌实体渲染器在服务端执行 — `EntityRendererRegistry` 仅在客户端有效
- - ❌忘记设置 `SpawnRestriction` — 实体无法在世界中自然生成
- - ❌在 `onInitialize()` 外注册 — 注册不会生效
- - ❌混淆 `EntityCategory` 和 `MobCategory`(后者是 1.17+ 的名称)
-
- ## 扩展点
-
- | 配合 Skill | 协作说明 |
- |------------|---------|
- | `mc-registry` | 实体通过 Registry.register() 注册 |
- | `mc-item` | 实体可以掉落物品(EntityDrops 事件) |
- | `mc-gui` | 实体可以打开 GUI(使用 Holder<MenuType>) |
- | `mc-datagen` | 实体可以生成 loot table JSON |
+ - 忘记 `client` entrypoint — 实体无渲染
+ - 把 1.16+ 的 `FabricDefaultAttributeRegistry` / `SpawnGroup` / `Registries` 抄到 1.14.4
+ - 用 Forge `RegistryObject` 包住 `Registry.register` 的返回值