From cd60cb26a0ee530f2cff1f4e4a88ef6998f411ac Mon Sep 17 00:00:00 2001 From: wuwenbo Date: Tue, 9 Jun 2026 20:49:52 +0800 Subject: [PATCH] =?UTF-8?q?=E7=83=AD=E6=9B=B4clr=E8=BF=9B=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MD/iOSMigration.meta | 8 + MD/iOSMigration/HybridCLR_Phase1.md | 49 +++++ MD/iOSMigration/HybridCLR_Phase1.md.meta | 7 + Unity/Assets/HybridCLRGenerate.meta | 8 + .../HybridCLRGenerate/AOTGenericReferences.cs | 20 ++ .../AOTGenericReferences.cs.meta | 11 ++ Unity/Assets/HybridCLRGenerate/link.xml | 24 +++ Unity/Assets/HybridCLRGenerate/link.xml.meta | 7 + Unity/Assets/Scripts/TH1_Hotfix.meta | 8 + .../Assets/Scripts/TH1_Hotfix/HotfixEntry.cs | 14 ++ .../Scripts/TH1_Hotfix/HotfixEntry.cs.meta | 11 ++ .../Scripts/TH1_Hotfix/TH1.Hotfix.asmdef | 14 ++ .../Scripts/TH1_Hotfix/TH1.Hotfix.asmdef.meta | 7 + .../Scripts/TH1_Logic/Editor/HybridCLR.meta | 8 + .../HybridCLR/TH1HybridCLRBuildTools.cs | 175 ++++++++++++++++++ .../HybridCLR/TH1HybridCLRBuildTools.cs.meta | 11 ++ Unity/Assets/Scripts/TH1_Logic/Hotfix.meta | 8 + .../TH1_Logic/Hotfix/HotfixBootstrap.cs | 117 ++++++++++++ .../TH1_Logic/Hotfix/HotfixBootstrap.cs.meta | 11 ++ .../TH1_Logic/Hotfix/HotfixManifest.cs | 25 +++ .../TH1_Logic/Hotfix/HotfixManifest.cs.meta | 11 ++ Unity/Packages/manifest.json | 1 + Unity/Packages/packages-lock.json | 65 ++++--- Unity/ProjectSettings/HybridCLRSettings.asset | 33 ++++ Unity/ProjectSettings/ProjectSettings.asset | 23 +-- Unity/ProjectSettings/ProjectVersion.txt | 4 +- .../ProjectSettings/ShaderGraphSettings.asset | 1 - 27 files changed, 629 insertions(+), 52 deletions(-) create mode 100644 MD/iOSMigration.meta create mode 100644 MD/iOSMigration/HybridCLR_Phase1.md create mode 100644 MD/iOSMigration/HybridCLR_Phase1.md.meta create mode 100644 Unity/Assets/HybridCLRGenerate.meta create mode 100644 Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs create mode 100644 Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs.meta create mode 100644 Unity/Assets/HybridCLRGenerate/link.xml create mode 100644 Unity/Assets/HybridCLRGenerate/link.xml.meta create mode 100644 Unity/Assets/Scripts/TH1_Hotfix.meta create mode 100644 Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs create mode 100644 Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs.meta create mode 100644 Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef create mode 100644 Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef.meta create mode 100644 Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR.meta create mode 100644 Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs create mode 100644 Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs.meta create mode 100644 Unity/Assets/Scripts/TH1_Logic/Hotfix.meta create mode 100644 Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs create mode 100644 Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs.meta create mode 100644 Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs create mode 100644 Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs.meta create mode 100644 Unity/ProjectSettings/HybridCLRSettings.asset diff --git a/MD/iOSMigration.meta b/MD/iOSMigration.meta new file mode 100644 index 000000000..8843e79b3 --- /dev/null +++ b/MD/iOSMigration.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17a20616b59b4a50aea9057818b224a5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/MD/iOSMigration/HybridCLR_Phase1.md b/MD/iOSMigration/HybridCLR_Phase1.md new file mode 100644 index 000000000..24bbde921 --- /dev/null +++ b/MD/iOSMigration/HybridCLR_Phase1.md @@ -0,0 +1,49 @@ +# HybridCLR Phase 1 + +## Scope + +This phase only adds the hot-update foundation. It must not move turn actions, AI, network sync, MapData, replay, save compatibility, MemoryPack, Steam lobby/P2P, Workshop, or backend auth into hotfix assemblies. + +## Added Layout + +- `Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef`: first hot-update assembly. +- `Assets/Scripts/TH1_Hotfix/HotfixEntry.cs`: smoke-test hotfix entry. +- `Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs`: AOT-side loader. +- `Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs`: TH1 menu shortcuts. + +Runtime artifact layout: + +```text +Assets/StreamingAssets/HybridCLR/ + HotfixDlls/ + TH1.Hotfix.dll.bytes + AOTAssemblies/ + mscorlib.dll.bytes + System.dll.bytes + System.Core.dll.bytes +``` + +The loader silently skips when `TH1.Hotfix.dll.bytes` is missing, so the Steam/editor flow can still run without any hotfix package. + +## First Local Verification + +1. Let Unity resolve `com.code-philosophy.hybridclr`. +2. Run `HybridCLR/Installer...`. +3. Run `Tools/TH1/iOS Migration/HybridCLR/2. Configure TH1 Hotfix Settings`. +4. Run `Tools/TH1/iOS Migration/HybridCLR/3. Generate All`. +5. Run `Tools/TH1/iOS Migration/HybridCLR/4. Compile Hotfix Dll`. +6. Run `Tools/TH1/iOS Migration/HybridCLR/5. Copy Hotfix Artifacts To StreamingAssets`. +7. Run `Tools/TH1/iOS Migration/HybridCLR/6. Test Load StreamingAssets Hotfix In Editor`. + +Expected editor console smoke output: + +```text +[TH1.Hotfix] Initialize version 0.1.0 +[TH1.Hotfix] Loaded TH1.Hotfix, ... +``` + +## Next Boundaries + +- Keep first hotfix content limited to UI presentation helpers, non-networked fixes, and feature flags. +- Do not add Steamworks references to `TH1.Hotfix`. +- Do not use hotfix as a way to bypass App Store review. Prefer resources/config for content updates and reserve code hotfix for cautious compatibility fixes. diff --git a/MD/iOSMigration/HybridCLR_Phase1.md.meta b/MD/iOSMigration/HybridCLR_Phase1.md.meta new file mode 100644 index 000000000..0dbce6a9c --- /dev/null +++ b/MD/iOSMigration/HybridCLR_Phase1.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6b8e7fe2c7074d9e99bf77214afb1e74 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/HybridCLRGenerate.meta b/Unity/Assets/HybridCLRGenerate.meta new file mode 100644 index 000000000..a01c77cff --- /dev/null +++ b/Unity/Assets/HybridCLRGenerate.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 69da6df6a219a4b41815c8b315d5c2d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs b/Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs new file mode 100644 index 000000000..63774a6f8 --- /dev/null +++ b/Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +public class AOTGenericReferences : UnityEngine.MonoBehaviour +{ + + // {{ AOT assemblies + public static readonly IReadOnlyList PatchedAOTAssemblyList = new List + { + }; + // }} + + // {{ constraint implement type + // }} + + // {{ AOT generic types + // }} + + public void RefMethods() + { + } +} \ No newline at end of file diff --git a/Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs.meta b/Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs.meta new file mode 100644 index 000000000..27a447359 --- /dev/null +++ b/Unity/Assets/HybridCLRGenerate/AOTGenericReferences.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82d467b90d646a34e9f91bb15a58752d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/HybridCLRGenerate/link.xml b/Unity/Assets/HybridCLRGenerate/link.xml new file mode 100644 index 000000000..62aeb9c25 --- /dev/null +++ b/Unity/Assets/HybridCLRGenerate/link.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Unity/Assets/HybridCLRGenerate/link.xml.meta b/Unity/Assets/HybridCLRGenerate/link.xml.meta new file mode 100644 index 000000000..6b43d10a7 --- /dev/null +++ b/Unity/Assets/HybridCLRGenerate/link.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 09e7d09de0ac0dc46aa9c5ae2f43a611 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Hotfix.meta b/Unity/Assets/Scripts/TH1_Hotfix.meta new file mode 100644 index 000000000..cf481a258 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Hotfix.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a31ef57469b74a26802d55500df1fb90 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs b/Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs new file mode 100644 index 000000000..475cc9d8d --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace TH1_Hotfix +{ + public static class HotfixEntry + { + public const string Version = "0.1.0"; + + public static void Initialize() + { + Debug.Log($"[TH1.Hotfix] Initialize version {Version}"); + } + } +} diff --git a/Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs.meta b/Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs.meta new file mode 100644 index 000000000..d971a5ac0 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Hotfix/HotfixEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e0a1f19517144ff8a49726755c99516 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef b/Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef new file mode 100644 index 000000000..8ed311c29 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef @@ -0,0 +1,14 @@ +{ + "name": "TH1.Hotfix", + "rootNamespace": "TH1_Hotfix", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": false, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef.meta b/Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef.meta new file mode 100644 index 000000000..5baf5a82d --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Hotfix/TH1.Hotfix.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 267e9d456fb04f7cb0386f921d67598c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR.meta b/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR.meta new file mode 100644 index 000000000..4b3df3d96 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fcb6bf33c8f24eb394c0f2385ff60b64 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs b/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs new file mode 100644 index 000000000..60410af9f --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs @@ -0,0 +1,175 @@ +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()).ToList(); + if (!values.Contains(value)) + { + values.Add(value); + field.SetValue(instance, values.ToArray()); + } + } + } +} diff --git a/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs.meta new file mode 100644 index 000000000..682c1544c --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Editor/HybridCLR/TH1HybridCLRBuildTools.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1aa132302254cd386955a4c94487eab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Hotfix.meta b/Unity/Assets/Scripts/TH1_Logic/Hotfix.meta new file mode 100644 index 000000000..9daa2a198 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Hotfix.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46d4a569e4eb49caa31e4dc5a2522a85 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs new file mode 100644 index 000000000..fd5cf93a9 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs @@ -0,0 +1,117 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace TH1_Logic.Hotfix +{ + public static class HotfixBootstrap + { + private static bool _initialized; + + public static bool IsLoaded { get; private set; } + public static string LoadedAssemblyFullName { get; private set; } + + [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] + private static void AutoInitialize() + { + InitializeFromStreamingAssets(false); + } + + public static bool InitializeFromStreamingAssets(bool requireHotfix) + { + if (_initialized) return IsLoaded; + + try + { + var root = Path.Combine(Application.streamingAssetsPath, HotfixManifest.RootFolderName); + LoadAotMetadata(root); + + var hotfixPath = Path.Combine(root, HotfixManifest.HotfixDllFolderName, HotfixManifest.HotfixAssemblyFileName); + if (!File.Exists(hotfixPath)) + { + if (requireHotfix) + { + Debug.LogWarning($"[TH1.Hotfix] Hotfix dll missing: {hotfixPath}"); + } + + return false; + } + + var assembly = Assembly.Load(File.ReadAllBytes(hotfixPath)); + LoadedAssemblyFullName = assembly.FullName; + InvokeHotfixEntry(assembly); + _initialized = true; + IsLoaded = true; + Debug.Log($"[TH1.Hotfix] Loaded {LoadedAssemblyFullName}"); + return true; + } + catch (Exception e) + { + Debug.LogError($"[TH1.Hotfix] Initialize failed: {e}"); + return false; + } + } + + private static void LoadAotMetadata(string root) + { + var runtimeApiType = FindType("HybridCLR.RuntimeApi"); + var modeType = FindType("HybridCLR.HomologousImageMode"); + if (runtimeApiType == null || modeType == null) + { + return; + } + + var method = runtimeApiType.GetMethod( + "LoadMetadataForAOTAssembly", + BindingFlags.Public | BindingFlags.Static, + null, + new[] { typeof(byte[]), modeType }, + null); + if (method == null) + { + Debug.LogWarning("[TH1.Hotfix] HybridCLR RuntimeApi.LoadMetadataForAOTAssembly not found."); + return; + } + + var mode = Enum.Parse(modeType, "SuperSet"); + var aotDir = Path.Combine(root, HotfixManifest.AotMetadataFolderName); + + foreach (var fileName in HotfixManifest.AotMetadataAssemblyFileNames) + { + var path = Path.Combine(aotDir, fileName); + if (!File.Exists(path)) continue; + + var result = method.Invoke(null, new object[] { File.ReadAllBytes(path), mode }); + Debug.Log($"[TH1.Hotfix] Load AOT metadata {fileName}: {result}"); + } + } + + private static void InvokeHotfixEntry(Assembly assembly) + { + var entryType = assembly.GetType(HotfixManifest.EntryTypeName); + if (entryType == null) + { + Debug.LogWarning($"[TH1.Hotfix] Entry type not found: {HotfixManifest.EntryTypeName}"); + return; + } + + var method = entryType.GetMethod(HotfixManifest.EntryMethodName, BindingFlags.Public | BindingFlags.Static); + if (method == null) + { + Debug.LogWarning($"[TH1.Hotfix] Entry method not found: {HotfixManifest.EntryMethodName}"); + return; + } + + method.Invoke(null, null); + } + + private static Type FindType(string fullName) + { + return AppDomain.CurrentDomain.GetAssemblies() + .Select(assembly => assembly.GetType(fullName, false)) + .FirstOrDefault(type => type != null); + } + } +} diff --git a/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs.meta new file mode 100644 index 000000000..c4bb0c773 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixBootstrap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 219e5d567ddb4e638c9148177e53f87a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs new file mode 100644 index 000000000..c04451909 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs @@ -0,0 +1,25 @@ +namespace TH1_Logic.Hotfix +{ + public static class HotfixManifest + { + public const string BaseAppVersion = "0.1.0"; + public const string HotfixManifestVersion = "0.1.0"; + public const string MinCompatibleAppVersion = "0.1.0"; + + public const string RootFolderName = "HybridCLR"; + public const string AotMetadataFolderName = "AOTAssemblies"; + public const string HotfixDllFolderName = "HotfixDlls"; + + public const string HotfixAssemblyName = "TH1.Hotfix"; + public const string HotfixAssemblyFileName = HotfixAssemblyName + ".dll.bytes"; + public const string EntryTypeName = "TH1_Hotfix.HotfixEntry"; + public const string EntryMethodName = "Initialize"; + + public static readonly string[] AotMetadataAssemblyFileNames = + { + "mscorlib.dll.bytes", + "System.dll.bytes", + "System.Core.dll.bytes", + }; + } +} diff --git a/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs.meta b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs.meta new file mode 100644 index 000000000..36b3ad0f7 --- /dev/null +++ b/Unity/Assets/Scripts/TH1_Logic/Hotfix/HotfixManifest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c598a2c57a1a4f35bcf8a5b2b4f72621 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/Packages/manifest.json b/Unity/Packages/manifest.json index c2330d6da..4bc4c15a5 100644 --- a/Unity/Packages/manifest.json +++ b/Unity/Packages/manifest.json @@ -1,5 +1,6 @@ { "dependencies": { + "com.code-philosophy.hybridclr": "https://github.com/focus-creative-games/hybridclr_unity.git#v8.12.0", "com.cysharp.memorypack": "https://github.com/Cysharp/MemoryPack.git?path=src/MemoryPack.Unity/Assets/Plugins/MemoryPack#1.10.0", "com.github-glitchenzo.nugetforunity": "https://github.com/GlitchEnzo/NuGetForUnity.git?path=/src/NuGetForUnity", "com.tuyoogame.yooasset": "2.1.1", diff --git a/Unity/Packages/packages-lock.json b/Unity/Packages/packages-lock.json index bd6a67517..55200729b 100644 --- a/Unity/Packages/packages-lock.json +++ b/Unity/Packages/packages-lock.json @@ -1,5 +1,12 @@ { "dependencies": { + "com.code-philosophy.hybridclr": { + "version": "https://github.com/focus-creative-games/hybridclr_unity.git#v8.12.0", + "depth": 0, + "source": "git", + "dependencies": {}, + "hash": "e4def761d69b27b7b51a5de0f6d272861416a2d6" + }, "com.cysharp.memorypack": { "version": "https://github.com/Cysharp/MemoryPack.git?path=src/MemoryPack.Unity/Assets/Plugins/MemoryPack#1.10.0", "depth": 0, @@ -27,11 +34,11 @@ "url": "https://package.openupm.com" }, "com.unity.2d.animation": { - "version": "9.1.3", + "version": "9.0.3", "depth": 1, "source": "registry", "dependencies": { - "com.unity.2d.common": "8.0.4", + "com.unity.2d.common": "8.0.1", "com.unity.2d.sprite": "1.0.0", "com.unity.collections": "1.1.0", "com.unity.modules.animation": "1.0.0", @@ -40,7 +47,7 @@ "url": "https://packages.unity.com" }, "com.unity.2d.aseprite": { - "version": "1.1.6", + "version": "1.0.0", "depth": 1, "source": "registry", "dependencies": { @@ -52,7 +59,7 @@ "url": "https://packages.unity.com" }, "com.unity.2d.common": { - "version": "8.0.4", + "version": "8.0.1", "depth": 2, "source": "registry", "dependencies": { @@ -72,13 +79,13 @@ "url": "https://packages.unity.com" }, "com.unity.2d.psdimporter": { - "version": "8.0.5", + "version": "8.0.2", "depth": 1, "source": "registry", "dependencies": { - "com.unity.2d.common": "8.0.2", + "com.unity.2d.common": "8.0.1", "com.unity.2d.sprite": "1.0.0", - "com.unity.2d.animation": "9.1.1" + "com.unity.2d.animation": "9.0.1" }, "url": "https://packages.unity.com" }, @@ -89,11 +96,11 @@ "dependencies": {} }, "com.unity.2d.spriteshape": { - "version": "9.0.5", + "version": "9.0.2", "depth": 1, "source": "registry", "dependencies": { - "com.unity.2d.common": "8.0.4", + "com.unity.2d.common": "8.0.1", "com.unity.mathematics": "1.1.0", "com.unity.modules.physics2d": "1.0.0" }, @@ -109,7 +116,7 @@ } }, "com.unity.2d.tilemap.extras": { - "version": "3.1.3", + "version": "3.1.1", "depth": 1, "source": "registry", "dependencies": { @@ -121,12 +128,11 @@ "url": "https://packages.unity.com" }, "com.unity.burst": { - "version": "1.8.18", + "version": "1.8.8", "depth": 1, "source": "registry", "dependencies": { - "com.unity.mathematics": "1.2.1", - "com.unity.modules.jsonserialize": "1.0.0" + "com.unity.mathematics": "1.2.1" }, "url": "https://packages.unity.com" }, @@ -159,14 +165,14 @@ "depth": 0, "source": "builtin", "dependencies": { - "com.unity.2d.animation": "9.1.3", + "com.unity.2d.animation": "9.0.3", "com.unity.2d.pixel-perfect": "5.0.3", - "com.unity.2d.psdimporter": "8.0.5", + "com.unity.2d.psdimporter": "8.0.2", "com.unity.2d.sprite": "1.0.0", - "com.unity.2d.spriteshape": "9.0.5", + "com.unity.2d.spriteshape": "9.0.2", "com.unity.2d.tilemap": "1.0.0", - "com.unity.2d.tilemap.extras": "3.1.3", - "com.unity.2d.aseprite": "1.1.6" + "com.unity.2d.tilemap.extras": "3.1.1", + "com.unity.2d.aseprite": "1.0.0" } }, "com.unity.ide.rider": { @@ -195,7 +201,7 @@ "url": "https://packages.unity.com" }, "com.unity.render-pipelines.core": { - "version": "14.0.11", + "version": "14.0.8", "depth": 1, "source": "builtin", "dependencies": { @@ -211,22 +217,13 @@ "source": "builtin", "dependencies": { "com.unity.mathematics": "1.2.1", - "com.unity.burst": "1.8.9", - "com.unity.render-pipelines.core": "14.0.11", - "com.unity.shadergraph": "14.0.11", - "com.unity.render-pipelines.universal-config": "14.0.9" - } - }, - "com.unity.render-pipelines.universal-config": { - "version": "14.0.10", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.render-pipelines.core": "14.0.10" + "com.unity.burst": "1.8.4", + "com.unity.render-pipelines.core": "14.0.8", + "com.unity.shadergraph": "14.0.8" } }, "com.unity.scriptablebuildpipeline": { - "version": "1.21.25", + "version": "1.21.21", "depth": 1, "source": "registry", "dependencies": {}, @@ -240,11 +237,11 @@ "url": "https://packages.unity.com" }, "com.unity.shadergraph": { - "version": "14.0.11", + "version": "14.0.8", "depth": 1, "source": "builtin", "dependencies": { - "com.unity.render-pipelines.core": "14.0.11", + "com.unity.render-pipelines.core": "14.0.8", "com.unity.searcher": "4.9.2" } }, diff --git a/Unity/ProjectSettings/HybridCLRSettings.asset b/Unity/ProjectSettings/HybridCLRSettings.asset new file mode 100644 index 000000000..f10e0b45d --- /dev/null +++ b/Unity/ProjectSettings/HybridCLRSettings.asset @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e189374413a3f00468e49d51d8b27a09, type: 3} + m_Name: + m_EditorClassIdentifier: + enable: 1 + useGlobalIl2cpp: 0 + hybridclrRepoURL: https://gitee.com/focus-creative-games/hybridclr + il2cppPlusRepoURL: https://gitee.com/focus-creative-games/il2cpp_plus + hotUpdateAssemblyDefinitions: [] + hotUpdateAssemblies: + - TH1.Hotfix + preserveHotUpdateAssemblies: [] + hotUpdateDllCompileOutputRootDir: HybridCLRData/HotUpdateDlls + externalHotUpdateAssembliyDirs: [] + strippedAOTDllOutputRootDir: HybridCLRData/AssembliesPostIl2CppStrip + patchAOTAssemblies: + - mscorlib + - System + - System.Core + outputLinkFile: HybridCLRGenerate/link.xml + outputAOTGenericReferenceFile: HybridCLRGenerate/AOTGenericReferences.cs + maxGenericReferenceIteration: 10 + maxMethodBridgeGenericIteration: 10 diff --git a/Unity/ProjectSettings/ProjectSettings.asset b/Unity/ProjectSettings/ProjectSettings.asset index d56f2a480..b81f45c3d 100644 --- a/Unity/ProjectSettings/ProjectSettings.asset +++ b/Unity/ProjectSettings/ProjectSettings.asset @@ -13,7 +13,7 @@ PlayerSettings: useOnDemandResources: 0 accelerometerFrequency: 60 companyName: Remilia Command - productName: TOHOTOPIA + productName: TOHOTOPIA v0.7.3e defaultCursor: {fileID: 0} cursorHotspot: {x: 0, y: 0} m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} @@ -48,13 +48,12 @@ PlayerSettings: defaultScreenHeightWeb: 600 m_StereoRenderingPath: 0 m_ActiveColorSpace: 1 - unsupportedMSAAFallback: 0 m_SpriteBatchVertexThreshold: 300 m_MTRendering: 1 mipStripping: 0 numberOfMipsStripped: 0 numberOfMipsStrippedPerMipmapLimitGroup: {} - m_StackTraceTypes: 010000000100000000000000000000000100000001000000 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 iosUseCustomAppBackgroundBehavior: 0 @@ -76,7 +75,6 @@ PlayerSettings: androidMinimumWindowWidth: 400 androidMinimumWindowHeight: 300 androidFullscreenMode: 1 - androidAutoRotationBehavior: 1 defaultIsNativeResolution: 0 macRetinaSupport: 1 runInBackground: 0 @@ -84,11 +82,10 @@ PlayerSettings: muteOtherAudioSources: 0 Prepare IOS For Recording: 0 Force IOS Speakers When Recording: 0 - audioSpatialExperience: 0 deferSystemGesturesMode: 0 hideHomeButton: 0 submitAnalytics: 1 - usePlayerLog: 0 + usePlayerLog: 1 dedicatedServerOptimizations: 0 bakeCollisionMeshes: 0 forceSingleInstance: 0 @@ -138,8 +135,6 @@ PlayerSettings: vulkanEnableLateAcquireNextImage: 0 vulkanEnableCommandBufferRecycling: 1 loadStoreDebugModeEnabled: 0 - visionOSBundleVersion: 1.0 - tvOSBundleVersion: 1.0 bundleVersion: 0.7.3e preloadedAssets: [] metroInputSource: 0 @@ -152,7 +147,6 @@ PlayerSettings: isWsaHolographicRemotingEnabled: 0 enableFrameTimingStats: 0 enableOpenGLProfilerGPURecorders: 1 - allowHDRDisplaySupport: 0 useHDRDisplay: 0 hdrBitDepth: 0 m_ColorGamuts: 00000000 @@ -234,7 +228,6 @@ PlayerSettings: iOSMetalForceHardShadows: 0 metalEditorSupport: 1 metalAPIValidation: 1 - metalCompileShaderBinary: 0 iOSRenderExtraFrameOnPause: 0 iosCopyPluginsCodeInsteadOfSymlink: 0 appleDeveloperTeamID: @@ -447,7 +440,7 @@ PlayerSettings: playModeTestRunnerEnabled: 0 runPlayModeTestAsEditModeTest: 0 actionOnDotNetUnhandledException: 1 - enableInternalProfiler: 0 + enableInternalProfiler: 1 logObjCUncaughtExceptions: 1 enableCrashReportAPI: 0 cameraUsageDescription: @@ -462,7 +455,7 @@ PlayerSettings: switchSocketConcurrencyLimit: 14 switchScreenResolutionBehavior: 2 switchUseCPUProfiler: 0 - switchEnableFileSystemTrace: 0 + switchUseGOLDLinker: 0 switchLTOSetting: 0 switchApplicationID: 0x01004b9000490000 switchNSODependencies: @@ -592,6 +585,7 @@ PlayerSettings: switchSocketBufferEfficiency: 4 switchSocketInitializeEnabled: 1 switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 switchUseNewStyleFilepaths: 0 switchUseLegacyFmodPriorities: 0 switchUseMicroSleepForYield: 1 @@ -702,7 +696,7 @@ PlayerSettings: webGLMemoryGeometricGrowthCap: 96 webGLPowerPreference: 2 scriptingDefineSymbols: - Standalone: UNITY;ENABLE_VIEW;NODECANVAS;STEAMWORKS_NET;STEAM_CHANNEL + Standalone: UNITY;ENABLE_VIEW;NODECANVAS;STEAMWORKS_NET;STEAM_CHANNEL;USE_INPUT additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: @@ -756,7 +750,6 @@ PlayerSettings: metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} metroSplashScreenUseBackgroundColor: 0 - syncCapabilities: 0 platformCapabilities: {} metroTargetDeviceFamilies: {} metroFTAName: @@ -814,7 +807,7 @@ PlayerSettings: embeddedLinuxEnableGamepadInput: 1 hmiLogStartupTiming: 0 hmiCpuConfiguration: - apiCompatibilityLevel: 6 + apiCompatibilityLevel: 3 activeInputHandler: 0 windowsGamepadBackendHint: 0 cloudProjectId: e4975dbe-fc42-475f-a775-250045253218 diff --git a/Unity/ProjectSettings/ProjectVersion.txt b/Unity/ProjectSettings/ProjectVersion.txt index 720af25d1..31ad2467e 100644 --- a/Unity/ProjectSettings/ProjectVersion.txt +++ b/Unity/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2022.3.53f1c1 -m_EditorVersionWithRevision: 2022.3.53f1c1 (f16e16b78e06) +m_EditorVersion: 2022.3.8f1c1 +m_EditorVersionWithRevision: 2022.3.8f1c1 (4ec8ee1b2212) diff --git a/Unity/ProjectSettings/ShaderGraphSettings.asset b/Unity/ProjectSettings/ShaderGraphSettings.asset index 59c4647f4..a11ed5823 100644 --- a/Unity/ProjectSettings/ShaderGraphSettings.asset +++ b/Unity/ProjectSettings/ShaderGraphSettings.asset @@ -12,6 +12,5 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3} m_Name: m_EditorClassIdentifier: - shaderVariantLimit: 2048 customInterpolatorErrorThreshold: 32 customInterpolatorWarningThreshold: 16