Skip to content

Capacity

This page covers EmakiStorage's capacity domain model: the capacity section of config.yml, the four capacity sources, the three-level stackLimit, and what happens to occupancy when capacity shrinks.

capacity

yaml
capacity:
  base_slots: 45
  max_slots: 1000
  warn_entry_count: 5000
  default_stack_limit: 100
FieldTypeDefaultDescription
base_slotsint45Default open slot count (45 = 5 × 9, matching the gui.storage_rows default).
max_slotsint1000Hard ceiling on total slots. 0 means unlimited.
warn_entry_countint5000Logs a console warning when the entry count exceeds this value. 0 disables the warning.
default_stack_limitlong100Config-level per-slot ceiling. At this level 0 means unlimited.

Four Capacity Sources

effectiveSlots is the sum of four independently persisted sources, then clamped:

text
effective = clamp(base_slots + permission tier + grantedSlots + purchasedSlots, 0, max_slots)

The upper clamp is skipped when max_slots is 0. Because the four sources are stored separately, lowering base_slots never consumes slots a player was granted or purchased.

SourceComes fromCan be negative
baseSlotscapacity.base_slotsNo (negatives treated as 0)
permissionSlotsHighest emakistorage.slots.<n> tierNo
grantedSlots/estorage slot grant, API grantSlots, action storage-grant-slotYes
purchasedSlotsIn-GUI paid expansion, action storage-unlock-slotNo

Page count is derived from slot count and cannot be configured in reverse:

text
totalPages     = max(1, ceil(effectiveSlots / slots per page))
reachablePages = max(1, ceil(usedSlots / slots per page))

Page 1 is always reachable (an empty warehouse must still open and accept its first item); a page holding no entry at all cannot be paged into.

Confirm you have enough memory before setting max_slots to 0 (unlimited). The figure given in the config comment is roughly 100–200MB of heap for 100,000 entries on one player; that is an estimate and has not been measured.

Three-Level stackLimit

The per-slot ceiling resolves most-specific-first across three levels:

LevelStored inSet throughMeaning of 0
EntryThe matching entry in meta.yml/estorage stacklimit slot, API setSlotStackLimit, action storage-set-stacklimit with slotInherit the player level
PlayerdefaultStackLimit in meta.yml/estorage stacklimit player, API setStackLimit, action storage-set-stacklimit without slotInherit the config level
Configcapacity.default_stack_limit in config.ymlConfig fileUnlimited (equivalent to Long.MAX_VALUE)

The same 0 means different things per level: at entry and player level it means "inherit the next level", at config level it means "no limit". Resolution order is entry level > 0, then player level > 0, then the config level; a config level <= 0 yields Long.MAX_VALUE.

The emakistorage.stacklimit.<n> permission tier can also supply a player-level ceiling, again taking the highest value and not supporting wildcards.

Shrinking and Overflow

When a lowered capacity leaves occupancy beyond the boundary, the outcome is decided by unlock.overflow_policy. The key itself is documented in the unlock section of Configuration.

The Four overflow_policy Values

ValueBehaviour
lock_readonlyEntries beyond the capacity boundary become read-only: withdrawable, not depositable, released as soon as they are emptied. Recommended.
compactOverflowing entries roll forward into free slots. Entries are already stored in a gap-free compact list, so "roll forward" is the list's natural state; whatever still does not fit degrades to lock_readonly.
return_inventoryTries to hand overflowing entries back to the player's inventory; whatever does not fit degrades to lock_readonly. Nothing is returned while the player is offline, entries are simply locked.
reject_changeRefuses the shrink outright.

All four policies are zero-loss. There is deliberately no drop or delete: irreversible data loss must never be triggered implicitly by adjusting a config value.

Overflow state is not persisted. It is derived from capacity versus occupancy and recomputed whenever capacity changes — login, reload, permission change, command grant — so a stored flag can never drift out of sync with the facts.