事件 API
EmakiStation 在 emaki.jiuwu.craft.station.api.event 包发布三个 Bukkit 事件。
三个事件全部在合成玩家的 owner 线程触发:Folia 上是实体调度器 owner,Paper 上是主服务器线程。
| 事件 | 可取消 | 触发时机 |
|---|---|---|
StationCraftSubmitEvent | 是 | 扣款与扣材料之前。 |
StationCraftCancelEvent | 是 | 移除队列条目与退还之前。 |
StationCraftCompletedEvent | 否 | 结算完成、产物路由之后。 |
StationCraftSubmitEvent
public class StationCraftSubmitEvent extends Event implements Cancellable| 成员 | 类型 | 说明 |
|---|---|---|
getPlayer() | Player | 提交的玩家。 |
getStationId() | String | 工作站 id。 |
getRecipeId() | String | 配方 id。 |
getBatch() | long | 本次提交的倍率。 |
getChannel() | MaterialChannel | 材料通道,已不再决定取材来源。 |
isCancelled() / setCancelled(boolean) | boolean | 取消控制。 |
取消意味着整笔提交停止:不扣款、不扣材料、不建立队列条目。这是唯一可以零补偿否决一次合成的时点。
覆盖范围:任何到达扣款阶段的提交,无论来自 GUI、命令还是 StationOperations#submitAsync。不会为被权限、条件、队列容量或材料检查提前拒绝的提交触发,也不会在队列条目后续推进或结算时触发。
StationCraftCancelEvent
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
public class StationCraftCompletedEvent extends Event不可取消:触发时材料早已消耗、产物已发放或已停放待领,无可否决。
| 成员 | 类型 | 说明 |
|---|---|---|
getPlayer() | Player | 合成玩家。 |
getStationId() | String | 工作站 id。 |
getRecipeId() | String | 配方 id。 |
getBatch() | long | 本次结算的倍率。 |
getDeliveredOutputs() | List<PendingOutput> | 已成功投递的产物。 |
getPendingOutputs() | List<PendingOutput> | 未能投递、转入待领取的产物。 |
覆盖范围:队列条目的结算,以及零耗时配方的立即结算。
getPendingOutputs() 非空表示没有任何已配置目标能接收产物、现在等待手动领取。因此「completed」描述的是合成本身完成,而不是投递成功。
本事件不会在玩家后来领取停放产物时触发,也不是审计日志:被取消的条目永远到不了这里。
示例
@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 变为空列表。