Skip to content

Developer API

Use zone.vao:craftcanvas-api:1.0.0-SNAPSHOT as a compile-only dependency and declare depend: [CraftCanvas]. The API is included in the CraftCanvas plugin; keep it out of your addon JAR.

Start with the Java and Kotlin quick start. Runnable source examples are in examples/addon.

Method Result
CanvasApi.whenReady(owner) Future completed when startup publishes the service; call from addon onEnable or the global scheduler
CanvasApi.isAvailable() Whether a service is registered now
CanvasApi.serviceOrNull() Registered service, or null
CanvasApi.service() Registered service; throws IllegalStateException while unavailable

depend establishes plugin load order. CraftCanvas also prepares configuration and resources asynchronously, so use whenReady during addon startup. Waiting is cancelled when either plugin disables. The helper removes its temporary listeners on success, cancellation or failure. A missing or disabled CraftCanvas fails immediately.

For available screens, variable types/defaults and component targets, use the screen catalog. screenCatalog() is a cached immutable read from any thread and does not require a player or an async helper.

Synchronous methods run on the player’s owning entity region, or Paper’s main thread. For calls from a worker or another region, use the asynchronous helpers. Each future reports the actual operation result rather than just task submission.

Synchronous method Async equivalent Result
openDetailed(player, screen[, data]) openAsync(player, screen[, data]) CanvasOpenResult / future of that result
open(player, screen[, data]) Use openAsync and inspect opened Boolean, true only for OPENED
close(player) closeAsync(player) Void / completion future
session(player) sessionAsync(player) SessionView or null
setVariables(player, sessionId, values) setVariablesAsync(player, sessionId, values) Boolean acceptance; stale session returns false
setVariable(player, name, value) withPlayer(player, api -> ...) Typed mutation; missing session/variable fails
setItemTooltip(player, sessionId, slot, item) withPlayer(player, api -> ...) Boolean acceptance
showNotification(player, sessionId, target, text[, durationTicks]) showNotificationAsync(...) Boolean acceptance
dismissNotification(player, sessionId, target) dismissNotificationAsync(...) Boolean acceptance
playComponentAnimation(player, sessionId, target) playComponentAnimationAsync(...) Boolean acceptance
setScrollOffset(player, sessionId, target, offset) setScrollOffsetAsync(...) Boolean acceptance
setListItems(player, sessionId, target, items) setListItemsAsync(...) Atomic session-local list snapshot

withPlayer(player, operation) executes a short function with the service on the correct player thread and returns its result in a CompletableFuture. It is useful for reading a snapshot and changing several presentation values in one scheduled operation. It runs inline when the caller already owns the player. Async opening and variable updates copy the input map before scheduling.

Pending player operations complete exceptionally if CraftCanvas disables or the player becomes unavailable before execution. Operation exceptions are carried by the future. Cancelling a queued player future prevents its function from starting; it cannot interrupt an operation that has already started. Continuations inherit the completing thread and must not assume a player or global context. Never call join() or get() from a tick thread.

See opening results, batching and tooltips.

See GUI controls for addons for literal Adventure notifications, configured component animations, filtered scrolling and session/thread guarantees.

See dynamic lists for addon records, reusable YAML row slots, searchable snapshots and record-aware callbacks.

Method Thread Result
registerAction(owner, id, action) Global / Paper main CanvasRegistration
registerAsyncAction(owner, id, action) Global / Paper main CanvasRegistration; pending stages cancel on removal
registerAction/registerAsyncAction/registerCondition(owner, id, schema, handler) Global / Paper main CanvasRegistration; validates typed callback data
registerCondition(owner, id, condition) Global / Paper main CanvasRegistration
registerProvider(owner, provider) Global / Paper main CanvasRegistration
installBundle(owner, bundle[, mode]) Request on global / Paper main Future of CanvasBundleResult
reload([screen]) Any Future of CanvasReloadResult

Registrations are automatically removed when their owning plugin disables. Handles support early removal. Callbacks and providers includes examples and ownership rules. Bundles installs addon-owned YAML and artwork; reloading compiles them and returns diagnostics.

SessionView exposes id, screen, revision, selected, tab, page and a read-only variables map. Keys in that map are scope-qualified, such as session.greeting or player.volume. Keep the session ID with asynchronous repository requests and pass it to batch/tooltip updates. A replaced session rejects the old ID. Multiple requests within one session still need addon-managed ordering.

Row action callbacks/events also expose an optional SessionView.listSelection with the captured container and immutable record. Ordinary session reads return null for this field; see dynamic lists.

Player events expose screen opening/closing, action execution and selection changes. Callbacks and events run on the corresponding player owner and can execute concurrently for different players on Folia. Shared addon state must be thread-safe. Plugin registration and provider invalidation run globally.

Use Paper/Folia 1.21.11 through 26.3 and the Java version required by that server. Compile addons targeting the complete range with Java 21 bytecode. Newer server-only APIs require your own version checks. The graphical renderer uses signed books; the separate native text editor is described in input controls.

Async addon actions await a CompletionStage<CanvasActionResult> before continuing YAML, with a server-tick deadline and session/registration cancellation.

Typed callback parameters provide immutable schema keys, defaults, bounds, choices and typed reads without casts, with configuration and invocation validation.