From 1a1dddef1613da4304e9eda98d43cebfe5424158 Mon Sep 17 00:00:00 2001
From: dymanoid <9433345+dymanoid@users.noreply.github.com>
Date: Sun, 1 Jul 2018 03:04:58 +0200
Subject: [PATCH 1/3] Improve the UI slider attribute and default display
format
---
src/RealTime/UI/ConfigItemSliderAttribute.cs | 29 ++++++++++++++++----
src/RealTime/UI/UnitySliderItem.cs | 3 +-
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/src/RealTime/UI/ConfigItemSliderAttribute.cs b/src/RealTime/UI/ConfigItemSliderAttribute.cs
index c057364a..286d8e53 100644
--- a/src/RealTime/UI/ConfigItemSliderAttribute.cs
+++ b/src/RealTime/UI/ConfigItemSliderAttribute.cs
@@ -26,7 +26,7 @@ internal sealed class ConfigItemSliderAttribute : ConfigItemUIBaseAttribute
///
/// Thrown when the value is less or equal to zero.
///
- public ConfigItemSliderAttribute(float min, float max, float step = 1f, SliderValueType valueType = SliderValueType.Percentage)
+ public ConfigItemSliderAttribute(float min, float max, float step, SliderValueType valueType)
{
if (max <= min)
{
@@ -44,16 +44,35 @@ public ConfigItemSliderAttribute(float min, float max, float step = 1f, SliderVa
ValueType = valueType;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The minimum slider value.
+ /// The maximum slider value.
+ /// The slider step value. Default is 1.
+ /// The type of the value to display. Default is .
+ ///
+ /// Thrown when the value is less or equal to the
+ /// value.
+ ///
+ ///
+ /// Thrown when the value is less or equal to zero.
+ ///
+ public ConfigItemSliderAttribute(float min, float max)
+ : this(min, max, 1.0f, SliderValueType.Percentage)
+ {
+ }
+
/// Gets the slider minimum value.
public float Min { get; }
/// Gets the slider maximum value.
public float Max { get; }
- /// Gets the slider step value.
- public float Step { get; }
+ /// Gets or sets the slider step value.
+ public float Step { get; set; }
- /// Gets the type of the value that will be displayed.
- public SliderValueType ValueType { get; }
+ /// Gets or sets the type of the value that will be displayed.
+ public SliderValueType ValueType { get; set; }
}
}
\ No newline at end of file
diff --git a/src/RealTime/UI/UnitySliderItem.cs b/src/RealTime/UI/UnitySliderItem.cs
index 8ba9369c..c817add7 100644
--- a/src/RealTime/UI/UnitySliderItem.cs
+++ b/src/RealTime/UI/UnitySliderItem.cs
@@ -145,7 +145,8 @@ private void UpdateValueLabel(float value)
break;
default:
- return;
+ valueString = value.ToString();
+ break;
}
valueLabel.text = valueString;
From ad23c971f69e7ab0a97bbf7bb4c09ff4728efafd Mon Sep 17 00:00:00 2001
From: dymanoid <9433345+dymanoid@users.noreply.github.com>
Date: Sun, 1 Jul 2018 03:06:33 +0200
Subject: [PATCH 2/3] Add configuration validation
---
src/RealTime/Config/ConfigurationProvider.cs | 2 +-
src/RealTime/Config/RealTimeConfig.cs | 41 ++++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/src/RealTime/Config/ConfigurationProvider.cs b/src/RealTime/Config/ConfigurationProvider.cs
index d57547c3..dc99b7e4 100644
--- a/src/RealTime/Config/ConfigurationProvider.cs
+++ b/src/RealTime/Config/ConfigurationProvider.cs
@@ -70,7 +70,7 @@ private static RealTimeConfig Deserialize()
var serializer = new XmlSerializer(typeof(RealTimeConfig));
using (var sr = new StreamReader(SettingsFileName))
{
- return (RealTimeConfig)serializer.Deserialize(sr);
+ return ((RealTimeConfig)serializer.Deserialize(sr)).Validate();
}
}
diff --git a/src/RealTime/Config/RealTimeConfig.cs b/src/RealTime/Config/RealTimeConfig.cs
index 80ca57da..7406bf22 100644
--- a/src/RealTime/Config/RealTimeConfig.cs
+++ b/src/RealTime/Config/RealTimeConfig.cs
@@ -4,6 +4,7 @@
namespace RealTime.Config
{
+ using System.Collections.Generic;
using RealTime.UI;
///
@@ -149,5 +150,45 @@ public sealed class RealTimeConfig
[ConfigItem("4Time", 6)]
[ConfigItemSlider(11, 16, 0.25f, SliderValueType.Time)]
public float SchoolEnd { get; set; } = 14f;
+
+ /// Validates this instance and corrects possible invalid property values.
+ /// This instance.
+ public RealTimeConfig Validate()
+ {
+ VirtualCitizens = (VirtualCitizensLevel)Clamp((int)VirtualCitizens, (int)VirtualCitizensLevel.None, (int)VirtualCitizensLevel.Many);
+ ConstructionSpeed = Clamp(ConstructionSpeed, 0u, 100u);
+ LunchQuota = Clamp(LunchQuota, 0u, 100u);
+ LocalBuildingSearchQuota = Clamp(LocalBuildingSearchQuota, 0u, 100u);
+ OnTimeQuota = Clamp(OnTimeQuota, 0u, 100u);
+ EarliestHourEventStartWeekday = Clamp(EarliestHourEventStartWeekday, 0f, 23.75f);
+ LatestHourEventStartWeekday = Clamp(LatestHourEventStartWeekday, 0f, 23.75f);
+ EarliestHourEventStartWeekend = Clamp(EarliestHourEventStartWeekend, 0f, 23.75f);
+ LatestHourEventStartWeekend = Clamp(LatestHourEventStartWeekend, 0f, 23.75f);
+ WorkBegin = Clamp(WorkBegin, 4f, 11f);
+ WorkEnd = Clamp(WorkEnd, 12f, 20f);
+ LunchBegin = Clamp(LunchBegin, 11f, 13f);
+ LunchEnd = Clamp(LunchEnd, 13f, 15f);
+ SchoolBegin = Clamp(SchoolBegin, 4f, 10f);
+ SchoolEnd = Clamp(SchoolEnd, 11f, 16f);
+ MaxOvertime = Clamp(MaxOvertime, 0f, 4f);
+ return this;
+ }
+
+ private static T Clamp(T value, T min, T max)
+ where T : struct
+ {
+ Comparer comparer = Comparer.Default;
+ if (comparer.Compare(value, min) < 0)
+ {
+ return min;
+ }
+
+ if (comparer.Compare(value, max) > 0)
+ {
+ return max;
+ }
+
+ return value;
+ }
}
}
From 17274bc15a93c9ec2d245cd20b45b8759e62c810 Mon Sep 17 00:00:00 2001
From: dymanoid <9433345+dymanoid@users.noreply.github.com>
Date: Sun, 1 Jul 2018 03:08:13 +0200
Subject: [PATCH 3/3] Implement #20 by enabling of manual time speed changes
(day and night)
---
src/RealTime/Config/RealTimeConfig.cs | 26 +++++--
src/RealTime/Core/RealTimeCore.cs | 4 +-
src/RealTime/Localization/Translations/de.xml | 4 ++
src/RealTime/Localization/Translations/en.xml | 4 ++
src/RealTime/Localization/Translations/es.xml | 4 ++
src/RealTime/Localization/Translations/fr.xml | 4 ++
src/RealTime/Localization/Translations/ko.xml | 4 ++
src/RealTime/Localization/Translations/pl.xml | 4 ++
src/RealTime/Localization/Translations/pt.xml | 4 ++
src/RealTime/Localization/Translations/ru.xml | 4 ++
src/RealTime/Localization/Translations/zh.xml | 4 ++
src/RealTime/Simulation/SimulationHandler.cs | 4 ++
src/RealTime/Simulation/TimeAdjustment.cs | 68 +++++++++++--------
13 files changed, 104 insertions(+), 34 deletions(-)
diff --git a/src/RealTime/Config/RealTimeConfig.cs b/src/RealTime/Config/RealTimeConfig.cs
index 7406bf22..f84d3ece 100644
--- a/src/RealTime/Config/RealTimeConfig.cs
+++ b/src/RealTime/Config/RealTimeConfig.cs
@@ -13,37 +13,51 @@ namespace RealTime.Config
public sealed class RealTimeConfig
{
///
- /// Gets or sets the virtual citizens mode.
+ /// Gets or sets the speed of the time flow on daytime. Valid values are 1..7.
///
[ConfigItem("1General", 0)]
+ [ConfigItemSlider(1, 7, ValueType = SliderValueType.Default)]
+ public uint DayTimeSpeed { get; set; } = 5;
+
+ ///
+ /// Gets or sets the speed of the time flow on night time. Valid values are 1..7.
+ ///
+ [ConfigItem("1General", 1)]
+ [ConfigItemSlider(1, 7, ValueType = SliderValueType.Default)]
+ public uint NightTimeSpeed { get; set; } = 5;
+
+ ///
+ /// Gets or sets the virtual citizens mode.
+ ///
+ [ConfigItem("1General", 2)]
[ConfigItemComboBox]
public VirtualCitizensLevel VirtualCitizens { get; set; } = VirtualCitizensLevel.Few;
///
/// Gets or sets a value indicating whether the weekends are enabled. Cims don't go to work on weekends.
///
- [ConfigItem("1General", 1)]
+ [ConfigItem("1General", 3)]
[ConfigItemCheckBox]
public bool IsWeekendEnabled { get; set; } = true;
///
/// Gets or sets a value indicating whether Cims should go out at lunch for food.
///
- [ConfigItem("1General", 2)]
+ [ConfigItem("1General", 4)]
[ConfigItemCheckBox]
public bool IsLunchtimeEnabled { get; set; } = true;
///
/// Gets or sets a value indicating whether the construction sites should pause at night time.
///
- [ConfigItem("1General", 3)]
+ [ConfigItem("1General", 5)]
[ConfigItemCheckBox]
public bool StopConstructionAtNight { get; set; } = true;
///
/// Gets or sets the percentage value of the building construction speed. Valid values are 1..100.
///
- [ConfigItem("1General", 4)]
+ [ConfigItem("1General", 6)]
[ConfigItemSlider(1, 100)]
public uint ConstructionSpeed { get; set; } = 50;
@@ -155,6 +169,8 @@ public sealed class RealTimeConfig
/// This instance.
public RealTimeConfig Validate()
{
+ DayTimeSpeed = Clamp(DayTimeSpeed, 1u, 7u);
+ NightTimeSpeed = Clamp(NightTimeSpeed, 1u, 7u);
VirtualCitizens = (VirtualCitizensLevel)Clamp((int)VirtualCitizens, (int)VirtualCitizensLevel.None, (int)VirtualCitizensLevel.Many);
ConstructionSpeed = Clamp(ConstructionSpeed, 0u, 100u);
LunchQuota = Clamp(LunchQuota, 0u, 100u);
diff --git a/src/RealTime/Core/RealTimeCore.cs b/src/RealTime/Core/RealTimeCore.cs
index c995714b..385a8da0 100644
--- a/src/RealTime/Core/RealTimeCore.cs
+++ b/src/RealTime/Core/RealTimeCore.cs
@@ -80,8 +80,9 @@ public static RealTimeCore Run(RealTimeConfig config, string rootPath, Localizat
return null;
}
- var timeAdjustment = new TimeAdjustment();
+ var timeAdjustment = new TimeAdjustment(config);
DateTime gameDate = timeAdjustment.Enable();
+ SimulationHandler.TimeAdjustment = timeAdjustment;
var timeInfo = new TimeInfo();
var buildingManager = new BuildingManagerConnection();
@@ -155,6 +156,7 @@ public void Stop()
SimulationHandler.EventManager = null;
SimulationHandler.DayTimeSimulation = null;
SimulationHandler.CommercialAI = null;
+ SimulationHandler.TimeAdjustment = null;
try
{
diff --git a/src/RealTime/Localization/Translations/de.xml b/src/RealTime/Localization/Translations/de.xml
index 3a8682cc..acf41ae4 100644
--- a/src/RealTime/Localization/Translations/de.xml
+++ b/src/RealTime/Localization/Translations/de.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/en.xml b/src/RealTime/Localization/Translations/en.xml
index 4eced2e3..5e9891ee 100644
--- a/src/RealTime/Localization/Translations/en.xml
+++ b/src/RealTime/Localization/Translations/en.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/es.xml b/src/RealTime/Localization/Translations/es.xml
index 59fe7ad7..6f2e0b6c 100644
--- a/src/RealTime/Localization/Translations/es.xml
+++ b/src/RealTime/Localization/Translations/es.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/fr.xml b/src/RealTime/Localization/Translations/fr.xml
index a50951e4..fb60bb8d 100644
--- a/src/RealTime/Localization/Translations/fr.xml
+++ b/src/RealTime/Localization/Translations/fr.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/ko.xml b/src/RealTime/Localization/Translations/ko.xml
index 89721a2a..86fd5a2a 100644
--- a/src/RealTime/Localization/Translations/ko.xml
+++ b/src/RealTime/Localization/Translations/ko.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/pl.xml b/src/RealTime/Localization/Translations/pl.xml
index da87a949..776c4323 100644
--- a/src/RealTime/Localization/Translations/pl.xml
+++ b/src/RealTime/Localization/Translations/pl.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/pt.xml b/src/RealTime/Localization/Translations/pt.xml
index 65467097..d59393b6 100644
--- a/src/RealTime/Localization/Translations/pt.xml
+++ b/src/RealTime/Localization/Translations/pt.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/ru.xml b/src/RealTime/Localization/Translations/ru.xml
index d188c8a1..55338206 100644
--- a/src/RealTime/Localization/Translations/ru.xml
+++ b/src/RealTime/Localization/Translations/ru.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Localization/Translations/zh.xml b/src/RealTime/Localization/Translations/zh.xml
index 63dbff06..a12d2eba 100644
--- a/src/RealTime/Localization/Translations/zh.xml
+++ b/src/RealTime/Localization/Translations/zh.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/RealTime/Simulation/SimulationHandler.cs b/src/RealTime/Simulation/SimulationHandler.cs
index e13aa93f..1837076a 100644
--- a/src/RealTime/Simulation/SimulationHandler.cs
+++ b/src/RealTime/Simulation/SimulationHandler.cs
@@ -37,6 +37,9 @@ public sealed class SimulationHandler : ThreadingExtensionBase
///
internal static RealTimeCommercialBuildingAI CommercialAI { get; set; }
+ /// Gets or sets the time adjustment simulation class instance.
+ internal static TimeAdjustment TimeAdjustment { get; set; }
+
///
/// Called after each game simulation tick. A tick contains multiple frames.
/// Performs the dispatching for this simulation phase.
@@ -44,6 +47,7 @@ public sealed class SimulationHandler : ThreadingExtensionBase
public override void OnAfterSimulationTick()
{
EventManager?.ProcessEvents();
+ TimeAdjustment?.Update();
DateTime currentDate = SimulationManager.instance.m_currentGameTime.Date;
if (currentDate != lastHandledDate)
diff --git a/src/RealTime/Simulation/TimeAdjustment.cs b/src/RealTime/Simulation/TimeAdjustment.cs
index 8e1e09a9..7a05b1f3 100644
--- a/src/RealTime/Simulation/TimeAdjustment.cs
+++ b/src/RealTime/Simulation/TimeAdjustment.cs
@@ -1,56 +1,62 @@
-//
-// Copyright (c) dymanoid. All rights reserved.
-//
+// Copyright (c) dymanoid. All rights reserved.
namespace RealTime.Simulation
{
using System;
- using RealTime.Tools;
+ using RealTime.Config;
///
/// Manages the customized time adjustment. This class depends on the class.
///
internal sealed class TimeAdjustment
{
- private const int CustomFramesPerDay = 1 << 17;
- private static readonly TimeSpan CustomTimePerFrame = new TimeSpan(24L * 3600L * 10_000_000L / CustomFramesPerDay);
-
+ private const int RealtimeSpeed = 23;
private readonly uint vanillaFramesPerDay;
- private readonly TimeSpan vanillaTimePerFrame;
+ private readonly RealTimeConfig config;
+ private uint lastDayTimeSpeed;
+ private uint lastNightTimeSpeed;
+ private bool isDayTime;
- ///
- /// Initializes a new instance of the class.
- ///
- public TimeAdjustment()
+ /// Initializes a new instance of the class.
+ /// The configuration to run with.
+ /// Thrown when the argument is null.
+ public TimeAdjustment(RealTimeConfig config)
{
+ this.config = config ?? throw new ArgumentNullException(nameof(config));
+ lastDayTimeSpeed = config.DayTimeSpeed;
+ lastNightTimeSpeed = config.NightTimeSpeed;
vanillaFramesPerDay = SimulationManager.DAYTIME_FRAMES;
- vanillaTimePerFrame = SimulationManager.instance.m_timePerFrame;
}
- ///
- /// Enables the customized time adjustment.
- ///
- ///
+ /// Enables the customized time adjustment.
/// The current game date and time.
public DateTime Enable()
{
- if (vanillaTimePerFrame == CustomTimePerFrame)
+ isDayTime = !SimulationManager.instance.m_isNightTime;
+ return UpdateTimeSimulationValues(CalculateFramesPerDay());
+ }
+
+ /// Updates the time adjustment to be synchronized with the configuration and the daytime.
+ public void Update()
+ {
+ if (SimulationManager.instance.m_isNightTime == isDayTime
+ || lastDayTimeSpeed != config.DayTimeSpeed
+ || lastNightTimeSpeed != config.NightTimeSpeed)
{
- Log.Warning("The 'Real Time' mod has not been properly deactivated! Check the TimeAdjustment.Disable() calls.");
+ isDayTime = !SimulationManager.instance.m_isNightTime;
+ lastDayTimeSpeed = config.DayTimeSpeed;
+ lastNightTimeSpeed = config.NightTimeSpeed;
+ UpdateTimeSimulationValues(CalculateFramesPerDay());
}
-
- return UpdateTimeSimulationValues(CustomFramesPerDay, CustomTimePerFrame);
}
- ///
- /// Disables the customized time adjustment restoring the default vanilla values.
- ///
+ /// Disables the customized time adjustment restoring the default vanilla values.
public void Disable()
{
- UpdateTimeSimulationValues(vanillaFramesPerDay, vanillaTimePerFrame);
+ UpdateTimeSimulationValues(vanillaFramesPerDay);
}
- private static DateTime UpdateTimeSimulationValues(uint framesPerDay, TimeSpan timePerFrame)
+ private static DateTime UpdateTimeSimulationValues(uint framesPerDay)
{
SimulationManager sm = SimulationManager.instance;
DateTime originalDate = sm.m_ThreadingWrapper.simulationTime;
@@ -59,7 +65,7 @@ private static DateTime UpdateTimeSimulationValues(uint framesPerDay, TimeSpan t
SimulationManager.DAYTIME_FRAME_TO_HOUR = 24f / SimulationManager.DAYTIME_FRAMES;
SimulationManager.DAYTIME_HOUR_TO_FRAME = SimulationManager.DAYTIME_FRAMES / 24f;
- sm.m_timePerFrame = timePerFrame;
+ sm.m_timePerFrame = new TimeSpan(24L * 3600L * 10_000_000L / framesPerDay);
sm.m_timeOffsetTicks = originalDate.Ticks - (sm.m_currentFrameIndex * sm.m_timePerFrame.Ticks);
sm.m_currentGameTime = originalDate;
@@ -69,5 +75,11 @@ private static DateTime UpdateTimeSimulationValues(uint framesPerDay, TimeSpan t
return sm.m_currentGameTime;
}
+
+ private uint CalculateFramesPerDay()
+ {
+ uint offset = isDayTime ? lastDayTimeSpeed : lastNightTimeSpeed;
+ return 1u << (int)(RealtimeSpeed - offset);
+ }
}
-}
+}
\ No newline at end of file