Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 213 additions & 34 deletions UnityUtilities/UnityEngine.Il2CppAssetBundleManager/Il2CppAssetBundle.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,62 @@
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using MelonLoader;
using MelonLoader.InternalUtils;
using System;
using System.Runtime.InteropServices;
using System.Xml.Linq;

namespace UnityEngine;

public class Il2CppAssetBundle
{
// Since here we're not using il2cpp_runtime_invoke, but we're resolving the icalls directly, we need to unwrap the object by ourselves.
private readonly IntPtr wrappedBundlePtr = IntPtr.Zero;
private readonly IntPtr bundleptr = IntPtr.Zero;

public Il2CppAssetBundle(IntPtr ptr) { bundleptr = ptr; }
public Il2CppAssetBundle(IntPtr ptr)
{
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
wrappedBundlePtr = ptr;
bundleptr = Marshal.ReadIntPtr(wrappedBundlePtr + 0x10); // Skip the Il2CppObject header + read the REAL object ptr from there.
}
else
{
bundleptr = ptr;
}
}

static Il2CppAssetBundle()
{
get_isStreamedSceneAssetBundleDelegateField = IL2CPP.ResolveICall<get_isStreamedSceneAssetBundleDelegate>("UnityEngine.AssetBundle::get_isStreamedSceneAssetBundle");
returnMainAssetDelegateField = IL2CPP.ResolveICall<returnMainAssetDelegate>("UnityEngine.AssetBundle::returnMainAsset");
ContainsDelegateField = IL2CPP.ResolveICall<ContainsDelegate>("UnityEngine.AssetBundle::Contains");
GetAllAssetNamesDelegateField = IL2CPP.ResolveICall<GetAllAssetNamesDelegate>("UnityEngine.AssetBundle::GetAllAssetNames");
GetAllScenePathsDelegateField = IL2CPP.ResolveICall<GetAllScenePathsDelegate>("UnityEngine.AssetBundle::GetAllScenePaths");
LoadAsset_InternalDelegateField = IL2CPP.ResolveICall<LoadAsset_InternalDelegate>("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)");
LoadAssetAsync_InternalDelegateField = IL2CPP.ResolveICall<LoadAssetAsync_InternalDelegate>("UnityEngine.AssetBundle::LoadAssetAsync_Internal");
LoadAssetWithSubAssets_InternalDelegateField = IL2CPP.ResolveICall<LoadAssetWithSubAssets_InternalDelegate>("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal");
LoadAssetWithSubAssetsAsync_InternalDelegateField = IL2CPP.ResolveICall<LoadAssetWithSubAssetsAsync_InternalDelegate>("UnityEngine.AssetBundle::LoadAssetWithSubAssetsAsync_Internal");
UnloadDelegateField = IL2CPP.ResolveICall<UnloadDelegate>("UnityEngine.AssetBundle::Unload");
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
get_isStreamedSceneAssetBundleDelegateField = IL2CPP.ResolveICall<get_isStreamedSceneAssetBundleDelegate>("UnityEngine.AssetBundle::get_isStreamedSceneAssetBundle_Injected");
returnMainAssetDelegateField = IL2CPP.ResolveICall<returnMainAssetDelegate>("UnityEngine.AssetBundle::returnMainAsset_Injected");
ContainsDelegateField_Unity6 = IL2CPP.ResolveICall<ContainsDelegate_Unity6>("UnityEngine.AssetBundle::Contains_Injected");
GetAllAssetNamesDelegateField = IL2CPP.ResolveICall<GetAllAssetNamesDelegate>("UnityEngine.AssetBundle::GetAllAssetNames_Injected");
GetAllScenePathsDelegateField = IL2CPP.ResolveICall<GetAllScenePathsDelegate>("UnityEngine.AssetBundle::GetAllScenePaths_Injected");
LoadAsset_InternalDelegateField_Unity6 = IL2CPP.ResolveICall<LoadAsset_InternalDelegate_Unity6>("UnityEngine.AssetBundle::LoadAsset_Internal_Injected(System.String,System.Type)");
LoadAssetAsync_InternalDelegateField_Unity6 = IL2CPP.ResolveICall<LoadAssetAsync_InternalDelegate_Unity6>("UnityEngine.AssetBundle::LoadAssetAsync_Internal_Injected");
LoadAssetWithSubAssets_InternalDelegateField_Unity6 = IL2CPP.ResolveICall<LoadAssetWithSubAssets_InternalDelegate_Unity6>("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal_Injected");
LoadAssetWithSubAssetsAsync_InternalDelegateField_Unity6 = IL2CPP.ResolveICall<LoadAssetWithSubAssetsAsync_InternalDelegate_Unity6>("UnityEngine.AssetBundle::LoadAssetWithSubAssetsAsync_Internal_Injected");
UnloadDelegateField = IL2CPP.ResolveICall<UnloadDelegate>("UnityEngine.AssetBundle::Unload_Injected");
}
else
{
get_isStreamedSceneAssetBundleDelegateField = IL2CPP.ResolveICall<get_isStreamedSceneAssetBundleDelegate>("UnityEngine.AssetBundle::get_isStreamedSceneAssetBundle");
returnMainAssetDelegateField = IL2CPP.ResolveICall<returnMainAssetDelegate>("UnityEngine.AssetBundle::returnMainAsset");
ContainsDelegateField = IL2CPP.ResolveICall<ContainsDelegate>("UnityEngine.AssetBundle::Contains");
GetAllAssetNamesDelegateField = IL2CPP.ResolveICall<GetAllAssetNamesDelegate>("UnityEngine.AssetBundle::GetAllAssetNames");
GetAllScenePathsDelegateField = IL2CPP.ResolveICall<GetAllScenePathsDelegate>("UnityEngine.AssetBundle::GetAllScenePaths");
LoadAsset_InternalDelegateField = IL2CPP.ResolveICall<LoadAsset_InternalDelegate>("UnityEngine.AssetBundle::LoadAsset_Internal(System.String,System.Type)");
LoadAssetAsync_InternalDelegateField = IL2CPP.ResolveICall<LoadAssetAsync_InternalDelegate>("UnityEngine.AssetBundle::LoadAssetAsync_Internal");
LoadAssetWithSubAssets_InternalDelegateField = IL2CPP.ResolveICall<LoadAssetWithSubAssets_InternalDelegate>("UnityEngine.AssetBundle::LoadAssetWithSubAssets_Internal");
LoadAssetWithSubAssetsAsync_InternalDelegateField = IL2CPP.ResolveICall<LoadAssetWithSubAssetsAsync_InternalDelegate>("UnityEngine.AssetBundle::LoadAssetWithSubAssetsAsync_Internal");
UnloadDelegateField = IL2CPP.ResolveICall<UnloadDelegate>("UnityEngine.AssetBundle::Unload");
}
}

public bool isStreamedSceneAssetBundle
Expand All @@ -45,8 +79,17 @@ public Object mainAsset
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);
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
// Signature doesn't change, but the resulting ptr is actually a gchandle in Unity 6.
var gcHandle = returnMainAssetDelegateField(bundleptr);
return ((gcHandle != IntPtr.Zero) ? new Object(Marshal.ReadIntPtr(gcHandle)) : null);
}
else
{
var intPtr = returnMainAssetDelegateField(bundleptr);
return ((intPtr != IntPtr.Zero) ? new Object(intPtr) : null);
}
}
}

Expand All @@ -56,9 +99,29 @@ public bool Contains(string name)
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));
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
if (ContainsDelegateField_Unity6 == null)
throw new NullReferenceException("The ContainsDelegateField_Unity6 cannot be null.");
unsafe
{
fixed (char* charPtr = name)
{
var span = new ManagedSpanWrapper
{
begin = charPtr,
length = name.Length
};
return ContainsDelegateField_Unity6(bundleptr, ref span);
}
}
}
else
{
if (ContainsDelegateField == null)
throw new NullReferenceException("The ContainsDelegateField cannot be null.");
return ContainsDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name));
}
}

public Il2CppStringArray AllAssetNames() => GetAllAssetNames();
Expand Down Expand Up @@ -119,9 +182,30 @@ public IntPtr LoadAsset(string name, IntPtr typeptr)
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);
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
if (LoadAsset_InternalDelegateField_Unity6 == null)
throw new NullReferenceException("The LoadAsset_InternalDelegateField_Unity6 cannot be null.");
unsafe
{
fixed (char* charPtr = name)
{
var span = new ManagedSpanWrapper
{
begin = charPtr,
length = name.Length
};
var gcHandle = LoadAsset_InternalDelegateField_Unity6(bundleptr, ref span, typeptr);
return ((gcHandle != IntPtr.Zero) ? Marshal.ReadIntPtr(gcHandle) : IntPtr.Zero);
}
}
}
else
{
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<Object>(name);
Expand Down Expand Up @@ -150,9 +234,29 @@ public IntPtr LoadAssetAsync(string name, IntPtr typeptr)
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);
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
if (LoadAssetAsync_InternalDelegateField_Unity6 == null)
throw new NullReferenceException("The LoadAssetAsync_InternalDelegateField_Unity6 cannot be null.");
unsafe
{
fixed (char* charPtr = name)
{
var span = new ManagedSpanWrapper
{
begin = charPtr,
length = name.Length
};
return LoadAssetAsync_InternalDelegateField_Unity6(bundleptr, ref span, typeptr);
}
}
}
else
{
if (LoadAssetAsync_InternalDelegateField == null)
throw new NullReferenceException("The LoadAssetAsync_InternalDelegateField cannot be null.");
return LoadAssetAsync_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(name), typeptr);
}
}

public Il2CppReferenceArray<Object> LoadAll() => LoadAllAssets();
Expand Down Expand Up @@ -185,9 +289,29 @@ 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);
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
if (LoadAssetWithSubAssets_InternalDelegateField_Unity6 == null)
throw new NullReferenceException("The LoadAssetWithSubAssets_InternalDelegateField_Unity6 cannot be null.");
unsafe
{
fixed (char* charPtr = string.Empty)
{
var span = new ManagedSpanWrapper
{
begin = charPtr,
length = 0
};
return LoadAssetWithSubAssets_InternalDelegateField_Unity6(bundleptr, ref span, typeptr);
}
}
}
else
{
if (LoadAssetWithSubAssets_InternalDelegateField == null)
throw new NullReferenceException("The LoadAssetWithSubAssets_InternalDelegateField cannot be null.");
return LoadAssetWithSubAssets_InternalDelegateField(bundleptr, IL2CPP.ManagedStringToIl2Cpp(string.Empty), typeptr);
}
}

public Il2CppReferenceArray<Object> LoadAssetWithSubAssets(string name) => LoadAssetWithSubAssets<Object>(name);
Expand Down Expand Up @@ -216,9 +340,29 @@ public IntPtr LoadAssetWithSubAssets(string name, IntPtr typeptr)
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);
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
if (LoadAssetWithSubAssets_InternalDelegateField_Unity6 == null)
throw new NullReferenceException("The LoadAssetWithSubAssets_InternalDelegateField_Unity6 cannot be null.");
unsafe
{
fixed (char* charPtr = name)
{
var span = new ManagedSpanWrapper
{
begin = charPtr,
length = name.Length
};
return LoadAssetWithSubAssets_InternalDelegateField_Unity6(bundleptr, ref span, typeptr);
}
}
}
else
{
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<Object>(name);

Expand Down Expand Up @@ -246,9 +390,29 @@ public IntPtr LoadAssetWithSubAssetsAsync(string name, IntPtr typeptr)
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);
if (UnityInformationHandler.EngineVersion.Major >= 6000)
{
if (LoadAssetWithSubAssetsAsync_InternalDelegateField_Unity6 == null)
throw new NullReferenceException("The LoadAssetWithSubAssetsAsync_InternalDelegateField_Unity6 cannot be null.");
unsafe
{
fixed (char* charPtr = name)
{
var span = new ManagedSpanWrapper
{
begin = charPtr,
length = name.Length
};
return LoadAssetWithSubAssetsAsync_InternalDelegateField_Unity6(bundleptr, ref span, typeptr);
}
}
}
else
{
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)
Expand All @@ -259,11 +423,10 @@ public void Unload(bool unloadAllLoadedObjects)
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 IntPtr returnMainAssetDelegate(IntPtr _this);
private static readonly returnMainAssetDelegate returnMainAssetDelegateField;
private delegate bool ContainsDelegate(IntPtr _this, IntPtr name);
private static readonly ContainsDelegate ContainsDelegateField;
private delegate IntPtr GetAllAssetNamesDelegate(IntPtr _this);
Expand All @@ -280,4 +443,20 @@ public void Unload(bool unloadAllLoadedObjects)
private static readonly LoadAssetWithSubAssetsAsync_InternalDelegate LoadAssetWithSubAssetsAsync_InternalDelegateField;
private delegate void UnloadDelegate(IntPtr _this, bool unloadAllObjects);
private static readonly UnloadDelegate UnloadDelegateField;

// get_isStreamedSceneAssetBundle doesn't change.
// returnMainAsset doesn't change.
private delegate bool ContainsDelegate_Unity6(IntPtr _this, ref ManagedSpanWrapper name);
private static readonly ContainsDelegate_Unity6 ContainsDelegateField_Unity6;
// GetAllAssetNames doesn't change.
// GetAllScenePaths doesn't change.
private delegate IntPtr LoadAsset_InternalDelegate_Unity6(IntPtr _this, ref ManagedSpanWrapper name, IntPtr type);
private static readonly LoadAsset_InternalDelegate_Unity6 LoadAsset_InternalDelegateField_Unity6;
private delegate IntPtr LoadAssetAsync_InternalDelegate_Unity6(IntPtr _this, ref ManagedSpanWrapper name, IntPtr type);
private static readonly LoadAssetAsync_InternalDelegate_Unity6 LoadAssetAsync_InternalDelegateField_Unity6;
private delegate IntPtr LoadAssetWithSubAssets_InternalDelegate_Unity6(IntPtr _this, ref ManagedSpanWrapper name, IntPtr type);
private static readonly LoadAssetWithSubAssets_InternalDelegate_Unity6 LoadAssetWithSubAssets_InternalDelegateField_Unity6;
private delegate IntPtr LoadAssetWithSubAssetsAsync_InternalDelegate_Unity6(IntPtr _this, ref ManagedSpanWrapper name, IntPtr type);
private static readonly LoadAssetWithSubAssetsAsync_InternalDelegate_Unity6 LoadAssetWithSubAssetsAsync_InternalDelegateField_Unity6;
// Unload doesn't change.
}
Loading