GameLoadDll.cs 20 KB

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