Class ChestSpillService
reclaimTempInto(java.util.UUID, int)). Each first
force-closes every viewer's GUI via ChestSessionManager.forceCloseAll(java.util.UUID, int) (flushing the live
session), then runs the load-decode-split exclusively per (owner, index) via
ChestSessionManager.runExclusive(java.util.UUID, int, java.util.function.Supplier<T>) so no concurrent open sees a half-applied state — keeping
the swaps dupe-safe even with multiple concurrent viewers. Drives /ee resize, /ee
delete, and the expiry sweeper.-
Constructor Summary
ConstructorsConstructorDescriptionChestSpillService(ChestSessionManager sessions, EnderChestStorage storage, ContainerCodec codec, StorageGateway storageGateway, TempReclaimNotifier reclaimNotifier, long tempExpiryMillis, boolean autoReclaim) -
Method Summary
Modifier and TypeMethodDescriptionclearChest(UUID owner, int index) Empties a chest's contents (admin "clear chest" action), keeping the chest itself (size, name, icon, kind).reclaimTempInto(UUID owner, int targetIndex) The inverse of a spill: moves one temp chest's items whole into the freshly created, still-empty chest attargetIndex, then deletes the temp chest.removeChest(UUID owner, int index, boolean force) Removes a chest.removeNewestChests(UUID owner, int count, boolean force) Bulk-removes thecounthighest-numbered NORMAL chests a player owns, spilling (or force-discarding) each, and completes with the number actually removed.resizeOrSpill(UUID owner, int index, int newSize) Resizes a chest, spilling any cut-off items into a temp chest if it is shrunk below its used slots.voidsetTempConfig(long tempExpiryMillis, boolean autoReclaim) Re-applies the runtime-tunable temp-chest settings after a/ee reload.Sorts a chest's contents in place: identical items are merged into full stacks and everything is reordered by item type (then by descending stack size), packed from the first slot.
-
Constructor Details
-
ChestSpillService
public ChestSpillService(ChestSessionManager sessions, EnderChestStorage storage, ContainerCodec codec, StorageGateway storageGateway, TempReclaimNotifier reclaimNotifier, long tempExpiryMillis, boolean autoReclaim)
-
-
Method Details
-
setTempConfig
public void setTempConfig(long tempExpiryMillis, boolean autoReclaim) Re-applies the runtime-tunable temp-chest settings after a/ee reload. Only affects temp chests stamped (and reclaims started) after this call, so it is dupe-safe to set on the main thread while async storage work is pending. -
resizeOrSpill
Resizes a chest, spilling any cut-off items into a temp chest if it is shrunk below its used slots. Force-closes every viewer's GUI first (flushing the live session), then runs the load-decode-split exclusively per (owner, index) so no concurrent open sees a half-applied state. A grow, or a shrink that loses no items, is a plain resize. -
removeChest
Removes a chest. Withforcethe row is hard-deleted (items lost immediately); otherwise any items are spilled into a temp chest first. Force-closes every viewer's GUI, then performs the delete exclusively per (owner, index) so the swap is dupe-safe. Used by/ee deleteand by the expiry sweeper (NORMAL → spill, TEMP → force). -
reclaimTempInto
The inverse of a spill: moves one temp chest's items whole into the freshly created, still-empty chest attargetIndex, then deletes the temp chest. Called right after a new chest is granted (a permission reconcile,/ee add), so a player who lost a chest and got its items parked in a temp chest gets them back automatically when a chest of at least that size comes back. A no-op (completingfalse) when the feature is off, when the target is gone or is itself a temp chest, or when no temp chest fits.One temp chest, one target, no repacking. Only a temp chest whose slot count is
<=the target's is eligible, and its stored bytes are copied verbatim, so every item lands on the exact slot it already occupied. Items are never split across several chests and an existing layout is never reshuffled — a partially fitting temp chest is left alone rather than merged in. When several temp chests fit, the one expiring soonest is taken first: it is the one closest to being lost.A move that actually happened is announced to the owner through
TempReclaimNotifier(temp-enderchest.reclaim-notify), so items do not silently change chest number under them.Dupe-safety follows the same model as the spills above, widened to the two chests involved: both GUIs are force-closed (flushing any live session), then the swap runs behind the pending saves of both keys via
ChestSessionManager.runExclusiveAcross(java.util.List<com.enhancedechest.service.ChestSessionManager.ChestRef>, java.util.function.Supplier<T>), and the storage call re-checks every precondition under the cache lock. -
clearChest
Empties a chest's contents (admin "clear chest" action), keeping the chest itself (size, name, icon, kind). Force-closes every viewer's GUI first so the live session can't re-save the old contents over the wipe, then clears exclusively per (owner, index) so the swap is dupe-safe. -
sortChest
Sorts a chest's contents in place: identical items are merged into full stacks and everything is reordered by item type (then by descending stack size), packed from the first slot. Force-closes every viewer's GUI first (so the live session can't re-save the old order over the sort), then runs the load-sort-save exclusively per (owner, index) so the swap is dupe-safe. A no-op for a missing or empty chest. The chest's size, name, icon and kind are untouched — only the item layout changes. -
removeNewestChests
Bulk-removes thecounthighest-numbered NORMAL chests a player owns, spilling (or force-discarding) each, and completes with the number actually removed. The player's first chest — the lowest-indexed NORMAL chest — is always protected, so a player can never be left with no chests; deleting fewer thancountwhen that is all that is eligible is not an error. Temp chests are ignored (they are transient and expire on their own).Targets are snapshotted up front, then deleted sequentially: a spilling delete creates a fresh temp chest at a higher index, but those are not in the target list so they are never re-touched. Each per-index delete still serializes behind its own pending saves and force-closes open GUIs, so the bulk op is dupe-safe.
-