Files

72 lines
4.2 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Collections;
using Newtonsoft.Json;
using UnityEngine;
public static class InspectHomeCampAot
{
public static string BuildAndCheck()
{
var built = AOT.Editor.YooAssetTools.BuildAndStageHotUpdate.BuildAndStage();
if (!built.StartsWith("ok", StringComparison.Ordinal)) throw new Exception(built);
return built + " | " + CheckHotUpdate();
}
public static string CheckHotUpdate()
{
var cecil = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "Mono.Cecil");
var definition = cecil.GetType("Mono.Cecil.AssemblyDefinition");
var stripped = Path.GetFullPath(Path.Combine(Application.dataPath, "../Library/Bee/artifacts/WebGL/ManagedStripped/YooAsset.dll"));
object original = definition.GetMethod("ReadAssembly", new[] { typeof(string) }).Invoke(null, new object[] { stripped });
object update = definition.GetMethod("ReadAssembly", new[] { typeof(string) }).Invoke(null, new object[] { Path.Combine(Application.dataPath, "Bundles/Raw/HotUpdate.Runtime.bytes") });
var calls = new System.Collections.Generic.List<string>();
using ((IDisposable)original)
using ((IDisposable)update)
{
var oldModule = Property(original, "MainModule");
var module = Property(update, "MainModule");
var references = (IEnumerable)module.GetType().GetMethod("GetMemberReferences", Type.EmptyTypes).Invoke(module, null);
foreach (object reference in references)
{
var declaring = Property(reference, "DeclaringType");
string typeName = (string)Property(declaring, "FullName");
if (typeName != "YooAsset.SceneHandle" && typeName != "YooAsset.HandleBase") continue;
string fullName = (string)Property(reference, "FullName");
object type = oldModule.GetType().GetMethod("GetType", new[] { typeof(string) }).Invoke(oldModule, new object[] { typeName });
var retained = ((IEnumerable)Property(type, "Methods")).Cast<object>().Any(m => (string)Property(m, "FullName") == fullName);
if (!retained) throw new Exception("Hot update uses a method absent from the shipped shell: " + fullName);
calls.Add(fullName);
}
}
var report = JsonConvert.SerializeObject(new { passed=true, baseline=stripped, retainedCalls=calls });
var output = Path.GetFullPath(Path.Combine(Application.dataPath, "../../Tools/output/homecamp_aot_compatibility"));
Directory.CreateDirectory(output); File.WriteAllText(Path.Combine(output, "aot_check.json"), report);
return report;
}
public static string Run()
{
var directory = Path.GetFullPath(Path.Combine(Application.dataPath, "../Library/Bee/artifacts/WebGL/ManagedStripped"));
var cecil = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "Mono.Cecil");
var definition = cecil.GetType("Mono.Cecil.AssemblyDefinition");
var output = new System.Collections.Generic.List<object>();
foreach (var file in new[] { "YooAsset.dll", "UnityEngine.CoreModule.dll" })
{
object assembly = definition.GetMethod("ReadAssembly", new[] { typeof(string) }).Invoke(null, new object[] { Path.Combine(directory, file) });
using ((IDisposable)assembly)
{
object module = Property(assembly, "MainModule");
foreach (var name in new[] { "YooAsset.SceneHandle", "YooAsset.HandleBase", "UnityEngine.SceneManagement.SceneManager" })
{
object type = module.GetType().GetMethod("GetType", new[] { typeof(string) }).Invoke(module, new object[] { name });
if (type != null) output.Add(new { file, written = File.GetLastWriteTimeUtc(Path.Combine(directory, file)), type = name,
methods = ((IEnumerable)Property(type, "Methods")).Cast<object>().Select(m => Property(m, "FullName")).ToArray() });
}
}
}
return JsonConvert.SerializeObject(output);
}
static object Property(object value, string name) => value.GetType().GetProperty(name).GetValue(value);
}