-
Notifications
You must be signed in to change notification settings - Fork 20
Gamevals
This repository uses a small binary .dat format to ship gameval mappings (name → numeric id) generated from an OSRS cache revision.
They are a compact binary packing of UTF‑8 strings so upstream OSRS mappings can be generated from the cache and then treated as immutable inputs for custom content.
OpenRune uses gamevals to give stable, readable names to cache-backed IDs:
-
items.bronze_axe→1351 -
interfaces.toplevel_move_events→29998 -
tables.firemaking_logs→1223 -
dbrows.firemaking_magic_logs→96854 -
columns.firemaking_logs:log_id→ a packed int (see Columns)
At runtime and during codegen, these mappings let the code refer to definitions by string keys while still working with the numeric IDs required by the cache.
A key design goal (from the referenced CI/cache rework) is:
- Upstream OSRS mappings come from the cache revision and are generated when building the cache from upstream.
- Custom mappings are allowed, but only as new IDs above the upstream OSRS ID range, so you cannot silently override upstream OSRS IDs and introduce ID conflicts.
They are written to:
data/cfg/gamevals-binary/gamevals.datdata/cfg/gamevals-binary/gamevals_columns.dat
They are produced by the cache tool in cache/src/main/kotlin/org/alter/gamevals/GamevalDumper.kt.
They are loaded by:
and initialized early in both:
Both gamevals.dat and gamevals_columns.dat share the exact same structure.
All integers are big-endian (Java DataInputStream / DataOutputStream). All strings are UTF‑8.
File :=
int32 tableCount
repeat tableCount times:
uint16 tableNameLength
byte[tableNameLength] tableNameUtf8
int32 itemCount
repeat itemCount times:
uint16 itemLength
byte[itemLength] itemUtf8
Each itemUtf8 is a single mapping entry encoded as text. The loader accepts two shapes:
key=value
- Example:
bronze_axe=1351
-
key:subkey=value(used for grouped mappings such as components and sprite indices)
- Example:
toplevel_move_events:some_component=76023455
Internally, the loader stores mappings as <tableName>.<key> -> value.
Table names are the top-level group keys, matching the allowed RSCM prefixes in cache/src/main/kotlin/org/alter/rscm/RSCM.kt:
-
items,npcs,objects,sequences,spotanims, … -
interfaces,components -
tables,dbrows,columns -
enums,fonts,inv,varp,varbits, …
gamevals.dat contains many tables (sprites, interfaces, tables, dbrows, etc.).
gamevals_columns.dat contains only the columns table.
Columns are packed during generation in cache/src/main/kotlin/org/alter/gamevals/GamevalDumper.kt. Each entry is written as:
<tableName>:<columnName>=<packed>
where:
$packed = (tableId \ll 16) \lor columnId$
This makes column mappings unique across all tables.
The mapping provider loads sources in this order (see GameValProvider.load):
-
data/cfg/gamevals-binary/gamevals.dat(upstream OSRS) -
data/cfg/gamevals-binary/gamevals_columns.dat(upstream OSRS) - All
gamevals.tomlfiles undercontent/src/main/resources/org/alter/**(custom) - RSCM directories like
data/cfg/gamevals(custom, legacy-style)
After each .dat table is decoded, the loader computes maxBaseID[table] as the maximum ID present in that table (the upstream OSRS ceiling for that table).
When loading custom values (TOML or RSCM files), OpenRune enforces:
- Custom IDs must be strictly greater than the upstream OSRS max for that table.
- Keys must be unique within the table.
- Values must be unique within the table.
If you try to reuse/override an OSRS ID, you’ll get an error like:
- “Custom value must exceed the current max base ID … Cannot override existing osrs IDs.”
This is the mechanism described in the linked conversation: it prevents overriding upstream OSRS mappings, which avoids ID conflicts.
gamevals.toml is the preferred way for content/modules to declare new mappings.
Each module can ship its own file under its resources directory, e.g.:
content/src/main/resources/org/alter/skills/firemaking/gamevals.toml
The loader expects a top-level section named gamevals containing subtables named by prefix:
[gamevals.tables]
firemaking_logs = 1223
[gamevals.dbrows]
firemaking_magic_logs = 96854Valid subtable names are the same prefixes listed in RSCMType (items, npcs, tables, dbrows, enums, interfaces, components, columns, …).
Inside each TOML subtable, the left-hand side is the unprefixed name. OpenRune automatically prefixes it when storing the mapping.
Example:
[gamevals.tables]
firemaking_logs = 1223becomes the mapping key:
tables.firemaking_logs
This is what code will resolve via RSCM.getRSCM("tables.firemaking_logs").
- Pick the correct group (tables, dbrows, enums, etc.).
- Choose a new ID greater than the current upstream OSRS max for that group.
- Add it to a
gamevals.tomlin your module. - Rebuild/run so mappings are loaded.
Practical tips:
- Keep your additions in the module that “owns” the feature to reduce merge conflicts.
- Don’t guess low IDs—upstream OSRS content often already uses large ranges.
The loader computes max IDs from the generated .dat at startup; it doesn’t provide a dedicated CLI in this repo.
Common approaches:
- Inspect existing module
gamevals.tomlIDs for the same table type and follow the established high range. - If you need certainty, write a quick Kotlin snippet or temporarily log
GameValProvider.maxBaseIDafterGameValProvider.load().
You may also see legacy mapping files like:
data/cfg/gamevals/enums.rscm
These are line-oriented text mappings:
regular_tree_stumps=29999
They are still supported and loaded after TOML, but gamevals.toml is the recommended per-module mechanism.
They’re generated as part of cache build tooling and are derived from the current upstream OSRS cache revision (and, for columns, from the currently packed tables/rows).
- In cache/src/main/kotlin/org/alter/CacheTools.kt,
GamevalDumper.dumpGamevals(...)is called duringFRESH_INSTALLto emitgamevals.dat. - Cache builds regenerate
gamevals_columns.datviaGamevalDumper.dumpCols(...)after packing tables, so column IDs stay in sync with the current tables/rows.
If you change the upstream OSRS revision, treat both .dat files as generated artifacts that should be regenerated for that revision.
In Gradle, see the cache tasks in cache/build.gradle.kts (freshCache, buildCache).
- If the server/codegen fails with “Expected at least two files… gamevals.dat and gamevals_columns.dat”, you likely haven’t generated the
.datfiles yet. - If you get a “must exceed max base ID” error, pick a higher ID; you’re trying to override an upstream OSRS mapping.
- If you get a “mapping conflict” error, you duplicated a key or reused an ID value inside the same table.