Galactic Archive - rebaserHEAD/NexusForever GitHub Wiki
The Galactic Archive is the game's lore encyclopedia: articles about the creatures, places and people of Nexus, each made of up to 16 entries that fill in as you play. On stable, articles and entries unlock when a character completes an achievement or hands in a quest, and the state is saved per character and survives world changes and restarts. This page covers how that works and why; the wire and table layouts are on Galactic Archive messages and storage.
Upstream: #587 corrects the packet models and #588 adds the feature on top of it.
What it does
What a player sees
- An article appears in the panel the first time anything unlocks it. Some of its entries open with it.
- More entries fill in as the character finishes the achievements and quests tied to them.
- The panel's Updated Articles count includes every article holding an unlocked entry the player hasn't read yet, so it drops as they open them.
- A title, for the two articles that carry one, once every entry in the article is unlocked.
Vocabulary
| Term | Meaning |
|---|---|
| Article | One page of the archive, a row of ArchiveArticle |
| Entry | One section of an article, a row of ArchiveEntry |
| Slot | An entry's position in its article, 0 to 15. An entry can sit in more than one article, in a different slot in each |
| Unlock rule | A row of ArchiveEntryUnlockRule: one entry, and the achievements, quests or path missions that open it |
| Flag words | The two 32-bit words the server keeps per article: what's unlocked, and what's been read |
How it works
How the pieces hook together
flowchart TD
DONE["Achievement or quest done"] --> IDX["Rule index"]
IDX -->|article, slots| UL["Article unlock"]
CU["Client unlock or view"] --> UL
UL -->|update| CL["Client"]
UL -->|character save| DB[("Saved rows")]
WE["World entry"] -->|every article| CL
- At start-up, the server reads the three archive tables and builds an index: for each achievement or quest, which slots in which articles it opens.
- When a character completes an achievement or hands in a quest, a hook at the end of that code asks the index what opens. The server unlocks it and sends the client one update per article that changed.
- When the client unlocks or reads an article itself, it has already applied the change, so it tells the server, which records it and sends nothing back.
- After every world entry, the server sends every stored article again, because the client empties its archive on each world change.
- Changes are saved with the rest of the character, writing only the words that changed.
Why it's shaped this way
The server decides unlocks. The client applies its own unlocks and views locally, but only the server sees an achievement complete or a quest handed in. So the server owns the state, and the client's two messages are reports, not requests.
Every update is absolute. Each update carries both whole flag words for its article, and the client replaces its copy. There's no delta and no "clear this bit", so a resend can never get the client out of step.
A quest counts when it's handed in, not when its objectives are done. The hook sits at the end of the hand-in code, after the quest is marked complete, so achieving the objectives alone opens nothing.
Rules are OR-ed and never take bits away. Any one object in a rule satisfies it, and an entry with several rules opens on whichever fires first. Once a slot is set, no rule clears it. That's why unlocking is idempotent: a second completion that opens the same slot changes nothing and sends nothing.
The view rule mirrors the client exactly. When the player opens an article, the client marks it read and then reports it. The server applies the same change to its own words. If the two sides ended up different, the client would keep reporting the view.
Coverage
What isn't covered
- Path missions. Their rules are in the index, but nothing on
game_reworkcompletes a path mission yet, so they never fire. Adding them is one more hook beside the quest and achievement ones. - Backfill. A character only picks up articles from completions after the feature landed. Achievements and quests finished earlier don't count.
- A GM command for the archive. Commands need a new permission, and that needs a migration of the auth database.
- The title reward in game. The code grants it, but only two articles carry one, and nothing we could trigger completes either of them.
How it was verified
On a local server, from a Debug build, with the method on Verifying a feature:
| Check | Result |
|---|---|
| Start-up | 251 articles and 847 unlock rules loaded |
180 achievement grant commands, every achievement that unlocks something |
134 articles saved, every word matching the prediction from the tables |
| Two quest hand-ins in game | The expected articles updated to the predicted words |
| The archive panel | Its updated count matched the saved rows, and read state held across world changes |
| A server restart and a fresh login | The stored articles came back on world entry |
Where the code lives
| Piece | Path |
|---|---|
| Rule index | Source/NexusForever.Game/GalacticArchive/GlobalGalacticArchiveManager.cs |
| Per-character state | Source/NexusForever.Game/Entity/GalacticArchiveManager.cs, Source/NexusForever.Game/Entity/ArchiveArticle.cs |
| Hooks | The end of QuestManager.QuestComplete and of CharacterAchievementManager.CompleteAchievement |
The messages, flag words, table and the rest of the code map are on Galactic Archive messages and storage.