Show navigation
Save Data
The save, its lease, the shared blob-state path with its If-Match, the slices of the bag, Adventure Rank, achievements, wish counters, Reputation and Companionship, the guest merge and the replaced signal are built as save data describes. What is left is what the world holds that the save does not yet.
Decisions
- The roster is the save's next slice, and Companionship EXP is applied to it. Companionship EXP is saved by character id already, but no character is saved, so the EXP has no character to land on. The roster slice is each held character's id, level, ascension, constellations, talent levels, weapon and artifacts, with its copy count beside it, each piece owned by the model it is.
- A set whose entries paid into the wallet or the bag merges as the account's copy. When the opened chests or the collected items gain a slice, it merges with the wallet and the bag, never by union, since a union would keep a guest's opened chest while the account's wallet drops what it paid, and the chest could never pay again.
- A character's Companionship EXP stays in its own slice. The world's
CharactercarriesfriendshipExp, and the save keeps it once, incompanionshipExpby the character's id: a loaded character reads it from there, and a save writes each character's back, a character the roster lacks keeping its saved EXP. - A guest's character is merged whole. A character both copies hold is the copy further on, by its level and then its constellations, kept whole so its weapon and artifacts stay one copy's, as a kind of wish keeps one copy's counters; its copy count takes the larger. A character only one copy holds is kept.
Left to build
Copy
packages/genshin-world/src/models/character/CharacterSave.ts
- The characters the player holds and their copies. A wish grants characters, which the World screen keeps in its
charactersroster andcharacterCopyCountMap, and no save holds either, so a reload loses every character a wish granted. AddCharacterSave.ts, one held character as the save keeps it: itsid,level,ascension,constellationCount,stellaFortunaCountandtalentLevels, itsweaponandartifactswith the fields their models hold, and itscopyCount, each bounded as the other slices' fields are.GenshinSavegainscharacters: z.array(characterSaveSchema).max(MAX_CHARACTER_COUNT), with no default, as the save's slices carry none,MAX_CHARACTER_COUNTbeing inservices/save/constants.tsalready, andGenshinSaveStategainscharactersandcharacterCopyCountMap.services/save/toCharacters.tsreads them andservices/save/toCharacterSaves.tswrites them, wired inreadGenshinSaveandtoGenshinSave, andmergeGenshinSavemerges them by the decision above.useWorldCombat'scharactersstarts from the saved roster, the Traveler alone where it is empty, the session'scharacterCopyCountMapfrom the saved counts, anduseWorldSaveSyncwrites both. Tests:services/save/readGenshinSave.test.tsreads back a charactertoGenshinSavewrote, its Companionship EXP among it;services/save/mergeGenshinSave.test.tsmerges a character both copies hold (the higher level's copy, the larger copy count) and keeps one only the guest holds. - The enemy respawn timers, once they are saved. The Enemies component keeps each defeated enemy's instant in memory on the local clock, so a reload resets them. When the save holds them, they are read through the server's offset like the gathering points' respawns.
Scroll to top