GameLoadDll.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Http;
  8. using System.Threading.Tasks;
  9. using hirdParty.DownloadSystem;
  10. using HybridCLR;
  11. using ThirdParty;
  12. using ThirdParty.DownloadSystem;
  13. using UnityEditor;
  14. using UnityEngine;
  15. public class GameLoadDll
  16. {
  17. private bool _isHadNetwork;
  18. private bool _hadEnterGame;
  19. private float _per;
  20. private float _currentProgress;
  21. private bool _isMarkClose;
  22. private readonly Dictionary<string, byte[]> _assetBytes = new Dictionary<string, byte[]>();
  23. string versionName = "versionInfo.txt";
  24. private System.Action callBack;
  25. private AssetMD5Info remoteMD5Info;
  26. private GameStartUIPanel _downloadUI;
  27. private string[] localVersionInfo;
  28. private GameStart gameStart;
  29. public void StartLoadDll(GameStart gameStart, string url, System.Action callBack)
  30. {
  31. this.gameStart = gameStart;
  32. // _downloadUI = HotSyncContent.DownloadUI;
  33. _downloadUI.SetMassge("开始校验脚本");
  34. this.callBack = callBack;
  35. if (HotSyncContent.isOpenHotFix)
  36. {
  37. if (HotSyncContent.isOpenDllStreamingLoad)
  38. {
  39. LoadStreamingDllLoad();
  40. }
  41. else
  42. {
  43. LoadBenDiVersion();
  44. }
  45. }
  46. }
  47. private void LoadStreamingDllLoad()
  48. {
  49. string DllMD5 = HotSyncContent.GetDllWebRequestPath("DllMD5.txt");
  50. DownloadFileData versiondownloadFileData = new DownloadFileData();
  51. versiondownloadFileData.remoteUrl = DllMD5;
  52. DownloadHander downloadHander = FileDownloadSystem.Instance.DownloadFile(versiondownloadFileData);
  53. downloadHander.OnFinishCallBack = delegate(DownloadHander hander)
  54. {
  55. remoteMD5Info =
  56. JsonUtility.FromJson(hander.Text, typeof(AssetMD5Info)) as AssetMD5Info;
  57. LoadLoaclDll();
  58. };
  59. }
  60. private byte[] GetAssetBytes(string dllName)
  61. {
  62. if (_assetBytes.ContainsKey(dllName))
  63. {
  64. return _assetBytes[dllName];
  65. }
  66. else
  67. {
  68. Debug.Log("没有找到dll数据" + dllName);
  69. return new byte[] { };
  70. }
  71. }
  72. // private void LoadVersion()
  73. // {
  74. // string md5Name = "DllMD5.txt";
  75. // string versionInfoUrl = ($"{HotSyncContent.AssetURL}/{HotSyncContent.platform}/{versionName}");
  76. // DownloadFileData versiondownloadFileData = new DownloadFileData();
  77. // versiondownloadFileData.remoteUrl = versionInfoUrl;
  78. // DownloadHander downloadHander = FileDownloadSystem.Instance.DownloadFile(versiondownloadFileData);
  79. // downloadHander.OnFinishCallBack = delegate(DownloadHander hander)
  80. // {
  81. // string[] remoteVersionInfo = hander.Text.Split('\n');
  82. // string versionInfo =
  83. // $"{remoteVersionInfo[0].Split('=')[1]}.{remoteVersionInfo[1].Split('=')[1]}.{remoteVersionInfo[2].Split('=')[1]}";
  84. // HotSyncContent.Currversion = versionInfo;
  85. // if (localVersionInfo[0]!=remoteVersionInfo[0])
  86. // {
  87. // // 本地版本和远程一致也需要更新,防止散文件错误
  88. // Debug.Log("本地版本更大,不需要更新");
  89. // }
  90. // else
  91. // {
  92. // LoadMD5();
  93. // }
  94. // };
  95. // }
  96. private void LoadBenDiVersion()
  97. {
  98. string versionInfoUrl = HotSyncContent.GetWebRequestPath(versionName);
  99. DownloadFileData versiondownloadFileData = new DownloadFileData();
  100. versiondownloadFileData.remoteUrl = versionInfoUrl;
  101. DownloadHander downloadHander = FileDownloadSystem.Instance.DownloadFile(versiondownloadFileData);
  102. downloadHander.OnFinishCallBack = delegate(DownloadHander hander)
  103. {
  104. localVersionInfo = hander.Text.Split('\n');
  105. GetAssetUrl();
  106. };
  107. }
  108. private async void GetAssetUrl()
  109. {
  110. #if UNITY_EDITOR || UNITY_STANDALONE_WIN
  111. string appSettingPath = "file://" + Application.streamingAssetsPath + "/AppSetting.txt";
  112. #elif UNITY_ANDROID
  113. string appSettingPath = Application.streamingAssetsPath + "/AppSetting.txt";
  114. #elif UNITY_IPHONE
  115. string appSettingPath = "file://"+ Application.streamingAssetsPath+"/AppSetting.txt";
  116. #else
  117. string appSettingPath = "";
  118. #endif
  119. WWW loader = new WWW(appSettingPath);
  120. while (!loader.isDone)
  121. {
  122. }
  123. if (!string.IsNullOrEmpty(loader.error))
  124. {
  125. Debug.LogError(appSettingPath);
  126. Debug.LogError(loader.error);
  127. }
  128. string url = "";
  129. string settingData = loader.text;
  130. string[] datas = settingData.Split('\n');
  131. for (int i = 0; i < datas.Length; i++)
  132. {
  133. datas[i] = datas[i].Replace("\r", "");
  134. string[] configInfo = datas[i].Split('=');
  135. if (configInfo[0].Contains("//") || configInfo.Length <= 1)
  136. {
  137. continue;
  138. }
  139. if (configInfo[0].Equals("loginServer"))
  140. {
  141. url = configInfo[1];
  142. }
  143. }
  144. url += "/client_config";
  145. LoadAsset(url, localVersionInfo[0].Split('=')[1]);
  146. }
  147. private async Task LoadAsset(string url, string v)
  148. {
  149. var replace = v.Replace("\r", "");
  150. _downloadUI.SetMassge($"等待服务器地址");
  151. Debug.Log("等待下载资源服地址" + url);
  152. Dictionary<string, string> dictionary = new Dictionary<string, string>();
  153. dictionary.Add("buildVer", replace);
  154. FormUrlEncodedContent formUrlEncodedContent = new FormUrlEncodedContent(dictionary);
  155. HttpClient httpClient = new HttpClient();
  156. httpClient.Timeout = TimeSpan.FromSeconds(5);
  157. string json = "";
  158. try
  159. {
  160. HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(url, formUrlEncodedContent);
  161. if (httpResponseMessage.StatusCode != HttpStatusCode.OK)
  162. {
  163. Debug.LogError(httpResponseMessage.RequestMessage);
  164. _downloadUI.SetMassge($"获取配置错误,正在在重新获取!");
  165. LoadAsset(url, v);
  166. return;
  167. }
  168. json = await httpResponseMessage.Content.ReadAsStringAsync();
  169. }
  170. catch (Exception e)
  171. {
  172. Debug.LogError(e);
  173. LoadAsset(url, v);
  174. return;
  175. }
  176. httpClient.Dispose();
  177. Debug.Log(json);
  178. _downloadUI.SetMassge($"地址获取成功");
  179. // UnityWebRequest webRequest = UnityWebRequest.Post(url, dictionary);
  180. // webRequest.timeout = 5;
  181. // UnityWebRequestAsyncOperation unityWebRequestAsyncOperation = webRequest.SendWebRequest();
  182. // while (!unityWebRequestAsyncOperation.isDone)
  183. // {
  184. // yield return 0;
  185. // }
  186. // if (!string.IsNullOrEmpty(webRequest.error))
  187. // {
  188. // Debug.LogError(webRequest.error);
  189. // _downloadUI.SetMassge($"获取配置错误,正在在重新获取!");
  190. // gameStart.StartCoroutine(LoadAsset(url, v));
  191. // }
  192. // string json = webRequest.downloadHandler.text;
  193. AssetUrlInfo assetUrlInfo = JsonUtility.FromJson<AssetUrlInfo>(json);
  194. HotSyncContent.AssetURL = assetUrlInfo.assetsUrl;
  195. // webRequest.Dispose();
  196. //HotSyncContent.AssetURL = "http://42.192.110.229/010";
  197. HotSyncContent.loadType = assetUrlInfo.loadType;
  198. HotSyncContent.assetsVer = assetUrlInfo.assetsVer;
  199. HotSyncContent.Currversion = $"{assetUrlInfo.apkVer}.{assetUrlInfo.buildVer}.{assetUrlInfo.assetsVer}";
  200. Debug.Log("版本号:" + HotSyncContent.Currversion);
  201. Debug.Log(HotSyncContent.Currversion + "获得的下载资源服地址" + HotSyncContent.AssetURL);
  202. if (localVersionInfo[0].Split('=')[1] != assetUrlInfo.apkVer.ToString())
  203. {
  204. Debug.Log("版本号:" + HotSyncContent.Currversion);
  205. Debug.Log(HotSyncContent.Currversion + "获得的下载资源服地址" + HotSyncContent.AssetURL);
  206. if (localVersionInfo[0].Split('=')[1] != assetUrlInfo.apkVer.ToString())
  207. {
  208. // 本地版本和远程一致也需要更新,防止散文件错误
  209. Debug.LogError("本地版本更大,不需要更新");
  210. }
  211. else
  212. {
  213. LoadMD5();
  214. }
  215. }
  216. else
  217. {
  218. LoadMD5();
  219. }
  220. // LoadVersion();
  221. // Debug.Log(assetUrlInfo.assetsUrl);
  222. }
  223. private void LoadBenDiVersion(string[] remoteVersionInfo)
  224. {
  225. string versionInfoUrl = HotSyncContent.GetWebRequestPath(versionName);
  226. DownloadFileData versiondownloadFileData = new DownloadFileData();
  227. versiondownloadFileData.remoteUrl = versionInfoUrl;
  228. DownloadHander downloadHander = FileDownloadSystem.Instance.DownloadFile(versiondownloadFileData);
  229. downloadHander.OnFinishCallBack = delegate(DownloadHander hander) { };
  230. }
  231. private void LoadMD5()
  232. {
  233. _downloadUI.SetMassge($"资源检查中");
  234. string md5Url =
  235. $"{HotSyncContent.AssetURL}/{HotSyncContent.platform}/{HotSyncContent.Currversion}/DLL/DllMD5.txt";
  236. DownloadFileData versiondownloadFileData = new DownloadFileData();
  237. versiondownloadFileData.remoteUrl = md5Url;
  238. versiondownloadFileData.maxCount = int.MaxValue;
  239. versiondownloadFileData.timeOut = 10;
  240. DownloadHander downloadHander = FileDownloadSystem.Instance.DownloadFile(versiondownloadFileData);
  241. downloadHander.OnFinishCallBack = delegate(DownloadHander hander)
  242. {
  243. remoteMD5Info =
  244. JsonUtility.FromJson(hander.Text, typeof(AssetMD5Info)) as AssetMD5Info;
  245. if (HotSyncContent.loadType == 1)
  246. {
  247. LoadLoaclDll();
  248. }
  249. else
  250. {
  251. JianYan();
  252. }
  253. };
  254. }
  255. private void JianYan()
  256. {
  257. List<MD5FileInfo> CheckFile = new List<MD5FileInfo>();
  258. CheckFile.AddRange(remoteMD5Info.fileInfo);
  259. string rootPath = HotSyncContent.AppHotfixResPath;
  260. CheckFilePool _checkFileThrans = new CheckFilePool();
  261. _checkFileThrans.isStreamingAssetsPath = true;
  262. _checkFileThrans.streamingAssetsPath = HotSyncContent.RootStreamingURL + "/Dll/";
  263. SliderData sliderData = new SliderData();
  264. sliderData.maxValue = CheckFile.Count;
  265. _downloadUI.SetMassge($"校验本地文件");
  266. sliderData.CcurrValue = delegate
  267. {
  268. float m = _checkFileThrans.FileCount();
  269. if (_checkFileThrans.isFinish)
  270. {
  271. // _downloadUI.ClearSlider();
  272. if (_checkFileThrans.shiBaiFile != null && _checkFileThrans.shiBaiFile.Count > 0)
  273. {
  274. DownJiaoBen(_checkFileThrans.shiBaiFile);
  275. }
  276. else
  277. {
  278. LoadLoaclDll();
  279. }
  280. }
  281. else
  282. {
  283. _downloadUI.SetMassge(
  284. $"校验本地文件{m} / {sliderData.maxValue}");
  285. }
  286. return m;
  287. };
  288. // _downloadUI.SetSlider(sliderData);
  289. _checkFileThrans.Start(rootPath, CheckFile);
  290. }
  291. private void DownJiaoBen(List<MD5FileInfo> updateFlieInfo)
  292. {
  293. DownLoadHanderGroup downLoadHanderGroup = new DownLoadHanderGroup();
  294. long size = 0;
  295. for (int i = 0; i < updateFlieInfo.Count; i++)
  296. {
  297. MD5FileInfo md5FileInfo = updateFlieInfo[i];
  298. if (md5FileInfo.size <= 0)
  299. {
  300. continue;
  301. }
  302. DownloadFileData downloadFileData = new DownloadFileData();
  303. size += md5FileInfo.size;
  304. downloadFileData.remoteUrl =
  305. $"{HotSyncContent.AssetURL}/{HotSyncContent.platform}/{HotSyncContent.Currversion}/DLL/{md5FileInfo.fileName}";
  306. Debug.Log("下载文件" + downloadFileData.remoteUrl);
  307. downloadFileData.localPath = Path.Combine(HotSyncContent.AppHotfixResPath, md5FileInfo.fileName);
  308. DownloadHander fileDow = FileDownloadSystem.Instance.DownloadFile(downloadFileData);
  309. downLoadHanderGroup.AddHander(fileDow);
  310. }
  311. float sizeM = size / 1024f / 1024f;
  312. SliderData sliderData = new SliderData();
  313. sliderData.maxValue = size;
  314. _downloadUI.SetMassge($"开始下载文件,个数{updateFlieInfo.Count} 大小{sizeM}");
  315. sliderData.CcurrValue = delegate
  316. {
  317. float m = downLoadHanderGroup.size / 1024f / 1024f;
  318. float speed = downLoadHanderGroup.speed / 1024f;
  319. _downloadUI.SetMassge(
  320. $"开始下载文件,个数{updateFlieInfo.Count} 大小{m.ToString("0.00")}M / {sizeM.ToString("0.00")}M 速度{speed.ToString(".00")} Kb");
  321. return downLoadHanderGroup.size;
  322. };
  323. // _downloadUI.SetSlider(sliderData);
  324. downLoadHanderGroup.OnCallBack = JianYan;
  325. downLoadHanderGroup.StartUpdate();
  326. }
  327. private void LoadLoaclDll()
  328. {
  329. DownLoadHanderGroup downLoadHanderGroup = new DownLoadHanderGroup();
  330. for (int i = 0; i < remoteMD5Info.fileInfo.Count; i++)
  331. {
  332. MD5FileInfo md5FileInfo = remoteMD5Info.fileInfo[i];
  333. DownloadFileData downloadFileData = new DownloadFileData();
  334. downloadFileData.remoteUrl = HotSyncContent.GetDllWebRequestPath(md5FileInfo.fileName);
  335. Debug.Log("下载文件" + downloadFileData.remoteUrl);
  336. DownloadHander fileDow = FileDownloadSystem.Instance.DownloadFile(downloadFileData);
  337. fileDow.OnFinishCallBack = delegate(DownloadHander hander)
  338. {
  339. byte[] dllBytes = hander.Data;
  340. // dllBytes = DllTool.Instance.KeyDecryption(dllBytes);
  341. _assetBytes[md5FileInfo.fileName] = dllBytes;
  342. Debug.Log($"资源:{md5FileInfo.fileName} 大小:{dllBytes.Length}");
  343. HomologousImageMode mode = HomologousImageMode.SuperSet;
  344. // 加载Assembly对应的Dll,会自动为它hook。一旦AOT泛型函数的Native函数不存在,用解释器版本代码
  345. LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode);
  346. Debug.Log($"LoadMetadataForAOTAssembly:{md5FileInfo.fileName}. mode:{mode} ret:{err}");
  347. };
  348. downLoadHanderGroup.AddHander(fileDow);
  349. }
  350. downLoadHanderGroup.OnCallBack = LoadDll;
  351. downLoadHanderGroup.StartUpdate();
  352. }
  353. private void LoadDll()
  354. {
  355. _downloadUI.SetMassge($"初始化资源中,请稍等");
  356. Debug.Log("开始Fort23.Proto");
  357. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.Proto.dll.bytes"));
  358. // Debug.Log("开始FMODUnity");
  359. // System.Reflection.Assembly.Load(GetAssetBytes("FMODUnity.dll.bytes"));
  360. // Debug.Log("开始FMODUnityResonance");
  361. // System.Reflection.Assembly.Load(GetAssetBytes("FMODUnityResonance.dll.bytes"));
  362. Debug.Log("开始Fort23.Core");
  363. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.Core.dll.bytes"));
  364. Debug.Log("开始BGMController");
  365. System.Reflection.Assembly.Load(GetAssetBytes("BGMController.dll.bytes"));
  366. Debug.Log("开始Fort23.GameData");
  367. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.GameData.dll.bytes"));
  368. Debug.Log("开始spine-unity");
  369. System.Reflection.Assembly.Load(GetAssetBytes("spine-unity.dll.bytes"));
  370. Debug.Log("开始spine-timeline");
  371. System.Reflection.Assembly.Load(GetAssetBytes("spine-timeline.dll.bytes"));
  372. Debug.Log("开始Fort23.CombatCore");
  373. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.CombatCore.dll.bytes"));
  374. Debug.Log("开始Fort23.UTool");
  375. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.UTool.dll.bytes"));
  376. Debug.Log("开始Fort23.Combat");
  377. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.Combat.dll.bytes"));
  378. Debug.Log("开始Fort23.Mono");
  379. System.Reflection.Assembly.Load(GetAssetBytes("Fort23.Mono.dll.bytes"));
  380. // Debug.Log("spine-unity");
  381. // System.Reflection.Assembly.Load(GetAssetBytes("spine-unity.dll"));
  382. // Debug.Log("spine-timeline");
  383. // System.Reflection.Assembly.Load(GetAssetBytes("spine-timeline.dll"));
  384. Debug.Log("开始Assembly-CSharp");
  385. System.Reflection.Assembly.Load(GetAssetBytes("Assembly-CSharp.dll.bytes"));
  386. AppDomain.CurrentDomain.GetAssemblies()
  387. .First(assembly => assembly.GetName().Name == "Assembly-CSharp");
  388. Debug.Log("Assembly-CSharp.dll加载成功");
  389. // 2. 开始执行热更新代码逻辑,加载Init进入游戏流程
  390. Debug.Log("开始加载进入游戏");
  391. string path = Application.persistentDataPath + "/Bundle/init";
  392. if (!File.Exists(path))
  393. {
  394. path = Application.streamingAssetsPath + "/Bundle/init";
  395. }
  396. Debug.Log("path=" + path);
  397. // string[] assemblyNames =
  398. // {
  399. // "Fort23.Core.dll", "Fort23.MonoCore.dll", "Fort23.Mono.dll", "Fort23.Model.dll",
  400. // "Fort23.CommonCore.dll", "Fort23.Common.dll", "Assembly-CSharp.dll", "Fort23.UTool.dll",
  401. // "Fort23.GameData.dll", "spine-unity.dll", "spine-timeline.dll", "BGMController.dll", "Fort23.Combat.dll",
  402. // "Fort23.CombatCore.dll"
  403. // };
  404. // int addCount = 0;
  405. // foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
  406. // {
  407. // string assemblyName = $"{assembly.GetName().Name}.dll";
  408. // if (!((IList) assemblyNames).Contains(assemblyName))
  409. // {
  410. // continue;
  411. // }
  412. // Debug.Log(assemblyName);
  413. // foreach (var type in assembly.GetTypes())
  414. // {
  415. //
  416. // if ((typeof(MonoBehaviour).IsAssignableFrom(type)))
  417. // {
  418. // Debug.Log(type.Name);
  419. // var go = new GameObject();
  420. // // 我们不希望挂载到这个GameObject上的脚本执行
  421. // go.SetActive(false);
  422. // go.AddComponent(type);
  423. // GameObject.Destroy(go);
  424. // addCount++;
  425. // }
  426. // }
  427. //
  428. // }
  429. callBack?.Invoke();
  430. }
  431. }