Class PermissionChestService

java.lang.Object
com.enhancedechest.service.PermissionChestService

public final class PermissionChestService extends Object
Grants and revokes ender chests based on a player's permissions. A permission encodes both a count and a slot size as enhancedechest.additional_amount.<count>.slot.<size> (e.g. enhancedechest.additional_amount.2.slot.54 → two 54-slot chests). All matching permissions stack (summed per size), so a player gets the total of every matching permission.

The grants live as ChestKind.PERM chests: to the player they behave exactly like a NORMAL chest (open/rename/icon/set-main), but admin commands never touch them and they are managed entirely by reconcile(java.util.UUID, java.util.Map<java.lang.Integer, java.lang.Integer>, int, int, java.util.List<com.enhancedechest.model.ChestSummary>) — the diff between the player's permission-derived target and the PERM chests they currently own. ChestOpener runs the reconcile on open, reusing the chest list it already fetched so the common case (target already matches) issues zero extra queries.

The player's base chest is inviolable: reconcile bootstraps a NORMAL chest #1 before granting any PERM chest, and never deletes a NORMAL chest, so a player can never be left with no chests.

All deletions/shrinks go through ChestSpillService, so any items that no longer fit spill into a temp chest (recoverable from /eclist) rather than being lost. The move back is automatic too: a chest granted here pulls one fitting temp chest's items back in (ChestSpillService.reclaimTempInto(java.util.UUID, int)), so a re-granted rank restores what its revoke parked.

  • Constructor Details

  • Method Details

    • setConfig

      public void setConfig(int defaultSize)
      Re-applies the runtime-tunable values after a /ee reload. Dupe-safe (only future work).
    • resolveTargets

      public PermissionChestService.PermTargets resolveTargets(org.bukkit.entity.Player player)
      Resolves both permission-derived targets in a single pass over the player's effective permissions. This runs on the region/main thread per open, and with LuckPerms the effective set is often hundreds of nodes with each getEffectivePermissions() call building a fresh snapshot — so it is scanned exactly once, and a cheap String.startsWith(java.lang.String, int) prefilter skips the regex Matcher allocation for the ~all nodes that are neither grant nor size-override nodes. Must be called on the player's entity thread (getEffectivePermissions).
    • reconcile

      public CompletableFuture<List<ChestSummary>> reconcile(UUID owner, Map<Integer,Integer> desired, int defaultTarget, int appliedDefault, List<ChestSummary> chests)
      Reconciles both the player's PERM chests (against their permission-derived desired target) and the base NORMAL chest's size (against the default_size permission), then completes with the up-to-date chest list. When nothing needs to change, returns the passed-in list with no DB writes (fast path).

      PERM chests. The diff keeps as many items in place as possible: existing PERM chests already at a desired size are kept untouched; surplus PERM chests are resized in place to fill a still-missing size (preserving their items, name and icon — only a shrink spills the overflow); any remaining missing sizes create fresh empty chests; and any true surplus is removed with its items spilled to temp.

      Base chest size. Driven by defaultTarget (from resolveTargets(org.bukkit.entity.Player)) and the persisted appliedDefault baseline:

      • defaultTarget > 0 — the player holds a default_size permission: the base chest is resized to it (grow, or shrink spilling the overflow to a temp chest);
      • defaultTarget == 0 with appliedDefault > 0 — the permission was just revoked: the base chest shrinks back to the config default (spilling any overflow);
      • defaultTarget == 0 with appliedDefault == 0 — never permission-managed: the base chest is left alone (its size is the admin/config domain).
      A base chest bootstrapped here is created directly at the permission size when one applies, so a brand-new player with the permission never needs a follow-up resize. Persisting the new baseline is the caller's job (it equals defaultTarget); this method only moves items.
      Parameters:
      defaultTarget - the base-chest size override (0 = no default_size permission held)
      appliedDefault - the persisted applied_default_size baseline (last permission-set size)
      chests - the player's current chests (already fetched by the caller)