diff --git a/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundle.cs b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundle.cs new file mode 100644 index 00000000..3f1cf7ab --- /dev/null +++ b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundle.cs @@ -0,0 +1,284 @@ +using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using MelonLoader; +using System; +using MelonLoader.Engine.Unity.Il2Cpp; + +namespace UnityEngine; + +public class Il2CppAssetBundle +{ + private readonly IntPtr bundleptr = IntPtr.Zero; + + public Il2CppAssetBundle(IntPtr ptr) { bundleptr = ptr; } + + static Il2CppAssetBundle() + { + get_isStreamedSceneAssetBundleDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::get_isStreamedSceneAssetBundle"); + returnMainAssetDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::returnMainAsset"); + ContainsDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::Contains"); + GetAllAssetNamesDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::GetAllAssetNames"); + GetAllScenePathsDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::GetAllScenePaths"); + LoadAsset_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)"); + LoadAssetAsync_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadAssetAsync_Internal"); + LoadAssetWithSubAssets_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal"); + LoadAssetWithSubAssetsAsync_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadAssetWithSubAssetsAsync_Internal"); + UnloadDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::Unload"); + } + + public bool isStreamedSceneAssetBundle + { + get + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (get_isStreamedSceneAssetBundleDelegateField == null) + throw new NullReferenceException("The get_isStreamedSceneAssetBundleDelegateField cannot be null."); + return get_isStreamedSceneAssetBundleDelegateField(bundleptr); + } + } + + public Object mainAsset + { + get + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (returnMainAssetDelegateField == null) + throw new NullReferenceException("The returnMainAssetDelegateField cannot be null."); + var intPtr = returnMainAssetDelegateField(bundleptr); + return ((intPtr != IntPtr.Zero) ? new Object(intPtr) : null); + } + } + + public bool Contains(string name) + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("The input asset name cannot be null or empty."); + if (ContainsDelegateField == null) + throw new NullReferenceException("The ContainsDelegateField cannot be null."); + return ContainsDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name)); + } + + public Il2CppStringArray AllAssetNames() => GetAllAssetNames(); + + public Il2CppStringArray GetAllAssetNames() + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (GetAllAssetNamesDelegateField == null) + throw new NullReferenceException("The GetAllAssetNamesDelegateField cannot be null."); + var intPtr = GetAllAssetNamesDelegateField(bundleptr); + return ((intPtr != IntPtr.Zero) ? new Il2CppStringArray(intPtr) : null); + } + + public Il2CppStringArray AllScenePaths() => GetAllScenePaths(); + + public Il2CppStringArray GetAllScenePaths() + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (GetAllScenePathsDelegateField == null) + throw new NullReferenceException("The GetAllScenePathsDelegateField cannot be null."); + var intPtr = GetAllScenePathsDelegateField(bundleptr); + return ((intPtr != IntPtr.Zero) ? new Il2CppStringArray(intPtr) : null); + } + + public Object Load(string name) => LoadAsset(name); + + public Object LoadAsset(string name) => LoadAsset(name); + + public T Load(string name) where T : Object => LoadAsset(name); + + public T LoadAsset(string name) where T : Object + { + if (!typeof(T).IsGeneratedAssemblyType()) + throw new NullReferenceException("The type must be a Generated Assembly Type."); + var intptr = LoadAsset(name, Il2CppType.Of().Pointer); + return ((intptr != IntPtr.Zero) ? intptr.Il2CppObjectPtrToIl2CppObject() : null); + } + + public Object Load(string name, Il2CppSystem.Type type) => LoadAsset(name, type); + + public Object LoadAsset(string name, Il2CppSystem.Type type) + { + if (type == null) + throw new NullReferenceException("The input type cannot be null."); + var intptr = LoadAsset(name, type.Pointer); + return ((intptr != IntPtr.Zero) ? new Object(intptr) : null); + } + + public IntPtr Load(string name, IntPtr typeptr) => LoadAsset(name, typeptr); + + public IntPtr LoadAsset(string name, IntPtr typeptr) + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("The input asset name cannot be null or empty."); + if (typeptr == IntPtr.Zero) + throw new NullReferenceException("The input type cannot be IntPtr.Zero"); + if (LoadAsset_InternalDelegateField == null) + throw new NullReferenceException("The LoadAsset_InternalDelegateField cannot be null."); + return LoadAsset_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name), typeptr); + } + + public Il2CppAssetBundleRequest LoadAssetAsync(string name) => LoadAssetAsync(name); + + public Il2CppAssetBundleRequest LoadAssetAsync(string name) where T : Object + { + if (!typeof(T).IsGeneratedAssemblyType()) + throw new NullReferenceException("The type must be a Generated Assembly Type."); + var intptr = LoadAssetAsync(name, Il2CppType.Of().Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppAssetBundleRequest(intptr) : null); + } + + public Il2CppAssetBundleRequest LoadAssetAsync(string name, Il2CppSystem.Type type) + { + if (type == null) + throw new NullReferenceException("The input type cannot be null."); + var intptr = LoadAssetAsync(name, type.Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppAssetBundleRequest(intptr) : null); + } + + public IntPtr LoadAssetAsync(string name, IntPtr typeptr) + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("The input asset name cannot be null or empty."); + if (typeptr == IntPtr.Zero) + throw new NullReferenceException("The input type cannot be IntPtr.Zero"); + if (LoadAssetAsync_InternalDelegateField == null) + throw new NullReferenceException("The LoadAssetAsync_InternalDelegateField cannot be null."); + return LoadAssetAsync_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name), typeptr); + } + + public Il2CppReferenceArray LoadAll() => LoadAllAssets(); + + public Il2CppReferenceArray LoadAllAssets() => LoadAllAssets(); + + public Il2CppReferenceArray LoadAll() where T : Object => LoadAllAssets(); + + public Il2CppReferenceArray LoadAllAssets() where T : Object + { + if (!typeof(T).IsGeneratedAssemblyType()) + throw new NullReferenceException("The type must be a Generated Assembly Type."); + var intptr = LoadAllAssets(Il2CppType.Of().Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppReferenceArray(intptr) : null); + } + + public Il2CppReferenceArray LoadAll(Il2CppSystem.Type type) => LoadAllAssets(type); + + public Il2CppReferenceArray LoadAllAssets(Il2CppSystem.Type type) + { + if (type == null) + throw new NullReferenceException("The input type cannot be null."); + var intptr = LoadAllAssets(type.Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppReferenceArray(intptr) : null); + } + + public IntPtr LoadAll(IntPtr typeptr) => LoadAllAssets(typeptr); + + public IntPtr LoadAllAssets(IntPtr typeptr) + { + if (typeptr == IntPtr.Zero) + throw new NullReferenceException("The input type cannot be IntPtr.Zero"); + if (LoadAssetWithSubAssets_InternalDelegateField == null) + throw new NullReferenceException("The LoadAssetWithSubAssets_InternalDelegateField cannot be null."); + return LoadAssetWithSubAssets_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(string.Empty), typeptr); + } + + public Il2CppReferenceArray LoadAssetWithSubAssets(string name) => LoadAssetWithSubAssets(name); + + public Il2CppReferenceArray LoadAssetWithSubAssets(string name) where T : Object + { + if (!typeof(T).IsGeneratedAssemblyType()) + throw new NullReferenceException("The type must be a Generated Assembly Type."); + var intptr = LoadAssetWithSubAssets(name, Il2CppType.Of().Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppReferenceArray(intptr) : null); + } + + public Il2CppReferenceArray LoadAssetWithSubAssets(string name, Il2CppSystem.Type type) + { + if (type == null) + throw new NullReferenceException("The input type cannot be null."); + var intptr = LoadAssetWithSubAssets(name, type.Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppReferenceArray(intptr) : null); + } + + public IntPtr LoadAssetWithSubAssets(string name, IntPtr typeptr) + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("The input asset name cannot be null or empty."); + if (typeptr == IntPtr.Zero) + throw new NullReferenceException("The input type cannot be IntPtr.Zero"); + if (LoadAssetWithSubAssets_InternalDelegateField == null) + throw new NullReferenceException("The LoadAssetWithSubAssets_InternalDelegateField cannot be null."); + return LoadAssetWithSubAssets_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name), typeptr); + } + public Il2CppAssetBundleRequest LoadAssetWithSubAssetsAsync(string name) => LoadAssetWithSubAssetsAsync(name); + + public Il2CppAssetBundleRequest LoadAssetWithSubAssetsAsync(string name) where T : Object + { + if (!typeof(T).IsGeneratedAssemblyType()) + throw new NullReferenceException("The type must be a Generated Assembly Type."); + var intptr = LoadAssetWithSubAssetsAsync(name, Il2CppType.Of().Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppAssetBundleRequest(intptr) : null); + } + + public Il2CppAssetBundleRequest LoadAssetWithSubAssetsAsync(string name, Il2CppSystem.Type type) + { + if (type == null) + throw new NullReferenceException("The input type cannot be null."); + var intptr = LoadAssetWithSubAssetsAsync(name, type.Pointer); + return ((intptr != IntPtr.Zero) ? new Il2CppAssetBundleRequest(intptr) : null); + } + + public IntPtr LoadAssetWithSubAssetsAsync(string name, IntPtr typeptr) + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("The input asset name cannot be null or empty."); + if (typeptr == IntPtr.Zero) + throw new NullReferenceException("The input type cannot be IntPtr.Zero"); + if (LoadAssetWithSubAssetsAsync_InternalDelegateField == null) + throw new NullReferenceException("The LoadAssetWithSubAssetsAsync_InternalDelegateField cannot be null."); + return LoadAssetWithSubAssetsAsync_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name), typeptr); + } + + public void Unload(bool unloadAllLoadedObjects) + { + if (bundleptr == IntPtr.Zero) + throw new NullReferenceException("The bundleptr cannot be IntPtr.Zero"); + if (UnloadDelegateField == null) + throw new NullReferenceException("The UnloadDelegateField cannot be null."); + UnloadDelegateField(bundleptr, unloadAllLoadedObjects); + } + + private delegate bool get_isStreamedSceneAssetBundleDelegate(IntPtr _this); + private static readonly returnMainAssetDelegate returnMainAssetDelegateField; + private delegate IntPtr returnMainAssetDelegate(IntPtr _this); + private static readonly get_isStreamedSceneAssetBundleDelegate get_isStreamedSceneAssetBundleDelegateField; + private delegate bool ContainsDelegate(IntPtr _this, IntPtr name); + private static readonly ContainsDelegate ContainsDelegateField; + private delegate IntPtr GetAllAssetNamesDelegate(IntPtr _this); + private static readonly GetAllAssetNamesDelegate GetAllAssetNamesDelegateField; + private delegate IntPtr GetAllScenePathsDelegate(IntPtr _this); + private static readonly GetAllScenePathsDelegate GetAllScenePathsDelegateField; + private delegate IntPtr LoadAsset_InternalDelegate(IntPtr _this, IntPtr name, IntPtr type); + private static readonly LoadAsset_InternalDelegate LoadAsset_InternalDelegateField; + private delegate IntPtr LoadAssetAsync_InternalDelegate(IntPtr _this, IntPtr name, IntPtr type); + private static readonly LoadAssetAsync_InternalDelegate LoadAssetAsync_InternalDelegateField; + private delegate IntPtr LoadAssetWithSubAssets_InternalDelegate(IntPtr _this, IntPtr name, IntPtr type); + private static readonly LoadAssetWithSubAssets_InternalDelegate LoadAssetWithSubAssets_InternalDelegateField; + private delegate IntPtr LoadAssetWithSubAssetsAsync_InternalDelegate(IntPtr _this, IntPtr name, IntPtr type); + private static readonly LoadAssetWithSubAssetsAsync_InternalDelegate LoadAssetWithSubAssetsAsync_InternalDelegateField; + private delegate void UnloadDelegate(IntPtr _this, bool unloadAllObjects); + private static readonly UnloadDelegate UnloadDelegateField; +} diff --git a/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundleManager.cs b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundleManager.cs new file mode 100644 index 00000000..70956fa9 --- /dev/null +++ b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundleManager.cs @@ -0,0 +1,138 @@ +using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using Il2CppSystem.IO; + +namespace UnityEngine; + +public class Il2CppAssetBundleManager +{ + static Il2CppAssetBundleManager() + { + GetAllLoadedAssetBundles_NativeDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::GetAllLoadedAssetBundles_Native"); + LoadFromFile_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadFromFile_Internal(System.String,System.UInt32,System.UInt64)"); + LoadFromFileAsync_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadFromFileAsync_Internal"); + LoadFromMemory_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadFromMemory_Internal"); + LoadFromMemoryAsync_InternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadFromMemoryAsync_Internal"); + LoadFromStreamInternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadFromStreamInternal"); + LoadFromStreamAsyncInternalDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::LoadFromStreamAsyncInternal"); + UnloadAllAssetBundlesDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundle::UnloadAllAssetBundles"); + } + + public static Il2CppAssetBundle[] GetAllLoadedAssetBundles() + { + if (GetAllLoadedAssetBundles_NativeDelegateField == null) + throw new System.NullReferenceException("The GetAllLoadedAssetBundles_NativeDelegateField cannot be null."); + var intPtr = GetAllLoadedAssetBundles_NativeDelegateField(); + var refarr = ((intPtr != System.IntPtr.Zero) ? new Il2CppReferenceArray(intPtr) : null); + if (refarr == null) + throw new System.NullReferenceException("The refarr cannot be null."); + System.Collections.Generic.List bundlelist = []; + for (var i = 0; i < refarr.Length; i++) + bundlelist.Add(new Il2CppAssetBundle(IL2CPP.Il2CppObjectBaseToPtrNotNull(refarr[i]))); + return bundlelist.ToArray(); + } + + public static Il2CppAssetBundle LoadFromFile(string path) => LoadFromFile(path, 0u, 0UL); + + public static Il2CppAssetBundle LoadFromFile(string path, uint crc) => LoadFromFile(path, crc, 0UL); + + public static Il2CppAssetBundle LoadFromFile(string path, uint crc, ulong offset) + { + if (string.IsNullOrEmpty(path)) + throw new System.ArgumentException("The input asset bundle path cannot be null or empty."); + if (LoadFromFile_InternalDelegateField == null) + throw new System.NullReferenceException("The LoadFromFile_InternalDelegateField cannot be null."); + var intPtr = LoadFromFile_InternalDelegateField(IL2CPP.ManagedStringToIl2Cpp(path), crc, offset); + return ((intPtr != System.IntPtr.Zero) ? new Il2CppAssetBundle(intPtr) : null); + } + + public static Il2CppAssetBundleCreateRequest LoadFromFileAsync(string path) => LoadFromFileAsync(path, 0u, 0UL); + + public static Il2CppAssetBundleCreateRequest LoadFromFileAsync(string path, uint crc) => LoadFromFileAsync(path, crc, 0UL); + + public static Il2CppAssetBundleCreateRequest LoadFromFileAsync(string path, uint crc, ulong offset) + { + if (string.IsNullOrEmpty(path)) + throw new System.ArgumentException("The input asset bundle path cannot be null or empty."); + if (LoadFromFileAsync_InternalDelegateField == null) + throw new System.NullReferenceException("The LoadFromFileAsync_InternalDelegateField cannot be null."); + var intPtr = LoadFromFileAsync_InternalDelegateField(IL2CPP.ManagedStringToIl2Cpp(path), crc, offset); + return ((intPtr != System.IntPtr.Zero) ? new Il2CppAssetBundleCreateRequest(intPtr) : null); + } + + public static Il2CppAssetBundle LoadFromMemory(Il2CppStructArray binary) => LoadFromMemory(binary, 0u); + + public static Il2CppAssetBundle LoadFromMemory(Il2CppStructArray binary, uint crc) + { + if (binary == null) + throw new System.ArgumentException("The binary cannot be null or empty."); + if (LoadFromMemory_InternalDelegateField == null) + throw new System.NullReferenceException("The LoadFromMemory_InternalDelegateField cannot be null."); + var intPtr = LoadFromMemory_InternalDelegateField(IL2CPP.Il2CppObjectBaseToPtrNotNull(binary), crc); + return ((intPtr != System.IntPtr.Zero) ? new Il2CppAssetBundle(intPtr) : null); + } + + public static Il2CppAssetBundleCreateRequest LoadFromMemoryAsync(Il2CppStructArray binary) => LoadFromMemoryAsync(binary, 0u); + + public static Il2CppAssetBundleCreateRequest LoadFromMemoryAsync(Il2CppStructArray binary, uint crc) + { + if (binary == null) + throw new System.ArgumentException("The binary cannot be null or empty."); + if (LoadFromMemoryAsync_InternalDelegateField == null) + throw new System.NullReferenceException("The LoadFromMemoryAsync_InternalDelegateField cannot be null."); + var intPtr = LoadFromMemoryAsync_InternalDelegateField(IL2CPP.Il2CppObjectBaseToPtrNotNull(binary), crc); + return ((intPtr != System.IntPtr.Zero) ? new Il2CppAssetBundleCreateRequest(intPtr) : null); + } + + public static Il2CppAssetBundle LoadFromStream(Stream stream) => LoadFromStream(stream, 0u, 0u); + + public static Il2CppAssetBundle LoadFromStream(Stream stream, uint crc) => LoadFromStream(stream, crc, 0u); + + public static Il2CppAssetBundle LoadFromStream(Stream stream, uint crc, uint managedReadBufferSize) + { + if (stream == null) + throw new System.ArgumentException("The stream cannot be null or empty."); + if (LoadFromStreamInternalDelegateField == null) + throw new System.NullReferenceException("The LoadFromStreamInternalDelegateField cannot be null."); + var intPtr = LoadFromStreamInternalDelegateField(IL2CPP.Il2CppObjectBaseToPtrNotNull(stream), crc, managedReadBufferSize); + return ((intPtr != System.IntPtr.Zero) ? new Il2CppAssetBundle(intPtr) : null); + } + + public static Il2CppAssetBundleCreateRequest LoadFromStreamAsync(Stream stream) => LoadFromStreamAsync(stream, 0u, 0u); + + public static Il2CppAssetBundleCreateRequest LoadFromStreamAsync(Stream stream, uint crc) => LoadFromStreamAsync(stream, crc, 0u); + + public static Il2CppAssetBundleCreateRequest LoadFromStreamAsync(Stream stream, uint crc, uint managedReadBufferSize) + { + if (stream == null) + throw new System.ArgumentException("The stream cannot be null or empty."); + if (LoadFromStreamAsyncInternalDelegateField == null) + throw new System.NullReferenceException("The LoadFromStreamAsyncInternalDelegateField cannot be null."); + var intPtr = LoadFromStreamAsyncInternalDelegateField(IL2CPP.Il2CppObjectBaseToPtrNotNull(stream), crc, managedReadBufferSize); + return ((intPtr != System.IntPtr.Zero) ? new Il2CppAssetBundleCreateRequest(intPtr) : null); + } + + public static void UnloadAllAssetBundles(bool unloadAllObjects) + { + if (UnloadAllAssetBundlesDelegateField == null) + throw new System.NullReferenceException("The UnloadAllAssetBundlesDelegateField cannot be null."); + UnloadAllAssetBundlesDelegateField(unloadAllObjects); + } + + private delegate System.IntPtr GetAllLoadedAssetBundles_NativeDelegate(); + private static readonly GetAllLoadedAssetBundles_NativeDelegate GetAllLoadedAssetBundles_NativeDelegateField; + private delegate System.IntPtr LoadFromFile_InternalDelegate(System.IntPtr path, uint crc, ulong offset); + private static readonly LoadFromFile_InternalDelegate LoadFromFile_InternalDelegateField; + private delegate System.IntPtr LoadFromFileAsync_InternalDelegate(System.IntPtr path, uint crc, ulong offset); + private static readonly LoadFromFileAsync_InternalDelegate LoadFromFileAsync_InternalDelegateField; + private delegate System.IntPtr LoadFromMemory_InternalDelegate(System.IntPtr binary, uint crc); + private static readonly LoadFromMemory_InternalDelegate LoadFromMemory_InternalDelegateField; + private delegate System.IntPtr LoadFromMemoryAsync_InternalDelegate(System.IntPtr binary, uint crc); + private static readonly LoadFromMemoryAsync_InternalDelegate LoadFromMemoryAsync_InternalDelegateField; + private delegate System.IntPtr LoadFromStreamInternalDelegate(System.IntPtr stream, uint crc, uint managedReadBufferSize); + private static readonly LoadFromStreamInternalDelegate LoadFromStreamInternalDelegateField; + private delegate System.IntPtr LoadFromStreamAsyncInternalDelegate(System.IntPtr stream, uint crc, uint managedReadBufferSize); + private static readonly LoadFromStreamAsyncInternalDelegate LoadFromStreamAsyncInternalDelegateField; + private delegate System.IntPtr UnloadAllAssetBundlesDelegate(bool unloadAllObjects); + private static readonly UnloadAllAssetBundlesDelegate UnloadAllAssetBundlesDelegateField; +} diff --git a/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundleRequest.cs b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundleRequest.cs new file mode 100644 index 00000000..642403b3 --- /dev/null +++ b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppAssetBundleRequest.cs @@ -0,0 +1,73 @@ +using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using System; + +namespace UnityEngine; + +public class Il2CppAssetBundleCreateRequest : AsyncOperation +{ + public Il2CppAssetBundleCreateRequest(IntPtr ptr) : base(ptr) { } + + static Il2CppAssetBundleCreateRequest() + { + Il2CppInterop.Runtime.Injection.ClassInjector.RegisterTypeInIl2Cpp(); + + get_assetBundleDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundleCreateRequest::get_assetBundle"); + } + + public Il2CppAssetBundle assetBundle + { + [Il2CppInterop.Runtime.Attributes.HideFromIl2Cpp] + get + { + var ptr = get_assetBundleDelegateField(this.Pointer); + if (ptr == IntPtr.Zero) + return null; + return new Il2CppAssetBundle(ptr); + } + } + + private delegate IntPtr get_assetBundleDelegate(IntPtr _this); + private static readonly get_assetBundleDelegate get_assetBundleDelegateField; +} + +public class Il2CppAssetBundleRequest : AsyncOperation +{ + public Il2CppAssetBundleRequest(IntPtr ptr) : base(ptr) { } + + static Il2CppAssetBundleRequest() + { + Il2CppInterop.Runtime.Injection.ClassInjector.RegisterTypeInIl2Cpp(); + + get_assetDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundleRequest::get_asset"); + get_allAssetsDelegateField = IL2CPP.ResolveICall("UnityEngine.AssetBundleRequest::get_allAssets"); + } + + public Object asset + { + get + { + var ptr = get_assetDelegateField(this.Pointer); + if (ptr == IntPtr.Zero) + return null; + return new Object(ptr); + } + } + + public Il2CppReferenceArray allAssets + { + get + { + var ptr = get_allAssetsDelegateField(this.Pointer); + if (ptr == IntPtr.Zero) + return null; + return new Il2CppReferenceArray(ptr); + } + } + + private delegate IntPtr get_assetDelegate(IntPtr _this); + private static readonly get_assetDelegate get_assetDelegateField; + + private delegate IntPtr get_allAssetsDelegate(IntPtr _this); + private static readonly get_allAssetsDelegate get_allAssetsDelegateField; +} \ No newline at end of file diff --git a/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppExtensions.cs b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppExtensions.cs index 33425092..40343971 100644 --- a/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppExtensions.cs +++ b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppExtensions.cs @@ -1,4 +1,11 @@ -using System.Collections; +using Il2CppInterop.Common; +using Il2CppInterop.Common.Attributes; +using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.Injection; +using Il2CppInterop.Runtime.InteropTypes; +using System; +using System.Collections; +using System.Reflection; using UnityEngine; namespace MelonLoader.Engine.Unity.Il2Cpp @@ -7,16 +14,68 @@ public static class Il2CppExtensions { #region Coroutine - internal static Coroutine StartCoroutine(this T behaviour, IEnumerator enumerator) + public static Coroutine StartCoroutine(this T behaviour, IEnumerator enumerator) where T : MonoBehaviour => behaviour.StartCoroutine( new Il2CppSystem.Collections.IEnumerator( new Il2CppEnumeratorWrapper(enumerator).Pointer)); - internal static void StopCoroutine(this T behaviour, Coroutine routine) + public static void StopCoroutine(this T behaviour, Coroutine routine) where T : MonoBehaviour => behaviour.StopCoroutine(routine); #endregion + + #region Interop + + public static int? GetIl2CppMethodCallerCount(this MethodBase method) + { + CallerCountAttribute att = method.GetCustomAttribute(); + if (att == null) + return null; + return att.Count; + } + + public static FieldInfo MethodBaseToIl2CppFieldInfo(this MethodBase method) + => Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method); + + public static void RegisterTypeInIl2CppDomain(this Type type, bool logSuccess) + => ClassInjector.RegisterTypeInIl2Cpp(type, new() { LogSuccess = logSuccess }); + public static void RegisterTypeInIl2CppDomainWithInterfaces(this Type type, Type[] interfaces, bool logSuccess) + => ClassInjector.RegisterTypeInIl2Cpp(type, new() { LogSuccess = logSuccess, Interfaces = interfaces }); + + public static bool IsGeneratedAssemblyType(this Type type) + => type.IsInheritedFromIl2CppObjectBase() && !type.IsInjectedType(); + + public static bool IsInheritedFromIl2CppObjectBase(this Type type) + => (type != null) && type.IsSubclassOf(typeof(Il2CppObjectBase)); + + public static bool IsInjectedType(this Type type) + { + IntPtr ptr = GetClassPointerForType(type); + return ptr != IntPtr.Zero && RuntimeSpecificsStore.IsInjected(ptr); + } + + public static IntPtr GetClassPointerForType(this Type type) + { + if (type == typeof(void)) return Il2CppClassPointerStore.NativeClassPtr; + return (IntPtr)typeof(Il2CppClassPointerStore<>).MakeGenericType(type) + .GetField(nameof(Il2CppClassPointerStore.NativeClassPtr)).GetValue(null); + } + + public static T Il2CppObjectPtrToIl2CppObject(this IntPtr ptr) + { + if (ptr == IntPtr.Zero) + throw new NullReferenceException("The ptr cannot be IntPtr.Zero."); + if (!IsGeneratedAssemblyType(typeof(T))) + throw new NullReferenceException("The type must be a Generated Assembly Type."); + return (T)typeof(T).GetConstructor(BindingFlags.Public | BindingFlags.Instance, + null, + [typeof(IntPtr)], + Array.Empty()) + .Invoke([ptr]); + } + + #endregion } } diff --git a/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppImageConversionManager.cs b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppImageConversionManager.cs new file mode 100644 index 00000000..01128bc5 --- /dev/null +++ b/Dependencies/Modules/Engines/Unity/Il2Cpp/Unity.Il2Cpp.Shared/Il2CppImageConversionManager.cs @@ -0,0 +1,101 @@ +using Il2CppInterop.Runtime; +using Il2CppInterop.Runtime.InteropTypes.Arrays; +using System; + +namespace UnityEngine; + +public class Il2CppImageConversionManager +{ + static Il2CppImageConversionManager() + { + EncodeToTGADelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToTGA"); + EncodeToEXRDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToEXR"); + EncodeToPNGDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToPNG"); + EncodeToJPGDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::EncodeToJPG"); + LoadImageDelegateField = IL2CPP.ResolveICall("UnityEngine.ImageConversion::LoadImage"); + } + + public static Il2CppStructArray EncodeToTGA(Texture2D tex) + { + if (tex == null) + throw new ArgumentException("The texture cannot be null."); + if (EncodeToTGADelegateField == null) + throw new NullReferenceException("The EncodeToTGADelegateField cannot be null."); + Il2CppStructArray il2CppStructArray; + var encodeToTGADelegateField = EncodeToTGADelegateField(IL2CPP.Il2CppObjectBaseToPtr(tex)); + if (encodeToTGADelegateField != IntPtr.Zero) + il2CppStructArray = new Il2CppStructArray(encodeToTGADelegateField); + else + il2CppStructArray = null; + return il2CppStructArray; + } + + public static Il2CppStructArray EncodeToPNG(Texture2D tex) + { + if (tex == null) + throw new ArgumentException("The texture cannot be null."); + if (EncodeToPNGDelegateField == null) + throw new NullReferenceException("The EncodeToPNGDelegateField cannot be null."); + Il2CppStructArray il2CppStructArray; + var encodeToPNGDelegateField = EncodeToPNGDelegateField(IL2CPP.Il2CppObjectBaseToPtr(tex)); + if (encodeToPNGDelegateField != IntPtr.Zero) + il2CppStructArray = new Il2CppStructArray(encodeToPNGDelegateField); + else + il2CppStructArray = null; + return il2CppStructArray; + } + + public static Il2CppStructArray EncodeToJPG(Texture2D tex, int quality) + { + if (tex == null) + throw new ArgumentException("The texture cannot be null."); + if (EncodeToJPGDelegateField == null) + throw new NullReferenceException("The EncodeToJPGDelegateField cannot be null."); + Il2CppStructArray il2CppStructArray; + var encodeToJPGDelegateField = EncodeToJPGDelegateField(IL2CPP.Il2CppObjectBaseToPtr(tex), quality); + if (encodeToJPGDelegateField != IntPtr.Zero) + il2CppStructArray = new Il2CppStructArray(encodeToJPGDelegateField); + else + il2CppStructArray = null; + return il2CppStructArray; + } + public static Il2CppStructArray EncodeToJPG(Texture2D tex) => EncodeToJPG(tex, 75); + + public static Il2CppStructArray EncodeToEXR(Texture2D tex, Texture2D.EXRFlags flags) + { + if (tex == null) + throw new ArgumentException("The texture cannot be null."); + if (EncodeToEXRDelegateField == null) + throw new NullReferenceException("The EncodeToEXRDelegateField cannot be null."); + Il2CppStructArray il2CppStructArray; + var encodeToEXRDelegateField = EncodeToEXRDelegateField(IL2CPP.Il2CppObjectBaseToPtr(tex), flags); + if (encodeToEXRDelegateField != IntPtr.Zero) + il2CppStructArray = new Il2CppStructArray(encodeToEXRDelegateField); + else + il2CppStructArray = null; + return il2CppStructArray; + } + public static Il2CppStructArray EncodeToEXR(Texture2D tex) => EncodeToEXR(tex, 0); + + public static bool LoadImage(Texture2D tex, Il2CppStructArray data, bool markNonReadable) + { + if (tex == null) + throw new ArgumentException("The texture cannot be null."); + if (data == null) + throw new ArgumentException("The data cannot be null."); + if (LoadImageDelegateField == null) + throw new NullReferenceException("The LoadImageDelegateField cannot be null."); + return LoadImageDelegateField(IL2CPP.Il2CppObjectBaseToPtr(tex), IL2CPP.Il2CppObjectBaseToPtr(data), markNonReadable); + } + public static bool LoadImage(Texture2D tex, Il2CppStructArray data) => LoadImage(tex, data, false); + + private delegate IntPtr TextureOnlyDelegate(IntPtr tex); + private delegate IntPtr TextureAndQualityDelegate(IntPtr tex, int quality); + private delegate IntPtr TextureAndFlagDelegate(IntPtr tex, Texture2D.EXRFlags flags); + private delegate bool LoadImageDelegate(IntPtr tex, IntPtr data, bool markNonReadable); + private readonly static TextureAndFlagDelegate EncodeToEXRDelegateField; + private readonly static TextureOnlyDelegate EncodeToTGADelegateField; + private readonly static TextureOnlyDelegate EncodeToPNGDelegateField; + private readonly static TextureAndQualityDelegate EncodeToJPGDelegateField; + private readonly static LoadImageDelegate LoadImageDelegateField; +} \ No newline at end of file