Skip to content

ax.util

Source: gamemode/framework/util/util_store.lua

Utility helpers used across the Parallax framework (printing, file handling, text utilities, etc.).

Section: store

Documented functions: 16

Functions


ax.util:CreateStore(spec, oldStore)

Creates and returns a new store instance for managing key/value settings.

A store is a self-contained object that handles registration of typed settings, persistence to a JSON file (or ax.data), optional networking between server and client, and change callbacks. The framework uses two stores: ax.config (server authority, broadcast to clients) and ax.option (client authority, synced to server for server-side reads).

spec fields:

  • name string: identifier used in debug messages (e.g. "config").
  • authority string: "server" or "client" — only that side persists and loads values from disk.
  • path string|function: DATA-relative path to the JSON file, or a function (spec, store) → string for dynamic paths.
  • net table: net channel names used for networking: init (bulk sync), set (single key update), sync (option bulk upload), request (server asks client to sync).
  • data table (optional): { key, options } for ax.data-backed persistence instead of raw JSON.
  • legacyPaths table (optional): array of older paths to migrate data from on first load.

When oldStore is provided (hot-reload scenario), registry, defaults, values, and networkedKeys are copied from it before the new store is configured, preserving runtime state across live code reloads.

Realm: shared

Parameters

Name Type Description
spec table The store specification (see above).
oldStore table\|nil An existing store to migrate state from, used during hot-reload to avoid losing in-memory values.

Returns

  • table: The new store object with all methods attached.

Usage

local store = ax.util:CreateStore({
    name = "config",
    authority = "server",
    path = ax.util:BuildDataPath("config"),
    net = { init = "ax.config.init", set = "ax.config.set" }
})

store:_setupNetworking()

Internal: wires up all net channel receivers and lifecycle hooks.

Called once during store initialisation. If ax.net is not yet available, defers via timer.Simple(0, ...) and retries on the next frame.

Registers the following depending on store type and realm:

  • config/server: PlayerReady hook (sends initial values to joining clients); spec.net.set receiver (admin-only remote config changes).
  • config/client: spec.net.init receiver (bulk initial values); spec.net.set receiver (individual key updates from server).
  • option/server: spec.net.sync receiver (bulk preference upload); spec.net.set receiver (single key updates); PlayerDisconnected hook (cleans up SERVER_CACHE); exposes store.RequestPlayerSync.
  • option/client: spec.net.request receiver (triggers Sync); InitPostEntity hook (auto-syncs after 2 seconds).

Also registers a ShutDown hook on the authority side to call Save.

This is an internal method — do not call it directly.

Realm: shared


store:Add(key, type, default, data)

Registers a new key/type/default definition in the store.

After registration, the key is available for Get and Set. The initial value is loaded from persisted data (if available and on the authority side), coerced to the registered type, and stored. If persisted data is absent or fails coercion, the default is used.

Keys are automatically added to store.networkedKeys unless data.bNoNetworking = true.

data fields:

  • category string: grouping label for UI (default "general").
  • bNoNetworking boolean: exclude this key from network sync.
  • bServerOnly boolean: (config only) value lives only on the server and is never transmitted to clients. Implies bNoNetworking and skips registration entirely on the client side, so ax.config:Get on the client returns the caller's fallback rather than a misleading default.
  • min / max number: clamp bounds applied when the type is ax.type.number.
  • decimals number: decimal precision for number clamping.
  • choices table / populate function: valid values for ax.type.array. populate() is called to build the choices list dynamically.
  • OnChanged function: callback (oldValue, newValue, key) fired when the value changes (unless bNoCallback is set in Set).

Returns false (with a debug message) when any required parameter is nil.

Realm: shared

Parameters

Name Type Description
key string The unique setting key.
type any An ax.type constant (e.g. ax.type.number, ax.type.string).
default any The default value used when no persisted value exists.
data table\|nil Optional metadata table (see field descriptions above).

Returns

  • boolean: True if registered successfully, false on invalid input.

store:Get(...)

Retrieves a value from the store with optional fallback.

Normal call: store:Get(key, fallback) — returns the stored value for key, or store.defaults[key], or fallback (in that priority order).

On the client, config values are served from the local CONFIG_CACHE (populated by server sync) rather than store.values.

Special call for option stores on the server: store:Get(player, key, fallback) — reads a per-player option value from SERVER_CACHE (populated when the client sends its preferences). If no cached value exists for that player, the registered default is used.

Realm: shared

Parameters

Name Type Description
... any Either (key, fallback) or (player, key, fallback).

Returns

  • any: The resolved value, or the fallback when no value is found.

store:GetAllByCategory(category)

Returns definitions for all keys whose category matches a filter string.

Matching is performed by ax.util:FindString — case-insensitive substring match. For example, "gen" will match "general". Keys with no category fall under "misc" for the purposes of this filter.

The returned map contains deep copies of the matched registry entries.

Realm: shared

Parameters

Name Type Description
category string The category string to filter by (partial match).

Returns

  • table: Map of key → { type, default, data } for matched keys.

store:GetAllCategories()

Returns an array of all unique category names in the registry.

Iterates all registered keys and collects their data.category field.

Keys without an explicit category are counted under "general".

The returned array contains each category string exactly once, in arbitrary order. Useful for building category tabs in a settings UI.

Realm: shared

Returns

  • table: An array of unique category name strings.

store:GetAllDefinitions()

Returns a deep copy of all registered setting definitions.

Each entry in the returned map is a copy of the registry entry (type, default, data) keyed by the setting key. Modifying the returned table does not affect the live registry. Useful for introspecting all available settings, e.g. for building a settings panel or exporting documentation.

Realm: shared

Returns

  • table: Map of key → { type, default, data } for all registered keys.

store:GetData(key)

Returns a copy of the metadata table for a registered key.

Returns a deep copy so callers cannot accidentally mutate the registry.

Returns nil when key is not a string or is not registered.

Realm: shared

Parameters

Name Type Description
key string The setting key to look up.

Returns

  • table|nil: A copy of the data table provided when the key was registered, or nil if the key is unknown.

store:GetDefault(key)

Returns the registered default value for a key.

This is the value passed as default to store:Add, or subsequently updated by store:SetDefault. Returns nil when key is not a string or is not registered.

Realm: shared

Parameters

Name Type Description
key string The setting key.

Returns

  • any: The default value, or nil if the key is unknown.

store:HandleConfigChange(regEntry, oldValue, newValue, key)

Invokes the OnChanged callback for a key if one is registered.

Called by the networking layer after a config value arrives from the server (on the client side). The callback is called via SafeCall so errors in user-defined callbacks do not break the networking flow.

oldValue may be nil when this is the initial sync (no prior value).

regEntry being nil or having no OnChanged function is safe — the call is silently skipped.

Realm: shared

Parameters

Name Type Description
regEntry table\|nil The registry entry for the key (from store.registry[key]).
oldValue any The previous value of the key, or nil on first sync.
newValue any The newly received value.
key string The setting key that changed.

store:Load()

Loads persisted values from disk into the store.

Only executes on the authority side (spec.authority): server stores load on SERVER, client stores load on CLIENT. Calling from the non-authority side is a no-op that returns false.

Clears the persisted data cache first (InvalidatePersistedCache), then loads from the primary path (or ax.data if configured). If the primary path is absent, falls back to any spec.legacyPaths entries and migrates the data to the primary path on success.

Each loaded key is coerced to its registered type; keys that fail coercion are skipped (debug message only). After loading, fires either hook.Run("OnConfigsLoaded") or hook.Run("OnOptionsLoaded").

Realm: shared

Returns

  • boolean: True if values were loaded successfully, false if no data file exists or the store is on the wrong realm.

store:Save()

Persists the current store values to disk.

Only executes on the authority side (spec.authority). No-op on the non-authority side. Serialises store.values and writes it to the primary path via ax.data:Set (if configured) or ax.util:WriteJSON.

On success, updates the persisted cache so subsequent Add calls can read back the correct initial value without re-reading the file.

A warning is printed (but false is returned silently) if the path is invalid or the write fails. This function is called automatically by Set (unless bNoSave is true) and on ShutDown.

Realm: shared

Returns

  • boolean: True if values were saved successfully, false otherwise.

store:Set(key, value, bNoSave, bNoCallback)

Sets a value in the store, triggering coercion, callbacks, and networking.

The full pipeline when setting a value:

  1. Coercion: value is sanitised to the registered type via ax.type:Sanitise. Numbers are additionally clamped and rounded using data.min, data.max, and data.decimals. Array values are validated against data.choices / data.populate.
  2. Change check: if the coerced value equals the current value, returns false immediately (no-op).
  3. Callbacks (unless bNoCallback is true):
  4. regEntry.data.OnChanged(oldValue, newValue, key) if defined.
  5. hook.Run("OnConfigChanged", ...) or hook.Run("OnOptionChanged", ...).
  6. Persistence (unless bNoSave is true): calls store:Save().
  7. Networking (if the key is in networkedKeys): broadcasts the new value via the appropriate net channel for the store type and realm.

Returns false (silently, with a debug message) for unknown keys or invalid values. Returns true when the value was actually changed.

Realm: shared

Parameters

Name Type Description
key string The setting key to update.
value any The new value (will be coerced to the registered type).
bNoSave boolean\|nil When true, skips writing to disk.
bNoCallback boolean\|nil When true, skips OnChanged and hooks.

Returns

  • boolean: True if the value changed, false otherwise.

store:SetDefault(key, value)

Updates the registered default value for a key without changing the current value.

Modifies both the registry entry's default field and store.defaults[key]. The live value in store.values is only changed if it is currently nil — existing values are preserved. Useful for overriding defaults set during initial registration, e.g. when a gamemode wants to change framework defaults.

Returns false when the key is not registered.

Realm: shared

Parameters

Name Type Description
key string The setting key whose default should be changed.
value any The new default value.

Returns

  • boolean: True on success, false if the key is unknown.

store:SetToDefault(key)

Resets a key's value to its registered default.

Convenience wrapper around store:Set(key, default). Goes through the full Set pipeline including coercion, callbacks, persistence, and networking — the reset is treated the same as any other value change.

Returns false when the key is not registered, or when the current value is already equal to the default (no change).

Realm: shared

Parameters

Name Type Description
key string The setting key to reset.

Returns

  • boolean: True if the value was changed, false otherwise.

store:Sync(target)

Synchronises networked key values across the network.

Behaviour depends on the store type and current realm:

  • config on server: collects all keys in store.networkedKeys and sends them via spec.net.init to target (a player or table of players). When target is nil, broadcasts to player.GetAll(). This is called automatically on PlayerReady to initialise new clients.
  • option on client: collects all networked option values from store.values and sends them to the server via spec.net.sync. This is called automatically 2 seconds after InitPostEntity and when the server sends a request net message.

Does nothing in other realm/store combinations.

Realm: shared

Parameters

Name Type Description
target Player\|table\|nil For config syncs: the recipient player(s). Defaults to all players when nil. Ignored for option syncs.