| name | pasterdream-entity-api |
| description | PasterDream模组实体注册专用API,提供Facade+Builder模式一键注册自定义实体。在需要创建新实体、配置实体属性/AI/碰撞箱/追踪范围/生物技能、动画系统或注册渲染器时调用。 |
PasterDream Entity API
本 Skill 提供 PasterDream 模组实体注册专用 API 的使用指南,采用 Facade + Builder 模式(与 BlockAPI / DimensionAPI 风格一致),通过链式调用即可完成实体的注册、属性配置、渲染器注册和生成蛋颜色管理。
适用场景
- 创建新的自定义实体(Entity / LivingEntity 子类)
- 配置实体碰撞箱尺寸、追踪范围、更新频率
- 设置实体 AI 属性(攻击力、生命值、移动速度等)
- 注册实体渲染器(客户端)
- 配置生成蛋颜色(底色 + 高光色)
- 批量查询已注册的实体类型和属性
快速开始
EntityResult<ShadowGolemEntity> shadowGolem = EntityAPI.createEntity("shadow_golem")
.category(MobCategory.MONSTER)
.size(2.2f, 3.5f)
.trackingRange(64)
.updateInterval(3)
.velocityUpdates(true)
.entityClass(ShadowGolemEntity.class)
.attributes(ShadowGolemEntity::createAttributes)
.spawnEgg(0x333333, 0xFF4444)
.build();
@SubscribeEvent
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
EntityAPI.registerRenderer(event, shadowGolem, ShadowGolemRenderer::new);
}
@SubscribeEvent
public static void registerAttributes(EntityAttributeCreationEvent event) {
EntityAPI.registerAttributes(event, shadowGolem);
}
EntityType<ShadowGolemEntity> type = shadowGolem.entityType();
ShadowGolemEntity golem = type.create(level);
golem.setPos(x, y, z);
level.addFreshEntity(golem);
前置条件
在 PasterDreamMod 构造函数中注册 EntityAPI 的 REGISTRY:
public PasterDreamMod(IEventBus modEventBus) {
EntityAPI.REGISTRY.register(modEventBus);
}
API 架构
EntityAPI ← Facade 门面
├── createEntity(name) ← 工厂方法 → EntityBuilder
├── registerRenderer(event, result, provider) ← 渲染器注册
├── registerRenderer(event, name, provider) ← 按名称注册渲染器
├── registerAttributes(event, result) ← 属性注册(缓存)
├── registerAttributes(event, result, supplier) ← 属性注册(显式)
├── registerAttributes(event, name) ← 按名称注册属性
├── createSpawnEggItem(registry, name, supplier) ← 刷怪蛋物品注册
├── setSpawnEggModelsOutputDir(path) ← 刷怪蛋模型输出目录
├── cacheSpawnEgg(name, bg, hl) ← 缓存刷怪蛋颜色
├── getSpawnEggColors(name) ← 查询刷怪蛋颜色
├── getEntityType(name) ← 查询 EntityType
├── getEntityResult(name) ← 查询 EntityResult
└── getRegisteredEntities() ← 所有已注册实体
EntityBuilder<T> ← Builder 构建器
├── category(MobCategory) ← 实体分类(必要)
├── size(float, float) ← 碰撞箱尺寸(必要)
├── entityClass(Class<T>) ← 实体类(必要)
├── trackingRange(int) ← 追踪范围(默认 64)
├── updateInterval(int) ← 更新间隔(默认 3)
├── velocityUpdates(boolean) ← 速度同步(默认 true)
├── attributes(Supplier<Builder>) ← AI 属性(AttributeSupplier.Builder)
├── attributesBuilt(Supplier) ← AI 属性(预构建)
├── spawnEgg(int, int) ← 刷怪蛋颜色 [底色, 高光色]
└── build() ← 注册 → EntityResult<T>
EntityResult<T> ← Record 结果
├── name() → String(实体注册名)
├── entityTypeSupplier() → Supplier<EntityType<T>>
├── entityClass() → Class<T>
├── entityType() → EntityType<T>(便捷获取)
└── deferredHolder() → DeferredHolder
Builder 配置参考
| 方法 | 参数 | 说明 | 必需 |
|---|
category(MobCategory) | 实体分类 | 决定生物容量和生成行为 | ✅ |
size(float, float) | 宽度, 高度 | 碰撞箱尺寸 | ✅ |
entityClass(Class) | 实体 Class | 实体 Java 类(需有 (EntityType, Level) 构造) | ✅ |
trackingRange(int) | 格数 | 客户端同步距离(默认 64) | ❌ |
updateInterval(int) | tick 数 | 位置同步频率(默认 3) | ❌ |
velocityUpdates(boolean) | bool | 是否接收速度更新(默认 true) | ❌ |
attributes(Supplier) | AttributeSupplier.Builder | AI 属性配置 | ❌ |
attributesBuilt(Supplier) | AttributeSupplier | 预构建的属性 | ❌ |
spawnEgg(int, int) | 底色, 高光色 | 生成蛋颜色(16 进制) | ❌ |
MobCategory 参考
| 分类 | 说明 |
|---|
MobCategory.MONSTER | 敌对生物(容量 70) |
MobCategory.CREATURE | 友好动物(容量 10) |
MobCategory.AMBIENT | 环境生物(如蝙蝠,容量 15) |
MobCategory.WATER_CREATURE | 水生生物(容量 5) |
MobCategory.WATER_AMBIENT | 水下环境生物(如鱼,容量 20) |
MobCategory.MISC | 其他(如掉落物、箭矢) |
EntityAttributesGenerator 预设模板
API 提供了 EntityAttributesGenerator 工具类,包含多种预设属性模板,可直接通过方法引用传入 Builder:
| 方法 | 适用 | 预设值 |
|---|
createMonsterAttributes() | 怪物 | 攻击 3.0, 盔甲 2.0, 追踪 32 |
createCreatureAttributes() | 动物 | 生命 10.0, 速度 0.2, 追踪 16 |
createFlyingAttributes() | 飞行生物 | 生命 10.0, 速度 0.2, 飞行 0.4, 追踪 24 |
createWaterCreatureAttributes() | 水生生物 | 生命 15.0, 速度 0.3, 追踪 16 |
完整示例
怪物 — 暗影傀儡
EntityResult<ShadowGolemEntity> golem = EntityAPI.createEntity("shadow_golem")
.category(MobCategory.MONSTER)
.size(2.2f, 3.5f)
.trackingRange(64)
.entityClass(ShadowGolemEntity.class)
.attributes(() -> Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, 80.0)
.add(Attributes.ATTACK_DAMAGE, 12.0)
.add(Attributes.ARMOR, 8.0)
.add(Attributes.MOVEMENT_SPEED, 0.25)
.add(Attributes.FOLLOW_RANGE, 48))
.spawnEgg(0x2C2C2C, 0x6B3FAF)
.build();
EntityAPI.registerRenderer(event, golem, ShadowGolemRenderer::new);
EntityAPI.registerAttributes(event, golem);
动物 — 森林精灵
EntityResult<ForestSpiritEntity> spirit = EntityAPI.createEntity("forest_spirit")
.category(MobCategory.CREATURE)
.size(0.6f, 1.8f)
.entityClass(ForestSpiritEntity.class)
.attributes(EntityAttributesGenerator::createCreatureAttributes)
.spawnEgg(0x4CAF50, 0x81C784)
.build();
飞行生物 — 梦魇蝙蝠
EntityResult<NightmareBatEntity> bat = EntityAPI.createEntity("nightmare_bat")
.category(MobCategory.AMBIENT)
.size(0.8f, 0.8f)
.entityClass(NightmareBatEntity.class)
.attributes(EntityAttributesGenerator::createFlyingAttributes)
.updateInterval(1)
.spawnEgg(0x1A1A2E, 0xE94560)
.build();
按名称注册(便捷方式)
@SubscribeEvent
public static void registerAttributes(EntityAttributeCreationEvent event) {
EntityAPI.registerAttributes(event, "shadow_golem");
}
@SubscribeEvent
public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) {
EntityAPI.registerRenderer(event, "shadow_golem", ShadowGolemRenderer::new);
}
刷怪蛋系统
Entity API 提供了一个完整的刷怪蛋解决方案,包括颜色配置、自动物品注册和模型文件自动生成。
1. 颜色配置(Builder 阶段)
在 EntityBuilder 的链式调用中通过 .spawnEgg() 配置颜色:
EntityResult<ShadowGolemEntity> golem = EntityAPI.createEntity("shadow_golem")
.category(MobCategory.MONSTER)
.size(2.2f, 3.5f)
.entityClass(ShadowGolemEntity.class)
.attributes(ShadowGolemEntity::createAttributes)
.spawnEgg(0x2C2C2C, 0x6B3FAF)
.build();
颜色值以 16 进制 RGB 格式传入,Builder 在 build() 时自动缓存颜色。
2. 刷怪蛋物品注册(PDItems 阶段)
在 PDItems.java 中使用 EntityAPI.createSpawnEggItem() 统一注册刷怪蛋物品,无需手动指定颜色:
public static final DeferredItem<Item> SHADOW_GOLEM_SPAWN_EGG =
EntityAPI.createSpawnEggItem(ITEMS, "shadow_golem", PDEntities.SHADOW_GOLEM);
原理:createSpawnEggItem() 会从 PDEntities 中 .spawnEgg() 缓存的颜色数组中自动读取,生成 SpawnEggItem。
3. 刷怪蛋模型自动生成
当 EntityBuilder 的 .build() 执行时,如果已配置模型输出目录,会自动在对应路径生成 {name}_spawn_egg.json 模型文件(内容固定为 {"parent": "minecraft:item/template_spawn_egg"})。
配置方式:在 PasterDreamMod.java 构造函数中设置输出目录:
public PasterDreamMod(IEventBus modEventBus, ModContainer modContainer) {
EntityAPI.setSpawnEggModelsOutputDir(
Path.of("PasterDream", "src", "main", "resources", "assets",
PasterDreamMod.MOD_ID, "models", "item"));
}
完整集成示例
private static final EntityResult<ShadowGolemEntity> SHADOW_GOLEM_RESULT =
EntityAPI.createEntity("shadow_golem")
.category(MobCategory.MONSTER).size(2.2f, 3.5f)
.entityClass(ShadowGolemEntity.class)
.attributes(ShadowGolemEntity::createAttributes)
.spawnEgg(0x191926, 0xA7A5B1)
.build();
public static final Supplier<EntityType<ShadowGolemEntity>> SHADOW_GOLEM =
SHADOW_GOLEM_RESULT.entityTypeSupplier();
public static final DeferredItem<Item> SHADOW_GOLEM_SPAWN_EGG =
EntityAPI.createSpawnEggItem(ITEMS, "shadow_golem", PDEntities.SHADOW_GOLEM);
public PasterDreamMod(IEventBus modEventBus, ModContainer modContainer) {
EntityAPI.setSpawnEggModelsOutputDir(
Path.of("PasterDream", "src", "main", "resources", "assets",
"pasterdream", "models", "item"));
}
检查清单
| 步骤 | 操作 | 位置 |
|---|
| 1 | 在 .spawnEgg() 中配置颜色 | PDEntities.java |
| 2 | 用 EntityAPI.createSpawnEggItem() 注册刷怪蛋物品 | PDItems.java |
| 3 | 调用 EntityAPI.setSpawnEggModelsOutputDir() 配置输出目录 | PasterDreamMod.java |
| 4 | 确保实体有向后兼容常量(public static final Supplier<EntityType<T>>) | PDEntities.java |
⚠️ 若未配置 .spawnEgg() 但调用了 createSpawnEggItem(),会在运行时抛出 IllegalStateException,提示 "未配置生成蛋颜色"。
实体类构造要求
实体类必须包含 (EntityType, Level) 构造方法:
public class ShadowGolemEntity extends Monster {
public ShadowGolemEntity(EntityType<? extends ShadowGolemEntity> type, Level level) {
super(type, level);
}
}
引用文件
动画系统
Entity API 提供了一套完整的 procedure 动画播放系统,用于播放由服务端触发的一次性动画(如技能释放、咆哮、受击等)。
架构
服务端 客户端
│ │
├─ setAnimation("roar") ──────► ├─ 同步数据到达
│ (更新 entityData.set) │
│ ├─ ProcedureAnimationHandler.predicate()
│ │ ├─ 检测新动画 → 通过 GeckoLib 播放一次
│ │ ├─ 动画播放中 → 返回 CONTINUE
│ │ └─ 动画播完 → 自动重置为 "empty"
│ │
│ └─ movementPredicate()
│ ├─ procedure 动画进行中 → STOP
│ └─ procedure 为空 → 播放 idle/walk/death
正确实现步骤
1. 实体类中加入 ProcedureAnimationHandler
private final ProcedureAnimationHandler procAnim = new ProcedureAnimationHandler();
2. 实现 procedurePredicate 回调
private PlayState procedurePredicate(AnimationState<MyEntity> state) {
return procAnim.predicate(state,
level().isClientSide(),
this::getSyncedAnimation,
() -> setAnimation("empty"));
}
参数说明:
state — GeckoLib 动画状态(传入原生 AnimationState)
level().isClientSide() — 是否在客户端侧(服务端不播动画)
this::getSyncedAnimation — 同步动画数据的 getter
() -> setAnimation("empty") — 动画播完后重置的回调
3. 实现 movementPredicate(正确检测 procedure)
private PlayState movementPredicate(AnimationState<MyEntity> state) {
if (this.getSyncedAnimation().equals("empty")) {
if ((state.isMoving() || !(state.getLimbSwingAmount() > -0.15F && state.getLimbSwingAmount() < 0.15F))) {
return state.setAndContinue(RawAnimation.begin().thenLoop("walk"));
}
if (this.isDeadOrDying()) {
return state.setAndContinue(RawAnimation.begin().thenPlay("death"));
}
return state.setAndContinue(RawAnimation.begin().thenLoop("idle"));
}
return PlayState.STOP;
}
关键规则:movementPredicate 必须检查 getSyncedAnimation()(同步数据),不能检查 this.animationprocedure(本地字段)。
4. 注册控制器
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(new AnimationController<>(this, "movement", 4, this::movementPredicate));
controllers.add(new AnimationController<>(this, "procedure", 4, this::procedurePredicate));
}
注意:procedure 控制器的 transition length 建议与 movement 一致(通常 4 tick)。
5. 服务端触发动画
this.setAnimation("roar");
❌ 常见错误
| 错误模式 | 后果 |
|---|
movementPredicate 使用 this.animationprocedure 判断 | procedure 动画被 movementPredicate 覆盖,永远播不出 |
procedurePredicate 不检查 level().isClientSide() | 服务端和客户端争抢控制,动画行为不可预测 |
procedurePredicate 没有 currentlyPlaying 追踪 | 每帧重复触发动画,导致卡顿或循环 |
| 直接在 procedurePredicate 里写完整逻辑 | 每个实体重复同样的代码,容易出错 |
ProcedureAnimationHandler API
| 方法 | 说明 |
|---|
predicate(state, isClientSide, syncedAnimSupplier, setEmptyAnim) | 标准 procedure 动画回调 |
reset() | 重置处理器状态(实体死亡时调用) |
getCurrentlyPlaying() | 获取当前正在播放的动画名称 |
与 EntitySkillManager 集成
EntitySkillManager 是更高级的技能管理系统,内置了动画同步机制:
private final EntitySkillManager skillManager = new EntitySkillManager(this);
public MyEntity(EntityType<? extends Monster> type, Level level) {
super(type, level);
skillManager.registerSkill(EntitySkill.builder("roar")
.animationName("roar")
.damage(12.0f).range(5.0f).cooldownTicks(200)
.particleName("explosion")
.soundId("pasterdream:terrorbeak_roar")
.build());
}
@Override
public void baseTick() {
super.baseTick();
skillManager.tick();
}
skillManager.tryTriggerSkill("roar", target);
EntitySkillManager 会自动处理:
- 冷却计时
- 动画同步(服务端 → 客户端)
- 技能音效播放
- 技能粒子效果
- 技能伤害范围判定
- 动画播完后重置
引用文件