Skip to content

Configuration

This page documents the keys of config.yml. EmakiStorage's configuration is split across three files, and the capacity domain model has a page of its own:

TopicPage
The gui/storage_gui.yml template plus the gui and display sectionsGUI and Display
The capacity section, four capacity sources, three-level stackLimit, shrinking and overflowCapacity
The unlock_costs.yml paid tiersUnlock Costs

Run /estorage reload afterwards to reload config, language and GUI templates.

config.yml Top Level

yaml
version: "1.0.1"
language: "zh_CN"
release_default_data: true
op_bypass: false
debug: false
FieldTypeDefaultDescription
versionstring1.0.1Default resource version marker, maintained by resource sync.
languagestringzh_CNUses lang/<language>.yml.
release_default_databooleantrueWhether to release the bundled unlock_costs.yml when it is missing.
op_bypassbooleanfalseWhen true, OPs are treated as holding emakistorage.admin.
debugbooleanfalseParsed into the config object, but no branch in the current implementation reads it; manage debugging through /estorage debug.

unlock

yaml
unlock:
  overflow_policy: lock_readonly
  purchase_enabled: true
  cost_file: "unlock_costs.yml"
FieldTypeDefaultDescription
overflow_policyenumlock_readonlyHow to handle occupancy that exceeds a lowered capacity; the four values are documented in Capacity.
purchase_enabledbooleantrueWhether in-GUI paid expansion is available. Also requires the emakistorage.unlock.purchase permission.
cost_filestringunlock_costs.ymlFile name of the paid tier configuration, documented key by key in Unlock Costs.

behavior

yaml
behavior:
  overflow_on_withdraw: return
  withdraw_amounts:
    left: 1
    right: 16
    shift_left: 32
    shift_right: 64
  withdraw_prompt_enabled: true
  deposit_filter:
    mode: blacklist
    entries: []
  allow_unique_items: true
  default_sort: amount_desc
  player_sort_enabled: true
FieldTypeDefaultDescription
overflow_on_withdrawenumreturnWhat happens to the part the inventory refuses: return credits it back to storage, drop drops it on the ground.
withdraw_amounts.leftlong1Left-click withdrawal amount.
withdraw_amounts.rightlong16Right-click withdrawal amount.
withdraw_amounts.shift_leftlong32Shift + left-click withdrawal amount.
withdraw_amounts.shift_rightlong64Shift + right-click withdrawal amount.
withdraw_prompt_enabledbooleantrueWhether middle-click opens the chat prompt for a custom amount.
deposit_filter.modeenumblacklistDeposit filter mode: blacklist / whitelist / off.
deposit_filter.entrieslist[]List of CoreLib ItemSource tokens.
allow_unique_itemsbooleantrueWhether items carrying a per-instance marker may be deposited.
default_sortenumamount_descDefault sort: material_asc / material_desc / name_asc / name_desc / amount_asc / amount_desc.
player_sort_enabledbooleantrueWhether players may change the sort in the GUI. When false, default_sort is enforced.

When deposit_filter.mode is whitelist and entries is empty, nothing can be deposited. The unique-marker test is structural: it checks whether the item's own PersistentDataContainer is non-empty rather than reading its display name or lore.

These keys decide the amount each click moves and whether it is allowed at all; the full click semantics table, the rejected click kinds and the search-mode restriction live in GUI and Display.

yaml
search:
  enabled: true
  operators:
    name: "@"
    lore: "#"
    id: "$"
    exclude: "!"
  input_timeout: 30
  cancel_keywords: ["取消", "cancel"]
FieldTypeDefaultDescription
enabledbooleantrueWhether search is available.
operators.namestring@Matches the display name only.
operators.lorestring#Matches lore only.
operators.idstring$Matches the material key or ItemSource id only.
operators.excludestring!Exclusion: a match rejects the entry.
input_timeoutint30Chat input timeout in seconds.
cancel_keywordslist[取消, cancel]Keywords that cancel the input.

Operator prefixes are configurable so they can avoid clashing with item names. Search syntax:

  • Whitespace separates terms and every term must match (AND).
  • A term may carry one scope prefix and one exclusion prefix in either order, so !@diamond and @!diamond are equivalent.
  • Without a scope prefix a term matches the combined text, which is built from display name plus lore plus identifier, so an unscoped search can also hit a material key.
  • All matching is substring matching against text that was already lower-cased and stripped of formatting.

No regular-expression search is provided, not even behind an admin flag: a hostile pattern can stall the server through catastrophic backtracking, and substring matching covers the actual use case.

persistence

yaml
persistence:
  autosave_interval: 300
  drain_timeout: 10
FieldTypeDefaultDescription
autosave_intervalint300Autosave interval in seconds. 0 saves only when the GUI closes and on logout.
drain_timeoutint10Seconds to wait for file writes to drain when the plugin disables.

Multiple amount changes within one interval are merged into a single write. Every save is a full rewrite of storage.dat: write a sibling .tmp, re-read and validate the record count, then replace atomically. A failed write leaves the previous file untouched and deletes the tmp.

logging

yaml
logging:
  enabled: true
  retention_days: 30
  sources: []
FieldTypeDefaultDescription
enabledbooleantrueWhether ordinary flow records are written.
retention_daysint30Log retention in days. <= 0 disables purging.
sourceslist[]Record only these surfaces: gui / command / api / action. Empty means all.

The log layout is one directory per player and one file per day: logs/<uuid>/<yyyy-MM-dd>.log. Expired files are deleted per day; once every file for a player has expired, their directory is removed as well.

The three admin operation kinds ADMIN_SET, ADMIN_GIVE and ADMIN_CLEAR are always recorded, ignoring both enabled and sources. An admin disabling logging to save disk is no reason to lose the audit trail of admin changes.

The flow log is write-only: business logic never reads these files, which removes the need for an index, compaction, schema versioning or cross-file transactions. A failed write only logs a warning and never fails the storage transaction that produced it. Records queued for the same player are flushed as one append, so a 36-slot bulk deposit produces one file operation rather than 36.

  • GUI and Display: the gui and display sections, the gui/storage_gui.yml template and click semantics.
  • Capacity: the capacity section, the three-level stackLimit and the four overflow_policy values.
  • Unlock Costs: the tiers, pricing and payment ordering of unlock_costs.yml.
  • Commands and Permissions: the scope of /estorage reload and the permission tiers.
  • CoreLib Actions: changing slots and stackLimit from an action chain.
  • API and Integration: how StorageCapacity fields map onto configuration keys.