/// <summary> /// Called before each game simulation tick. A tick contains multiple frames. /// Performs the dispatching for this simulation phase. /// </summary> public override void OnBeforeSimulationTick() { if (SimulationManager.instance.SimulationPaused || SimulationManager.instance.ForcedSimulationPaused) { wasPaused = true; return; } WeatherInfo?.Update(); bool updateFrameLength = TimeAdjustment?.Update(wasPaused) ?? false; wasPaused = false; if (CitizenProcessor != null) { if (updateFrameLength) { CitizenProcessor.UpdateFrameDuration(); } CitizenProcessor.ProcessTick(); } if (updateFrameLength) { Buildings?.UpdateFrameDuration(); Statistics?.RefreshUnits(); VanillaEvents.ProcessUpdatedTimeSpeed(TimeAdjustment.GetOriginalTime); } EventManager?.ProcessEvents(); if (DayTimeSimulation == null || CitizenProcessor == null) { return; } DateTime currentDateTime = SimulationManager.instance.m_currentGameTime; if (currentDateTime.Hour != lastHandledDate.Hour || lastHandledDate == default) { int triggerHour = lastHandledDate == default ? 0 : currentDateTime.Hour; lastHandledDate = currentDateTime; CitizenProcessor.TriggerHour(triggerHour); if (triggerHour == 0) { DayTimeSimulation.Process(currentDateTime); OnNewDay(this); } } }
private RealTimeCore( TimeAdjustment timeAdjustment, CustomTimeBar timeBar, RealTimeEventManager eventManager, MethodPatcher patcher, VanillaEvents vanillaEvents) { this.timeAdjustment = timeAdjustment; this.timeBar = timeBar; this.eventManager = eventManager; this.patcher = patcher; this.vanillaEvents = vanillaEvents; isEnabled = true; }
public static RealTimeCore Run( ConfigurationProvider <RealTimeConfig> configProvider, string rootPath, ILocalizationProvider localizationProvider, bool setDefaultTime, Compatibility compatibility) { if (configProvider == null) { throw new ArgumentNullException(nameof(configProvider)); } if (string.IsNullOrEmpty(rootPath)) { throw new ArgumentException("The root path cannot be null or empty string", nameof(rootPath)); } if (localizationProvider == null) { throw new ArgumentNullException(nameof(localizationProvider)); } if (compatibility == null) { throw new ArgumentNullException(nameof(compatibility)); } var patches = GetMethodPatches(compatibility); var patcher = new MethodPatcher(HarmonyId, patches); var appliedPatches = patcher.Apply(); if (!CheckRequiredMethodPatches(appliedPatches)) { Log.Error("The 'Real Time' mod failed to perform method redirections for required methods"); patcher.Revert(); return(null); } if (StorageBase.CurrentLevelStorage != null) { LoadStorageData(new[] { configProvider }, StorageBase.CurrentLevelStorage); } localizationProvider.SetEnglishUSFormatsState(configProvider.Configuration.UseEnglishUSFormats); var timeInfo = new TimeInfo(configProvider.Configuration); var buildingManager = new BuildingManagerConnection(); var randomizer = new GameRandomizer(); var weatherInfo = new WeatherInfo(new WeatherManagerConnection(), randomizer); var gameConnections = new GameConnections <Citizen>( timeInfo, new CitizenConnection(), new CitizenManagerConnection(), buildingManager, randomizer, new TransferManagerConnection(), weatherInfo); var eventManager = new RealTimeEventManager( configProvider.Configuration, CityEventsLoader.Instance, new EventManagerConnection(), buildingManager, randomizer, timeInfo, Constants.MaxTravelTime); if (!SetupCustomAI(timeInfo, configProvider.Configuration, gameConnections, eventManager, compatibility)) { Log.Error("The 'Real Time' mod failed to setup the customized AI and will now be deactivated."); patcher.Revert(); return(null); } var timeAdjustment = new TimeAdjustment(configProvider.Configuration); var gameDate = timeAdjustment.Enable(setDefaultTime); SimulationHandler.CitizenProcessor.UpdateFrameDuration(); CityEventsLoader.Instance.ReloadEvents(rootPath); var customTimeBar = new CustomTimeBar(); customTimeBar.Enable(gameDate); customTimeBar.CityEventClick += CustomTimeBarCityEventClick; var vanillaEvents = VanillaEvents.Customize(); var result = new RealTimeCore(timeAdjustment, customTimeBar, eventManager, patcher, vanillaEvents); eventManager.EventsChanged += result.CityEventsChanged; var statistics = new Statistics(timeInfo, localizationProvider); if (statistics.Initialize()) { statistics.RefreshUnits(); } else { statistics = null; } SimulationHandler.NewDay += result.CityEventsChanged; SimulationHandler.TimeAdjustment = timeAdjustment; SimulationHandler.DayTimeSimulation = new DayTimeSimulation(configProvider.Configuration); SimulationHandler.EventManager = eventManager; SimulationHandler.WeatherInfo = weatherInfo; SimulationHandler.Buildings = BuildingAIPatch.RealTimeAI; SimulationHandler.Buildings.UpdateFrameDuration(); if (appliedPatches.Contains(CitizenManagerPatch.CreateCitizenPatch1)) { CitizenManagerPatch.NewCitizenBehavior = new NewCitizenBehavior(randomizer, configProvider.Configuration); } if (appliedPatches.Contains(BuildingAIPatch.GetColor)) { SimulationHandler.Buildings.InitializeLightState(); } SimulationHandler.Statistics = statistics; if (appliedPatches.Contains(WorldInfoPanelPatch.UpdateBindings)) { WorldInfoPanelPatch.CitizenInfoPanel = CustomCitizenInfoPanel.Enable(ResidentAIPatch.RealTimeAI, localizationProvider); WorldInfoPanelPatch.VehicleInfoPanel = CustomVehicleInfoPanel.Enable(ResidentAIPatch.RealTimeAI, localizationProvider); WorldInfoPanelPatch.CampusWorldInfoPanel = CustomCampusWorldInfoPanel.Enable(localizationProvider); } AwakeSleepSimulation.Install(configProvider.Configuration); var schedulesStorage = ResidentAIPatch.RealTimeAI.GetStorageService( schedules => new CitizenScheduleStorage(schedules, gameConnections.CitizenManager.GetCitizensArray, timeInfo)); result.storageData.Add(schedulesStorage); result.storageData.Add(eventManager); if (StorageBase.CurrentLevelStorage != null) { StorageBase.CurrentLevelStorage.GameSaving += result.GameSaving; LoadStorageData(result.storageData, StorageBase.CurrentLevelStorage); } result.storageData.Add(configProvider); result.Translate(localizationProvider); result.IsRestrictedMode = appliedPatches.Count != patches.Count; return(result); }