예제 #1
0
 public void OnDisabled()
 {
     Log.Info("The 'Real Time' mod has been disabled.");
     ConfigurationProvider.SaveConfiguration(config);
     config   = null;
     configUI = null;
 }
예제 #2
0
        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);
        }
예제 #3
0
        /// <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();
            }
        }
예제 #4
0
        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;
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
 /// <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));
 }
예제 #7
0
 /// <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));
 }
예제 #8
0
 /// <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));
 }
예제 #9
0
        /// <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];
        }
예제 #10
0
 /// <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);
 }
예제 #11
0
 /// <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));
 }
예제 #12
0
        /// <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()];
        }
예제 #13
0
 /// <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>();
 }
예제 #14
0
        /// <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()];
        }
예제 #15
0
        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();
        }
예제 #16
0
        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);
        }
예제 #17
0
        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();
        }
예제 #18
0
        /// <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();
        }
예제 #19
0
        /// <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);
        }
예제 #20
0
        /// <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;
        }
예제 #21
0
        /// <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);
        }
예제 #22
0
        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);
        }
예제 #23
0
 /// <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);
 }
예제 #24
0
        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);
        }
예제 #25
0
 /// <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;
 }
예제 #26
0
 /// <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));
 }
예제 #27
0
 /// <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];
 }
예제 #28
0
        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);
        }
예제 #29
0
 /// <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));
 }
예제 #30
0
 private AwakeSleepSimulation(RealTimeConfig config)
 {
     threadProfiler = new ThreadProfiler();
     this.config    = config;
 }