Przeglądaj źródła

添加网络时间校验

lzx 1 dzień temu
rodzic
commit
f429430286

+ 3 - 0
Assets/Scripts/Core/Utility/Helper/NetworkTime.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: dd55f514c8bf42a8aa5bc06376addb9e
+timeCreated: 1762674701

+ 106 - 47
Assets/Scripts/Core/Utility/Helper/TimeHelper.cs

@@ -1,23 +1,21 @@
 using System;
 using System.Linq;
-
+using Fort23.UTool;
+using UnityEngine;
 
 namespace Fort23.Core
 {
     public static class TimeHelper
     {
         public static int refreshHour = 0;
-
         public static readonly long epoch = 0;
-        
-        private static readonly DateTime ServerStartTime = new DateTime(2025, 4, 1, 0, 0, 0, DateTimeKind.Utc); // 服务器开服时间
-
-
+        private static readonly DateTime ServerStartTime = new DateTime(2025, 4, 1, 0, 0, 0, DateTimeKind.Utc);
         public static DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
 
         public const long OneDay = 86400000;
         public const long Hour = 3600000;
         public const long Minute = 60000;
+
         private static long _clientFrame;
 
         public static long clientFrame
@@ -25,18 +23,80 @@ namespace Fort23.Core
             set => _clientFrame = value;
         }
 
-        public static long GetServerStartTime()
-        {
-            return ((ServerStartTime.Ticks - epoch) / 10000) + (8 * 60 * 60 * 1000);
-        }
+
+        // 最近一次校准的网络时间戳毫秒
+        private static long _startNetworkMs = 0;
+
+        // 最近一次校准时的 Unity 时间
+        private static float _lastSyncUnityTime = 0f;
+
+        // 游戏首次启动时间
+        private static float _gameStartTime;
+
+        private const int SyncInterval = 300;
 
         /// <summary>
-        /// 用于唯一Id生成,不重复
+        /// 是否获取了网络时间
         /// </summary>
-        /// <returns></returns>
-        public static long ClientNowMicroseconds()
+        public static bool IsNetworkTimeReady { get; private set; } = false;
+
+
+        /// <summary>
+        /// 必须在游戏启动时调用(异步)
+        /// </summary>
+        public static async CTask InitNetworkTime()
         {
-            return DateTime.UtcNow.Ticks - epoch;
+            // 启动时的 Unity 时间
+            _gameStartTime = Time.unscaledTime;
+
+            // 首次同步
+            await SyncWithNetwork();
+
+            //每隔五分钟重新同步一次时间
+            TimerComponent.Instance.AddTimer(SyncInterval * 1000, null, Int32.MaxValue, () => { SyncWithNetwork(); });
+        }
+
+
+        // 核心:与百度时间同步
+        private static async CTask SyncWithNetwork()
+        {
+            var networkTime = await NetworkTime.GetNetworkTimeAsync();
+            if (networkTime.HasValue)
+            {
+                long networkMs = (long)(networkTime.Value - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
+                    .TotalMilliseconds;
+
+                if (!IsNetworkTimeReady)
+                {
+                    // 首次同步
+                    _startNetworkMs = networkMs;
+                    _lastSyncUnityTime = Time.unscaledTime;
+                    IsNetworkTimeReady = true;
+                    LogTool.Log($"首次网络时间同步成功: {networkTime.Value:yyyy-MM-dd HH:mm:ss} UTC");
+                }
+                else
+                {
+                    // 定期校准:计算漂移并修正
+                    float elapsedUnity = Time.unscaledTime - _lastSyncUnityTime;
+                    long expectedMs = _startNetworkMs + (long)(elapsedUnity * 1000);
+                    long driftMs = networkMs - expectedMs;
+
+                    if (Mathf.Abs((float)driftMs) > 5000) // 漂移 > 5 秒才修正(避免微小误差)
+                    {
+                        _startNetworkMs = networkMs;
+                        _lastSyncUnityTime = Time.unscaledTime;
+                        LogTool.Log($"时间校准: 漂移 {driftMs}ms,已修正");
+                    }
+                    else
+                    {
+                        LogTool.Log($"时间校准: 漂移 {driftMs}ms,正常");
+                    }
+                }
+            }
+            else
+            {
+                LogTool.Warning("网络时间校准失败,保持当前时间");
+            }
         }
 
 
@@ -50,18 +110,37 @@ namespace Fort23.Core
         }
 
         /// <summary>
-        /// 客户端时间(毫秒)
+        /// 获取安全的当前时间戳(毫秒)
         /// </summary>
-        /// <returns></returns>
+        private static long GetSafeNowMs()
+        {
+            if (!IsNetworkTimeReady || _startNetworkMs == 0)
+                return (long)(DateTime.UtcNow.Ticks / 10000); // 回退
+
+            // Unity运行毫秒(完全不受系统时间影响)
+            float elapsedUnity = Time.unscaledTime - _gameStartTime;
+            long elapsedMs = (long)(elapsedUnity * 1000);
+
+
+            return _startNetworkMs + elapsedMs;
+        }
+
+
+        public static long GetServerStartTime()
+        {
+            return ((ServerStartTime.Ticks - epoch) / 10000) + (8 * 60 * 60 * 1000);
+        }
+
+        public static long ClientNowMicroseconds()
+        {
+            return GetSafeNowMs() * 1000;
+        }
+
         public static long ClientNow()
         {
-            return ((DateTime.UtcNow.Ticks - epoch) / 10000) + (8 * 60 * 60 * 1000);
+            return GetSafeNowMs() + (8 * 60 * 60 * 1000); // 东八区
         }
 
-        /// <summary>
-        /// 客户端时间(秒)
-        /// </summary>
-        /// <returns></returns>
         public static long ClientNowSeconds()
         {
             return ClientNow() / 1000;
@@ -69,38 +148,19 @@ namespace Fort23.Core
 
         public static DateTime DateTimeNow()
         {
-            return DateTime.Now;
+            return DateTimeOffset.FromUnixTimeMilliseconds(ClientNow()).UtcDateTime;
         }
 
-        /// <summary>
-        /// 服务器时间(毫秒)
-        /// </summary>
-        /// <returns></returns>
         public static long ServerNow()
         {
             return ClientNow();
         }
 
-        /// <summary>
-        /// 服务器时间(秒)
-        /// </summary>
-        /// <returns></returns>
         public static long ServerNowSeconds()
         {
             return ClientNowSeconds();
         }
 
-        /// <summary>
-        /// 时间戳转字符串
-        /// </summary>
-        /// <param name="value"></param>
-        /// <returns></returns>
-        public static string ToHour(this int value)
-        {
-            int fen = value / 60;
-            int hour = fen / 60;
-            return (hour + 1) + "";
-        }
 
         /// <summary>
         /// 客户端时间(年月日)
@@ -143,7 +203,6 @@ namespace Fort23.Core
             return 20201010;
         }
 
-
         /// <summary>
         /// 客户端时间(月日时分秒)
         /// </summary>
@@ -204,7 +263,6 @@ namespace Fort23.Core
             }
 
             string result = $"{month}月{day}日{hour}:{minute}:{second}";
-
             return result;
         }
 
@@ -223,7 +281,8 @@ namespace Fort23.Core
             string[] holiday2022 = { "1231" };
             string[] holiday2023 =
             {
-                "0101", "0102", "0121", "0122", "0123", "0124", "0125", "0126", "0127", "0405", "0501", "0502", "0503", "0504", "0505", "0622", "0623",
+                "0101", "0102", "0121", "0122", "0123", "0124", "0125", "0126", "0127", "0405", "0501", "0502", "0503",
+                "0504", "0505", "0622", "0623",
                 "0929", "1002", "1003", "1004", "1005", "1006"
             };
 
@@ -271,20 +330,20 @@ namespace Fort23.Core
             return 0;
         }
 
+
         public static long GetBaseRefreshTime(long baseTime, int day = 1)
         {
             DateTime dateTime = DateTimeOffset.FromUnixTimeMilliseconds(baseTime).DateTime;
             int hour = dateTime.Hour;
-            DateTime refreshDateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, refreshHour, 0, 0, DateTimeKind.Utc);
+            DateTime refreshDateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, refreshHour, 0, 0,
+                DateTimeKind.Utc);
             if (hour < refreshHour)
             {
                 day -= 1;
             }
 
             refreshDateTime = refreshDateTime.AddDays(day);
-
             long refreshTime = new DateTimeOffset(refreshDateTime).ToUnixTimeMilliseconds();
-
             return refreshTime;
         }
     }

+ 6 - 2
Assets/Scripts/GameLogic/Player/PlayerManager.cs

@@ -367,12 +367,16 @@ public class PlayerManager : Singleton<PlayerManager>
 
     private void Update()
     {
+        
+        if (!TimeHelper.IsNetworkTimeReady)
+        {
+            LogTool.Error($"获取网络时间失败,挂机奖励停止计算");
+            return;
+        }
         timer += Time.deltaTime;
         if (timer > 1)
         {
             timer = 0;
-            // PlayerManager.Instance.myHero.heroData.exp += myHero.powerUpConfig.AutoXiuwei;
-            // AccountFileInfo.Instance.SavePlayerData();
             if (AccountFileInfo.Instance.playerData.QiankundaiDropTimer <= gameConstantConfig.qiankundaiMaxTime)
             {
                 AccountFileInfo.Instance.playerData.QiankundaiDropTimer++;

+ 3 - 0
Assets/Scripts/GameUI/GameApplction.cs

@@ -141,6 +141,9 @@ public class GameApplction : IGameStart
         //     LogTool.Error("登陆失败");
         //     return;
         // }
+        
+        await TimeHelper.InitNetworkTime();
+        
         EventManager.Instance.RemoveEventListener(CustomEventType.DialoguePanelOpen, DialoguePanelOpenEvent);
         EventManager.Instance.AddEventListener(CustomEventType.DialoguePanelOpen, DialoguePanelOpenEvent);
         UIManager.Instance.Canvas.gameObject.SetActive(true);

+ 9 - 0
Assets/Scripts/GameUI/GameApplctionMono.cs

@@ -63,6 +63,11 @@ namespace GameUI
 
         private void OnApplicationFocus(bool hasFocus)
         {
+            if (!TimeHelper.IsNetworkTimeReady)
+            {
+                return;
+            }
+
             if (hasFocus && PlayerManager.Instance.isLogin)
             {
                 // 退出时记录时间
@@ -77,6 +82,10 @@ namespace GameUI
 
         private void OnApplicationQuit()
         {
+            if (!TimeHelper.IsNetworkTimeReady)
+            {
+                return;
+            }
             // 退出时记录时间
             AccountFileInfo.Instance.playerData.ExitTime = TimeHelper.ClientNow();
             AccountFileInfo.Instance.SavePlayerData();

+ 11 - 0
Assets/Scripts/GameUI/UI/BoxPanel/BoxPanel.cs

@@ -16,6 +16,11 @@ namespace Fort23.Mono
     {
         public async static CTask<List<ItemInfo>> TenBox(int configId, bool isFree = false)
         {
+            if (!TimeHelper.IsNetworkTimeReady)
+            {
+                LogTool.Error($"获取网络时间失败,抽卡失败");
+                return null;
+            }
             AccountFileInfo.SummonData summonData = PlayerManager.Instance.SummonManager.summonDataMap[configId];
             OpenBoxConfig openBoxConfig = ConfigComponent.Instance.Get<OpenBoxConfig>(configId);
             //有免费次数,并且让到时间了就免费抽
@@ -42,6 +47,12 @@ namespace Fort23.Mono
 
         public async static CTask<List<ItemInfo>> OneBox(int configId)
         {
+            if (!TimeHelper.IsNetworkTimeReady)
+            {
+                LogTool.Error($"获取网络时间失败,抽卡失败");
+                return null;
+            }
+            
             AccountFileInfo.SummonData summonData = PlayerManager.Instance.SummonManager.summonDataMap[configId];
             OpenBoxConfig openBoxConfig = ConfigComponent.Instance.Get<OpenBoxConfig>(configId);
             //有免费次数,并且让到时间了就免费抽

+ 3 - 3
Assets/StreamingAssets/versionInfo.txt

@@ -1,3 +1,3 @@
-version=1
-buildVersion=1
-assetVersion=1
+version=0
+buildVersion=0
+assetVersion=0