From 5119a75fbb91a145021386c24abca4db22295ddc Mon Sep 17 00:00:00 2001 From: Tick-git <62646477+Tick-git@users.noreply.github.com> Date: Sun, 20 Jul 2025 14:35:39 +0200 Subject: [PATCH] Fix scenario research lost on reconnect (#585) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix for #585 . ScenPart_StartingResearch.PostGameStart was only executed on the local machine of the faction creator. As a result, the host/save did not reflect this change properly. I’ve opened an issue #587 to improve the overall handling of ScenParts. I believe there’s more to gain by reviewing the other available part scenParts. I’ve added this as a TODO for future work. --- Source/Client/Factions/FactionCreator.cs | 64 +++++++++++------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/Source/Client/Factions/FactionCreator.cs b/Source/Client/Factions/FactionCreator.cs index 801cc7dd8..99d5693a6 100644 --- a/Source/Client/Factions/FactionCreator.cs +++ b/Source/Client/Factions/FactionCreator.cs @@ -32,14 +32,14 @@ public static void SendPawn(int playerId, Pawn p) [SyncMethod] public static void CreateFaction(int playerId, FactionCreationData creationData) { - var self = TickPatch.currentExecutingCmdIssuedBySelf; + var executingOnlyOnIssuer = TickPatch.currentExecutingCmdIssuedBySelf; LongEventHandler.QueueLongEvent(() => { var scenario = creationData.scenarioDef?.scenario ?? Current.Game.Scenario; Map newMap = null; - PrepareGameInitData(playerId, scenario, self, creationData.startingPossessions); + PrepareGameInitData(playerId, scenario, executingOnlyOnIssuer, creationData.startingPossessions); var newFaction = NewFactionWithIdeo( creationData.factionName, @@ -62,17 +62,15 @@ public static void CreateFaction(int playerId, FactionCreationData creationData) map.attackTargetsCache.Notify_FactionHostilityChanged(f, newFaction); using (MpScope.PushFaction(newFaction)) - InitNewGame(); + InitNewGame(scenario); - if (self) + if (executingOnlyOnIssuer) { Current.Game.CurrentMap = newMap; Multiplayer.game.ChangeRealPlayerFaction(newFaction); - CameraJumper.TryJump(MapGenerator.playerStartSpotInt, newMap); - - PostGameStart(scenario); + InitLocalVisuals(scenario, newMap); // todo setting faction of self Multiplayer.Client.Send( @@ -84,35 +82,15 @@ public static void CreateFaction(int playerId, FactionCreationData creationData) }, "GeneratingMap", doAsynchronously: true, GameAndMapInitExceptionHandlers.ErrorWhileGeneratingMap); } - private static void PostGameStart(Scenario scenario) + private static void InitLocalVisuals(Scenario scenario, Map generatedMap) { - /** - ScenPart_StartingResearch.cs - ScenPart_AutoActivateMonolith.cs - ScenPart_CreateIncident.cs - ScenPart_GameStartDialog.cs - ScenPart_PlayerFaction.cs - ScenPart_Rule.cs - - Would like to call PostGameStart on all implementations (scenario.PostGameStart) - - but dont know if it breaks with dlcs other than biotech - especially while only called - on self - **/ - - HashSet types = new HashSet - { - typeof(ScenPart_PlayerFaction), - typeof(ScenPart_GameStartDialog), - typeof(ScenPart_StartingResearch), - }; + // TODO #587: There may be other logical ScenParts (e.g., ScenPart_StartingResearch) that + // need to be executed by all players in the game. + var onlyVisualScenParts = new HashSet() { typeof(ScenPart_GameStartDialog) }; - foreach (ScenPart part in scenario.AllParts) - { - if (types.Contains(part.GetType())) - { - part.PostGameStart(); - } - } + PostGameStart(scenario, onlyVisualScenParts); + + CameraJumper.TryJump(MapGenerator.playerStartSpotInt, generatedMap); } private static Map GenerateNewMap(PlanetTile tile, Scenario scenario, bool setupNextMapFromTickZero) @@ -173,17 +151,33 @@ private static void SetAllThingWithCompsOnMapForbidden(Map map) } } - private static void InitNewGame() + private static void InitNewGame(Scenario scenario) { PawnUtility.GiveAllStartingPlayerPawnsThought(ThoughtDefOf.NewColonyOptimism); ResearchUtility.ApplyPlayerStartingResearch(); + + // TODO #587: There may be other only visual ScenParts (e.g., ScenPart_GameStartDialog) that only need to + // be executed by the local client (the issuer/creator of the new faction). + PostGameStart(scenario, new HashSet() { typeof(ScenPart_StartingResearch) }); + // Initialize anomaly. Since the Anomaly comp is currently shared by all players, // we need to ensure that any new factions have access to anomaly research if // anomaly content was started. Find.ResearchManager.Notify_MonolithLevelChanged(Find.Anomaly.Level); } + private static void PostGameStart(Scenario scenario, IEnumerable scenPartTypesToInvoke) + { + foreach (ScenPart part in scenario.AllParts) + { + if (scenPartTypesToInvoke.Contains(part.GetType())) + { + part.PostGameStart(); + } + } + } + private static void PrepareGameInitData(int sessionId, Scenario scenario, bool self, List startingPossessions) { if (!self)