Skip to content

Generated reference. This page mirrors Code/Jobs/README.md, this module's source-of-truth documentation (Standards/02_DOCUMENTATION_STANDARDS.md §1). Edit it there, not here -- this file is regenerated on every docs build and any local edit is silently overwritten.

Jobs

Purpose. The group→gang→team hierarchy, job definitions, and joining. See 16_JOBS_FRAMEWORK.md.

Responsibilities. - TeamGroup — the fixed, closed set of groups (Officials, Civilians, Underground). - JobDefinition — content, not code: display name, group, gang id, level, max players, required character permission, mandatory-transit flag, rejoin cooldown, sort order, and (Milestone 8) CanManufacture — legacy's canmake list, the categories a holder may manufacture. See 16_JOBS_FRAMEWORK.md §2 for what's still deliberately not modelled (the cantuse blacklist, loadouts, ammo grants, governance flags, salary). - IJobRegistry / JobRegistry — every loaded JobDefinition, sorted by SortOrder. Mirrors IItemRegistry, minus inheritance resolution (jobs don't have ParentId). - JobsConfigurationDefaultJobName (the job a never-saved character starts as; legacy's TEAM_DEFAULT = TEAM_CITIZEN). - TeamMembership (internal) / IJobService / JobStore — the values themselves: LoadOrCreateAsync, GetCurrentJobName, JoinJobAsync. JobStore is the one implementation; nothing else writes a character's job. Follows EconomyStore's persist-on-write shape — joining is a discrete event, not a per-frame decay. - /team <jobName> — Jobs' own first real Commands entry, registered by JobsModule. - Persistence of job membership under jobs/{characterId} (08_DATA_MODEL.md §8).

Not responsible for. - Demotion and mutiny. Real governance logic (level/flag checks, quorum, supermajority) — see 16_JOBS_FRAMEWORK.md §6. - Job-blacklisting. No blacklist data model exists anywhere in this codebase — Code/Characters/AccountModeration.cs is account-ban status, unrelated. - Term-limit auto-expiry. Needs a ticking/polling mechanism, not built here. The rejoin cooldown half of the same legacy setting is built. - Salary and payday. Code/Economy/README.md already defers this; still deferred — crediting a lump sum at join would be inventing a mechanic legacy doesn't actually have. - Enforcing CanManufacture, or cantuse. CanManufacture (Milestone 8) is recipe data ready to be read; the /manufacture command that would read it isn't built — see Code/Items/README.md's "Not responsible for". cantuse (a per-job category blacklist on using an item, not manufacturing it) isn't modelled at all yet. - Telling the calling player the outcome of /team. Chat now exists (Milestone 7), but /team's Execute closure was not revisited to use it — still the same "only in the server log" limitation /help originally carried, now a real gap rather than a can't-exist-yet one.

Dependencies. Core (IServiceRegistry, IServiceResolver, IPersistenceBackend, ISchemaRegistry, IGameLog, IClock), Characters (CharacterId, Character.HasPermission), Items (ItemCategory, for CanManufacture), Commands (ICommandRegistry, for /team's registration).

Public API. - IJobRegistryFind(string), Get(string), All. - IJobServiceLoadOrCreateAsync(CharacterId), GetCurrentJobName(CharacterId), JoinJobAsync(Character, string). - JobDefinition, TeamGroup, JobsConfiguration.

Events published. None yet — a JobChanged event is natural once a consumer (a scoreboard, a HUD element) needs to react, deferred until that consumer exists, following Inventories' README's identical deferral.

Persistence. JobDocument { CharacterId, CurrentJobName, CooldownUntil } under jobs/{characterId}, schema version 1.

Not unit-tested. JobRegistry's own constructor (dedupe-by-AssetId, sort by SortOrder) has no test. JobDefinition.AssetId is computed from GameResource.ResourceName and unsettable without a real engine-loaded asset — the identical reason UnitTests/Items/ItemRegistryTests.cs never constructs a real ItemRegistry either, testing only its separately-exposed ResolveInheritance (against ItemDefinitionFixture, not ItemDefinition). JobRegistry has no equivalently-complex static method worth extracting the same way, so it's left untested, matching ItemRegistry's own constructor precedent rather than inventing a new technique. JobStoreTests.cs avoids the same problem entirely by using a FakeJobRegistry keyed however the test chooses, not by any real JobDefinition's own AssetId.

Future improvements. - Demotion and mutiny, once governance logic is designed as its own pass. - Job-blacklisting, once a blacklist data model exists. - Term-limit auto-expiry, once a ticking mechanism for Jobs is built. - Salary/payday, once a recurring-tick mechanism exists for Economy to drive. - The /manufacture command reading CanManufacture, once target-agnostic world-position resolution exists (see Code/Items/README.md). - The cantuse blacklist, loadouts, and starting ammo grants — real features, not fields. - A reply-to-caller path for /team, now that Chat exists but hasn't been wired to it.