ToLuaInjection.cs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. #if ENABLE_LUA_INJECTION
  2. using System;
  3. using System.IO;
  4. using System.Xml;
  5. using System.Text;
  6. using System.Linq;
  7. using UnityEngine;
  8. using UnityEditor;
  9. using Mono.Cecil;
  10. using Mono.Cecil.Cil;
  11. using Unity.CecilTools;
  12. using Unity.CecilTools.Extensions;
  13. using CustomCecilRocks;
  14. using System.Reflection;
  15. using LuaInterface;
  16. using UnityEditor.Callbacks;
  17. using System.Collections.Generic;
  18. using MethodBody = Mono.Cecil.Cil.MethodBody;
  19. class InjectedMethodInfo
  20. {
  21. public string methodFullSignature;
  22. public string methodOverloadSignature;
  23. public string methodPublishedName;
  24. public string methodName;
  25. public int methodIndex;
  26. }
  27. [InitializeOnLoad]
  28. public static class ToLuaInjection
  29. {
  30. static int offset = 0;
  31. static int methodCounter = 0;
  32. static bool EnableSymbols = true;
  33. static Instruction cursor;
  34. static VariableDefinition flagDef;
  35. static VariableDefinition funcDef;
  36. static TypeReference intTypeRef;
  37. static TypeReference injectFlagTypeRef;
  38. static TypeReference noToLuaAttrTypeRef;
  39. static TypeDefinition injectStationTypeDef;
  40. static TypeDefinition luaFunctionTypeDef;
  41. static TypeDefinition luaTableTypeDef;
  42. static MethodReference injectFlagGetter;
  43. static MethodReference injectedFuncGetter;
  44. static HashSet<string> dropTypeGroup = new HashSet<string>();
  45. static HashSet<string> injectableTypeGroup = new HashSet<string>();
  46. static Dictionary<MethodDefinition, VariableDefinition> resultTableGroup = new Dictionary<MethodDefinition, VariableDefinition>();
  47. static SortedDictionary<string, List<InjectedMethodInfo>> bridgeInfo = new SortedDictionary<string, List<InjectedMethodInfo>>();
  48. static OpCode[] ldargs = new OpCode[] { OpCodes.Ldarg_0, OpCodes.Ldarg_1, OpCodes.Ldarg_2, OpCodes.Ldarg_3 };
  49. static OpCode[] ldcI4s = new OpCode[] { OpCodes.Ldc_I4_1, OpCodes.Ldc_I4_2, OpCodes.Ldc_I4_4, OpCodes.Ldc_I4_8 };
  50. const string assemblyPath = "./Library/ScriptAssemblies/Assembly-CSharp.dll";
  51. const InjectType injectType = InjectType.After | InjectType.Before | InjectType.Replace | InjectType.ReplaceWithPreInvokeBase | InjectType.ReplaceWithPostInvokeBase;
  52. const InjectFilter injectIgnoring = InjectFilter.IgnoreGeneric | InjectFilter.IgnoreConstructor;// | InjectFilter.IgnoreNoToLuaAttr | InjectFilter.IgnoreProperty;
  53. static HashSet<string> dropGenericNameGroup = new HashSet<string>
  54. {
  55. };
  56. static HashSet<string> dropNamespaceGroup = new HashSet<string>
  57. {
  58. "LuaInterface",
  59. };
  60. static HashSet<string> forceInjectTypeGroup = new HashSet<string>
  61. {
  62. };
  63. static ToLuaInjection()
  64. {
  65. LoadAndCheckAssembly(true);
  66. InjectAll();
  67. }
  68. static void InjectAll()
  69. {
  70. var injectionStatus = EditorPrefs.GetInt(Application.dataPath + "WaitForInjection", 0);
  71. if (Application.isPlaying || EditorApplication.isCompiling || injectionStatus == 0)
  72. {
  73. return;
  74. }
  75. bool bInjectInterupted = !LoadBlackList() || ToLuaMenu.UpdateMonoCecil(ref EnableSymbols) != 0 || !LoadBridgeEditorInfo();
  76. if (!bInjectInterupted)
  77. {
  78. CacheInjectableTypeGroup();
  79. Inject();
  80. AssetDatabase.Refresh();
  81. }
  82. }
  83. [PostProcessBuildAttribute()]
  84. static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
  85. {
  86. var injectionStatus = EditorPrefs.GetInt(Application.dataPath + "WaitForInjection", 0);
  87. if (injectionStatus == 0)
  88. {
  89. Debug.LogError("Inject Failed!!!");
  90. }
  91. EditorPrefs.SetInt(Application.dataPath + "WaitForInjection", 0);
  92. }
  93. [PostProcessScene]
  94. static void OnPostProcessScene()
  95. {
  96. if (BuildPipeline.isBuildingPlayer)
  97. {
  98. EditorPrefs.SetInt(Application.dataPath + "WaitForInjection", 1);
  99. }
  100. InjectAll();
  101. }
  102. [DidReloadScripts]
  103. static void OnDidReloadScripts()
  104. {
  105. if (!BuildPipeline.isBuildingPlayer)
  106. {
  107. EditorPrefs.SetInt(Application.dataPath + "WaitForInjection", 0);
  108. }
  109. }
  110. [MenuItem("Lua/Inject All &i", false, 5)]
  111. static void InjectByMenu()
  112. {
  113. if (Application.isPlaying)
  114. {
  115. EditorUtility.DisplayDialog("警告", "游戏运行过程中无法操作", "确定");
  116. return;
  117. }
  118. EditorPrefs.SetInt(Application.dataPath + "WaitForInjection", 1);
  119. if (EditorApplication.isCompiling)
  120. {
  121. EditorUtility.DisplayDialog("警告", "请等待编辑器编译完成", "确定");
  122. return;
  123. }
  124. InjectAll();
  125. }
  126. static AssemblyDefinition LoadAndCheckAssembly(bool bPulse)
  127. {
  128. var assemblyReader = new ReaderParameters
  129. {
  130. ReadSymbols = EnableSymbols,
  131. AssemblyResolver = GetAssemblyResolver()
  132. };
  133. AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyPath, assemblyReader);
  134. var alreadyInjected = assembly.CustomAttributes.Any((attr) =>
  135. {
  136. return attr.AttributeType.FullName == "LuaInterface.UseDefinedAttribute";
  137. });
  138. EditorPrefs.SetInt(Application.dataPath + "InjectStatus", alreadyInjected ? 1 : 0);
  139. if (bPulse)
  140. {
  141. Clean(assembly);
  142. }
  143. return assembly;
  144. }
  145. static void Inject()
  146. {
  147. AssemblyDefinition assembly = null;
  148. try
  149. {
  150. assembly = LoadAndCheckAssembly(false);
  151. if (InjectPrepare(assembly))
  152. {
  153. foreach (var module in assembly.Modules)
  154. {
  155. int cursor = 0;
  156. int typesCount = module.Types.Count;
  157. foreach (var type in module.Types)
  158. {
  159. ++cursor;
  160. EditorUtility.DisplayProgressBar("Injecting:" + module.FullyQualifiedName, type.FullName, (float)cursor / typesCount);
  161. if (!InjectProcess(assembly, type))
  162. {
  163. EditorUtility.ClearProgressBar();
  164. return;
  165. }
  166. }
  167. }
  168. EditorUtility.ClearProgressBar();
  169. UpdateInjectionCacheSize();
  170. ExportInjectionBridgeInfo();
  171. WriteInjectedAssembly(assembly, assemblyPath);
  172. resultTableGroup.Clear();
  173. EditorApplication.Beep();
  174. Debug.Log("Lua Injection Finished!");
  175. EditorPrefs.SetInt(Application.dataPath + "InjectStatus", 1);
  176. }
  177. }
  178. catch (Exception e)
  179. {
  180. Debug.LogError(e.ToString());
  181. }
  182. finally
  183. {
  184. if (assembly != null)
  185. {
  186. Clean(assembly);
  187. }
  188. }
  189. }
  190. static bool InjectPrepare(AssemblyDefinition assembly)
  191. {
  192. bool alreadyInjected = EditorPrefs.GetInt(Application.dataPath + "InjectStatus") == 1;
  193. if (alreadyInjected)
  194. {
  195. Debug.Log("Already Injected!");
  196. return false;
  197. }
  198. resultTableGroup.Clear();
  199. var injectAttrType = assembly.MainModule.Types.Single(type => type.FullName == "LuaInterface.UseDefinedAttribute");
  200. var attrCtorInfo = injectAttrType.Methods.Single(method => method.IsConstructor);
  201. assembly.CustomAttributes.Add(new CustomAttribute(attrCtorInfo));
  202. intTypeRef = assembly.MainModule.TypeSystem.Int32;
  203. injectFlagTypeRef = assembly.MainModule.TypeSystem.Byte;
  204. noToLuaAttrTypeRef = assembly.MainModule.Types.Single(type => type.FullName == "LuaInterface.NoToLuaAttribute");
  205. injectStationTypeDef = assembly.MainModule.Types.Single(type => type.FullName == "LuaInterface.LuaInjectionStation");
  206. luaFunctionTypeDef = assembly.MainModule.Types.Single(method => method.FullName == "LuaInterface.LuaFunction");
  207. luaTableTypeDef = assembly.MainModule.Types.Single(method => method.FullName == "LuaInterface.LuaTable");
  208. injectFlagGetter = injectStationTypeDef.Methods.Single(method => method.Name == "GetInjectFlag");
  209. injectedFuncGetter = injectStationTypeDef.Methods.Single(method => method.Name == "GetInjectionFunction");
  210. return true;
  211. }
  212. static BaseAssemblyResolver GetAssemblyResolver()
  213. {
  214. DefaultAssemblyResolver resolver = new DefaultAssemblyResolver();
  215. AppDomain.CurrentDomain
  216. .GetAssemblies()
  217. .Select(assem => Path.GetDirectoryName(assem.ManifestModule.FullyQualifiedName))
  218. .Distinct()
  219. .Foreach(dir => resolver.AddSearchDirectory(dir));
  220. return resolver;
  221. }
  222. static bool InjectProcess(AssemblyDefinition assembly, TypeDefinition type)
  223. {
  224. if (!DoesTypeInjectable(type))
  225. {
  226. return true;
  227. }
  228. foreach (var nestedType in type.NestedTypes)
  229. {
  230. if (!InjectProcess(assembly, nestedType))
  231. {
  232. return false;
  233. }
  234. }
  235. foreach (var target in type.Methods)
  236. {
  237. if (target.IsGenericMethodDefinition())
  238. {
  239. continue;
  240. }
  241. if (!DoesMethodInjectable(target))
  242. {
  243. continue;
  244. }
  245. int methodIndex = AppendMethod(target);
  246. if (methodIndex == -1)
  247. {
  248. return false;
  249. }
  250. if (target.IsEnumerator())
  251. {
  252. InjectCoroutine(assembly, target, methodIndex);
  253. }
  254. else
  255. {
  256. InjectMethod(assembly, target, methodIndex);
  257. }
  258. }
  259. return true;
  260. }
  261. static void FillBegin(MethodDefinition target, int methodIndex)
  262. {
  263. MethodBody targetBody = target.Body;
  264. ILProcessor il = targetBody.GetILProcessor();
  265. targetBody.InitLocals = true;
  266. flagDef = new VariableDefinition(injectFlagTypeRef);
  267. funcDef = new VariableDefinition(luaFunctionTypeDef);
  268. targetBody.Variables.Add(flagDef);
  269. targetBody.Variables.Add(funcDef);
  270. Instruction startInsertPos = targetBody.Instructions[0];
  271. il.InsertBefore(startInsertPos, il.Create(OpCodes.Ldc_I4, methodIndex));
  272. il.InsertBefore(startInsertPos, il.Create(OpCodes.Call, injectFlagGetter));
  273. il.InsertBefore(startInsertPos, il.Create(OpCodes.Stloc, flagDef));
  274. il.InsertBefore(startInsertPos, il.Create(OpCodes.Ldloc, flagDef));
  275. il.InsertBefore(startInsertPos, il.Create(OpCodes.Brfalse, startInsertPos));
  276. il.InsertBefore(startInsertPos, il.Create(OpCodes.Ldc_I4, methodIndex));
  277. il.InsertBefore(startInsertPos, il.Create(OpCodes.Call, injectedFuncGetter));
  278. il.InsertBefore(startInsertPos, il.Create(OpCodes.Stloc, funcDef));
  279. offset = targetBody.Instructions.IndexOf(startInsertPos);
  280. }
  281. #region GenericMethod
  282. static void InjectGenericMethod(AssemblyDefinition assembly, MethodDefinition target, int methodIndex)
  283. {
  284. }
  285. #endregion GenericMethod
  286. #region Coroutine
  287. static void InjectCoroutine(AssemblyDefinition assembly, MethodDefinition target, int methodIndex)
  288. {
  289. InjectType runtimeInjectType = GetMethodRuntimeInjectType(target);
  290. if (runtimeInjectType == InjectType.None)
  291. {
  292. return;
  293. }
  294. target.Body.SimplifyMacros();
  295. FillBegin(target, methodIndex);
  296. FillReplaceCoroutine(target, runtimeInjectType & InjectType.Replace);
  297. FillCoroutineMonitor(target, runtimeInjectType & (~InjectType.Replace), methodIndex);
  298. target.Body.OptimizeMacros();
  299. }
  300. static void FillReplaceCoroutine(MethodDefinition target, InjectType runtimeInjectType)
  301. {
  302. if (runtimeInjectType == InjectType.None)
  303. {
  304. return;
  305. }
  306. MethodBody targetBody = target.Body;
  307. ILProcessor il = targetBody.GetILProcessor();
  308. cursor = GetMethodNextInsertPosition(target, null, false);
  309. if (cursor != null)
  310. {
  311. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, flagDef));
  312. il.InsertBefore(cursor, il.Create(ldcI4s[(int)InjectType.Replace / 2]));
  313. il.InsertBefore(cursor, il.Create(OpCodes.Bne_Un, cursor));
  314. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, funcDef));
  315. FillArgs(target, cursor, null);
  316. il.InsertBefore(cursor, il.Create(OpCodes.Call, GetLuaMethodInvoker(target, false, false)));
  317. il.InsertBefore(cursor, il.Create(OpCodes.Ret));
  318. }
  319. }
  320. static void FillCoroutineMonitor(MethodDefinition target, InjectType runtimeInjectType, int methodIndex)
  321. {
  322. if (runtimeInjectType == InjectType.None)
  323. {
  324. return;
  325. }
  326. MethodBody targetBody = target.Body;
  327. FieldDefinition hostField = null;
  328. var coroutineEntity = targetBody.Variables[0].VariableType.Resolve();
  329. if (!target.DeclaringType.NestedTypes.Any(type => coroutineEntity == type))
  330. {
  331. return;
  332. }
  333. cursor = GetMethodNextInsertPosition(target, cursor, true);
  334. CopyCoroutineCreatorReference(target, coroutineEntity, ref hostField);
  335. var coroutineCarrier = coroutineEntity.Methods.Single(method => method.Name == "MoveNext");
  336. CopyCreatorArgsToCarrier(target, coroutineCarrier);
  337. FillBegin(coroutineCarrier, methodIndex);
  338. var fillInjectInfoFunc = GetCoroutineInjectInfoFiller(target, hostField);
  339. FillInjectMethod(coroutineCarrier, fillInjectInfoFunc, runtimeInjectType & InjectType.After);
  340. FillInjectMethod(coroutineCarrier, fillInjectInfoFunc, runtimeInjectType & InjectType.Before);
  341. }
  342. static Action<MethodDefinition, InjectType> GetCoroutineInjectInfoFiller(MethodDefinition coroutineCreator, FieldDefinition hostRef)
  343. {
  344. return (coroutineCarrier, runtimeInjectType) =>
  345. {
  346. MethodBody targetBody = coroutineCarrier.Body;
  347. ILProcessor il = targetBody.GetILProcessor();
  348. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, funcDef));
  349. if (coroutineCreator.HasThis)
  350. {
  351. il.InsertBefore(cursor, il.Create(OpCodes.Ldarg_0));
  352. il.InsertBefore(cursor, il.Create(OpCodes.Ldfld, hostRef));
  353. }
  354. CopyCarrierFieldsToArg(coroutineCreator, coroutineCarrier);
  355. FillCoroutineState(coroutineCarrier);
  356. il.InsertBefore(cursor, il.Create(OpCodes.Call, GetLuaMethodInvoker(coroutineCreator, true, true)));
  357. };
  358. }
  359. static void CopyCoroutineCreatorReference(MethodDefinition coroutineCreator, TypeDefinition coroutineCarrier, ref FieldDefinition hostField)
  360. {
  361. if (coroutineCreator.HasThis)
  362. {
  363. ILProcessor il = coroutineCreator.Body.GetILProcessor();
  364. hostField = new FieldDefinition("__iHost", Mono.Cecil.FieldAttributes.Public, coroutineCreator.DeclaringType);
  365. coroutineCarrier.Fields.Add(hostField);
  366. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc_0));
  367. il.InsertBefore(cursor, il.Create(OpCodes.Ldarg_0));
  368. il.InsertBefore(cursor, il.Create(OpCodes.Stfld, hostField));
  369. }
  370. }
  371. static void CopyCreatorArgsToCarrier(MethodDefinition coroutineCreator, MethodDefinition coroutineCarrier)
  372. {
  373. ILProcessor il = coroutineCreator.Body.GetILProcessor();
  374. var carrierFields = coroutineCarrier.DeclaringType.Fields;
  375. coroutineCreator
  376. .Parameters
  377. .Foreach(param =>
  378. {
  379. var name = "<$>" + param.Name;
  380. if (!carrierFields.Any(field => field.Name == name))
  381. {
  382. var hostArg = new FieldDefinition(name, Mono.Cecil.FieldAttributes.Public, param.ParameterType);
  383. carrierFields.Add(hostArg);
  384. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc_0));
  385. il.InsertBefore(cursor, il.Create(OpCodes.Ldarg, param));
  386. il.InsertBefore(cursor, il.Create(OpCodes.Stfld, hostArg));
  387. }
  388. });
  389. }
  390. static void CopyCarrierFieldsToArg(MethodDefinition coroutineCreator, MethodDefinition coroutineCarrier)
  391. {
  392. ILProcessor il = coroutineCarrier.Body.GetILProcessor();
  393. var carrierFields = coroutineCarrier.DeclaringType.Fields;
  394. coroutineCreator
  395. .Parameters
  396. .Select(param => "<$>" + param.Name)
  397. .Foreach(name =>
  398. {
  399. var arg = carrierFields.Single(field => field.Name == name);
  400. il.InsertBefore(cursor, il.Create(OpCodes.Ldarg_0));
  401. il.InsertBefore(cursor, il.Create(OpCodes.Ldfld, arg));
  402. });
  403. }
  404. static void FillCoroutineState(MethodDefinition coroutineCarrier)
  405. {
  406. MethodBody targetBody = coroutineCarrier.Body;
  407. ILProcessor il = targetBody.GetILProcessor();
  408. il.InsertBefore(cursor, il.Create(OpCodes.Ldarg_0));
  409. var stateField = coroutineCarrier.DeclaringType.Fields.Single(field => field.Name == "$PC");
  410. il.InsertBefore(cursor, il.Create(OpCodes.Ldfld, stateField));
  411. }
  412. #endregion Coroutine
  413. #region NormalMethod
  414. static void InjectMethod(AssemblyDefinition assembly, MethodDefinition target, int methodIndex)
  415. {
  416. target.Body.SimplifyMacros();
  417. FillBegin(target, methodIndex);
  418. InjectType runtimeInjectType = GetMethodRuntimeInjectType(target);
  419. FillInjectMethod(target, FillInjectInfo, runtimeInjectType & InjectType.After);
  420. FillInjectMethod(target, FillInjectInfo, runtimeInjectType & (~InjectType.After));
  421. target.Body.OptimizeMacros();
  422. }
  423. static void FillInjectMethod(MethodDefinition target, Action<MethodDefinition, InjectType> fillInjectInfo, InjectType runtimeInjectType)
  424. {
  425. if (runtimeInjectType == InjectType.None)
  426. {
  427. return;
  428. }
  429. MethodBody targetBody = target.Body;
  430. ILProcessor il = targetBody.GetILProcessor();
  431. cursor = GetMethodNextInsertPosition(target, null, runtimeInjectType.HasFlag(InjectType.After));
  432. while (cursor != null)
  433. {
  434. bool bAfterInject = runtimeInjectType == InjectType.After;
  435. Instruction startPos = il.Create(OpCodes.Ldloc, flagDef);
  436. if (bAfterInject)
  437. {
  438. /// Replace instruction with references reserved
  439. Instruction endPos = il.Create(OpCodes.Ret);
  440. int replaceIndex = targetBody.Instructions.IndexOf(cursor);
  441. cursor.OpCode = startPos.OpCode;
  442. cursor.Operand = startPos.Operand;
  443. il.InsertAfter(targetBody.Instructions[replaceIndex], endPos);
  444. cursor = targetBody.Instructions[replaceIndex + 1];
  445. }
  446. else il.InsertBefore(cursor, startPos);
  447. il.InsertBefore(cursor, il.Create(ldcI4s[(int)InjectType.After / 2]));
  448. il.InsertBefore(cursor, il.Create(bAfterInject ? OpCodes.Bne_Un : OpCodes.Ble_Un, cursor));
  449. fillInjectInfo(target, runtimeInjectType);
  450. cursor = GetMethodNextInsertPosition(target, cursor, runtimeInjectType.HasFlag(InjectType.After));
  451. }
  452. }
  453. static void FillInjectInfo(MethodDefinition target, InjectType runtimeInjectType)
  454. {
  455. FillBaseCall(target, runtimeInjectType, true);
  456. FillLuaMethodCall(target, runtimeInjectType == InjectType.After);
  457. FillBaseCall(target, runtimeInjectType, false);
  458. FillJumpInfo(target, runtimeInjectType == InjectType.After);
  459. }
  460. static void FillBaseCall(MethodDefinition target, InjectType runtimeInjectType, bool preCall)
  461. {
  462. MethodBody targetBody = target.Body;
  463. ILProcessor il = targetBody.GetILProcessor();
  464. InjectType curBaseInjectType = preCall ? InjectType.ReplaceWithPreInvokeBase : InjectType.ReplaceWithPostInvokeBase;
  465. if (runtimeInjectType.HasFlag(curBaseInjectType))
  466. {
  467. Instruction end = il.Create(OpCodes.Nop);
  468. il.InsertBefore(cursor, end);
  469. il.InsertBefore(end, il.Create(OpCodes.Ldloc, flagDef));
  470. il.InsertBefore(end, il.Create(OpCodes.Ldc_I4, (int)curBaseInjectType));
  471. il.InsertBefore(end, il.Create(OpCodes.Bne_Un, end));
  472. FillArgs(target, end, PostProcessBaseMethodArg);
  473. il.InsertBefore(end, il.Create(OpCodes.Call, target.GetBaseMethodInstance()));
  474. if (!target.ReturnVoid())
  475. {
  476. il.InsertBefore(end, il.Create(OpCodes.Pop));
  477. }
  478. }
  479. }
  480. static void FillLuaMethodCall(MethodDefinition target, bool bConfirmPopReturnValue)
  481. {
  482. ILProcessor il = target.Body.GetILProcessor();
  483. Instruction start = il.Create(OpCodes.Ldloc, funcDef);
  484. if (cursor.Previous.OpCode == OpCodes.Nop)
  485. {
  486. cursor.Previous.OpCode = start.OpCode;
  487. cursor.Previous.Operand = start.Operand;
  488. }
  489. else
  490. {
  491. il.InsertBefore(cursor, start);
  492. }
  493. FillArgs(target, cursor, ParseArgumentReference);
  494. il.InsertBefore(cursor, il.Create(OpCodes.Call, GetLuaMethodInvoker(target, bConfirmPopReturnValue, false)));
  495. CacheResultTable(target, bConfirmPopReturnValue);
  496. UpdatePassedByReferenceParams(target, bConfirmPopReturnValue);
  497. }
  498. static void CacheResultTable(MethodDefinition target, bool bConfirmPopReturnValue)
  499. {
  500. ILProcessor il = target.Body.GetILProcessor();
  501. if (target.GotPassedByReferenceParam())
  502. {
  503. il.InsertBefore(cursor, il.Create(OpCodes.Stloc, GetResultTable(target)));
  504. }
  505. }
  506. static VariableDefinition GetResultTable(MethodDefinition target)
  507. {
  508. VariableDefinition luaTable = null;
  509. resultTableGroup.TryGetValue(target, out luaTable);
  510. if (luaTable == null)
  511. {
  512. luaTable = new VariableDefinition(luaTableTypeDef);
  513. target.Body.Variables.Add(luaTable);
  514. resultTableGroup.Add(target, luaTable);
  515. }
  516. return luaTable;
  517. }
  518. static void UpdatePassedByReferenceParams(MethodDefinition target, bool bConfirmPopReturnValue)
  519. {
  520. if (!target.GotPassedByReferenceParam())
  521. {
  522. return;
  523. }
  524. int updateCount = 0;
  525. ILProcessor il = target.Body.GetILProcessor();
  526. VariableDefinition luaTable = GetResultTable(target);
  527. var rawGetGenericMethod = luaTableTypeDef.Methods.Single(method => method.Name == "RawGetIndex");
  528. foreach (var param in target.Parameters)
  529. {
  530. if (!param.ParameterType.IsByReference)
  531. {
  532. continue;
  533. }
  534. var paramType = ElementType.For(param.ParameterType);
  535. il.InsertBefore(cursor, il.Create(OpCodes.Ldarg, param));
  536. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, luaTable));
  537. il.InsertBefore(cursor, il.Create(OpCodes.Ldc_I4, ++updateCount));
  538. il.InsertBefore(cursor, il.Create(OpCodes.Call, rawGetGenericMethod.MakeGenericMethod(paramType)));
  539. if (paramType.IsValueType)
  540. {
  541. il.InsertBefore(cursor, il.Create(OpCodes.Stobj, paramType));
  542. }
  543. else
  544. {
  545. il.InsertBefore(cursor, il.Create(OpCodes.Stind_Ref));
  546. }
  547. }
  548. if (!bConfirmPopReturnValue && !target.ReturnVoid())
  549. {
  550. il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, luaTable));
  551. il.InsertBefore(cursor, il.Create(OpCodes.Ldc_I4, ++updateCount));
  552. il.InsertBefore(cursor, il.Create(OpCodes.Call, rawGetGenericMethod.MakeGenericMethod(target.ReturnType)));
  553. }
  554. }
  555. static void FillJumpInfo(MethodDefinition target, bool bConfirmPopReturnValue)
  556. {
  557. MethodBody targetBody = target.Body;
  558. ILProcessor il = targetBody.GetILProcessor();
  559. if (!bConfirmPopReturnValue)
  560. {
  561. Instruction retIns = il.Create(OpCodes.Ret);
  562. if (!injectType.HasFlag(InjectType.Before))
  563. {
  564. if (cursor.Previous.OpCode == OpCodes.Nop)
  565. {
  566. cursor.Previous.OpCode = retIns.OpCode;
  567. cursor.Previous.Operand = retIns.Operand;
  568. retIns = cursor.Previous;
  569. }
  570. else
  571. {
  572. il.InsertBefore(cursor, retIns);
  573. }
  574. }
  575. else
  576. {
  577. Instruction start = il.Create(OpCodes.Ldloc, flagDef);
  578. if (cursor.Previous.OpCode == OpCodes.Nop)
  579. {
  580. cursor.Previous.OpCode = start.OpCode;
  581. cursor.Previous.Operand = start.Operand;
  582. il.InsertAfter(cursor.Previous, retIns);
  583. }
  584. else
  585. {
  586. il.InsertBefore(cursor, retIns);
  587. il.InsertBefore(retIns, start);
  588. }
  589. Instruction popIns = il.Create(OpCodes.Pop);
  590. bool bGotReturnValue = !target.ReturnVoid();
  591. if (bGotReturnValue)
  592. {
  593. il.InsertBefore(cursor, popIns);
  594. }
  595. il.InsertBefore(retIns, il.Create(ldcI4s[(int)InjectType.Before / 2]));
  596. il.InsertBefore(retIns, il.Create(OpCodes.Ble_Un, bGotReturnValue ? popIns : cursor));
  597. }
  598. }
  599. else if (cursor.Previous.OpCode == OpCodes.Nop)
  600. {
  601. targetBody.Instructions.Remove(cursor.Previous);
  602. }
  603. }
  604. #endregion NormalMethod
  605. static void FillArgs(MethodDefinition target, Instruction endPoint, Action<MethodDefinition, Instruction, int> parseReferenceProcess)
  606. {
  607. MethodBody targetBody = target.Body;
  608. ILProcessor il = targetBody.GetILProcessor();
  609. int paramCount = target.Parameters.Count + (target.HasThis ? 1 : 0);
  610. for (int i = 0; i < paramCount; ++i)
  611. {
  612. if (i < ldargs.Length)
  613. {
  614. il.InsertBefore(endPoint, il.Create(ldargs[i]));
  615. }
  616. else if (i <= byte.MaxValue)
  617. {
  618. il.InsertBefore(endPoint, il.Create(OpCodes.Ldarg_S, (byte)i));
  619. }
  620. else
  621. {
  622. il.InsertBefore(endPoint, il.Create(OpCodes.Ldarg, (short)i));
  623. }
  624. if (parseReferenceProcess != null)
  625. {
  626. parseReferenceProcess(target, endPoint, i);
  627. }
  628. }
  629. }
  630. static void PostProcessBaseMethodArg(MethodDefinition target, Instruction endPoint, int paramIndex)
  631. {
  632. var declaringType = target.DeclaringType;
  633. ILProcessor il = target.Body.GetILProcessor();
  634. if (paramIndex == 0 && declaringType.IsValueType)
  635. {
  636. il.InsertBefore(endPoint, il.Create(OpCodes.Ldobj, declaringType));
  637. il.InsertBefore(endPoint, il.Create(OpCodes.Box, declaringType));
  638. }
  639. }
  640. static void ParseArgumentReference(MethodDefinition target, Instruction endPoint, int paramIndex)
  641. {
  642. ParameterDefinition param = null;
  643. ILProcessor il = target.Body.GetILProcessor();
  644. if (target.HasThis)
  645. {
  646. if (paramIndex > 0)
  647. {
  648. param = target.Parameters[paramIndex - 1];
  649. }
  650. else if (target.DeclaringType.IsValueType)
  651. {
  652. il.InsertBefore(endPoint, il.Create(OpCodes.Ldobj, target.DeclaringType));
  653. }
  654. }
  655. else if (!target.HasThis)
  656. {
  657. param = target.Parameters[paramIndex];
  658. }
  659. if (param != null && param.ParameterType.IsByReference)
  660. {
  661. TypeReference paramType = ElementType.For(param.ParameterType);
  662. if (paramType.IsValueType)
  663. {
  664. il.InsertBefore(endPoint, il.Create(OpCodes.Ldobj, paramType));
  665. }
  666. else
  667. {
  668. il.InsertBefore(endPoint, il.Create(OpCodes.Ldind_Ref));
  669. }
  670. }
  671. }
  672. static Instruction GetMethodNextInsertPosition(MethodDefinition target, Instruction curPoint, bool bInsertBeforeRet)
  673. {
  674. MethodBody targetBody = target.Body;
  675. if (target.IsConstructor || bInsertBeforeRet)
  676. {
  677. if (curPoint != null)
  678. {
  679. return targetBody.Instructions
  680. .SkipWhile(ins => ins != curPoint)
  681. .FirstOrDefault(ins => ins != curPoint && ins.OpCode == OpCodes.Ret);
  682. }
  683. else
  684. {
  685. return targetBody.Instructions
  686. .FirstOrDefault(ins => ins.OpCode == OpCodes.Ret);
  687. }
  688. }
  689. else
  690. {
  691. if (curPoint != null) return null;
  692. else return targetBody.Instructions[offset];
  693. }
  694. }
  695. static InjectType GetMethodRuntimeInjectType(MethodDefinition target)
  696. {
  697. InjectType type = injectType;
  698. //bool bOverrideParantMethodFlag = target.IsVirtual && target.IsReuseSlot;
  699. var parantMethod = target.GetBaseMethodInstance();
  700. if (target.IsConstructor)
  701. {
  702. type &= ~InjectType.Before;
  703. type &= ~InjectType.Replace;
  704. type &= ~InjectType.ReplaceWithPostInvokeBase;
  705. type &= ~InjectType.ReplaceWithPreInvokeBase;
  706. }
  707. else if (parantMethod == null || target.IsEnumerator())
  708. {
  709. type &= ~InjectType.ReplaceWithPostInvokeBase;
  710. type &= ~InjectType.ReplaceWithPreInvokeBase;
  711. }
  712. else if (!target.HasBody)
  713. {
  714. type &= ~InjectType.After;
  715. type &= ~InjectType.Before;
  716. }
  717. return type;
  718. }
  719. static MethodReference GetLuaMethodInvoker(MethodDefinition prototypeMethod, bool bIgnoreReturnValue, bool bAppendCoroutineState)
  720. {
  721. MethodReference injectMethod = null;
  722. GetLuaInvoker(prototypeMethod, bIgnoreReturnValue, bAppendCoroutineState, ref injectMethod);
  723. FillLuaInvokerGenericArguments(prototypeMethod, bIgnoreReturnValue, bAppendCoroutineState, ref injectMethod);
  724. return injectMethod;
  725. }
  726. static void GetLuaInvoker(MethodDefinition prototypeMethod, bool bIgnoreReturnValue, bool bAppendCoroutineState, ref MethodReference invoker)
  727. {
  728. bool bRequireResult = prototypeMethod.GotPassedByReferenceParam()
  729. || (!bIgnoreReturnValue && !prototypeMethod.ReturnVoid());
  730. string methodName = bRequireResult ? "Invoke" : "Call";
  731. int paramCount = prototypeMethod.Parameters.Count;
  732. int paramExtraCount = prototypeMethod.HasThis ? 1 : 0;
  733. paramExtraCount = bAppendCoroutineState ? paramExtraCount + 1 : paramExtraCount;
  734. paramCount += paramExtraCount;
  735. invoker = luaFunctionTypeDef.Methods.FirstOrDefault(method =>
  736. {
  737. return method.Name == methodName && method.Parameters.Count == paramCount && bRequireResult == !method.ReturnVoid();
  738. });
  739. if (invoker == null)
  740. {
  741. Debug.Log(prototypeMethod.FullName + " Got too many parameters!!!Skipped!!!");
  742. }
  743. }
  744. static void FillLuaInvokerGenericArguments(MethodDefinition prototypeMethod, bool bIgnoreReturnValue, bool bAppendCoroutineState, ref MethodReference invoker)
  745. {
  746. if (invoker.HasGenericParameters)
  747. {
  748. GenericInstanceMethod genericInjectMethod = new GenericInstanceMethod(invoker.CloneMethod());
  749. if (prototypeMethod.HasThis)
  750. {
  751. genericInjectMethod.GenericArguments.Add(prototypeMethod.DeclaringType);
  752. }
  753. foreach (ParameterDefinition parameter in prototypeMethod.Parameters)
  754. {
  755. var paramType = parameter.ParameterType.IsByReference ? ElementType.For(parameter.ParameterType) : parameter.ParameterType;
  756. genericInjectMethod.GenericArguments.Add(paramType);
  757. }
  758. if (bAppendCoroutineState)
  759. {
  760. genericInjectMethod.GenericArguments.Add(intTypeRef);
  761. }
  762. if (prototypeMethod.GotPassedByReferenceParam())
  763. {
  764. genericInjectMethod.GenericArguments.Add(luaTableTypeDef);
  765. }
  766. else if (!bIgnoreReturnValue && !prototypeMethod.ReturnVoid())
  767. {
  768. genericInjectMethod.GenericArguments.Add(prototypeMethod.ReturnType);
  769. }
  770. invoker = genericInjectMethod;
  771. }
  772. }
  773. static void UpdateInjectionCacheSize()
  774. {
  775. var staticConstructor = injectStationTypeDef.Methods.Single((method) =>
  776. {
  777. return method.Name == ".cctor";
  778. });
  779. var il = staticConstructor.Body.GetILProcessor();
  780. Instruction loadStaticFieldIns = null;
  781. loadStaticFieldIns = staticConstructor
  782. .Body
  783. .Instructions
  784. .FirstOrDefault(ins =>
  785. {
  786. return ins.OpCode == OpCodes.Ldsfld
  787. && (ins.Operand as FieldReference).Name == "cacheSize";
  788. });
  789. var loadCacheSizeIns = il.Create(OpCodes.Ldc_I4, methodCounter + 1);
  790. il.InsertBefore(loadStaticFieldIns, loadCacheSizeIns);
  791. il.InsertBefore(loadStaticFieldIns, il.Create(OpCodes.Stsfld, (loadStaticFieldIns.Operand as FieldReference)));
  792. }
  793. static void WriteInjectedAssembly(AssemblyDefinition assembly, string assemblyPath)
  794. {
  795. var writerParameters = new WriterParameters { WriteSymbols = EnableSymbols };
  796. assembly.Write(assemblyPath, writerParameters);
  797. }
  798. static void ExportInjectionBridgeInfo()
  799. {
  800. ExportInjectionPublishInfo(bridgeInfo);
  801. ExportInjectionEditorInfo(bridgeInfo);
  802. }
  803. static void ExportInjectionPublishInfo(SortedDictionary<string, List<InjectedMethodInfo>> data)
  804. {
  805. var temp = data.ToDictionary(
  806. typeInfo => typeInfo.Key,
  807. typeinfo =>
  808. {
  809. return typeinfo.Value
  810. .OrderBy(methodInfo => methodInfo.methodPublishedName)
  811. .ToDictionary(
  812. methodInfo => methodInfo.methodPublishedName,
  813. methodInfo => methodInfo.methodIndex
  814. );
  815. }
  816. );
  817. StringBuilder sb = StringBuilderCache.Acquire();
  818. sb.Append("return ");
  819. ToLuaText.TransferDic(temp, sb);
  820. sb.Remove(sb.Length - 1, 1);
  821. File.WriteAllText(CustomSettings.baseLuaDir + "System/Injection/InjectionBridgeInfo.lua", StringBuilderCache.GetStringAndRelease(sb));
  822. }
  823. static int AppendMethod(MethodDefinition method)
  824. {
  825. string methodSignature = GetMethodSignature(method);
  826. string methodFullSignature = method.FullName;
  827. InjectedMethodInfo newInfo = new InjectedMethodInfo();
  828. string typeName = ToLuaInjectionHelper.GetTypeName(method.DeclaringType, true);
  829. List<InjectedMethodInfo> typeMethodIndexGroup = null;
  830. bridgeInfo.TryGetValue(typeName, out typeMethodIndexGroup);
  831. if (typeMethodIndexGroup == null)
  832. {
  833. typeMethodIndexGroup = new List<InjectedMethodInfo>();
  834. newInfo.methodPublishedName = method.Name;
  835. bridgeInfo.Add(typeName, typeMethodIndexGroup);
  836. }
  837. else
  838. {
  839. InjectedMethodInfo existInfo = typeMethodIndexGroup.Find(info => info.methodOverloadSignature == methodSignature);
  840. if (existInfo == null)
  841. {
  842. existInfo = typeMethodIndexGroup.Find(info => info.methodName == method.Name);
  843. if (existInfo != null)
  844. {
  845. newInfo.methodPublishedName = methodSignature;
  846. existInfo.methodPublishedName = existInfo.methodOverloadSignature;
  847. }
  848. else
  849. {
  850. newInfo.methodPublishedName = method.Name;
  851. }
  852. }
  853. else
  854. {
  855. if (existInfo.methodFullSignature != methodFullSignature)
  856. {
  857. Debug.LogError(typeName + "." + existInfo.methodPublishedName + " 签名跟历史签名不一致,无法增量,Injection中断,请修改函数签名、或者直接删掉InjectionBridgeEditorInfo.xml(该操作会导致无法兼容线上版的包体,需要强制换包)!");
  858. EditorPrefs.SetInt(Application.dataPath + "WaitForInjection", 0);
  859. return -1;
  860. }
  861. return existInfo.methodIndex;
  862. }
  863. }
  864. newInfo.methodName = method.Name;
  865. newInfo.methodOverloadSignature = methodSignature;
  866. newInfo.methodFullSignature = methodFullSignature;
  867. newInfo.methodIndex = ++methodCounter;
  868. typeMethodIndexGroup.Add(newInfo);
  869. return methodCounter;
  870. }
  871. static string GetMethodSignature(MethodDefinition method)
  872. {
  873. StringBuilder paramsTypeNameBuilder = StringBuilderCache.Acquire();
  874. paramsTypeNameBuilder.Append(method.Name);
  875. foreach (var param in method.Parameters)
  876. {
  877. paramsTypeNameBuilder
  878. .Append("-")
  879. .Append(ToLuaInjectionHelper.GetTypeName(param.ParameterType));
  880. }
  881. return StringBuilderCache.GetStringAndRelease(paramsTypeNameBuilder);
  882. }
  883. static void ExportInjectionEditorInfo(SortedDictionary<string, List<InjectedMethodInfo>> data)
  884. {
  885. string incrementalFilePath = CustomSettings.injectionFilesPath + "InjectionBridgeEditorInfo.xml";
  886. if (File.Exists(incrementalFilePath))
  887. {
  888. File.Delete(incrementalFilePath);
  889. }
  890. var doc = new XmlDocument();
  891. var fileInforRoot = doc.CreateElement("Root");
  892. doc.AppendChild(fileInforRoot);
  893. foreach (var type in data)
  894. {
  895. XmlElement typeNode = doc.CreateElement("Type");
  896. typeNode.SetAttribute("Name", type.Key);
  897. var sortedMethodsGroup = type.Value.OrderBy(info => info.methodPublishedName);
  898. foreach (var method in sortedMethodsGroup)
  899. {
  900. XmlElement typeMethodNode = doc.CreateElement("Method");
  901. typeMethodNode.SetAttribute("Name", method.methodName);
  902. typeMethodNode.SetAttribute("PublishedName", method.methodPublishedName);
  903. typeMethodNode.SetAttribute("Signature", method.methodOverloadSignature);
  904. typeMethodNode.SetAttribute("FullSignature", method.methodFullSignature);
  905. typeMethodNode.SetAttribute("Index", method.methodIndex.ToString());
  906. typeNode.AppendChild(typeMethodNode);
  907. }
  908. fileInforRoot.AppendChild(typeNode);
  909. }
  910. doc.Save(incrementalFilePath);
  911. }
  912. static bool LoadBridgeEditorInfo()
  913. {
  914. bridgeInfo.Clear();
  915. methodCounter = 0;
  916. string incrementalFilePath = CustomSettings.injectionFilesPath + "InjectionBridgeEditorInfo.xml";
  917. if (!File.Exists(incrementalFilePath))
  918. {
  919. return true;
  920. }
  921. var doc = new XmlDocument();
  922. doc.Load(incrementalFilePath);
  923. var fileInfoRoot = doc.FindChildByName("Root");
  924. if (fileInfoRoot == null)
  925. {
  926. return true;
  927. }
  928. foreach (XmlNode typeChild in fileInfoRoot.ChildNodes)
  929. {
  930. List<InjectedMethodInfo> typeMethodInfo = new List<InjectedMethodInfo>();
  931. string typeName = typeChild.FindAttributeByName("Name").Value;
  932. foreach (XmlNode methodChild in typeChild.ChildNodes)
  933. {
  934. InjectedMethodInfo info = new InjectedMethodInfo();
  935. info.methodName = methodChild.FindAttributeByName("Name").Value;
  936. info.methodPublishedName = methodChild.FindAttributeByName("PublishedName").Value;
  937. info.methodOverloadSignature = methodChild.FindAttributeByName("Signature").Value;
  938. info.methodFullSignature = methodChild.FindAttributeByName("FullSignature").Value;
  939. info.methodIndex = int.Parse(methodChild.FindAttributeByName("Index").Value);
  940. typeMethodInfo.Add(info);
  941. methodCounter = Math.Max(methodCounter, info.methodIndex);
  942. }
  943. bridgeInfo.Add(typeName, typeMethodInfo);
  944. }
  945. return true;
  946. }
  947. static void Clean(AssemblyDefinition assembly)
  948. {
  949. if (assembly.MainModule.SymbolReader != null)
  950. {
  951. assembly.MainModule.SymbolReader.Dispose();
  952. }
  953. }
  954. static void CacheInjectableTypeGroup()
  955. {
  956. injectableTypeGroup.Clear();
  957. Assembly assebly = Assembly.Load("Assembly-CSharp");
  958. foreach (Type t in assebly.GetTypes())
  959. {
  960. if (DoesTypeInjectable(t))
  961. {
  962. injectableTypeGroup.Add(t.FullName);
  963. }
  964. }
  965. }
  966. static bool DoesTypeInjectable(Type type)
  967. {
  968. if (dropTypeGroup.Contains(type.FullName) || (type.DeclaringType != null && dropTypeGroup.Contains(type.DeclaringType.FullName)))
  969. {
  970. return false;
  971. }
  972. if (type.IsGenericType)
  973. {
  974. Type genericTypeDefinition = type.GetGenericTypeDefinition();
  975. if (dropGenericNameGroup.Contains(genericTypeDefinition.FullName))
  976. {
  977. return false;
  978. }
  979. }
  980. if (typeof(System.Delegate).IsAssignableFrom(type))
  981. {
  982. return false;
  983. }
  984. if (type.FullName.Contains("<") || type.IsInterface)
  985. {
  986. return false;
  987. }
  988. if (!injectIgnoring.HasFlag(InjectFilter.IgnoreNoToLuaAttr))
  989. {
  990. foreach (var attr in type.GetCustomAttributes(true))
  991. {
  992. Type attrT = attr.GetType();
  993. if (attrT == typeof(LuaInterface.NoToLuaAttribute))
  994. {
  995. return false;
  996. }
  997. }
  998. }
  999. return true;
  1000. }
  1001. static bool DoesTypeInjectable(TypeDefinition type)
  1002. {
  1003. if (dropNamespaceGroup.Contains(type.SafeNamespace()))
  1004. {
  1005. return false;
  1006. }
  1007. if (!injectableTypeGroup.Contains(type.FullName.Replace("/", "+")))
  1008. {
  1009. return false;
  1010. }
  1011. if (injectIgnoring.HasFlag(InjectFilter.IgnoreConstructor) && type.Methods.Count == 1)
  1012. {
  1013. return false;
  1014. }
  1015. if (!injectIgnoring.HasFlag(InjectFilter.IgnoreNoToLuaAttr))
  1016. {
  1017. if (type.CustomAttributes.Any((attr) => attr.AttributeType == noToLuaAttrTypeRef))
  1018. {
  1019. return false;
  1020. }
  1021. }
  1022. return true;
  1023. }
  1024. static bool DoesMethodInjectable(MethodDefinition method)
  1025. {
  1026. if (method.IsSpecialName)
  1027. {
  1028. if (method.Name == ".cctor")
  1029. {
  1030. return false;
  1031. }
  1032. bool bIgnoreConstructor = injectIgnoring.HasFlag(InjectFilter.IgnoreConstructor)
  1033. || method.DeclaringType.IsAssignableTo("UnityEngine.MonoBehaviour")
  1034. || method.DeclaringType.IsAssignableTo("UnityEngine.ScriptableObject");
  1035. if (method.IsConstructor)
  1036. {
  1037. if (bIgnoreConstructor)
  1038. {
  1039. return false;
  1040. }
  1041. }
  1042. else
  1043. {
  1044. ///Skip add_、remove_、op_、Finalize
  1045. if (!method.IsGetter && !method.IsSetter)
  1046. {
  1047. return false;
  1048. }
  1049. }
  1050. }
  1051. if (method.Name.Contains("<") || method.IsUnmanaged || method.IsAbstract || method.IsPInvokeImpl || !method.HasBody)
  1052. {
  1053. return false;
  1054. }
  1055. /// Skip Unsafe
  1056. if (method.Body.Variables.Any(var => var.VariableType.IsPointer) || method.Parameters.Any(param => param.ParameterType.IsPinned))
  1057. {
  1058. return false;
  1059. }
  1060. /// Hmm... Sometimes method.IsSpecialName Got False
  1061. if (method.Name == "Finalize")
  1062. {
  1063. return false;
  1064. }
  1065. if ((method.IsGetter || method.IsSetter) && injectIgnoring.HasFlag(InjectFilter.IgnoreProperty))
  1066. {
  1067. return false;
  1068. }
  1069. if (!injectIgnoring.HasFlag(InjectFilter.IgnoreNoToLuaAttr))
  1070. {
  1071. if (method.CustomAttributes.Any((attr) => attr.AttributeType == noToLuaAttrTypeRef))
  1072. {
  1073. return false;
  1074. }
  1075. }
  1076. if (method.ReturnType.IsAssignableTo("System.Collections.IEnumerable"))
  1077. {
  1078. return false;
  1079. }
  1080. MethodReference luaInjector = null;
  1081. GetLuaInvoker(method, true, false, ref luaInjector);
  1082. if (luaInjector == null)
  1083. {
  1084. return false;
  1085. }
  1086. return true;
  1087. }
  1088. static bool LoadBlackList()
  1089. {
  1090. if (File.Exists(InjectionBlackListGenerator.blackListFilePath))
  1091. {
  1092. dropTypeGroup.UnionWith(File.ReadAllLines(InjectionBlackListGenerator.blackListFilePath));
  1093. dropTypeGroup.ExceptWith(forceInjectTypeGroup);
  1094. }
  1095. else
  1096. {
  1097. if (EditorUtility.DisplayDialog("警告", "由于Injection会额外增加代码量,故可以先设置一些Injection跳过的代码目录(比如NGUI插件代码目录),减少生成的代码量", "设置黑名单", "全量生成"))
  1098. {
  1099. InjectionBlackListGenerator.Open();
  1100. InjectionBlackListGenerator.onBlackListGenerated += InjectAll;
  1101. return false;
  1102. }
  1103. }
  1104. return true;
  1105. }
  1106. }
  1107. public static class SystemXMLExtension
  1108. {
  1109. public static XmlNode FindChildByName(this XmlNode root, string childName)
  1110. {
  1111. var child = root.FirstChild;
  1112. while (child != null)
  1113. {
  1114. if (child.Name.Equals(childName))
  1115. {
  1116. return child;
  1117. }
  1118. else
  1119. {
  1120. child = child.NextSibling;
  1121. }
  1122. }
  1123. return null;
  1124. }
  1125. public static XmlAttribute FindAttributeByName(this XmlNode node, string attributeName)
  1126. {
  1127. var attributeCollection = node.Attributes;
  1128. for (int i = 0; i < attributeCollection.Count; i++)
  1129. {
  1130. if (attributeCollection[i].Name.Equals(attributeName))
  1131. {
  1132. return attributeCollection[i];
  1133. }
  1134. }
  1135. return null;
  1136. }
  1137. }
  1138. #endif