Skip to content

Desync when spamming the gravship launch button (RNG in CanReachGravship not isolated) #967

Description

@cmlee119

Summary

Spamming the gravship launch button desyncs clients. Reproduced on vanilla Multiplayer + Odyssey with no third-party mods (async time + multifaction, 2 players).

Reproduce

  • Async time + multifaction game with a gravship.
  • Rapidly click the gravship launch button many times (easier under a little lag). No simulation needs to be running - it happens with the game paused.
  • A client desyncs with Random state from commands doesn't match.

Cause

Building the launch confirmation dialog decides which pawns can board, in Dialog_BeginRitual's constructor:

Dialog_BeginRitual..ctor -> CreateRitualRoleAssignments
  -> RitualRoleAssignments.PawnNotAssignableReason
  -> RitualBehaviorWorker_GravshipLaunch.PawnCanFillRole
  -> CanReachGravship -> GravshipUtility.TryFindSpotOnGravship
  -> Region.RandomCell -> Rand.Range        // consumes RNG

Building the dialog is UI work that is opened only by the issuing peer (the currentExecutingCmdIssuedBySelf gate in CancelDialogBeginRitual), so this RNG runs on just one peer and advances the shared stream there only. Spamming the launch button repeats it and the divergence accumulates.

Measured

With nothing ticking (every map's mapTicks differed by only +1), the gravship map alone was off by +11,617 rand iterations, all consumed by the host who pressed launch. The vanilla desync report's local_metadata.txt lists only Prepatcher + Harmony + DLCs (including Odyssey) + Multiplayer - no third-party mods.

Present on current master (4a3be27).

A PR fixing this follows.


Investigated and written with the help of Claude (Anthropic).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions