Persistent configuration, game preferences, cache data, and live session state have different owners and durability requirements. Store only data that remains meaningful when the client restarts.
Data classes
| Class | Lifetime | Examples |
|---|---|---|
| Game setting | Managed by the client | Graphics, controls and interface preferences |
| Mod configuration | Across client restarts | Enabled flags, positions and semantic selections |
| Account-specific configuration | Across restarts for one account | Per-account preferences and history |
| Cache | Rebuildable | Indexes, downloaded metadata and derived values |
| Session state | Current process/account/arena/view | Callbacks, entity IDs and open windows |
Background file-cache mutation and notification are separate
FileLocalCache(isAsync=True) is a different persistence layer from account preferences and mod-owned JSON. The Python helper starts an I/O thread per read or write and serializes operations with a lock keyed by its path. The lock provides mutual exclusion, not submission-order completion. The read worker invokes its internal event under that lock. The cache's _setCache therefore runs on that worker path; only the outward onRead notification is submitted through BigWorld.callback(0, ...). A deferred notification does not prove that all preceding state mutation happened on the game thread. Empty decoded values schedule no outward notification, so this event is not a guaranteed terminal result for every read attempt.
The helper does not retain a worker handle or expose write completion. Its asynchronous clear() path removes read-event subscriptions; it does not join or cancel an in-flight thread. Base read() does not reattach the internal subscription after that clear. An owner reusing the cache needs an explicitly verified reinitialization contract, while pending work still needs separate lifetime and result-admission checks.
Cache readiness does not establish freshness. A consumer can accept remote data while a disk read is still pending; a later read can replace that mapping. A queued read notification may instead inspect remote data written after the read, because it carries no read snapshot. The cache implementation and its readiness consumer illustrate this distinction. For mod-owned data, choose which disk or remote generation may replace the cache before mutation; checking only at notification time cannot undo an older result already accepted.
For mod-owned persistence, distinguish immutable data captured for I/O, worker completion, current-generation acceptance and game-thread publication. A path lock is not a main-thread dispatcher or a durable-write acknowledgement. See the Python local-cache helper in the latest public source. This establishes wrapper control flow, not real-thread scheduling, disk durability or an installed-client failure.