HarbourMasters / HarbourMasters/Lighthouse
[ANCHOR] Automatic seed alignment and save identity
- Dominant language
- C
- Stars
- 431
- Forks
- 38
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 26
Description
Here's the scenario: a host starts a rando game. Joiners can only play vanilla or roll their own seed, with the sole workaround being manual distribution of a spoiler log. That doesn't scale to, say, a streamer's 100+ viewers.
- You can't just send the seed, because the pool is filtered by local CVars. Same seed, different settings, different game.
- `std::shuffle`'s permutation is implementation-defined even with a standardized `mt19937`. Cross-platforms disagree.
- `GlitchlessLogic.cpp` uses `srand()` and `rand()`, which is also implementation-defined. Cross-platforms disagree.
- The code already treats `seedId` as a label, it's never re-simulated.
It's not user friendly and not intuitive. With Lighthouse especially, it's more likely that players in private rooms will hotswap rando vs vanilla and romhacks.
This may be a smaller resolution than we think though. Both halves exist: rando files currently write a spoiler log, and `GenerateFromSpoiler` reconstructs from that. Size will fit one packet, ~79KB compacted, which is still over the server's limit, and 38.9KB if check-name keys are dropped (names are re-derived from `StaticData::Checks` on import). Check-name keys must be dropped if spoiler files are to be sent as a packet, given the server's 64KB `bufio.Scanner` limit.
My sketch:
- Joiner enters a room with `roomState.isRando`, requests the spoiler from `roomState.ownerClientId`; owner replies.
- Prefetch and cache on join: file creation in `onFileLoad` is synchronous, so the blob must already be in hand.
- The existing `UseExistingLog` branch prefers the cached anchor spoiler, falls back if nothing arrives.
- Must land on a newly created file, never adopting an existing one.
- Must complete before the team-state exchange, or `gameSig` (see #530 where it's added) will refuse the host's state on the way in.
### Session identity:
`gameSig` can't tell "solo vanilla file" from "the team's vanilla file". Same game, different session. A joiner with an existing vanilla file in a vanilla room still gets overwritten. An `anchorSessionId` on `shipSaveData` would let a fresh file adopt the session, let a returning file match it, and a file carrying unrelated progress would prompt first.
### TL;DR
A host starts a randomizer game. Anyone who joins them cannot play that same randomized game unless the host manually sends each of them a file. For a couple of friends that's annoying; for a streamer with an audience it doesn't work at all.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with GlitchlessLogic.cpp, GenerateFromSpoiler, the UseExistingLog branch, and onFileLoad; then trace the team-state exchange and gameSig, including shipSaveData. Define the owner-to-joiner spoiler transfer and session identity behavior, including the file-creation and completion-order constraints. Done means joiners can obtain the host's randomized game and safely distinguish matching, new, and unrelated save files.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- distributed-systems, game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100