Skip to content

Fix desync when cancelling a gravship launch#966

Open
cmlee119 wants to merge 1 commit into
rwmt:masterfrom
cmlee119:fix/gravship-launch-cancel-currentmap-desync
Open

Fix desync when cancelling a gravship launch#966
cmlee119 wants to merge 1 commit into
rwmt:masterfrom
cmlee119:fix/gravship-launch-cancel-currentmap-desync

Conversation

@cmlee119

Copy link
Copy Markdown

Fixes #965.

Problem

PatchGravshipPreLaunchCancel.Postfix closed the GravshipTravelSession with:

GravshipTravelUtils.CloseSessionAt(Find.CurrentMap.Tile);

Cancelling a gravship launch is a synced command, so this runs on every peer — but Find.CurrentMap is the map each peer's camera is on, i.e. local UI state, not synchronized simulation state. A peer whose camera is on another map calls CloseSessionAt with the wrong tile and never closes the session, so that map stays paused only for them. Because GravshipTravelSession.IsCurrentlyPausing(map) => map == Map gates whether the map ticks, the per-map tick counts then diverge and the game desyncs (Map instances don't match / Wrong random state on map N).

Of the four CloseSessionAt call sites in GravshipTravelSessionPatches.cs, this was the only one using Find.CurrentMap; the others already pass deterministic tiles (curTile / landingTile / takeoffTile).

Fix

Close the session by looking it up instead of by the local camera. There is exactly one open GravshipTravelSession while a launch is pending, so a small CloseAllSessions() helper closes it deterministically on every peer.

Testing

  • Reproduced on vanilla Multiplayer + Odyssey (async time + multifaction, no third-party mods): host launches from the gravship map with a client looking at another map, host cancels → client desyncs, gravship map paused only on the client.
  • With the fix, cancelling releases the pause on the gravship map on all peers and no desync occurs.
  • Source/Client builds clean (Release).

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

The prelaunch-cancel handler closed the GravshipTravelSession with
CloseSessionAt(Find.CurrentMap.Tile). Cancelling runs as a synced command
on every peer, but Find.CurrentMap is the map each peer's camera is on -
local UI state, not synchronized simulation state. A peer whose camera is
on a different map closes the wrong tile and never closes the gravship
session, so that map stays paused only for them. The per-map tick counts
then diverge and the game desyncs ("Map instances don't match" /
"Wrong random state on map N").

Close the session by looking it up instead of by the local camera. Of the
four CloseSessionAt call sites, this was the only one using Find.CurrentMap;
the others already pass deterministic tiles (curTile/landingTile/takeoffTile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desync when cancelling a gravship launch (CloseSessionAt uses Find.CurrentMap)

1 participant