176 lines
7.2 KiB
C#
176 lines
7.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using TH1_Logic.Hotfix;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace TH1_Logic.Editor.HybridCLR
|
|
{
|
|
public static class TH1HybridCLRBuildTools
|
|
{
|
|
private const string HybridClrInstallerMenu = "HybridCLR/Installer...";
|
|
private const string HybridClrGenerateAllMenu = "HybridCLR/Generate/All";
|
|
private const string HybridClrCompileDllMenu = "HybridCLR/CompileDll/ActiveBuildTarget";
|
|
|
|
[MenuItem("Tools/TH1/iOS Migration/HybridCLR/1. Run HybridCLR Installer")]
|
|
public static void RunHybridClrInstaller()
|
|
{
|
|
ExecuteHybridClrMenu(HybridClrInstallerMenu);
|
|
}
|
|
|
|
[MenuItem("Tools/TH1/iOS Migration/HybridCLR/2. Configure TH1 Hotfix Settings")]
|
|
public static void ConfigureHotfixSettings()
|
|
{
|
|
var settingsType = FindType("HybridCLR.Editor.Settings.HybridCLRSettings");
|
|
if (settingsType == null)
|
|
{
|
|
Debug.LogWarning("[TH1.HybridCLR] HybridCLR package is not available yet. Let Unity resolve packages, then run this menu again.");
|
|
return;
|
|
}
|
|
|
|
var instance = settingsType.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static)?.GetValue(null);
|
|
if (instance == null)
|
|
{
|
|
Debug.LogWarning("[TH1.HybridCLR] HybridCLRSettings.Instance is unavailable.");
|
|
return;
|
|
}
|
|
|
|
SetBoolField(settingsType, instance, "enable", true);
|
|
AddStringToArrayField(settingsType, instance, "hotUpdateAssemblies", HotfixManifest.HotfixAssemblyName);
|
|
AddStringToArrayField(settingsType, instance, "patchAOTAssemblies", "mscorlib");
|
|
AddStringToArrayField(settingsType, instance, "patchAOTAssemblies", "System");
|
|
AddStringToArrayField(settingsType, instance, "patchAOTAssemblies", "System.Core");
|
|
|
|
settingsType.GetMethod("Save", BindingFlags.Public | BindingFlags.Static)?.Invoke(null, null);
|
|
Debug.Log("[TH1.HybridCLR] Configured HybridCLRSettings for TH1.Hotfix.");
|
|
}
|
|
|
|
[MenuItem("Tools/TH1/iOS Migration/HybridCLR/3. Generate All")]
|
|
public static void GenerateAll()
|
|
{
|
|
ExecuteHybridClrMenu(HybridClrGenerateAllMenu);
|
|
}
|
|
|
|
[MenuItem("Tools/TH1/iOS Migration/HybridCLR/4. Compile Hotfix Dll")]
|
|
public static void CompileHotfixDll()
|
|
{
|
|
if (!ExecuteHybridClrMenu(HybridClrCompileDllMenu))
|
|
{
|
|
Debug.LogWarning("[TH1.HybridCLR] Compile menu was not found. Run HybridCLR/Generate/All or use the package CompileDll menu manually.");
|
|
}
|
|
}
|
|
|
|
[MenuItem("Tools/TH1/iOS Migration/HybridCLR/5. Copy Hotfix Artifacts To StreamingAssets")]
|
|
public static void CopyHotfixArtifactsToStreamingAssets()
|
|
{
|
|
CopyHotfixDll();
|
|
CopyAotMetadataDlls();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
[MenuItem("Tools/TH1/iOS Migration/HybridCLR/6. Test Load StreamingAssets Hotfix In Editor")]
|
|
public static void TestLoadHotfixInEditor()
|
|
{
|
|
var loaded = HotfixBootstrap.InitializeFromStreamingAssets(true);
|
|
Debug.Log($"[TH1.HybridCLR] Test load result: {loaded}, assembly: {HotfixBootstrap.LoadedAssemblyFullName}");
|
|
}
|
|
|
|
private static void CopyHotfixDll()
|
|
{
|
|
var buildTarget = EditorUserBuildSettings.activeBuildTarget.ToString();
|
|
var source = Path.Combine("HybridCLRData", "HotUpdateDlls", buildTarget, HotfixManifest.HotfixAssemblyName + ".dll");
|
|
if (!File.Exists(source))
|
|
{
|
|
source = Path.Combine("Library", "ScriptAssemblies", HotfixManifest.HotfixAssemblyName + ".dll");
|
|
}
|
|
|
|
var destination = Path.Combine(
|
|
Application.streamingAssetsPath,
|
|
HotfixManifest.RootFolderName,
|
|
HotfixManifest.HotfixDllFolderName,
|
|
HotfixManifest.HotfixAssemblyFileName);
|
|
|
|
CopyFile(source, destination, "hotfix dll");
|
|
}
|
|
|
|
private static void CopyAotMetadataDlls()
|
|
{
|
|
var buildTarget = EditorUserBuildSettings.activeBuildTarget.ToString();
|
|
var sourceDir = Path.Combine("HybridCLRData", "AssembliesPostIl2CppStrip", buildTarget);
|
|
var destinationDir = Path.Combine(Application.streamingAssetsPath, HotfixManifest.RootFolderName, HotfixManifest.AotMetadataFolderName);
|
|
|
|
if (!Directory.Exists(sourceDir))
|
|
{
|
|
Debug.LogWarning($"[TH1.HybridCLR] AOT metadata source missing: {sourceDir}. Run HybridCLR/Generate/All after an IL2CPP target is selected.");
|
|
return;
|
|
}
|
|
|
|
Directory.CreateDirectory(destinationDir);
|
|
foreach (var fileName in HotfixManifest.AotMetadataAssemblyFileNames)
|
|
{
|
|
var source = Path.Combine(sourceDir, fileName.Replace(".bytes", ""));
|
|
var destination = Path.Combine(destinationDir, fileName);
|
|
if (!File.Exists(source))
|
|
{
|
|
Debug.LogWarning($"[TH1.HybridCLR] AOT metadata dll missing: {source}");
|
|
continue;
|
|
}
|
|
|
|
File.Copy(source, destination, true);
|
|
Debug.Log($"[TH1.HybridCLR] Copied AOT metadata: {destination}");
|
|
}
|
|
}
|
|
|
|
private static bool ExecuteHybridClrMenu(string menuPath)
|
|
{
|
|
if (EditorApplication.ExecuteMenuItem(menuPath))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Debug.LogWarning($"[TH1.HybridCLR] Unity menu not found: {menuPath}. Make sure the HybridCLR package has been resolved.");
|
|
return false;
|
|
}
|
|
|
|
private static void CopyFile(string source, string destination, string label)
|
|
{
|
|
if (!File.Exists(source))
|
|
{
|
|
Debug.LogWarning($"[TH1.HybridCLR] {label} source missing: {source}");
|
|
return;
|
|
}
|
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(destination));
|
|
File.Copy(source, destination, true);
|
|
Debug.Log($"[TH1.HybridCLR] Copied {label}: {destination}");
|
|
}
|
|
|
|
private static Type FindType(string fullName)
|
|
{
|
|
return AppDomain.CurrentDomain.GetAssemblies()
|
|
.Select(assembly => assembly.GetType(fullName, false))
|
|
.FirstOrDefault(type => type != null);
|
|
}
|
|
|
|
private static void SetBoolField(Type type, object instance, string fieldName, bool value)
|
|
{
|
|
type.GetField(fieldName, BindingFlags.Public | BindingFlags.Instance)?.SetValue(instance, value);
|
|
}
|
|
|
|
private static void AddStringToArrayField(Type type, object instance, string fieldName, string value)
|
|
{
|
|
var field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.Instance);
|
|
if (field == null) return;
|
|
|
|
var values = ((string[])field.GetValue(instance) ?? Array.Empty<string>()).ToList();
|
|
if (!values.Contains(value))
|
|
{
|
|
values.Add(value);
|
|
field.SetValue(instance, values.ToArray());
|
|
}
|
|
}
|
|
}
|
|
}
|