public void OnDisabled() { Log.Info("The 'Real Time' mod has been disabled."); ConfigurationProvider.SaveConfiguration(config); config = null; configUI = null; }
private static bool SetupCustomAI( TimeInfo timeInfo, RealTimeConfig config, GameConnections <Citizen> gameConnections, RealTimeEventManager eventManager) { ResidentAIConnection <ResidentAI, Citizen> residentAIConnection = ResidentAIPatch.GetResidentAIConnection(); if (residentAIConnection == null) { return(false); } var spareTimeBehavior = new SpareTimeBehavior(config, timeInfo); var travelBehavior = new TravelBehavior(gameConnections.BuildingManager); var workBehavior = new WorkBehavior(config, gameConnections.Random, gameConnections.BuildingManager, timeInfo, travelBehavior); var realTimePrivateBuildingAI = new RealTimeBuildingAI( config, timeInfo, gameConnections.BuildingManager, new ToolManagerConnection(), workBehavior, travelBehavior); BuildingAIPatches.RealTimeAI = realTimePrivateBuildingAI; BuildingAIPatches.WeatherInfo = gameConnections.WeatherInfo; TransferManagerPatch.RealTimeAI = realTimePrivateBuildingAI; var realTimeResidentAI = new RealTimeResidentAI <ResidentAI, Citizen>( config, gameConnections, residentAIConnection, eventManager, realTimePrivateBuildingAI, workBehavior, spareTimeBehavior, travelBehavior); ResidentAIPatch.RealTimeAI = realTimeResidentAI; SimulationHandler.CitizenProcessor = new CitizenProcessor <ResidentAI, Citizen>( realTimeResidentAI, timeInfo, spareTimeBehavior, travelBehavior); TouristAIConnection <TouristAI, Citizen> touristAIConnection = TouristAIPatch.GetTouristAIConnection(); if (touristAIConnection == null) { return(false); } var realTimeTouristAI = new RealTimeTouristAI <TouristAI, Citizen>( config, gameConnections, touristAIConnection, eventManager, spareTimeBehavior); TouristAIPatch.RealTimeAI = realTimeTouristAI; return(true); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimeBuildingAI"/> class. /// </summary> /// /// <param name="config">The configuration to run with.</param> /// <param name="timeInfo">The time information source.</param> /// <param name="buildingManager">A proxy object that provides a way to call the game-specific methods of the <see cref="BuildingManager"/> class.</param> /// <param name="toolManager">A proxy object that provides a way to call the game-specific methods of the <see cref="ToolManager"/> class.</param> /// <param name="workBehavior">A behavior that provides simulation info for the citizens' work time.</param> /// <param name="travelBehavior">A behavior that provides simulation info for the citizens' traveling.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public RealTimeBuildingAI( RealTimeConfig config, ITimeInfo timeInfo, IBuildingManagerConnection buildingManager, IToolManagerConnection toolManager, IWorkBehavior workBehavior, ITravelBehavior travelBehavior) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); this.buildingManager = buildingManager ?? throw new ArgumentNullException(nameof(buildingManager)); this.toolManager = toolManager ?? throw new ArgumentNullException(nameof(toolManager)); this.workBehavior = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior)); this.travelBehavior = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior)); lightStates = new bool[buildingManager.GetMaxBuildingsCount()]; reachingTroubles = new byte[lightStates.Length]; // This is to preallocate the hash sets to a large capacity, .NET 3.5 doesn't provide a proper way. var preallocated = Enumerable.Range(0, MaximumBuildingsInConstruction * 2).Select(v => (ushort)v).ToList(); buildingsInConstruction = new[] { new HashSet <ushort>(preallocated), new HashSet <ushort>(preallocated), new HashSet <ushort>(preallocated), new HashSet <ushort>(preallocated), }; for (int i = 0; i < buildingsInConstruction.Length; ++i) { // Calling Clear() doesn't trim the capacity, we're using this trick for preallocating the hash sets buildingsInConstruction[i].Clear(); } }
private static void SetupCustomAI( TimeInfo timeInfo, RealTimeConfig config, GameConnections <Citizen> gameConnections, RealTimeEventManager eventManager) { var realTimeResidentAI = new RealTimeResidentAI <ResidentAI, Citizen>( config, gameConnections, ResidentAIHook.GetResidentAIConnection(), eventManager); ResidentAIHook.RealTimeAI = realTimeResidentAI; var realTimeTouristAI = new RealTimeTouristAI <TouristAI, Citizen>( config, gameConnections, TouristAIHook.GetTouristAIConnection(), eventManager); TouristAIHook.RealTimeAI = realTimeTouristAI; var realTimePrivateBuildingAI = new RealTimePrivateBuildingAI( config, timeInfo, new ToolManagerConnection()); PrivateBuildingAIHook.RealTimeAI = realTimePrivateBuildingAI; }
/// <summary> /// Creates the mod's configuration page using the specified object as data source. /// </summary> /// <param name="config">The configuration object to use as data source.</param> /// <param name="itemFactory">The view item factory to use for creating the UI elements.</param> /// <returns>A configured instance of the <see cref="ConfigUI"/> class.</returns> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public static ConfigUI Create(RealTimeConfig config, IViewItemFactory itemFactory) { if (config == null) { throw new ArgumentNullException(nameof(config)); } if (itemFactory == null) { throw new ArgumentNullException(nameof(itemFactory)); } var properties = config.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) .Select(p => new { Property = p, Attribute = GetCustomItemAttribute <ConfigItemAttribute>(p) }) .Where(v => v.Attribute != null); var viewItems = new List <IViewItem>(); foreach (var tab in properties.GroupBy(p => p.Attribute.TabId).OrderBy(p => p.Key)) { IContainerViewItem tabItem = itemFactory.CreateTabItem(tab.Key); viewItems.Add(tabItem); foreach (var group in tab.GroupBy(p => p.Attribute.GroupId).OrderBy(p => p.Key)) { IContainerViewItem containerItem; if (string.IsNullOrEmpty(group.Key)) { containerItem = tabItem; } else { containerItem = itemFactory.CreateGroup(tabItem, group.Key); viewItems.Add(containerItem); } foreach (var item in group.OrderBy(i => i.Attribute.Order)) { IViewItem viewItem = CreateViewItem(containerItem, item.Property, config, itemFactory); if (viewItem != null) { viewItems.Add(viewItem); } } } } var result = new ConfigUI(config, viewItems); IContainerViewItem toolsTab = itemFactory.CreateTabItem(ToolsId); viewItems.Add(toolsTab); IViewItem resetButton = itemFactory.CreateButton(toolsTab, ResetToDefaultsId, result.ResetToDefaults); viewItems.Add(resetButton); return(result); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimeTouristAI{TAI, TCitizen}"/> class. /// </summary> /// /// <param name="config">The configuration to run with.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="touristAI">A connection to game's tourist AI.</param> /// <param name="eventManager">The custom event manager.</param> /// /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public RealTimeTouristAI( RealTimeConfig config, GameConnections <TCitizen> connections, TouristAIConnection <TAI, TCitizen> touristAI, RealTimeEventManager eventManager) : base(config, connections, eventManager) { this.touristAI = touristAI ?? throw new ArgumentNullException(nameof(touristAI)); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class. /// </summary> /// /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, RealTimeEventManager eventManager) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimePrivateBuildingAI"/> class. /// </summary> /// /// <param name="config">The configuration to run with.</param> /// <param name="timeInfo">The time information source.</param> /// <param name="buildingManager">A proxy object that provides a way to call the game-specific methods of the <see cref="global::BuildingManager"/> class.</param> /// <param name="toolManager">A proxy object that provides a way to call the game-specific methods of the <see cref="global::ToolManager"/> class.</param> /// /// <exception cref="System.ArgumentNullException">Thrown when any argument is null.</exception> public RealTimePrivateBuildingAI( RealTimeConfig config, ITimeInfo timeInfo, IBuildingManagerConnection buildingManager, IToolManagerConnection toolManager) { this.config = config ?? throw new System.ArgumentNullException(nameof(config)); this.timeInfo = timeInfo ?? throw new System.ArgumentNullException(nameof(timeInfo)); this.buildingManager = buildingManager ?? throw new System.ArgumentNullException(nameof(buildingManager)); this.toolManager = toolManager ?? throw new System.ArgumentNullException(nameof(toolManager)); }
/// <summary>Initializes a new instance of the <see cref="SpareTimeBehavior"/> class.</summary> /// <param name="config">The configuration to run with.</param> /// <param name="timeInfo">The object providing the game time information.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public SpareTimeBehavior(RealTimeConfig config, ITimeInfo timeInfo) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); int agesCount = Enum.GetValues(typeof(Citizen.AgeGroup)).Length; defaultChances = new uint[agesCount]; secondShiftChances = new uint[agesCount]; nightShiftChances = new uint[agesCount]; shoppingChances = new uint[agesCount]; }
/// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param> /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, RealTimeEventManager eventManager, SpareTimeBehavior spareTimeBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior)); residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()]; workBehavior = new WorkBehavior(config, connections.Random, connections.BuildingManager, connections.TimeInfo, GetEstimatedTravelTime); }
/// <summary>Initializes a new instance of the <see cref="WorkBehavior"/> class.</summary> /// <param name="config">The configuration to run with.</param> /// <param name="randomizer">The randomizer implementation.</param> /// <param name="buildingManager">The building manager implementation.</param> /// <param name="timeInfo">The time information source.</param> /// <param name="travelTimeCalculator">A method accepting two building IDs and returning the estimated travel time /// between those buildings (in hours).</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public WorkBehavior( RealTimeConfig config, IRandomizer randomizer, IBuildingManagerConnection buildingManager, ITimeInfo timeInfo, Func <ushort, ushort, float> travelTimeCalculator) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.randomizer = randomizer ?? throw new ArgumentNullException(nameof(randomizer)); this.buildingManager = buildingManager ?? throw new ArgumentNullException(nameof(buildingManager)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); this.travelTimeCalculator = travelTimeCalculator ?? throw new ArgumentNullException(nameof(travelTimeCalculator)); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimeBuildingAI"/> class. /// </summary> /// /// <param name="config">The configuration to run with.</param> /// <param name="timeInfo">The time information source.</param> /// <param name="buildingManager">A proxy object that provides a way to call the game-specific methods of the <see cref="BuildingManager"/> class.</param> /// <param name="toolManager">A proxy object that provides a way to call the game-specific methods of the <see cref="ToolManager"/> class.</param> /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public RealTimeBuildingAI( RealTimeConfig config, ITimeInfo timeInfo, IBuildingManagerConnection buildingManager, IToolManagerConnection toolManager, WorkBehavior workBehavior) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); this.buildingManager = buildingManager ?? throw new ArgumentNullException(nameof(buildingManager)); this.toolManager = toolManager ?? throw new ArgumentNullException(nameof(toolManager)); this.workBehavior = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior)); lightStates = new bool[buildingManager.GetMaxBuildingsCount()]; }
/// <summary>Initializes a new instance of the <see cref="RealTimeEventManager"/> class.</summary> /// <param name="config">The configuration to run with.</param> /// <param name="eventProvider">The city event provider implementation.</param> /// <param name="eventManager"> /// A proxy object that provides a way to call the game-specific methods of the <see cref="global::EventManager"/> class. /// </param> /// <param name="buildingManager"> /// A proxy object that provides a way to call the game-specific methods of the <see cref="global::BuildingManager"/> class. /// </param> /// <param name="randomizer"> /// An object that implements of the <see cref="IRandomizer"/> interface. /// </param> /// <param name="timeInfo">The time information source.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public RealTimeEventManager( RealTimeConfig config, ICityEventsProvider eventProvider, IEventManagerConnection eventManager, IBuildingManagerConnection buildingManager, IRandomizer randomizer, ITimeInfo timeInfo) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.eventProvider = eventProvider ?? throw new ArgumentNullException(nameof(eventProvider)); this.eventManager = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); this.buildingManager = buildingManager ?? throw new ArgumentNullException(nameof(buildingManager)); this.randomizer = randomizer ?? throw new ArgumentNullException(nameof(randomizer)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); upcomingEvents = new LinkedList <ICityEvent>(); }
/// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">A <see cref="RealTimeEventManager"/> instance.</param> /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param> /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param> /// <param name="travelBehavior">A behavior that provides simulation info for the citizens traveling.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, RealTimeEventManager eventManager, WorkBehavior workBehavior, SpareTimeBehavior spareTimeBehavior, TravelBehavior travelBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); this.workBehavior = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior)); this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior)); this.travelBehavior = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior)); residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()]; }
protected RealTimeHumanAIBase(RealTimeConfig config, GameConnections <TCitizen> connections, RealTimeEventManager eventManager) { Config = config ?? throw new ArgumentNullException(nameof(config)); EventMgr = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); if (connections == null) { throw new ArgumentNullException(nameof(connections)); } CitizenMgr = connections.CitizenManager; BuildingMgr = connections.BuildingManager; TransferMgr = connections.TransferManager; CitizenProxy = connections.CitizenConnection; TimeInfo = connections.TimeInfo; randomizer = connections.SimulationManager.GetRandomizer(); }
private static bool SetupCustomAI( TimeInfo timeInfo, RealTimeConfig config, GameConnections <Citizen> gameConnections, RealTimeEventManager eventManager) { ResidentAIConnection <ResidentAI, Citizen> residentAIConnection = ResidentAIPatch.GetResidentAIConnection(); if (residentAIConnection == null) { return(false); } var realTimeResidentAI = new RealTimeResidentAI <ResidentAI, Citizen>( config, gameConnections, residentAIConnection, eventManager); ResidentAIPatch.RealTimeAI = realTimeResidentAI; TouristAIConnection <TouristAI, Citizen> touristAIConnection = TouristAIPatch.GetTouristAIConnection(); if (touristAIConnection == null) { return(false); } var realTimeTouristAI = new RealTimeTouristAI <TouristAI, Citizen>( config, gameConnections, touristAIConnection, eventManager); TouristAIPatch.RealTimeAI = realTimeTouristAI; var realTimePrivateBuildingAI = new RealTimePrivateBuildingAI( config, timeInfo, gameConnections.BuildingManager, new ToolManagerConnection()); BuildingAIPatches.RealTimeAI = realTimePrivateBuildingAI; return(true); }
public void OnSettingsUI(UIHelperBase helper) { if (helper == null) { return; } if (config == null) { Log.Warning("The 'Real Time' mod wants to display the configuration page, but the configuration is unexpectedly missing."); config = ConfigurationProvider.LoadConfiguration(); } IViewItemFactory itemFactory = new CitiesViewItemFactory(helper); configUI = ConfigUI.Create(config, itemFactory); ApplyLanguage(); }
/// <summary> /// Initializes a new instance of the <see cref="RealTimeHumanAIBase{TCitizen}"/> class. /// </summary> /// /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// /// <param name="config">A configuration to use with this custom logic.</param> /// <param name="connections">An object providing the proxies that connect the method calls to the game methods.</param> /// <param name="eventManager">A reference to an <see cref="IRealTimeEventManager"/> instance.</param> protected RealTimeHumanAIBase(RealTimeConfig config, GameConnections <TCitizen> connections, IRealTimeEventManager eventManager) { Config = config ?? throw new ArgumentNullException(nameof(config)); EventMgr = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); if (connections == null) { throw new ArgumentNullException(nameof(connections)); } CitizenMgr = connections.CitizenManager; BuildingMgr = connections.BuildingManager; TransferMgr = connections.TransferManager; CitizenProxy = connections.CitizenConnection; TimeInfo = connections.TimeInfo; Random = connections.Random; WeatherInfo = connections.WeatherInfo; CitizenInstancesMaxCount = CitizenMgr.GetMaxInstancesCount(); }
/// <summary>Installs the simulation into the game using the specified configuration.</summary> /// <param name="config">The configuration to run with.</param> /// <returns><c>true</c> when it succeeds; otherwise, <c>false</c>.</returns> /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception> public static bool Install(RealTimeConfig config) { if (config == null) { throw new ArgumentNullException(nameof(config)); } FastList <ISimulationManager> managers = GetSimulationManagers(); if (managers == null) { Log.Error("The 'Real Time' mod failed to get the simulation managers"); return(false); } if (managers.m_size == 0) { Log.Error("The 'Real Time' mod failed to register the awake/sleep simulation - no simulation managers found"); return(false); } if (managers.m_buffer[0] is AwakeSleepSimulation) { return(true); } if (managers.m_buffer[managers.m_buffer.Length - 1] != null) { managers.EnsureCapacity(managers.m_buffer.Length + 4); } ++managers.m_size; for (int i = managers.m_size - 1; i > 0; --i) { managers.m_buffer[i] = managers.m_buffer[i - 1]; } managers.m_buffer[0] = new AwakeSleepSimulation(config); return(true); }
/// <summary>Initializes a new instance of the <see cref="RealTimeResidentAI{TAI, TCitizen}"/> class.</summary> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> /// <param name="config">A <see cref="RealTimeConfig"/> instance containing the mod's configuration.</param> /// <param name="connections">A <see cref="GameConnections{T}"/> instance that provides the game connection implementation.</param> /// <param name="residentAI">A connection to the game's resident AI.</param> /// <param name="eventManager">An <see cref="IRealTimeEventManager"/> instance.</param> /// <param name="buildingAI">The custom building AI.</param> /// <param name="workBehavior">A behavior that provides simulation info for the citizens work time.</param> /// <param name="spareTimeBehavior">A behavior that provides simulation info for the citizens spare time.</param> /// <param name="travelBehavior">A behavior that provides simulation info for the citizens traveling.</param> public RealTimeResidentAI( RealTimeConfig config, GameConnections <TCitizen> connections, ResidentAIConnection <TAI, TCitizen> residentAI, IRealTimeEventManager eventManager, IRealTimeBuildingAI buildingAI, IWorkBehavior workBehavior, ISpareTimeBehavior spareTimeBehavior, ITravelBehavior travelBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); this.buildingAI = buildingAI ?? throw new ArgumentNullException(nameof(buildingAI)); this.workBehavior = workBehavior ?? throw new ArgumentNullException(nameof(workBehavior)); this.spareTimeBehavior = spareTimeBehavior ?? throw new ArgumentNullException(nameof(spareTimeBehavior)); this.travelBehavior = travelBehavior ?? throw new ArgumentNullException(nameof(travelBehavior)); residentSchedules = new CitizenSchedule[CitizenMgr.GetMaxCitizensCount()]; abandonCarRideDurationThreshold = Constants.MaxTravelTime * 0.8f; abandonCarRideToWorkDurationThreshold = Constants.MaxTravelTime; }
/// <summary>Initializes a new instance of the <see cref="RealTimeEventManager"/> class.</summary> /// <param name="config">The configuration to run with.</param> /// <param name="eventProvider">The city event provider implementation.</param> /// <param name="eventManager"> /// A proxy object that provides a way to call the game-specific methods of the <see cref="EventManager"/> class. /// </param> /// <param name="buildingManager"> /// A proxy object that provides a way to call the game-specific methods of the <see cref="BuildingManager"/> class. /// </param> /// <param name="randomizer"> /// An object that implements of the <see cref="IRandomizer"/> interface. /// </param> /// <param name="timeInfo">The time information source.</param> /// <param name="attendingTimeMargin">The time margin in hours specifying the maximum time before an event /// can be attended by the citizen.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public RealTimeEventManager( RealTimeConfig config, ICityEventsProvider eventProvider, IEventManagerConnection eventManager, IBuildingManagerConnection buildingManager, IRandomizer randomizer, ITimeInfo timeInfo, float attendingTimeMargin) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.eventProvider = eventProvider ?? throw new ArgumentNullException(nameof(eventProvider)); this.eventManager = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); this.buildingManager = buildingManager ?? throw new ArgumentNullException(nameof(buildingManager)); this.randomizer = randomizer ?? throw new ArgumentNullException(nameof(randomizer)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); this.attendingTimeMargin = attendingTimeMargin; upcomingEvents = new LinkedList <ICityEvent>(); eventsCache = new List <ICityEvent>(); readonlyEventsCache = new ReadOnlyList <ICityEvent>(eventsCache); eventsToAttend = new List <ICityEvent>(); EventsToAttend = new ReadOnlyList <ICityEvent>(eventsToAttend); }
public static RealTimeCore Run(RealTimeConfig config, string rootPath, ILocalizationProvider localizationProvider) { if (config == null) { throw new ArgumentNullException(nameof(config)); } 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)); } var patcher = new MethodPatcher( BuildingAIPatches.PrivateConstructionTime, BuildingAIPatches.PrivateHandleWorkers, BuildingAIPatches.CommercialSimulation, ResidentAIPatch.Location, ResidentAIPatch.ArriveAtDestination, TouristAIPatch.Location, UIGraphPatches.MinDataPoints, UIGraphPatches.VisibleEndTime, UIGraphPatches.BuildLabels); try { patcher.Apply(); Log.Info("The 'Real Time' successfully performed the methods redirections"); } catch (Exception ex) { Log.Error("The 'Real Time' mod failed to perform method redirections: " + ex); patcher.Revert(); return(null); } var timeInfo = new TimeInfo(config); var buildingManager = new BuildingManagerConnection(); var randomizer = new GameRandomizer(); var weatherInfo = new WeatherInfo(new WeatherManagerConnection()); var gameConnections = new GameConnections <Citizen>( timeInfo, new CitizenConnection(), new CitizenManagerConnection(), buildingManager, randomizer, new TransferManagerConnection(), weatherInfo); var eventManager = new RealTimeEventManager( config, CityEventsLoader.Instance, new EventManagerConnection(), buildingManager, randomizer, timeInfo); if (!SetupCustomAI(timeInfo, config, gameConnections, eventManager)) { 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(config); DateTime gameDate = timeAdjustment.Enable(); SimulationHandler.CitizenProcessor.SetFrameDuration(timeAdjustment.HoursPerFrame); CityEventsLoader.Instance.ReloadEvents(rootPath); var customTimeBar = new CustomTimeBar(); customTimeBar.Enable(gameDate); customTimeBar.CityEventClick += CustomTimeBarCityEventClick; var result = new RealTimeCore(timeAdjustment, customTimeBar, eventManager, patcher); eventManager.EventsChanged += result.CityEventsChanged; SimulationHandler.NewDay += result.CityEventsChanged; SimulationHandler.TimeAdjustment = timeAdjustment; SimulationHandler.DayTimeSimulation = new DayTimeSimulation(config); SimulationHandler.EventManager = eventManager; SimulationHandler.WeatherInfo = weatherInfo; SimulationHandler.Buildings = BuildingAIPatches.RealTimeAI; AwakeSleepSimulation.Install(config); RealTimeStorage.CurrentLevelStorage.GameSaving += result.GameSaving; result.storageData.Add(eventManager); result.storageData.Add(ResidentAIPatch.RealTimeAI.GetStorageService()); result.LoadStorageData(); result.Translate(localizationProvider); return(result); }
/// <summary> /// Called when this mod is enabled. /// </summary> public void OnEnabled() { Log.Info("The 'Real Time' mod has been enabled, version: " + modVersion); config = ConfigurationProvider.LoadConfiguration(); localizationProvider = new LocalizationProvider(modPath); }
public static RealTimeCore Run(RealTimeConfig config, string rootPath, LocalizationProvider localizationProvider) { if (config == null) { throw new ArgumentNullException(nameof(config)); } 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)); } try { int redirectedCount = Redirector.PerformRedirections(); Log.Info($"Successfully redirected {redirectedCount} methods."); } catch (Exception ex) { Log.Error("Failed to perform method redirections: " + ex.Message); return(null); } var timeAdjustment = new TimeAdjustment(); DateTime gameDate = timeAdjustment.Enable(); var timeInfo = new TimeInfo(); var buildingManager = new BuildingManagerConnection(); var simulationManager = new SimulationManagerConnection(); var gameConnections = new GameConnections <Citizen>( timeInfo, new CitizenConnection(), new CitizenManagerConnection(), buildingManager, simulationManager, new TransferManagerConnection()); var eventManager = new RealTimeEventManager( config, CityEventsLoader.Istance, new EventManagerConnection(), buildingManager, simulationManager, timeInfo); SetupCustomAI(timeInfo, config, gameConnections, eventManager); CityEventsLoader.Istance.ReloadEvents(rootPath); var customTimeBar = new CustomTimeBar(); customTimeBar.Enable(gameDate); customTimeBar.CityEventClick += CustomTimeBarCityEventClick; var result = new RealTimeCore(timeAdjustment, customTimeBar, eventManager); eventManager.EventsChanged += result.CityEventsChanged; SimulationHandler.NewDay += result.CityEventsChanged; SimulationHandler.DayTimeSimulation = new DayTimeSimulation(); SimulationHandler.EventManager = eventManager; SimulationHandler.CommercialAI = new CommercialAI(timeInfo, buildingManager); RealTimeStorage.Instance.GameSaving += result.GameSaving; result.storageData.Add(eventManager); result.LoadStorageData(); result.Translate(localizationProvider); return(result); }
/// <summary>Initializes a new instance of the <see cref="TimeAdjustment"/> class.</summary> /// <param name="config">The configuration to run with.</param> /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception> public TimeAdjustment(RealTimeConfig config) { this.config = config ?? throw new ArgumentNullException(nameof(config)); vanillaFramesPerDay = SimulationManager.DAYTIME_FRAMES; }
/// <summary> /// Initializes a new instance of the <see cref="NewCitizenBehavior"/> class. /// </summary> /// <param name="randomizer">The randomizer to use for random decisions.</param> /// <param name="config">The configuration to run with.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public NewCitizenBehavior(IRandomizer randomizer, RealTimeConfig config) { this.randomizer = randomizer ?? throw new ArgumentNullException(nameof(randomizer)); this.config = config ?? throw new ArgumentNullException(nameof(config)); }
/// <summary>Initializes a new instance of the <see cref="SpareTimeBehavior"/> class.</summary> /// <param name="config">The configuration to run with.</param> /// <param name="timeInfo">The object providing the game time information.</param> /// <exception cref="ArgumentNullException">Thrown when any argument is null.</exception> public SpareTimeBehavior(RealTimeConfig config, ITimeInfo timeInfo) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); chances = new uint[Enum.GetValues(typeof(Citizen.AgeGroup)).Length]; }
private static bool SetupCustomAI( TimeInfo timeInfo, RealTimeConfig config, GameConnections <Citizen> gameConnections, RealTimeEventManager eventManager, Compatibility compatibility) { var residentAIConnection = ResidentAIPatch.GetResidentAIConnection(); if (residentAIConnection == null) { return(false); } float travelDistancePerCycle = compatibility.IsAnyModActive(WorkshopMods.RealisticWalkingSpeed) ? Constants.AverageTravelDistancePerCycle * 0.583f : Constants.AverageTravelDistancePerCycle; var spareTimeBehavior = new SpareTimeBehavior(config, timeInfo); var travelBehavior = new TravelBehavior(gameConnections.BuildingManager, travelDistancePerCycle); var workBehavior = new WorkBehavior(config, gameConnections.Random, gameConnections.BuildingManager, timeInfo, travelBehavior); ParkPatch.SpareTimeBehavior = spareTimeBehavior; OutsideConnectionAIPatch.SpareTimeBehavior = spareTimeBehavior; var realTimePrivateBuildingAI = new RealTimeBuildingAI( config, timeInfo, gameConnections.BuildingManager, new ToolManagerConnection(), workBehavior, travelBehavior); BuildingAIPatch.RealTimeAI = realTimePrivateBuildingAI; BuildingAIPatch.WeatherInfo = gameConnections.WeatherInfo; TransferManagerPatch.RealTimeAI = realTimePrivateBuildingAI; var realTimeResidentAI = new RealTimeResidentAI <ResidentAI, Citizen>( config, gameConnections, residentAIConnection, eventManager, realTimePrivateBuildingAI, workBehavior, spareTimeBehavior, travelBehavior); ResidentAIPatch.RealTimeAI = realTimeResidentAI; SimulationHandler.CitizenProcessor = new CitizenProcessor <ResidentAI, Citizen>( realTimeResidentAI, timeInfo, spareTimeBehavior, travelBehavior); var touristAIConnection = TouristAIPatch.GetTouristAIConnection(); if (touristAIConnection == null) { return(false); } var realTimeTouristAI = new RealTimeTouristAI <TouristAI, Citizen>( config, gameConnections, touristAIConnection, eventManager, spareTimeBehavior); TouristAIPatch.RealTimeAI = realTimeTouristAI; return(true); }
/// <summary>Initializes a new instance of the <see cref="TimeInfo" /> class.</summary> /// <param name="config">The configuration to run with.</param> /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception> public TimeInfo(RealTimeConfig config) { this.config = config ?? throw new ArgumentNullException(nameof(config)); }
private AwakeSleepSimulation(RealTimeConfig config) { threadProfiler = new ThreadProfiler(); this.config = config; }