API 与集成
第三方插件通过 emaki-mobs-api 访问 EmakiMobs 的生物定义。
Maven 坐标
<repositories>
<repository>
<id>jiuwu-releases</id>
<url>https://repo.crypticlib.com/repository/maven-public/</url>
</repository>
</repositories>
<dependency>
<groupId>emaki.jiuwu.craft</groupId>
<artifactId>emaki-mobs-api</artifactId>
<version>1.0.6</version>
<scope>provided</scope>
</dependency>repositories { maven("https://repo.crypticlib.com/repository/maven-public/") }
dependencies { compileOnly("emaki.jiuwu.craft:emaki-mobs-api:1.0.6") }仅编译依赖
runtime 已内嵌未 relocate 的 API 类。不要安装、bundle、shade 或 relocate API Jar;重复 ClassLoader 类型会破坏事件与 bridge。
在 paper-plugin.yml 里把 EmakiMobs 声明为依赖:
dependencies:
server:
EmakiMobs:
load: BEFORE
required: false
join-classpath: true门面
emaki.jiuwu.craft.mobs.api.EmakiMobsApi 是静态门面:
| 方法 | 说明 |
|---|---|
status() | 可用性与身份元数据,返回 CoreLib 的 ApiStatus。 |
catalog() | 查询层,见下文 MobCatalog。 |
operations() | 操作层,见下文 MobOperations。 |
extensions() | 扩展层,见下文 MobExtensions。 |
访问器永不返回 null。EmakiMobs 缺失时 catalog 返回空答案,因此调用方不能把 NullPointerException 当作可用性信号。
MobCatalog 查询层
标注 @ApiStatus.NonExtendable。
| 方法 | 线程 | 返回类型 | 说明 |
|---|---|---|---|
definition(String mobId) | 任意线程 | Optional<MobDefinition> | 按 id 查询生物定义。 |
registeredIds() | 任意线程 | Set<String> | 列出所有已注册生物 id(不可变快照)。 |
所有方法返回不可变快照,线程安全。
MobOperations 操作层
| 方法 | 返回类型 | 说明 |
|---|---|---|
spawn(Location location, String mobId) | Optional<LivingEntity> | 在指定位置生成一只已注册的自定义生物。location 的世界不可为 null,mobId 区分大小写;id 未注册或生成失败时返回空 Optional。 |
remove(LivingEntity entity) | void | 移除一只受管实体。接口 default 实现为空操作,真实实现由运行时桥提供。 |
EmakiMobs 缺失或尚未就绪时,operations() 返回的是安全的空操作实现,spawn 恒返回 Optional.empty()。
生成实体属于 Bukkit 状态改动:在 Folia 上必须先切到该位置的 owner 线程再调用。
MobExtensions 扩展层
| 方法 | 说明 |
|---|---|
registerCustomSpawner(String id, CustomSpawner spawner) | 注册自定义刷怪器;id 用于去重。 |
MobExtensions.CustomSpawner 是定义在 MobExtensions 内部的函数式接口,只有一个 onReload() 回调:注册时立即调用一次,之后每次 EmakiMobs 配置重载再调用一次。在其中读取最新配置并重新排程自己的刷怪任务。
EmakiMobsApi.extensions().registerCustomSpawner("my_spawner", () -> {
// 注册时与每次 reload 后都会进入这里
reloadMySpawnConfig();
});MobDefinition 模型
暴露字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id() | String | YAML 文件与命令中使用的生物唯一 ID |
entityType() | EntityType | 底层原版实体类型 |
displayName() | @Nullable String | MiniMessage 格式的自定义名;未设置时为 null |
experience() | int | 击杀经验覆盖值;0 表示沿用原版默认 |
不暴露的内部实现: components、attributes、skills、threat、boss_bar 均不在公共 API 中。这些字段属于内部配置,第三方插件无法查询。
不要缓存层对象
在使用点解析 catalog(),不要把它存进字段:backing bridge 在 reload 时会被替换。
// 正确
EmakiMobsApi.catalog().definition("elite_zombie");
// 错误:reload 后这个引用会指向旧 bridge
private final MobCatalog cached = EmakiMobsApi.catalog();示例
import emaki.jiuwu.craft.mobs.api.EmakiMobsApi;
import emaki.jiuwu.craft.mobs.api.MobCatalog;
import emaki.jiuwu.craft.mobs.api.model.MobDefinition;
import org.bukkit.entity.EntityType;
public class MyPlugin extends JavaPlugin {
@Override
public void onEnable() {
if (!EmakiMobsApi.status().usable()) {
getLogger().warning("EmakiMobs API 不可用");
return;
}
MobCatalog catalog = EmakiMobsApi.catalog();
// 查询单个生物定义
catalog.definition("elite_zombie").ifPresent(mob -> {
getLogger().info("找到生物:" + mob.displayName()
+ "(类型:" + mob.entityType()
+ ",经验:" + mob.experience() + ")");
});
// 列出所有已注册生物
getLogger().info("已注册 " + catalog.registeredIds().size() + " 种生物");
for (String mobId : catalog.registeredIds()) {
catalog.definition(mobId).ifPresent(mob -> {
if (mob.entityType() == EntityType.ZOMBIE) {
getLogger().info(" - " + mobId + " (僵尸变种)");
}
});
}
}
}集成建议
- 使用
definition()在生物生成或交互时验证 id 是否为 EmakiMobs 管理的自定义生物。 registeredIds()可用于 tab-complete 或配置验证。MobDefinition字段有限,主要用于基础信息展示。需要更多细节(如 components、attributes)时,考虑直接读取 EmakiMobs 的配置文件或使用实体 PDC 标记。