简体中文
API 与集成
第三方插件通过 emaki-structure-api (当前版本 1.0.1) 访问 EmakiStructure. API Jar 只作编译依赖, 对应 runtime 产物为 EmakiStructure-1.0.5.jar
Maven 坐标
xml
<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-structure-api</artifactId>
<version>1.0.1</version>
<scope>provided</scope>
</dependency>kotlin
repositories { maven("https://repo.crypticlib.com/repository/maven-public/") }
dependencies { compileOnly("emaki.jiuwu.craft:emaki-structure-api:1.0.1") }仅编译依赖
runtime 已内嵌未 relocate 的 API 类. 不要安装, bundle, shade 或 relocate API Jar; 重复 ClassLoader 类型会破坏事件与 bridge
EmakiStructureApi 门面
静态门面只暴露两个查询入口, 访问器永不返回 null:
java
// 可用性与身份元数据; EmakiStructure 缺席时返回 notInstalled
var status = EmakiStructureApi.status();
// 结构模板目录; 缺席时返回空实现 (空答案不代表插件缺失, 须结合 status () 判断)
var catalog = EmakiStructureApi.catalog();install/uninstall与Bridge接口标记为内部/不可实现, 第三方不要调用或实现- 在使用点解析访问器, 不要缓存到字段: reload 会替换底层 bridge
status().usable()是判断桥是否可用的标准方式
StructureCatalog 查询层
只读快照, 线程安全, 所有方法返回不可变副本:
| 方法 | 返回 | 说明 |
|---|---|---|
registeredIds() | Set<String> | 当前已加载的全部模板 id |
template(String) | Optional<StructureTemplateView> | 指定 id 的模板视图, 未加载为空 |
StructureTemplateView 是不可变 record, 字段为 id, sizeX, sizeY, sizeZ, blockCount. 坐标为模板局部坐标 ((0,0,0) 为模板包围盒最小角), 不携带世界或 BlockData 引用, 可安全跨线程持有
事件
MultiblockTriggerEvent
emaki.jiuwu.craft.structure.api.event.MultiblockTriggerEvent -- 多方块结构通过条件与冷却检查后, 配置动作执行前同步触发
| 方法 | 返回 | 说明 |
|---|---|---|
getMultiblockId() | String | 触发的多方块定义 id |
getPlayer() / getPlayerId() | Player / UUID | 触发玩家 (永不为 null) |
getWorldName() | String | 结构锚点所在世界名 |
getX() / getY() / getZ() | int | 锚点方块坐标 |
getFacing() | String | 配置形式朝向: north/east/south/west 及 _mirror 变体 |
- 信息型, 不可取消: 取消对动作执行无效
- 在处理该交互的线程上触发; Folia 上为点击方块所属 region 线程
java
@EventHandler
public void onMultiblockTrigger(MultiblockTriggerEvent event) {
if ("teleporter".equals(event.getMultiblockId())) {
log(event.getPlayerId() + " 触发传送门 @ "
+ event.getWorldName() + " " + event.getX() + "," + event.getY() + "," + event.getZ());
}
}线程与生命周期
- 门面查询可在任意线程调用; 事件回调线程由触发交互决定, 触碰玩家/世界/背包前请自行调度到对应 owner 线程
- 模块 reload 时
status()报 loading,catalog()仍返回快照式实现; 不要把"目录为空"解释为"模板不存在" - EmakiStructure 未安装时, 首次加载 API 类存在链接失败风险, 建议把相关调用隔离并捕获
LinkageError | RuntimeException