using System; using System.Collections.Generic; using System.Diagnostics; using SUISS.Storage; using UnityEngine; namespace SUISS.Scheduling { public class Timing : MonoBehaviour { //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event Timing.TimingChangeEndedHandler TimingChangeEnded; private void FireTimingChangeEnded() { if (this.TimingChangeEnded != null) { this.TimingChangeEnded(); } } public static double scale { get { return Timing.Instance.GameScale; } set { Timing.Instance.GameScale = value; } } public static double time { get { return Timing.Instance.GameTime; } } public static DateTime ToUtc(double seconds) { return Timing.Instance.ToUtc_internal(seconds); } public static double UtcNow { get { return (double)DateTime.UtcNow.Ticks * 1E-07; } } public static long ConvertYMDhmsToUtc(string ymdhms) { long result; try { int year = int.Parse(ymdhms.Substring(0, 4)); int month = int.Parse(ymdhms.Substring(4, 2)); int day = int.Parse(ymdhms.Substring(6, 2)); int hour = int.Parse(ymdhms.Substring(8, 2)); int minute = int.Parse(ymdhms.Substring(10, 2)); int second = int.Parse(ymdhms.Substring(12, 2)); DateTime dateTime = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Local); result = dateTime.ToUniversalTime().Ticks / 10000000L; } catch (Exception arg) { UnityEngine.Debug.LogWarning(string.Format("Unable to parse ymdhms format {0}: {1}.", ymdhms, arg)); result = 0L; } return result; } public double GameScale { get { return this._scale; } set { this.SetBuildingScale(value); this.SetAnimationScale(value); } } public double GameTime { get { return (double)this._offset * 1E-07 + this.GameTimeWithoutOffset; } } public bool TimingChangeActive { get { return this._scale != 1.0; } } [Obsolete("Use Timing.GameTime")] public double t { get { return this.GameTime; } } [Obsolete("Use Timing.GameScale")] public double s { get { return this.GameScale; } set { this.GameScale = value; } } public void SetGameScale(double scale, double animationScaleMultiplier) { this.SetBuildingScale(scale); this.SetAnimationScale(scale * animationScaleMultiplier); } public void MakeTimeJump(TimeSpan jump) { this._offset += jump.Ticks; this._state["Offset"] = this._offset; this.FireTimingChangeEnded(); } private double GameTimeWithoutOffset { get { return ((double)this._baseTime + (double)(DateTime.UtcNow.Ticks - this._startTicks) * this.GameScale) * 1E-07; } } private void SetBuildingScale(double scale) { this._baseTime = (long)(10000000.0 * this.GameTimeWithoutOffset); this._startTicks = DateTime.UtcNow.Ticks; this._state["StartTicks"] = this._startTicks; this._state["BaseTime"] = this._baseTime; this._scale = scale; if (scale == 1.0) { this.FireTimingChangeEnded(); } } private void SetAnimationScale(double scale) { Time.timeScale = (float)Math.Max(1.0, Math.Min(this.maximumTimeScale, scale)); } private DateTime ToUtc_internal(double seconds) { long ticks = (long)(seconds * 10000000.0 - (double)this._offset - (double)this._baseTime + (double)this._startTicks); return new DateTime(ticks); } private void Awake() { Timing.Instance = this; this._state = SUISS.Storage.Storage.Get(this.StorageLifecycle).GetDictionary(this.StorageKey); if (this._state.ContainsKey("StartTicks") && this._state.ContainsKey("BaseTime")) { this._startTicks = (long)this._state["StartTicks"]; this._baseTime = (long)this._state["BaseTime"]; } else { this._startTicks = DateTime.UtcNow.Ticks; this._baseTime = 0L; this._state["StartTicks"] = this._startTicks; this._state["BaseTime"] = this._baseTime; } object obj; if (this._state.TryGetValue("Offset", out obj) && obj is long) { this._offset = (long)obj; } } private void OnDestroy() { Time.timeScale = 1f; } [SerializeField] private StorageLifecycle StorageLifecycle = StorageLifecycle.Game; [SerializeField] private string StorageKey = "Timing"; public double maximumTimeScale = 5.0; public const string BaseTimeKey = "BaseTime"; public const string StartTicksKey = "StartTicks"; public const string OffsetKey = "Offset"; private long _baseTime; private long _startTicks = -1L; private long _offset; private Dictionary _state; private double _scale = 1.0; public static Timing Instance; public delegate void TimingChangeEndedHandler(); } }