using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Text.RegularExpressions; public class InGameDownLoad : SingletonMonobehaviour { public const int BYTE_PER_KILOBYTE = 1024;//b 转 kb public const int BYTE_PER_MILLIONBYTE = 1048576;//b 转 mb List assets = new List(); //所有资源 Dictionary> mapTasks = new Dictionary>();//地图专属的资源 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 downLoadStateChangeEvent; public event Action 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 rewards = new List(); 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 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(); // } // 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(); // // WindowCenter.Instance.Open(); 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(); 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()) { 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 }