Skip to content

Event API

EmakiStation publishes three Bukkit events in the emaki.jiuwu.craft.station.api.event package.

All three fire on the crafting player's owner thread: on Folia that is the entity scheduler owner, on Paper the main server thread.

EventCancellableFires
StationCraftSubmitEventYesBefore any charge or material deduction.
StationCraftCancelEventYesBefore the queue entry is removed and refunded.
StationCraftCompletedEventNoAfter settlement completes and outputs are routed.

StationCraftSubmitEvent

java
public class StationCraftSubmitEvent extends Event implements Cancellable
MemberTypeDescription
getPlayer()PlayerThe submitting player.
getStationId()StringStation id.
getRecipeId()StringRecipe id.
getBatch()longThe multiplier of this submission.
getChannel()MaterialChannelMaterial channel; no longer decides where materials come from.
isCancelled() / setCancelled(boolean)booleanCancellation control.

Cancelling stops the whole submission: nothing is charged, nothing is deducted, no queue entry is created. This is the only point where a craft can be vetoed at zero compensation.

Coverage: any submission that reaches the charging stage, whether it came from the GUI, a command or StationOperations#submitAsync. It does not fire for submissions rejected earlier by permissions, conditions, queue capacity or material checks, and it does not fire when a queue entry later advances or settles.

StationCraftCancelEvent

java
public class StationCraftCancelEvent extends Event implements Cancellable
MemberTypeDescription
getPlayer()PlayerThe queue owner.
getStationId()StringStation id.
getRecipeId()StringRecipe id.
getIndex()intQueue position, zero-based.
getConsumedMaterials()List<ConsumedMaterial>The materials this entry consumed.
getRefundRate()doubleThe refund fraction about to be applied.
isCancelled() / setCancelled(boolean)booleanCancellation control.

Cancelling keeps the entry in the queue and refunds nothing, so the player's materials stay invested in that craft. A vetoed cancellation reports FailureKind.CANCELLED with the reason key station.cancel_vetoed.

getRefundRate() comes from the station's queue.cancel_refund_rate.

Coverage: cancellations a player triggers from the GUI or a command, plus StationOperations#cancelAsync. It does not fire when an entry completes normally, nor when queue data is discarded administratively.

Entries in the PENDING_CLAIM state are refused before this event fires, returning station.cancel_pending_claim, so listeners never observe that kind of cancellation.

StationCraftCompletedEvent

java
public class StationCraftCompletedEvent extends Event

Not cancellable: by the time it fires the materials are long spent and the outputs are already delivered or parked, leaving nothing to veto.

MemberTypeDescription
getPlayer()PlayerThe crafting player.
getStationId()StringStation id.
getRecipeId()StringRecipe id.
getBatch()longThe multiplier settled.
getDeliveredOutputs()List<PendingOutput>Outputs delivered successfully.
getPendingOutputs()List<PendingOutput>Outputs that could not be delivered and became pending-claim.

Coverage: settlement of a queue entry, plus immediate settlement of a zero-duration recipe.

A non-empty getPendingOutputs() means no configured target could accept the outputs and they now await a manual claim. "Completed" therefore describes the craft itself, not successful delivery.

This event does not fire when the player later claims parked outputs, and it is not an audit log: cancelled entries never reach it.

Examples

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("Some outputs could not be delivered. Free up space and claim them.");
    }
}

Both event classes defensively copy the lists passed to their constructors, turning null into an empty list.