using FJson; using Framework.Save; using Framework.Timer; using Framework.Utils; using Framework.Utils.SingletonTemplate; using Script.Core.Utils.Extend; using UnityEngine; namespace System.OfflineSystem { public class OfflineMgr : MgrBase { private const string OfflineMgrTimeKey = "OfflineMgr_HistoryTimeKey"; [Serializable] public class TimeNode { public ENumber64 timestamp = new ENumber64(); public float duration = 0; public bool HasValid => this.timestamp?.Read > 0; public DateTime StartTime => this.HasValid ? this.timestamp.Read.GetDateTime13 () : new DateTime(); public DateTime EndTime => this.StartTime.AddSeconds(this.duration); public override string ToString() => $"起始时间:{this.StartTime:u} , 在线时长: {this.duration:F1}s , 结束时间: {this.EndTime:u}"; } #region private protected override void OnCreateMge() { this.startTimeNode = new TimeNode(); var offlineMgrTime = Account.Instance.AccountGameData.OfflineMgrTime; this.historyTimeNode = !string.IsNullOrEmpty(offlineMgrTime) ? FJsonUtility.ToObject(offlineMgrTime) : new TimeNode(); if (this.historyTimeNode.StartTime.Year <= 1999) { //无效的历史记录,重新初始化一个空历史记录 this.historyTimeNode = new TimeNode(); } GameUpdateMgr.Instance.AddUpdater(DoUpdate); } private void DoUpdate() { this.startTimeNode.duration = Time.realtimeSinceStartup + this._extendTime; } private void OnTimeLoad(long timeStr) { if (timeStr <= 0) { this.initCallback?.Invoke(false); } else { var timestamp= timeStr; this.startTimeNode.timestamp.Write(timestamp); this.initCallback?.Invoke(true); } UpdateHistoryTime(); } #endregion private readonly OfflineTimeLoader timeLoader = new OfflineTimeLoader(); private TimeNode startTimeNode; private TimeNode historyTimeNode; private float _extendTime; //额外时间 private Action initCallback; public float ExtendTime { get => this._extendTime; set => this._extendTime = value; } // ReSharper disable once ConvertToAutoPropertyWithPrivateSetter /// /// 离线时间 /// public TimeSpan OfflineTimeSpan => this.startTimeNode.HasValid && this.historyTimeNode.HasValid ? this.startTimeNode.StartTime - this.historyTimeNode.EndTime: TimeSpan.Zero; // public TimeSpan OfflineTimeSpan => TimeSpan.FromSeconds(5); // ReSharper disable once ConvertToAutoPropertyWithPrivateSetter public TimeNode CurTimeNode => this.startTimeNode; // ReSharper disable once ConvertToAutoPropertyWithPrivateSetter public TimeNode HistoryTimeNode => this.historyTimeNode; #region Public API /// /// 初始化启动时间信息,此操作会自动获取网络时间 /// /// /// 无法获取到网络时间时,是否使用本地系统时间 public void InitStartTime(Action callback , bool useLocalTime = true ) { this.initCallback = callback; this.timeLoader.LoadTime(OnTimeLoad , useLocalTime); } /// /// 初始化启动时间信息 /// /// /// public void InitStartTime(Action callback , long timestr) { this.initCallback = callback; OnTimeLoad (timestr); } /// /// 更新并持久化存储本次在线时长 /// public void UpdateHistoryTime() { if (this.startTimeNode.HasValid) { // WX.StorageSetStringSync(OfflineMgrTimeKey , FJsonUtility.ToJson(startTimeNode)); Account.Instance.AccountGameData.OfflineMgrTime = FJsonUtility.ToJson(this.startTimeNode); } } // public void ResetStartTime (long timeStr) // { // var timestamp = timeStr; // this.startTimeNode.timestamp.Write(timestamp); // UpdateHistoryTime(); // } /// /// 创建一个离线计时器 /// /// 秒 /// public OfflineTimeHandler CreateTimeHandler (float duration) { return new OfflineTimeHandler (this.CurTimeNode.EndTime.ToTimeStamp13 () , duration); } #endregion } }