Public API
Compile-time dependency
<repositories><repository><id>emaki-public</id><url>https://repo.crypticlib.com/repository/maven-public/</url></repository></repositories>
<dependency><groupId>emaki.jiuwu.craft</groupId><artifactId>emaki-storage-api</artifactId><version>1.0.6</version><scope>provided</scope></dependency>repositories { maven("https://repo.crypticlib.com/repository/maven-public/") }
dependencies { compileOnly("emaki.jiuwu.craft:emaki-storage-api:1.0.6") }Compile only — never install, shade, or relocate this jar
EmakiStorage embeds the un-relocated API. A bundled copy breaks event and static bridge identity.
Use EmakiStorageApi.status().usable() and operations(). install, uninstall, and Bridge are internal.
All data methods are futures: readSnapshotAsync(UUID), depositAsync(UUID,ItemStack,long), withdrawAsync(UUID,ItemStack,long), countOfAsync(UUID,ItemStack), grantSlotsAsync(UUID,int), setStackLimitAsync(UUID,long), and setSlotStackLimitAsync(UUID,int,long). They may be submitted from any thread; reads use the storage lane as needed and mutations dispatch to the target player's owner thread. Completion callbacks are not guaranteed to be Bukkit-owner callbacks, so dispatch any Bukkit access yourself. StorageAmount reports requested versus applied amounts; zero count is a legitimate success value.
Batch, bulk-count, and reservation methods complete the surface:
| Method | Semantics |
|---|---|
countAllAsync(UUID,Collection<ItemStack>) | Counts several templates in one pass, returning Map<ItemStack,Long>. A template absent from storage maps to 0L rather than being missing. Available for offline players. |
applyBatchAsync(UUID,StorageBatchRequest) | Atomic signed increments that never route through the player's inventory. allOrNothing is declared inside StorageBatchRequest, not as a separate parameter; the payload is StorageBatchResult. Exceeding behavior.batch_max_ops returns INVALID_INPUT with batch_too_large and applies nothing. |
reserveAsync(UUID,StorageBatchRequest,Duration) | Holds only the withdrawal side of the request; the payload is a ReservationHandle. Deposit ops in the request are ignored, because a reservation holds stock back rather than pre-booking capacity. A non-positive ttl is rejected. Reservations survive a restart and are released on load once ttl has elapsed. |
commitAsync(ReservationHandle) | Applies a reserved batch; the payload is StorageBatchResult. It takes the handle only, with no UUID, and re-runs the deposit-side pre-checks. |
releaseAsync(ReservationHandle) | Drops a hold; the payload is Unit. It takes the handle only. Idempotent: an unknown or already-released handle returns NOT_FOUND rather than failing loudly. |
Reserved units stay visible through StorageEntrySnapshot#reservedAmount() but are excluded from what applyBatchAsync may take, so the same units cannot be promised twice. Exactly one StorageBatchEvent fires for a whole batch; per-op deposit and withdraw events are deliberately not fired.
openGui(player) is the only synchronous operation. It requires the supplied player's owner thread and never schedules a later open. Use EmakiResult<Unit> for GUI success/failure.
Use Success, Partial, Failure, and optionalValue(). Failure kinds are UNAVAILABLE, NOT_FOUND, INVALID_INPUT, REJECTED, CANCELLED, TARGET_OFFLINE, WRONG_THREAD, INTERNAL_ERROR.