/// <summary> /// Gets a state if there is one already in progress. /// </summary> /// <param name="currentTime">The current time.</param> /// <returns> /// Returns an instance of ITimeOfDayState that represents the current time of day if an instance with a StartTime /// before the current world-time can be found /// </returns> private TimeOfDayState GetInProgressState(TimeOfDay currentTime) { TimeOfDayState inProgressState = null; foreach (TimeOfDayState state in this.timeOfDayStates) { // If the state is already in progress, w if (state.StateStartTime.Hour <= currentTime.Hour || (state.StateStartTime.Hour <= currentTime.Hour && state.StateStartTime.Minute <= currentTime.Minute)) { if (inProgressState == null) { inProgressState = state; continue; } else { if (inProgressState.StateStartTime.Hour <= currentTime.Hour && inProgressState.StateStartTime.Minute <= currentTime.Minute) { inProgressState = state; } } } } return(inProgressState); }
/// <summary> /// Gets the state that is up next. /// </summary> /// <param name="currentTime">The current time.</param> /// <returns> /// Returns an instance of ITimeOfDayState that represents the up coming time of day if an instance with a StartTime /// after the current world-time can be found /// </returns> private TimeOfDayState GetNextState(TimeOfDay currentTime) { TimeOfDayState nextState = null; foreach (TimeOfDayState state in this.timeOfDayStates) { // If this state is a future state, then preserve it as a possible next state. if (state.StateStartTime.Hour > currentTime.Hour || (state.StateStartTime.Hour >= currentTime.Hour && state.StateStartTime.Minute > currentTime.Minute)) { // If we do not have a next state, set it. if (nextState == null) { nextState = state; continue; } else { // We have a next state, so we must check which is sooner. if (nextState.StateStartTime.Hour > state.StateStartTime.Hour && nextState.StateStartTime.Minute >= state.StateStartTime.Minute) { nextState = state; } } } } return(nextState); }
/// <summary> /// Event handler method fired when the Current TimeOfDay state has its time changed. /// </summary> /// <param name="sender">The TimeOfDayState that caused the time change.</param> /// <param name="updatedTimeOfDay">The new time of day.</param> private void CurrentTimeOfDayState_TimeUpdated(object sender, TimeOfDay updatedTimeOfDay) { // Takes our current time of day within the time of day state, and updates the realms with it. this.UpdateTimeOfDayStatesForRealms(); // Fetch the world time of day. // This acts as +0 GMT in-game. Each realm can have an offset via its own timezone. TimeOfDayState newTimeOfDay = this.timeOfDayStateManager.GetTimeOfDayState(updatedTimeOfDay); if (this.CurrentTimeOfDay == newTimeOfDay) { return; } // We need to store a reference to the current state, since the Setup method overwrites it. var currentTimeOfDay = this.CurrentTimeOfDay; this.SetupWorldClock(newTimeOfDay); // Since the world time of day state was changed, we need to re-evaluate our realms. this.UpdateTimeOfDayStatesForRealms(); // Invoke our event handler with the old state and the new state. this.OnTimeOfDayChanged(currentTimeOfDay, newTimeOfDay); }
/// <summary> /// Gets the state of the current time of day. /// </summary> /// <returns>Returns an instance representing the current time of day state.</returns> public TimeOfDayState GetCurrentTimeOfDayState() { TimeOfDayState state = this.timeOfDayStateManager.GetTimeOfDayState(this.CurrentTimeOfDay); if (state == null) { return(this.World.CurrentTimeOfDay); } else { return(state); } }
/// <summary> /// Called when the current time of day has changed and a new one is transitioning in. /// </summary> /// <param name="oldTimeOfDay">The old time of day.</param> /// <param name="newTimeOfDay">The new time of day.</param> protected virtual void OnTimeOfDayChanged(TimeOfDayState oldTimeOfDay, TimeOfDayState newTimeOfDay) { // Our event handler EventHandler <TimeOfDayChangedEventArgs> handler = this.TimeOfDayChanged; if (handler == null) { return; } // Invoke the handler handler(this.CurrentTimeOfDay, new TimeOfDayChangedEventArgs(oldTimeOfDay, newTimeOfDay)); }
/// <summary> /// Adds the time of day state to the world. /// </summary> /// <param name="state">The state.</param> /// <exception cref="System.InvalidOperationException">You can not have two states with the same start time in the same world.</exception> /// <exception cref="System.NullReferenceException">State's start time must not be null.</exception> public void AddTimeOfDayState(TimeOfDayState state) { // We prevent states with the same start time from being added to the world if (this.TimeOfDayStates.Any(s => s.StateStartTime.Equals(state))) { throw new InvalidOperationException("You can not have two states with the same start time in the same world."); } // Null start times engine from transitioning to the new state. if (state.StateStartTime == null) { throw new NullReferenceException("State's start time must not be null."); } this.timeOfDayStates.Add(state); }
/// <summary> /// Sets up the world clock. /// </summary> /// <param name="initialState">The initial state.</param> private void SetupWorldClock(TimeOfDayState initialState) { // We want to reset our current state before we set up the next state // The next state starts on a background thread and can cause listeners to access // the old state before the new state is assigned preventing a proper reset. if (this.CurrentTimeOfDay != null) { this.CurrentTimeOfDay.TimeUpdated -= this.CurrentTimeOfDayState_TimeUpdated; } // Register for event updates initialState.TimeUpdated += this.CurrentTimeOfDayState_TimeUpdated; // Initialize the state. // TODO: This could potentially reset an in-use state if a zone has a large time-zone offset. An exception should be thrown if still in-use. initialState.Initialize(this.GameTimeAdjustmentFactor, this.HoursPerDay); this.CurrentTimeOfDay = initialState; }
/// <summary> /// Looks at a supplied time of day and figures out what TimeOfDayState needs to be returned that matches the time of day. /// </summary> /// <param name="currentGameTime">The current time.</param> /// <returns> /// Returns an instance of ITimeOfDayState that represents the current time of day in the game. /// </returns> internal TimeOfDayState GetTimeOfDayState(TimeOfDay currentGameTime = null) { TimeOfDayState inProgressState = null; TimeOfDayState nextState = null; Parallel.Invoke( () => inProgressState = this.GetInProgressState(currentGameTime), () => nextState = this.GetNextState(currentGameTime)); if (inProgressState != null) { return(inProgressState); } else if (nextState != null && nextState.StateStartTime.Hour <= currentGameTime.Hour && nextState.StateStartTime.Minute <= currentGameTime.Minute) { return(nextState); } return(null); }
public async Task<IEnumerable<TimeOfDayState>> GetTimeOfDayStates() { IEnumerable<string> stateFiles = this.storageService.GetAllFilesByExtension(".tods", "TimeOfDayStates"); var states = new List<TimeOfDayState>(); foreach(string file in stateFiles) { var state = new TimeOfDayState(); state.Name = await this.storageService.LoadValueFromKeyAsync(file, state.GetPropertyName(p => p.Name)); state.StateStartTime.Hour = Convert.ToInt32(await this.storageService.LoadValueFromKeyAsync( file, state.StateStartTime.GetPropertyName(p => p.Hour))); state.StateStartTime.Minute = Convert.ToInt32(await this.storageService.LoadValueFromKeyAsync( file, state.StateStartTime.GetPropertyName(p => p.Minute))); state.StateStartTime.HoursPerDay = Convert.ToInt32(await this.storageService.LoadValueFromKeyAsync( file, state.StateStartTime.GetPropertyName(p => p.HoursPerDay))); states.Add(state); } return states; }
/// <summary> /// Determines whether the specified <see cref="System.Object" />, is equal to this instance. /// </summary> /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param> /// <returns> /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. /// </returns> public override bool Equals(object obj) { TimeOfDayState secondState = (TimeOfDayState)obj; return(secondState.StateStartTime.Hour == this.StateStartTime.Hour && secondState.StateStartTime.Minute == this.StateStartTime.Minute); }
/// <summary> /// Constructs the world. /// </summary> /// <param name="game">The game.</param> private async Task ConstructWorld(IGame game) { // Set up the Room var bedroom = new DefaultRoom { IsEnabled = true }; var hallway = new DefaultRoom { IsEnabled = true }; // Set up the Zone var weatherStates = new List<IWeatherState> { new ClearWeather(), new RainyWeather(), new ThunderstormWeather() }; DefaultZone zone = new DefaultZone(); zone.Name = "Country Side"; zone.Rooms = new List<DefaultRoom>() { bedroom }; zone.WeatherStates = weatherStates; zone.WeatherUpdateFrequency = 6; zone.WeatherChanged += (sender, weatherArgs) => Console.WriteLine($"{zone.Name} zone weather has changed to {weatherArgs.CurrentState.Name}"); DefaultZone zone2 = new DefaultZone(); zone2.Name = "Castle Rock"; zone2.Rooms = new List<DefaultRoom> { hallway }; zone2.WeatherStates = weatherStates; zone2.WeatherUpdateFrequency = 2; zone2.WeatherChanged += (sender, weatherArgs) => Console.WriteLine($"{zone2.Name} zone weather has changed to {weatherArgs.CurrentState.Name}"); // Set up the World. IWorld world = new DefaultWorld(); world.GameDayToRealHourRatio = 0.4; world.HoursPerDay = 10; world.Name = "Sample World"; world.SetNotificationManager(game.NotificationCenter); var morningState = new TimeOfDayState { Name = "Morning", StateStartTime = new TimeOfDay { Hour = 2 } }; var afternoonState = new TimeOfDayState { Name = "Afternoon", StateStartTime = new TimeOfDay { Hour = 5 } }; var nightState = new TimeOfDayState { Name = "Night", StateStartTime = new TimeOfDay { Hour = 8 } }; world.AddTimeOfDayState(morningState); world.AddTimeOfDayState(afternoonState); world.AddTimeOfDayState(nightState); world.TimeOfDayChanged += World_TimeOfDayChanged; // Set up the Realm. DefaultRealm realm = new DefaultRealm(world, new TimeOfDay { Hour = 3, HoursPerDay = 10 }); realm.TimeZoneOffset = new TimeOfDay { Hour = 3, Minute = 10, HoursPerDay = world.HoursPerDay }; realm.Name = "Realm 1"; realm.SetNotificationManager(game.NotificationCenter); // Initialize the environment. Task task = world.Initialize(); task.Wait(); await world.AddRealmToWorld(realm); realm.AddZoneToRealm(zone); realm.AddZoneToRealm(zone2); await game.AddWorld(world); }
/// <summary> /// Called when the current time of day has changed and a new one is transitioning in. /// </summary> /// <param name="oldTimeOfDay">The old time of day.</param> /// <param name="newTimeOfDay">The new time of day.</param> protected virtual void OnTimeOfDayChanged(TimeOfDayState oldTimeOfDay, TimeOfDayState newTimeOfDay) { // Our event handler EventHandler<TimeOfDayChangedEventArgs> handler = this.TimeOfDayChanged; if (handler == null) { return; } // Invoke the handler handler(this.CurrentTimeOfDay, new TimeOfDayChangedEventArgs(oldTimeOfDay, newTimeOfDay)); }
/// <summary> /// Initializes a new instance of the <see cref="TimeOfDayChangedEventArgs"/> class. /// </summary> /// <param name="transitionFrom">The transition from.</param> /// <param name="transitionTo">The transition to.</param> public TimeOfDayChangedEventArgs(TimeOfDayState transitionFrom, TimeOfDayState transitionTo) { this.TransitioningFrom = transitionFrom; this.TransitioningTo = transitionTo; }