Static Content, Dynamic State, Runtime Cache
Game data lives in three places. Knowing which is which saves you hours.
STATIC CONTENT DYNAMIC STATE RUNTIME CACHE
────────────── ───────────── ─────────────
dist/data/*.xml MySQL Singletons in
buylists/ (per-chronicle data/xml/ &
multisell/ schema in data/sql/
spawns/ dist/db_installer/
stats/ *.sql) HtmCache
zones/ World grid
scripts/ (java) players, clans, Managers
html/ items, mail,
geodata/ olympiad, ...
▲ ▲ ▲
parsed on boot read/write at filled on boot,
into POJOs runtime via JDBC queried by code
▼
gameserver code
(XML loaders, SQL tables, in-memory singletons
all called from handlers, managers, packets)
The three tiers
Static content - dist/data/*.xml
Items, skills, NPCs, multisell lists, buylists, spawns, zones, drop tables, geodata. Authored as XML, hand-written or copied from retail observation. Parsed exactly once at boot by Java loaders in gameserver/data/xml/, turned into immutable POJOs, and kept in singletons for the rest of the server's life.
If you change an XML file the on-disk content has updated, but the in-memory singleton is stale. On a development server you can refresh it with the matching //reload <type> admin command (see the reload reference); on a live server the recommended fix is a restart, because //reload carries a dev-only warning.
Dynamic state - MySQL
Anything that has to survive a server restart and that changes during play:
- Player characters: name, class, position, stats, inventory, skills learned.
- Clans: members, reputation, alliance, war declarations.
- Items in the world: existing item instances and their owners.
- Mail, offline trade listings, Olympiad standings, daily mission progress.
The schema lives in dist/db_installer/*.sql. Java access goes through table classes under gameserver/data/sql/ (e.g. ClanTable, OfflineTraderTable) which wrap JDBC reads/writes against the HikariCP pool.
Runtime cache - Java singletons
The in-memory state derived from the first two tiers:
ItemData,SkillData,NpcData,MultisellData, ... - the parsed XML.ClanTable,AnnouncementsTable, ... - the cached SQL.HtmCache- in-game HTML pages, loaded lazily.World- the spatial grid of everyWorldObjectcurrently online.- Every
*Managersingleton - its working state.
Most code talks to this tier, not directly to XML or SQL.
Why the split matters
Confusing these tiers is the most common reason a change "doesn't take":
- Edit an item XML and forget to
//reload item(or restart)? Old values still in the singleton cache. - Edit a row in the database while the server runs? Singletons that cache it will not notice.
- Add a new field to the XML but not the loader? It is silently ignored.
- Add a column to the schema but not to the table class? The new column is invisible.
The rule is simple: XML changes need a restart, SQL changes need a restart unless that table has a reload command, code changes need a rebuild + restart.