using System.Collections; using System.Collections.Generic; using System.IO; using taurus.client; using taurus.unity; using UnityEngine; using UnityEngine.Networking; public class Version { int _max_version = -1; int _min_version = -1; int _pack_version = -1; string _version = "0.0.0"; public static readonly Version DEFUALT = new Version("1.0.0"); public Version(string version) { var tem = ReadVersionArray(version); if (tem != null) { _version = version; _max_version = tem[0]; _min_version = tem[1]; _pack_version = tem[2]; } } public void FillData(Version version) { this.max_version = version.max_version; this.min_version = version.min_version; this.pack_version = version.pack_version; this._version = version._version; } public bool ContainAll(Version version) { if (_max_version != version._max_version || _min_version != version._min_version || _pack_version != version._pack_version) { return true; } return false; } public int max_version { get { return _max_version; } set { if (_max_version != value) { _max_version = value; _version = string.Format("{0}.{1}.{2}", _max_version, _min_version, _pack_version); } } } public int min_version { get { return _min_version; } set { if (_min_version != value) { _min_version = value; _version = string.Format("{0}.{1}.{2}", _max_version, _min_version, _pack_version); } } } public int pack_version { get { return _pack_version; } set { if (_pack_version != value) { _pack_version = value; _version = string.Format("{0}.{1}.{2}", _max_version, _min_version, _pack_version); } } } public override string ToString() { return _version; } public static int ReadVersion(string text, int index = 2) { try { var tem = text.Split(new char[] { '.' }); return int.Parse(tem[index]); } catch { return -1; } } public static int[] ReadVersionArray(string text) { if (string.IsNullOrEmpty(text)) return null; try { var tem_arr = text.Split(new char[] { '.' }); if (tem_arr == null || tem_arr.Length != 3) { return null; } int[] tem = new int[tem_arr.Length]; for (int i = 0; i < tem_arr.Length; ++i) { tem[i] = int.Parse(tem_arr[i]); } return tem; } catch { return null; } } } public class Hotupdate { const int LOCAL_PACK = 1; const int SERVER_PACK = 2; [LuaInterface.NoToLua] /// /// 热更新资源包下载地址 /// public static string PackUrl = string.Empty; static Dictionary localVersionMap = new Dictionary(); string _base_path; Version _server_version; Version _local_version; int _with_pack; float _stage; public bool isBuild32lua=false; public Hotupdate(string base_path, string local_version, string server_version): this(base_path,new Version(local_version),new Version(server_version)) { } public Hotupdate(string base_path, Version local_version, Version server_version) { _base_path = base_path; _server_version = server_version; _local_version = local_version; _with_pack = GameApplication.HideSdk ? LOCAL_PACK : SERVER_PACK; // #if !NOT_WITH_PACK // _with_pack = LOCAL_PACK; // #endif TextTip = "正在检查资源。。。"; HideDetail = false; } void __DeleteOldPack() { string dir = ResourcesManager.PACK_PATH + _base_path; if (Directory.Exists(dir)) Directory.Delete(dir, true); } public static Version GetLocalVersion(string _base_path) { string dir = ResourcesManager.PACK_PATH + _base_path; string rv = dir + "version.txt"; Version local_version1 = null; if (localVersionMap.ContainsKey(rv)) { local_version1 = localVersionMap[rv]; } else if (File.Exists(rv)) { try { local_version1 = new Version(File.ReadAllText(rv)); localVersionMap[rv] = local_version1; } catch { return local_version1; } } return local_version1; } public void LoadAsset() { /* Done = true; Progress = 1; return;*/ GameApplication.Instance.StartCoroutine(__LoadAsset()); } IEnumerator __LoadAsset() { bool _decompression = true; string dir = ResourcesManager.PACK_PATH + _base_path; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); string rv = dir + "version.txt"; Version local_version1 = GetLocalVersion(_base_path); if (local_version1!=null) { _local_version = local_version1; _decompression = _local_version.ContainAll(_server_version); } //如果没有发现本地文件,解压APP包 if ((_with_pack& LOCAL_PACK)!=0&& _decompression) { var path = Application.streamingAssetsPath + string.Format("/{0}/{1}asset_pack{2}.bytes", ResourcesManager.OS_Dir, _base_path,_server_version.ToString()); #if !UNITY_EDITOR && UNITY_ANDROID var www = new WWW(path); yield return www; var data = www.bytes; www.Dispose(); www = null; #else var data = File.ReadAllBytes(path); #endif var zip_path = ResourcesManager.PACK_PATH + "asset_pack.bytes"; File.WriteAllBytes(zip_path, data); data = null; System.GC.Collect(); var finsh = false; var tem_state = 0; VerCheck.Instance.StartCoroutine(__UnPack(_server_version, (state) => { tem_state = state; finsh = state == 0; },0.3f)); while (!finsh) { if (tem_state > 10) { if (__ShowTip("解压资源包时出问题,请重新下载客户端!", () => { __DeleteOldPack(); Application.Quit(); })) { __DeleteOldPack(); Application.Quit(); } yield break; } yield return null; } local_version1 = _local_version; _stage = 0.3f; } if((_with_pack & SERVER_PACK) != 0) { var update_pack2 = local_version1==null || local_version1.ContainAll(_server_version); if (update_pack2) { if (HideDetail) { TextTip = string.Format ("正在下载资源包。", "游戏公共基础"); //TextTip = string.Format("正在下载{0}更新包。。",AssetName); } else { TextTip = string.Format("正在下载资源包。"); } var down = false; var _ratio = 1 - _stage; VerCheck.Instance.StartCoroutine(DownAsset(() => { down = true; }, _server_version, _ratio * 0.6f)); while (!down) { yield return null; } var finsh = false; var tem_state = 0; _stage = 0.7f; VerCheck.Instance.StartCoroutine(__UnPack(_server_version, (state) => { tem_state = state; finsh = state == 0; }, _ratio * 0.4f)); while (!finsh) { if (tem_state > 10) { if(!__ShowTip("解压资源包时出问题,请重新下载客户端!", () => { __DeleteOldPack(); Application.Quit(); })) { __DeleteOldPack(); Application.Quit(); } yield break; } yield return null; } } } Done = true; Progress = 1; } public void LoadAssetSize() { GameApplication.Instance.StartCoroutine(__LoadAssetSize()); } IEnumerator __LoadAssetSize() { Size = 0; bool _decompression = true; string dir = ResourcesManager.PACK_PATH + _base_path; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); string rv = dir + "version.txt"; Version local_version1 = GetLocalVersion(_base_path); if (local_version1 != null) { _local_version = local_version1; _decompression = _local_version.ContainAll(_server_version); } //如果没有发现本地文件,解压APP包 if ((_with_pack & LOCAL_PACK) != 0 && _decompression) { var path = Application.streamingAssetsPath + string.Format("/{0}/{1}asset_pack{2}.bytes", ResourcesManager.OS_Dir, _base_path, _server_version.ToString()); #if !UNITY_EDITOR && UNITY_ANDROID var www = new WWW(path); yield return www; var data = www.bytes; www.Dispose(); www = null; #else var data = File.ReadAllBytes(path); #endif var zip_path = ResourcesManager.PACK_PATH + "asset_pack.bytes"; File.WriteAllBytes(zip_path, data); data = null; System.GC.Collect(); var finsh = false; var tem_state = 0; VerCheck.Instance.StartCoroutine(__UnPack(_server_version, (state) => { tem_state = state; finsh = state == 0; }, 0.3f)); while (!finsh) { if (tem_state > 10) { if (__ShowTip("解压资源包时出问题,请重新下载客户端!", () => { __DeleteOldPack(); Application.Quit(); })) { __DeleteOldPack(); Application.Quit(); } yield break; } yield return null; } local_version1 = _local_version; _stage = 0.3f; } if ((_with_pack & SERVER_PACK) != 0) { var update_pack2 = local_version1 == null || local_version1.ContainAll(_server_version); if (update_pack2) { var down = false; var _ratio = 1 - _stage; VerCheck.Instance.StartCoroutine(GetAssetSize((size) => { Size = size; down = true; }, _server_version)); while (!down) { yield return null; } } } Done = true; Progress = 1; } IEnumerator __UnPack(Version version,System.Action onback, float ratio) { TextTip = "正在解压资源包不消耗流量,请耐心等待"; string dir = ResourcesManager.PACK_PATH; var zip_path = dir + "asset_pack.bytes"; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); IFilePack zip = null; zip = new FilePack20(zip_path,PackMode.Read); zip.UnPackFileSyn(dir); while (!zip.Complete) { Progress = _stage + zip.Progress* ratio; yield return null; } File.Delete(zip_path); if (!string.IsNullOrEmpty(zip.Error)) { onback(11); yield break; } var lua_pack_path = dir + "lua_pack"; if (File.Exists(lua_pack_path)) { var lua_dir = dir + "lua/"; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); zip = new FilePack20(lua_pack_path, PackMode.Read); zip.UnPackFile(lua_dir); File.Delete(lua_pack_path); if (!string.IsNullOrEmpty(zip.Error)) { onback(11); yield break; } } string rv = ResourcesManager.PACK_PATH + _base_path + "version.txt"; File.WriteAllText(rv, version.ToString(), System.Text.Encoding.ASCII); localVersionMap[rv] = version; if (onback != null) { Progress = _stage + 1 * ratio; onback(0); } } IEnumerator DownAsset(System.Action downcall,Version version,float ratio) { var pack_path = string.Format("{0}asset_pack{1}.bytes", _base_path, version.ToString()); string osPath = ResourcesManager.OS_Dir; #if UNITY_ANDROID && !UNITY_EDITOR if (GameApplication.Instance.isAndroid64bit == false) { //if (isBuild32lua) //{ // osPath=osPath+"32"; //} osPath=osPath+"32"; } #endif var url =""; if(VerCheck.Instance.isGFF==false && VerCheck.Instance.isDXYGFF == false) url = string.Format("{0}/{1}/{2}", PackUrl, osPath, pack_path); else url = string.Format("{0}/{1}/{2}", "http://" + VerCheck.Instance.conn.ip + ":" + VerCheck.Instance.conn.port + "/NewFK", osPath, pack_path); url = string.Format("{0}/{1}/{2}", PackUrl, osPath, pack_path); if (Application.platform == RuntimePlatform.WindowsEditor) Debug.Log("url:" + url); var request = new WWW(url); while (!request.isDone) { Progress = _stage + request.progress * ratio; yield return null; } if (string.IsNullOrEmpty(request.error)) { var zip_path = ResourcesManager.PACK_PATH + "asset_pack.bytes"; File.WriteAllBytes(zip_path, request.bytes); if (downcall != null) downcall(); } else { if (!__ShowTip("资源包下载失败,请检查您的网络设置!", () => { VerCheck.Instance.StartCoroutine(DownAsset(downcall, version, ratio)); })) { Application.Quit(); } } } IEnumerator GetAssetSize(System.Action downcall, Version version) { var pack_path = string.Format("{0}asset_pack{1}.bytes", _base_path, version.ToString()); string osPath = ResourcesManager.OS_Dir; #if UNITY_ANDROID && !UNITY_EDITOR if (GameApplication.Instance.isAndroid64bit == false) { //if (isBuild32lua) //{ // osPath=osPath+"32"; //} osPath=osPath+"32"; } #endif var url = ""; if (VerCheck.Instance.isGFF == false && VerCheck.Instance.isDXYGFF == false) url = string.Format("{0}/{1}/{2}", Hotupdate.PackUrl, osPath, pack_path); else url = string.Format("{0}/{1}/{2}", "http://" + VerCheck.Instance.conn.ip + ":" + VerCheck.Instance.conn.port + "/NewFK", osPath, pack_path); url = string.Format("{0}/{1}/{2}", Hotupdate.PackUrl, osPath, pack_path); if (Application.platform == RuntimePlatform.WindowsEditor) Debug.Log("check_url:" + url); using (UnityWebRequest get = UnityWebRequest.Get(url)) { get.downloadHandler = new DownloadHandlerBuffer(); // 不下载内容也可以 yield return get.SendWebRequest(); #if UNITY_2020_2_OR_NEWER if (get.result == UnityWebRequest.Result.Success) #else if (!get.isNetworkError && !get.isHttpError) #endif { long size = (long)get.downloadedBytes; if (downcall != null) downcall(size); } else { Debug.LogError($"获取文件大小失败(GET): {get.error}"); yield return 0L; } } } bool __ShowTip(string text,System.Action callback) { if (this._tip_callback != null) { this._tip_callback(text, callback); return true; } return false; } public void SetTipCallback(System.Action callback) { this._tip_callback = callback; } public string TextTip { get; set; } public string AssetName { get; set; } public bool HideDetail { get; set; } private System.Action _tip_callback; public float Progress { get;set; } public bool Done { get;set; } public float Size { get; set; } }