GameLoadDll.cs 19 KB

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