CityRP Documentation Repository

Jobs are saved by job key

Last updated

Status: Accepted · 2026-10-04 · charted by #2187

A job's index is handed out in registration order, so adding, removing or reordering a job shifts every index after it, and its display name changes with renames and spelling fixes. Anything that saved either one silently starts pointing at a different job, or at none: spawn points and keypad saves stored display names, and keypad duplicator data stored indices inside players' own saves.

The decision

  • Every job has a job key, a literal written at its registration: lowercase snake_case, containing at least one letter, never changed once shipped, and never reused by another job. A duplicate key is a load-time error.
  • The index never leaves the process. It stays the runtime identity the engine needs; anything saved, or typed into configuration by staff, names the job by its key.
  • Saved data whose key no longer resolves is kept and ignored, with one warning per key, never deleted: the job may only be absent on this server.
  • Saved data looks a key up exactly. Commands people type into may accept a key alongside today's forgiving name match; saved data never goes through that match.

Rejected alternatives

Derive the key from the display name or a command name

It needs no new argument, but a derived key moves when its source is renamed, which is the drift this decision exists to remove.

Keep saving display names, matched exactly

Exact matching fixes the ambiguity of today's substring lookup but not renames, and display names are player-facing text that is expected to change.

Name jobs by their TEAM_* global

The globals are stable within the source code, which is why configuration written as code is already safe, but they exist only in source: saved data can't hold a Lua symbol, and the global's value is the index.

Consequences

Old saves migrate lazily: a saved value that isn't a key falls back to an exact, case-insensitive display-name match, or is read as an index when it is a number, and the next save writes keys. The fallback stays until a tracked removal, because a map's file may not be loaded for months. An old duplicator save whose indices have already shifted can't be repaired, because nothing recorded which job it meant.