Skip to content

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