Skip to content

事件 API ​

EmakiStation 在 emaki.jiuwu.craft.station.api.event 包发布三个 Bukkit 事件

事件可取消触发时机触发线程
StationCraftSubmitEvent是扣款与扣材料之前见下方说明 (API 路径不保证 owner 线程)
StationCraftCancelEvent是移除队列条目与退还之前队列所有者的 owner 线程
StationCraftCompletedEvent否结算完成, 产物路由之后合成玩家的 owner 线程

后两个事件总是通过实体的 owner 调度触发: Folia 上是实体调度器 owner, Paper 上是主服务器线程

StationCraftSubmitEvent 在 GUI 与命令路径上也在 owner 线程触发, 但API 的 submitAsync 允许任意线程调用且直接在该调用线程上派发事件. 因此监听器不得假定该事件总在 owner 线程触发; 需要修改玩家状态时必须自行切回 owner 线程

StationCraftSubmitEvent ​

java
public class StationCraftSubmitEvent extends Event implements Cancellable
成员类型说明
getPlayer()Player提交的玩家
getStationId()String工作站 id
getRecipeId()String配方 id
getBatch()long本次提交的倍率
getChannel()MaterialChannel事件携带的材料通道. 它是 bridge 按工作站配置推定的取值: 工作站启用了 channels.storage 且仓库通道可用时为 STORAGE, 否则为 BACKPACK; 不代表本次提交实际从哪个通道扣料
isCancelled() / setCancelled(boolean)boolean取消控制

取消意味着整笔提交停止: 不扣款, 不扣材料, 不建立队列条目. 这是唯一可以零补偿否决一次合成的时点

覆盖范围: 任何通过前置校验 (工作站/配方存在, 倍率合法, 配方可用, 权限, 条件门, 队列容量, 待领取上限) 并到达扣款阶段的提交, 无论来自 GUI, 命令还是 StationOperations#submitAsync. 事件在材料与余额校验之前触发, 因此之后因材料或余额不足而失败的提交也已收到本事件

被权限, 条件, 队列容量或待领取上限提前拒绝的提交不会触发本事件; 队列条目的后续推进或结算也不会触发本事件

StationCraftCancelEvent ​

java
public class StationCraftCancelEvent extends Event implements Cancellable
成员类型说明
getPlayer()Player队列所有者
getStationId()String工作站 id
getRecipeId()String配方 id
getIndex()int队列位置, 从 0 开始
getConsumedMaterials()List<ConsumedMaterial>该条目已消耗的材料清单
getRefundRate()double即将应用的退还比例
isCancelled() / setCancelled(boolean)boolean取消控制

取消意味着该条目留在队列, 什么都不退, 材料继续投在这次合成上. 被否决时调用方收到 FailureKind.CANCELLED 与原因键 station.cancel_vetoed

getRefundRate() 的取值来自工作站的 queue.cancel_refund_rate

覆盖范围: 玩家从 GUI 或命令发起的取消, 以及 StationOperations#cancelAsync. 条目正常完成时不会触发本事件, 队列数据被管理性丢弃时也不会触发本事件

PENDING_CLAIM 状态的条目在触发本事件之前就被拒绝, 返回 station.cancel_pending_claim, 因此监听器不会看到这类取消

StationCraftCompletedEvent ​

java
public class StationCraftCompletedEvent extends Event

不可取消: 触发时材料早已消耗, 产物已发放或已转入待领取, 没有可否决的内容

成员类型说明
getPlayer()Player合成玩家
getStationId()String工作站 id
getRecipeId()String配方 id
getBatch()long本次结算的倍率
getDeliveredOutputs()List<PendingOutput>已成功投递的产物
getPendingOutputs()List<PendingOutput>未能投递, 转入待领取的产物

覆盖范围: 队列条目的结算, 以及零耗时配方的立即结算

getPendingOutputs() 非空表示没有任何已配置目标能接收产物, 这些产物当前等待手动领取. 因此"completed"描述的是合成本身完成, 而不是投递成功

本事件不会在玩家后来领取停放产物时触发, 也不是审计日志: 被取消的条目永远到不了这里

示例 ​

java
@EventHandler(ignoreCancelled = true)
public void onSubmit(StationCraftSubmitEvent event) {
    if (isBlacklisted(event.getRecipeId())) {
        event.setCancelled(true);
    }
}

@EventHandler
public void onCompleted(StationCraftCompletedEvent event) {
    if (!event.getPendingOutputs().isEmpty()) {
        event.getPlayer().sendMessage("有产物未能投递,请清理仓库或背包后领取。");
    }
}

两个事件类的构造器都对传入的列表做防御性复制, 传入 null 时得到空列表