diff --git a/Source/Client/AsyncTime/AsyncTimeComp.cs b/Source/Client/AsyncTime/AsyncTimeComp.cs index 866609c3..3046b032 100644 --- a/Source/Client/AsyncTime/AsyncTimeComp.cs +++ b/Source/Client/AsyncTime/AsyncTimeComp.cs @@ -1,16 +1,15 @@ -using HarmonyLib; -using Multiplayer.Common; -using RimWorld; -using RimWorld.Planet; using System; using System.Collections.Generic; -using Verse; +using HarmonyLib; using Multiplayer.Client.Comp; using Multiplayer.Client.Factions; using Multiplayer.Client.Patches; using Multiplayer.Client.Saving; using Multiplayer.Client.Util; -using System.Linq; +using Multiplayer.Common; +using RimWorld; +using RimWorld.Planet; +using Verse; namespace Multiplayer.Client { @@ -51,11 +50,10 @@ public float TickRateMultiplier(TimeSpeed speed) } } - public TimeSpeed DesiredTimeSpeed => timeSpeedInt; - - public void SetDesiredTimeSpeed(TimeSpeed speed) + public TimeSpeed DesiredTimeSpeed { - timeSpeedInt = speed; + get => timeSpeedInt; + set => timeSpeedInt = value; } public bool Paused => this.ActualRateMultiplier(DesiredTimeSpeed) == 0f; @@ -86,8 +84,6 @@ public int GameStartAbsTick public bool forcedNormalSpeed; public int eventCount; - public Storyteller storyteller; - public StoryWatcher storyWatcher; public TimeSlower slower = new(); public TickList tickListNormal = new(TickerType.Normal); @@ -131,8 +127,8 @@ public void Tick() TickMapSessions(); - storyteller.StorytellerTick(); - storyWatcher.StoryWatcherTick(); + Find.Storyteller.StorytellerTick(); + Find.StoryWatcher.StoryWatcherTick(); QuestManagerTickAsyncTime(); @@ -173,28 +169,17 @@ public void UpdateManagers() } private TimeSnapshot? prevTime; - private Storyteller prevStoryteller; - private StoryWatcher prevStoryWatcher; public void PreContext() { - if (Multiplayer.GameComp.multifaction) - { - map.PushFaction( - map.ParentFaction is { IsPlayer: true } + map.PushFaction( + !Multiplayer.GameComp.multifaction || map.ParentFaction is { IsPlayer: true } ? map.ParentFaction : Multiplayer.WorldComp.spectatorFaction, - force: true); - } + force: true); prevTime = TimeSnapshot.GetAndSetFromMap(map); - prevStoryteller = Current.Game.storyteller; - prevStoryWatcher = Current.Game.storyWatcher; - - Current.Game.storyteller = storyteller; - Current.Game.storyWatcher = storyWatcher; - Rand.PushState(); Rand.StateCompressed = randState; @@ -204,16 +189,12 @@ public void PreContext() public void PostContext() { - Current.Game.storyteller = prevStoryteller; - Current.Game.storyWatcher = prevStoryWatcher; - prevTime?.Set(); randState = Rand.StateCompressed; Rand.PopState(); - if (Multiplayer.GameComp.multifaction) - map.PopFaction(); + map.PopFaction(); } public void ExposeData() @@ -223,12 +204,6 @@ public void ExposeData() Scribe_Values.Look(ref gameStartAbsTickMap, "gameStartAbsTickMap"); - Scribe_Deep.Look(ref storyteller, "storyteller"); - - Scribe_Deep.Look(ref storyWatcher, "storyWatcher"); - if (Scribe.mode == LoadSaveMode.LoadingVars && storyWatcher == null) - storyWatcher = new StoryWatcher(); - Scribe_Custom.LookULong(ref randState, "randState", 1); } @@ -264,7 +239,7 @@ public void ExecuteCmd(ScheduledCommand cmd) TickPatch.currentExecutingCmdType = cmdType; PreContext(); - map.PushFaction(cmd.GetFaction()); + map.PushFaction(cmd.GetFaction(), force: true); context.map = map; @@ -293,7 +268,7 @@ public void ExecuteCmd(ScheduledCommand cmd) if (cmdType == CommandType.MapTimeSpeed && Multiplayer.GameComp.asyncTime) { TimeSpeed speed = (TimeSpeed)data.ReadByte(); - SetDesiredTimeSpeed(speed); + DesiredTimeSpeed = speed; MpLog.Debug("Set map time speed " + speed); } diff --git a/Source/Client/AsyncTime/AsyncTimePatches.cs b/Source/Client/AsyncTime/AsyncTimePatches.cs index 543a8f9e..10a8bb05 100644 --- a/Source/Client/AsyncTime/AsyncTimePatches.cs +++ b/Source/Client/AsyncTime/AsyncTimePatches.cs @@ -1,10 +1,10 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using HarmonyLib; using Multiplayer.Client.Factions; using RimWorld; using RimWorld.Planet; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; using Verse; namespace Multiplayer.Client.AsyncTime @@ -205,7 +205,7 @@ private static void PauseOnLetter(TickManager manager) if (Multiplayer.GameComp.asyncTime) { var tickable = (ITickable)Multiplayer.MapContext.AsyncTime() ?? Multiplayer.AsyncWorldTime; - tickable.SetDesiredTimeSpeed(TimeSpeed.Paused); + tickable.DesiredTimeSpeed = TimeSpeed.Paused; Multiplayer.GameComp.ResetAllTimeVotes(tickable.TickableId); } else diff --git a/Source/Client/AsyncTime/AsyncWorldTimeComp.cs b/Source/Client/AsyncTime/AsyncWorldTimeComp.cs index 4be6aaa2..27843264 100644 --- a/Source/Client/AsyncTime/AsyncWorldTimeComp.cs +++ b/Source/Client/AsyncTime/AsyncWorldTimeComp.cs @@ -44,15 +44,14 @@ public float TickRateMultiplier(TimeSpeed speed) } // Run at the speed of the fastest map or at chosen speed if there are no maps - public TimeSpeed DesiredTimeSpeed => !Find.Maps.Any() ? - timeSpeedInt : - Find.Maps.Select(m => m.AsyncTime()) - .Where(a => a.ActualRateMultiplier(a.DesiredTimeSpeed) != 0f) - .Max(a => a?.DesiredTimeSpeed) ?? TimeSpeed.Paused; - - public void SetDesiredTimeSpeed(TimeSpeed speed) + public TimeSpeed DesiredTimeSpeed { - timeSpeedInt = speed; + get => !Find.Maps.Any() + ? timeSpeedInt + : Find.Maps.Select(m => m.AsyncTime()) + .Where(a => a.ActualRateMultiplier(a.DesiredTimeSpeed) != 0f) + .Max(a => a?.DesiredTimeSpeed) ?? TimeSpeed.Paused; + set => timeSpeedInt = value; } public Queue Cmds => cmds; @@ -274,8 +273,8 @@ private static void CreateJoinPointAndSendIfHost() public void SetTimeEverywhere(TimeSpeed speed) { foreach (var map in Find.Maps) - map.AsyncTime().SetDesiredTimeSpeed(speed); - SetDesiredTimeSpeed(speed); + map.AsyncTime().DesiredTimeSpeed = speed; + DesiredTimeSpeed = speed; } public static float lastSpeedChange; @@ -283,7 +282,7 @@ public void SetTimeEverywhere(TimeSpeed speed) private void HandleTimeSpeed(ScheduledCommand cmd, ByteReader data) { TimeSpeed speed = (TimeSpeed)data.ReadByte(); - SetDesiredTimeSpeed(speed); + DesiredTimeSpeed = speed; if (!Multiplayer.GameComp.asyncTime) { @@ -311,7 +310,7 @@ private void HandleTimeVote(ScheduledCommand cmd, ByteReader data) if (!Multiplayer.GameComp.asyncTime || vote == TimeVote.ResetGlobal) SetTimeEverywhere(Multiplayer.GameComp.GetLowestTimeVote(TickableId)); else if (TickPatch.TickableById(tickableId) is { } tickable) - tickable.SetDesiredTimeSpeed(Multiplayer.GameComp.GetLowestTimeVote(tickableId)); + tickable.DesiredTimeSpeed = Multiplayer.GameComp.GetLowestTimeVote(tickableId); } public void FinalizeInit() diff --git a/Source/Client/AsyncTime/ITickable.cs b/Source/Client/AsyncTime/ITickable.cs index 3b9dd6f4..31a19ce9 100644 --- a/Source/Client/AsyncTime/ITickable.cs +++ b/Source/Client/AsyncTime/ITickable.cs @@ -1,5 +1,5 @@ -using Multiplayer.Common; using System.Collections.Generic; +using Multiplayer.Common; using Verse; namespace Multiplayer.Client @@ -12,9 +12,7 @@ public interface ITickable float TimeToTickThrough { get; set; } - TimeSpeed DesiredTimeSpeed { get; } - - void SetDesiredTimeSpeed(TimeSpeed speed); + TimeSpeed DesiredTimeSpeed { get; set; } float TickRateMultiplier(TimeSpeed speed); diff --git a/Source/Client/Factions/FactionExtensions.cs b/Source/Client/Factions/FactionExtensions.cs index e2d7332a..a520c8cf 100644 --- a/Source/Client/Factions/FactionExtensions.cs +++ b/Source/Client/Factions/FactionExtensions.cs @@ -1,6 +1,6 @@ +using System.Linq; using RimWorld; using RimWorld.Planet; -using System.Linq; using Verse; namespace Multiplayer.Client.Factions; @@ -25,10 +25,7 @@ public static void PushFaction(this Map map, int factionId) map.PushFaction(faction); } - public static Faction PopFaction() - { - return PopFaction(null); - } + public static Faction PopFaction() => PopFaction(null); public static Faction PopFaction(this Map map) { diff --git a/Source/Client/MultiplayerStatic.cs b/Source/Client/MultiplayerStatic.cs index 07b1211f..275bf1c3 100644 --- a/Source/Client/MultiplayerStatic.cs +++ b/Source/Client/MultiplayerStatic.cs @@ -218,7 +218,7 @@ void LoadNextReplay() Replay.LoadReplay(Replay.SavedReplayFile(current[1]), true, () => { - TickPatch.AllTickables.Do(t => t.SetDesiredTimeSpeed(TimeSpeed.Normal)); + TickPatch.AllTickables.Do(t => t.DesiredTimeSpeed = TimeSpeed.Normal); void TickBatch() { diff --git a/Source/Client/Networking/HostUtil.cs b/Source/Client/Networking/HostUtil.cs index 10f305c7..bf3ad760 100644 --- a/Source/Client/Networking/HostUtil.cs +++ b/Source/Client/Networking/HostUtil.cs @@ -1,6 +1,3 @@ -using Multiplayer.Client.Networking; -using Multiplayer.Common; -using RimWorld; using System; using System.ComponentModel; using System.Diagnostics; @@ -9,7 +6,10 @@ using System.Threading.Tasks; using Multiplayer.Client.AsyncTime; using Multiplayer.Client.Comp; +using Multiplayer.Client.Networking; using Multiplayer.Client.Util; +using Multiplayer.Common; +using RimWorld; using UnityEngine; using Verse; @@ -94,9 +94,9 @@ private static void PrepareGame() private static void SetGameState(ServerSettings settings) { - Multiplayer.AsyncWorldTime.SetDesiredTimeSpeed(TimeSpeed.Paused); + Multiplayer.AsyncWorldTime.DesiredTimeSpeed = TimeSpeed.Paused; foreach (var map in Find.Maps) - map.AsyncTime().SetDesiredTimeSpeed(TimeSpeed.Paused); + map.AsyncTime().DesiredTimeSpeed = TimeSpeed.Paused; Find.TickManager.CurTimeSpeed = TimeSpeed.Paused; diff --git a/Source/Client/Patches/MapSetup.cs b/Source/Client/Patches/MapSetup.cs index a3a1d066..f83e0f24 100644 --- a/Source/Client/Patches/MapSetup.cs +++ b/Source/Client/Patches/MapSetup.cs @@ -9,24 +9,19 @@ namespace Multiplayer.Client; [HarmonyPatch(typeof(MapGenerator), nameof(MapGenerator.GenerateMap))] public static class MapSetup { - public static bool SetupNextMapFromTickZero = false; + public static bool SetupNextMapFromTickZero; static void Prefix(ref Action extraInitBeforeContentGen) { if (Multiplayer.Client == null) return; - extraInitBeforeContentGen += SetupMap; - } - - public static void SetupMap(Map map) - { - SetupMap(map, false); + extraInitBeforeContentGen += map => SetupMap(map); } public static void SetupMap(Map map, bool usingMapTimeFromSingleplayer = false) { Log.Message("MP: Setting up map " + map.uniqueID); - // Initialize and store Multiplayer + // Initialize and store Multiplayer var mapComp = new MultiplayerMapComp(map); Multiplayer.game.mapComps.Add(mapComp); @@ -40,7 +35,7 @@ public static void SetupMap(Map map, bool usingMapTimeFromSingleplayer = false) // Add all other (non Faction.OfPlayer) factions to the map foreach (var faction in Find.FactionManager.AllFactions.Where(f => f.IsPlayer)) if (faction != Faction.OfPlayer) - InitNewFactionData(map, faction); + InitNewFactionData(map, faction); } private static AsyncTimeComp CreateAsyncTimeCompForMap(Map map, bool usingMapTimeFromSingleplayer) @@ -48,7 +43,6 @@ private static AsyncTimeComp CreateAsyncTimeCompForMap(Map map, bool usingMapTim int startingMapTicks; int gameStartAbsTick; TimeSpeed startingTimeSpeed; - AsyncTimeComp asyncTimeCompForMap; bool startingMapTimeFromBeginning = Multiplayer.GameComp.multifaction && @@ -77,12 +71,11 @@ private static AsyncTimeComp CreateAsyncTimeCompForMap(Map map, bool usingMapTim if (!Multiplayer.GameComp.asyncTime) startingTimeSpeed = Find.TickManager.CurTimeSpeed; - asyncTimeCompForMap = new AsyncTimeComp(map, gameStartAbsTick); - asyncTimeCompForMap.mapTicks = startingMapTicks; - asyncTimeCompForMap.SetDesiredTimeSpeed(startingTimeSpeed); - - asyncTimeCompForMap.storyteller = new Storyteller(Find.Storyteller.def, Find.Storyteller.difficultyDef, Find.Storyteller.difficulty); - asyncTimeCompForMap.storyWatcher = new StoryWatcher(); + var asyncTimeCompForMap = new AsyncTimeComp(map, gameStartAbsTick) + { + mapTicks = startingMapTicks, + DesiredTimeSpeed = startingTimeSpeed + }; SetupNextMapFromTickZero = false; diff --git a/Source/Client/Patches/TickPatch.cs b/Source/Client/Patches/TickPatch.cs index 9ce615c8..bf6a1608 100644 --- a/Source/Client/Patches/TickPatch.cs +++ b/Source/Client/Patches/TickPatch.cs @@ -175,7 +175,11 @@ private static bool RunCmds() ScheduledCommand cmd = tickable.Cmds.Dequeue(); // Minimal code impact fix for #733. Having all the commands be added to a single queue gets rid of // the out-of-order execution problem. With a proper fix, this can be reverted to tickable.ExecuteCmd - TickableById(cmd.mapId).ExecuteCmd(cmd); + var target = TickableById(cmd.mapId); + if (target == null) + { + Log.Error($"!!! Tickable of {cmd.mapId} not found! {cmd}"); + } else target.ExecuteCmd(cmd); if (LongEventHandler.eventQueue.Count > 0) return true; // Yield to e.g. join-point creation } @@ -290,10 +294,7 @@ public static float ActualRateMultiplier(this ITickable tickable, TimeSpeed spee return rate; } - public static void ClearSimulating() - { - simulating = null; - } + public static void ClearSimulating() => simulating = null; public static void Reset() { @@ -309,15 +310,9 @@ public static void Reset() TimeControlPatch.prePauseTimeSpeed = null; } - public static void SetTimer(int value) - { - Timer = value; - } + public static void SetTimer(int value) => Timer = value; - public static ITickable TickableById(int tickableId) - { - return AllTickables.FirstOrDefault(t => t.TickableId == tickableId); - } + public static ITickable TickableById(int tickableId) => AllTickables.FirstOrDefault(t => t.TickableId == tickableId); } public class SimulatingData diff --git a/Source/Client/Syncing/Game/SyncFields.cs b/Source/Client/Syncing/Game/SyncFields.cs index 30b258db..8a3f58ba 100644 --- a/Source/Client/Syncing/Game/SyncFields.cs +++ b/Source/Client/Syncing/Game/SyncFields.cs @@ -1,12 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; using HarmonyLib; using Multiplayer.API; using Multiplayer.Client.Persistent; using RimWorld; using RimWorld.Planet; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; using UnityEngine; using Verse; using static Verse.Widgets; @@ -252,24 +252,14 @@ static void ChangeStoryteller() static void StorytellerDef_Post(object target, object value) { Find.Storyteller.Notify_DefChanged(); - - foreach (var comp in Multiplayer.game.asyncTimeComps) - { - comp.storyteller.def = Find.Storyteller.def; - comp.storyteller.Notify_DefChanged(); - } } static void StorytellerDifficultyDef_Post(object target, object value) { - foreach (var comp in Multiplayer.game.asyncTimeComps) - comp.storyteller.difficultyDef = Find.Storyteller.difficultyDef; } static void StorytellerDifficulty_Post(object target, object value) { - foreach (var comp in Multiplayer.game.asyncTimeComps) - comp.storyteller.difficulty = Find.Storyteller.difficulty; } [MpPrefix(typeof(HealthCardUtility), nameof(HealthCardUtility.DrawOverviewTab))]