| using System.Collections; | 
| using System.Collections.Generic; | 
| using UnityEngine; | 
| using System; | 
| using System.Text.RegularExpressions; | 
|   | 
|   | 
| public class InGameDownLoad : SingletonMonobehaviour<InGameDownLoad> | 
| { | 
|     public const int BYTE_PER_KILOBYTE = 1024;//b 转 kb | 
|     public const int BYTE_PER_MILLIONBYTE = 1048576;//b 转 mb | 
|   | 
|     List<AssetVersion> assets = new List<AssetVersion>(); //所有资源 | 
|     Dictionary<int, List<AssetVersion>> mapTasks = new Dictionary<int, List<AssetVersion>>();//地图专属的资源 | 
|   | 
|     public bool inGameDownLoadAllow = false; //是否可以下载 | 
|     public bool downLoadGo = false; //是否加速下载 | 
|   | 
|     public float progress //下载进度 | 
|     { | 
|         get | 
|         { | 
|             return Mathf.Clamp01((float)showDownLoadedSize / showTotalSize); | 
|         } | 
|     } | 
|   | 
|     public bool isDone { get { return state == State.Completed; } } //是否全部下载完成 | 
|   | 
|     //窗口中显示的已下载大小 | 
|     public long showDownLoadedSize { get { return DownloadMgr.Instance.DownloadedBytes - backGroundDownLoadSizeRecord; } } | 
|     public long showTotalSize { get { return totalSize - backGroundDownLoadSizeRecord; } }//窗口中显示的总大小 | 
|     public int showTotalCount { get { return totalCount - downLoadedCountRecord; } }//窗口中显示的总数量 | 
|     public int showOkCount { get { return okCount - downLoadedCountRecord; } }//窗口中显示的下载完成数量 | 
|   | 
|     long totalSize = 0; //资源总大小 | 
|     int totalCount = 0;//资源总数量 | 
|     int okCount = 0;//下载完成的数量 | 
|   | 
|     long backGroundDownLoadSizeRecord = 0;//后台偷偷已经下载到资源量 | 
|     int downLoadedCountRecord = 0;//后台已经下载完成的资源包数量 | 
|   | 
|     public event Action<State> downLoadStateChangeEvent; | 
|     public event Action<Dominant> dominantDownLoadEvent; | 
|   | 
|     Action onDownLoadOk;//资源全部下载完成回调 | 
|   | 
|     Dominant m_DominantState = Dominant.None; | 
|     public Dominant dominantState | 
|     { | 
|         get { return m_DominantState; } | 
|         private set | 
|         { | 
|             if (m_DominantState != value) | 
|             { | 
|                 m_DominantState = value; | 
|                 if (dominantDownLoadEvent != null) | 
|                 { | 
|                     dominantDownLoadEvent(m_DominantState); | 
|                 } | 
|             } | 
|         } | 
|     } | 
|   | 
|     State m_State = State.None; | 
|     public State state | 
|     { | 
|         get { return m_State; } | 
|         set | 
|         { | 
|             if (m_State != value) | 
|             { | 
|                 m_State = value; | 
|   | 
|                 if (downLoadStateChangeEvent != null) | 
|                 { | 
|                     downLoadStateChangeEvent(m_State); | 
|                 } | 
|             } | 
|         } | 
|     } | 
|   | 
|     public List<Reward> rewards = new List<Reward>(); | 
|     public bool hasReward { get; private set; }//是否有奖励 | 
|     public string completeDownLoadAccount | 
|     { | 
|         get { return LocalSave.GetString("InGameDownLoadCompleteAccount"); } | 
|         set { LocalSave.SetString("InGameDownLoadCompleteAccount", value); } | 
|     } | 
|   | 
|     public Redpoint downLoadRedpoint = new Redpoint(116); | 
|   | 
|     private void Awake() | 
|     { | 
|         DownloadMgr.MaxDownLoadTask = GetMaxTask(); | 
|     } | 
|   | 
|     private void LateUpdate() | 
|     { | 
|         if (state == State.None || state == State.Award || state == State.Completed) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         netCheckTimer += Time.deltaTime; | 
|   | 
|         if (InGameDownTestUtility.enable) | 
|         { | 
|             simulateWifi = InGameDownTestUtility.isWifi; | 
|         } | 
|         else | 
|         { | 
|             if (netCheckTimer > 3f) | 
|             { | 
|                 netCheckTimer = 0f; | 
|                 networkReachability = Application.internetReachability; | 
|             } | 
|         } | 
|   | 
|         if (mapId != 0) | 
|         { | 
|             var progress = GetMapAssetDownLoadProgress(mapId); | 
|             if (progress > 0.9999f) | 
|             { | 
|                 if (mapAssetDownLoadOk != null) | 
|                 { | 
|                     mapAssetDownLoadOk(); | 
|                     mapAssetDownLoadOk = null; | 
|                     mapId = 0; | 
|                 } | 
|             } | 
|         } | 
|   | 
|     } | 
|   | 
|     //开始分配任务 | 
|     public void AssignTasks(List<AssetVersion> assets, Action _onDownLoadOk) | 
|     { | 
|          | 
|         this.inGameDownLoadAllow = false; | 
|         this.assets = assets; | 
|         this.assets.Sort(this.AssetDownLoadPriorCompare);//所有任务根据优先级排序 | 
|         onDownLoadOk = _onDownLoadOk; | 
|   | 
|         totalCount = this.assets.Count; | 
|         okCount = 0; | 
|         totalSize = 0; | 
|   | 
|         DownloadMgr.Instance.Prepare(); | 
|   | 
|         for (int i = 0; i < this.assets.Count; i++) | 
|         { | 
|             var assetVersion = this.assets[i]; | 
|             totalSize += assetVersion.size;//统计资源总大小 | 
|             //统计地图专属的资源 TODO YYL | 
|             // var mapId = PriorBundleConfig.GetAssetBelongToMap(assetVersion.GetAssetCategory(), AssetVersionUtility.DecodeFileName(assetVersion.fileName)); | 
|             // if (mapId != 0) | 
|             // { | 
|             //     if (!mapTasks.ContainsKey(mapId)) | 
|             //     { | 
|             //         mapTasks[mapId] = new List<AssetVersion>(); | 
|             //     } | 
|             //     mapTasks[mapId].Add(assetVersion); | 
|             // } | 
|             //添加下载任务 | 
|             var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), Language.fixPath, "/", assetVersion.relativePath); | 
|             var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath); | 
|             DownloadMgr.Instance.AddTask(new DownloadTask(remoteURL, localURL, assetVersion)); | 
|         } | 
|   | 
|         state = State.None; | 
|   | 
|         PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerLevelChange; | 
|         PlayerDatas.Instance.playerDataRefreshEvent += OnPlayerLevelChange; | 
|     } | 
|   | 
|     //任务根据优先级排序 | 
|     private int AssetDownLoadPriorCompare(AssetVersion lhs, AssetVersion rhs) | 
|     { | 
|         var categoryA = lhs.GetAssetCategory(); | 
|         var categoryB = rhs.GetAssetCategory(); | 
|   | 
|         // TODO YYL | 
|         // var priorA = PriorBundleConfig.GetAssetPrior(categoryA, AssetVersionUtility.DecodeFileName(lhs.fileName)); | 
|         // var priorB = PriorBundleConfig.GetAssetPrior(categoryB, AssetVersionUtility.DecodeFileName(rhs.fileName)); | 
|   | 
|         // if (priorA != priorB) | 
|         // { | 
|         //     return priorA < priorB ? -1 : 1; | 
|         // } | 
|         // else | 
|         { | 
|             var isManifestA = lhs.extersion == ".manifest"; | 
|             var isManifestB = rhs.extersion == ".manifest"; | 
|   | 
|             if (!isManifestA && isManifestB) | 
|             { | 
|                 return -1; | 
|             } | 
|             else if (isManifestA && !isManifestB) | 
|             { | 
|                 return 1; | 
|             } | 
|             else | 
|             { | 
|                 return 0; | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void TryDownLoad(Dominant _dominant) | 
|     { | 
|         if (!inGameDownLoadAllow) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         if (assets == null || assets.Count == 0 || isDone) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         if (_dominant < dominantState) | 
|         { | 
|             return; | 
|         } | 
|   | 
|         switch (_dominant) | 
|         { | 
|             case Dominant.None: | 
|                 if (InGameDownTestUtility.enable) | 
|                 { | 
|                     if (InGameDownTestUtility.isWifi) | 
|                     { | 
|                         StartDownLoad(); | 
|                     } | 
|                 } | 
|                 else | 
|                 { | 
|                     if (Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork) | 
|                     { | 
|                         StartDownLoad(); | 
|                     } | 
|                 } | 
|                 break; | 
|             case Dominant.Half: | 
|                 if (dominantState == Dominant.None) | 
|                 { | 
|                     backGroundDownLoadSizeRecord = DownloadMgr.Instance.DownloadedBytes; | 
|                     downLoadedCountRecord = okCount; | 
|                 } | 
|                 StartDownLoad(); | 
|                 dominantState = Dominant.Half; | 
|                 break; | 
|             case Dominant.Whole: | 
|                 if (dominantState == Dominant.None) | 
|                 { | 
|                     backGroundDownLoadSizeRecord = DownloadMgr.Instance.DownloadedBytes; | 
|                     downLoadedCountRecord = okCount; | 
|                     Pause(); | 
|                     state = State.Prepared; | 
|                 } | 
|                 else if (dominantState == Dominant.Half) | 
|                 { | 
|                     Pause(); | 
|                     state = State.Prepared; | 
|                 } | 
|                 dominantState = Dominant.Whole; | 
|                 UIManager.Instance.OpenWindow<InGameDownLoadWin>(); | 
|                 // // WindowCenter.Instance.Open<InGameDownLoadWin>(); | 
|                 break; | 
|         } | 
|     } | 
|   | 
|     //开始下载 | 
|     public void StartDownLoad() | 
|     { | 
|         if (state == State.None || state == State.Prepared || state == State.Pause) | 
|         { | 
|             state = State.DownLoad; | 
|             DownloadMgr.Instance.Begin(OnFileDownLoadCompleted); | 
|         } | 
|     } | 
|   | 
|     //暂停下载 | 
|     public void Pause() | 
|     { | 
|         if (state == State.DownLoad) | 
|         { | 
|             DownloadMgr.Instance.Stop(); | 
|             state = State.Pause; | 
|         } | 
|     } | 
|   | 
|     //文件下载完成回调 | 
|     private bool OnFileDownLoadCompleted(bool finished, DownloadTask task) | 
|     { | 
|         if (task.IsDone && task.obj is AssetVersion) | 
|         { | 
|             (task.obj as AssetVersion).localValid = true; | 
|             okCount++; | 
|         } | 
|         if (finished) | 
|             OnDownLoadFinished(); | 
|         return true;//返回true表示如果下载失败,不重新排队,立即重试 | 
|     } | 
|   | 
|     //所有任务完成 | 
|     private void OnDownLoadFinished() | 
|     { | 
|         PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerLevelChange; | 
|   | 
|         UIManager.Instance.CloseWindow<InGameDownLoadWin>(); | 
|   | 
|         if (!hasReward) | 
|         { | 
|             if (dominantState == Dominant.None) | 
|             { | 
|                 RequestDownLoadReward(false); | 
|                 state = State.Completed; | 
|             } | 
|             else | 
|             { | 
|                 completeDownLoadAccount = PlayerDatas.Instance.baseData.AccID; | 
|                 state = State.Award; | 
|             } | 
|         } | 
|         else | 
|         { | 
|             state = State.Completed; | 
|         } | 
|   | 
|          | 
|         downLoadRedpoint.state = state == State.Award ? RedPointState.Simple : RedPointState.None; | 
|   | 
|         if (onDownLoadOk != null) | 
|         { | 
|             onDownLoadOk(); | 
|             onDownLoadOk = null; | 
|         } | 
|     } | 
|   | 
|     public void ParseRewardConfig() | 
|     { | 
|         var rewardString = FuncConfigConfig.Get("DownReward").Numerical1; | 
|         var matches = Regex.Matches(rewardString, "(\\d+,\\d+,\\d+)"); | 
|         for (int i = 0; i < matches.Count; i++) | 
|         { | 
|             rewards.Add(new Reward(matches[i].Value)); | 
|         } | 
|     } | 
|   | 
|     public void UpdateRewardInfo(HA319_tagMCPackDownloadRecord _package) | 
|     { | 
|         hasReward = _package.Record == 1; | 
|   | 
|         if (AssetVersionUtility.unPriorAssetDownLoadDone) | 
|         { | 
|             state = !hasReward && completeDownLoadAccount == PlayerDatas.Instance.baseData.AccID ? State.Award : State.Completed; | 
|         } | 
|   | 
|         downLoadRedpoint.state = state == State.Award ? RedPointState.Simple : RedPointState.None; | 
|     } | 
|   | 
|     public void RequestDownLoadReward(bool _manual) | 
|     { | 
|         var send = new CA504_tagCMPlayerGetReward(); | 
|         send.RewardType = 15; | 
|         send.DataEx = (byte)(_manual ? 0 : 1); | 
|         GameNetSystem.Instance.SendInfo(send); | 
|     } | 
|   | 
|     public float GetMapAssetDownLoadProgress(int mapId) | 
|     { | 
|         if (!mapTasks.ContainsKey(mapId)) | 
|         { | 
|             return 1f; | 
|         } | 
|   | 
|         var tasks = mapTasks[mapId]; | 
|         var total = tasks.Count; | 
|         if (total == 0) | 
|         { | 
|             return 1f; | 
|         } | 
|   | 
|         var completeCount = 0; | 
|         foreach (var task in tasks) | 
|         { | 
|             if (task.localValid) | 
|             { | 
|                 completeCount++; | 
|             } | 
|         } | 
|   | 
|         return completeCount / (float)total; | 
|     } | 
|   | 
|     int mapId = 0; | 
|     Action mapAssetDownLoadOk; | 
|     public void RegisterMapAssetDownLoadOk(int mapId, Action callBack) | 
|     { | 
|         var progress = GetMapAssetDownLoadProgress(mapId); | 
|         if (progress < 0.999f) | 
|         { | 
|             this.mapId = mapId; | 
|             mapAssetDownLoadOk = callBack; | 
|         } | 
|     } | 
|   | 
|     public void UnRegisterMapAssetDownLoadOk() | 
|     { | 
|         this.mapId = 0; | 
|         mapAssetDownLoadOk = null; | 
|     } | 
|   | 
|     Clock netSwitchClock; | 
|     NetworkReachability m_NetworkReachability = NetworkReachability.NotReachable; | 
|     NetworkReachability networkReachability | 
|     { | 
|         get { return m_NetworkReachability; } | 
|         set | 
|         { | 
|             if (m_NetworkReachability != value) | 
|             { | 
|                 m_NetworkReachability = value; | 
|   | 
|                 if (dominantState != Dominant.Whole) | 
|                 { | 
|                     switch (m_NetworkReachability) | 
|                     { | 
|                         case NetworkReachability.ReachableViaCarrierDataNetwork: | 
|                             Pause(); | 
|                             var endTime = DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 3); | 
|                             if (netSwitchClock != null) | 
|                             { | 
|                                 Clock.Stop(netSwitchClock); | 
|                             } | 
|   | 
|                             netSwitchClock = Clock.AlarmAt(endTime, () => | 
|                              { | 
|                                  if (CheckDominantDownLoad()) | 
|                                  { | 
|                                      TryDownLoad(Dominant.Whole); | 
|                                  } | 
|                              }); | 
|                             break; | 
|                         case NetworkReachability.ReachableViaLocalAreaNetwork: | 
|                             TryDownLoad(Dominant.None); | 
|                             break; | 
|                         default: | 
|                             break; | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|     } | 
|   | 
|     bool m_SimulateWifi = true; | 
|     public bool simulateWifi | 
|     { | 
|         get { return m_SimulateWifi; } | 
|         set | 
|         { | 
|             if (m_SimulateWifi != value) | 
|             { | 
|                 m_SimulateWifi = value; | 
|   | 
|                 if (dominantState != Dominant.Whole) | 
|                 { | 
|                     if (m_SimulateWifi) | 
|                     { | 
|                         TryDownLoad(Dominant.None); | 
|                     } | 
|                     else | 
|                     { | 
|                         Pause(); | 
|                         var endTime = DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 10); | 
|                         Clock.AlarmAt(endTime, () => | 
|                         { | 
|                             if (CheckDominantDownLoad()) | 
|                             { | 
|                                 TryDownLoad(Dominant.Whole); | 
|                             } | 
|                         }); | 
|                     } | 
|                 } | 
|             } | 
|   | 
|         } | 
|     } | 
|   | 
|     float netCheckTimer = 0f; | 
|   | 
|     public bool CheckDominantDownLoad() | 
|     { | 
|         if (assets == null || assets.Count == 0 || isDone || dominantState == Dominant.Whole /*|| NewBieCenter.Instance.inGuiding*/) | 
|         { | 
|             return false; | 
|         } | 
|   | 
|         if (GeneralDefine.inGameDownLoadLevelCheckPoints == null || GeneralDefine.inGameDownLoadLevelCheckPoints.Count == 0) | 
|         { | 
|             return false; | 
|         } | 
|   | 
|         if (PlayerDatas.Instance.baseData.LV < GeneralDefine.inGameDownLoadLevelCheckPoints[0]) | 
|         { | 
|             return false; | 
|         } | 
|   | 
|         if (PlayerDatas.Instance.baseData.LV < GeneralDefine.inGameDownLoadHighLevel) | 
|         { | 
|             if (InGameDownTestUtility.enable) | 
|             { | 
|                 if (InGameDownTestUtility.isWifi) | 
|                 { | 
|                     return false; | 
|                 } | 
|             } | 
|             else | 
|             { | 
|                 if (Application.internetReachability != NetworkReachability.ReachableViaCarrierDataNetwork) | 
|                 { | 
|                     return false; | 
|                 } | 
|             } | 
|         } | 
|   | 
|   | 
|         if (!UIManager.Instance.IsOpened<MainWin>()) | 
|         { | 
|             return false; | 
|         } | 
|   | 
|         // if (WindowCenter.Instance.ExistAnyFullScreenOrMaskWin()) | 
|         // { | 
|         //     return false; | 
|         // } | 
|   | 
|         return true; | 
|     } | 
|   | 
|     public bool IsHighLevelPlayer() | 
|     { | 
|         if (GeneralDefine.inGameDownLoadLevelCheckPoints == null | 
|             || GeneralDefine.inGameDownLoadLevelCheckPoints.Count == 0) | 
|         { | 
|             return false; | 
|         } | 
|   | 
|         var level = PlayerDatas.Instance.baseData.LV; | 
|         return level > GeneralDefine.inGameDownLoadHighLevel; | 
|     } | 
|   | 
|     //玩家升级 | 
|     private void OnPlayerLevelChange(PlayerDataType refreshType) | 
|     { | 
|         switch (refreshType) | 
|         { | 
|             case PlayerDataType.LV: | 
|                 var level = PlayerDatas.Instance.baseData.LV; | 
|                 var count = GeneralDefine.inGameDownLoadLevelCheckPoints.Count; | 
|                 var lastLevelCheckPoint = GeneralDefine.inGameDownLoadLevelCheckPoints[count - 1]; | 
|                 if (GeneralDefine.inGameDownLoadLevelCheckPoints.Contains(level) || IsHighLevelPlayer()) | 
|                 { | 
|                     if (CheckDominantDownLoad()) | 
|                     { | 
|                         TryDownLoad(Dominant.Whole); | 
|                     } | 
|                 } | 
|                 break; | 
|         } | 
|     } | 
|   | 
|   | 
|     //获取最大下载任务数 | 
|     public int GetMaxTask() | 
|     { | 
|         if (!LoginWin.firstOpenEnd) | 
|             return 20; | 
|   | 
|         if (downLoadGo) | 
|             return 20; | 
|   | 
|         switch (Application.platform) | 
|         { | 
|             case RuntimePlatform.Android: | 
|                 if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.2f * 1024) | 
|                 { | 
|                     return 2; | 
|                 } | 
|                 else | 
|                 { | 
|                     return 1; | 
|                 } | 
|             case RuntimePlatform.IPhonePlayer: | 
|                 if (DeviceUtility.cpu > 1 && DeviceUtility.memory > 1.5f * 1024) | 
|                 { | 
|                     return 2; | 
|                 } | 
|                 else | 
|                 { | 
|                     return 1; | 
|                 } | 
|             case RuntimePlatform.WindowsEditor: | 
|                 return 2; | 
|             default: | 
|                 return 1; | 
|         } | 
|     } | 
|   | 
|     public struct Reward | 
|     { | 
|         public int id; | 
|         public int count; | 
|         public bool bind; | 
|   | 
|         public Reward(string _input) | 
|         { | 
|             var matches = Regex.Matches(_input, "\\d+"); | 
|   | 
|             if (matches.Count > 0) | 
|             { | 
|                 int.TryParse(matches[0].Value, out id); | 
|             } | 
|             else | 
|             { | 
|                 id = 0; | 
|             } | 
|   | 
|             if (matches.Count > 1) | 
|             { | 
|                 int.TryParse(matches[1].Value, out count); | 
|             } | 
|             else | 
|             { | 
|                 count = 0; | 
|             } | 
|   | 
|             if (matches.Count > 2) | 
|             { | 
|                 var temp = 0; | 
|                 int.TryParse(matches[2].Value, out temp); | 
|                 bind = temp == 1; | 
|             } | 
|             else | 
|             { | 
|                 bind = false; | 
|             } | 
|         } | 
|   | 
|     } | 
|   | 
|     public enum State | 
|     { | 
|         None, | 
|         Prepared, | 
|         DownLoad, | 
|         Pause, | 
|         Award, | 
|         Completed, | 
|     } | 
|   | 
|     public enum Dominant | 
|     { | 
|         None = 0, | 
|         Half = 1, | 
|         Whole = 2, | 
|     } | 
|   | 
|     #region 登录下载界面 DownLoadWin | 
|     // 增加下载奖励 根据标识决定多次发放;注意不要与游戏内的完整下载混淆 | 
|     // 后续改成appversion_new增加扩展信息返回下载标识,用于控制当前是否显示奖励,此处首包还未包含图片资源 | 
|   | 
|     public int downloadMark = 0; | 
|   | 
|     public bool IsShowDownloadAward() | 
|     { | 
|         int downloadMark = 0; | 
|         int.TryParse(VersionUtility.Instance.versionInfo.ResourceAward, out downloadMark); | 
|         var mark = LocalSave.GetInt("downloadMark"); | 
|         return downloadMark > mark; | 
|   | 
|     } | 
|   | 
|     //下载完毕成功登录游戏即可设置 | 
|     public void SetDownloadMark() | 
|     { | 
|         LocalSave.SetInt("downloadMark", int.Parse(FuncConfigConfig.Get("DownReward").Numerical4)); | 
|     } | 
|   | 
|     #endregion | 
| } |