Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
af1daaf
Add Dependencies for AssetBundle things
chloelcdev Apr 27, 2025
064053b
Create AssetBundleHelper.cs
chloelcdev Apr 27, 2025
b60479f
Turned AssetBundleHelper into AssetLoader, added WrappedAssetBundle
chloelcdev Apr 27, 2025
c9564cc
Explicitly specify type for mono
chloelcdev Apr 27, 2025
a29dec2
remove deprecated "mainAsset" from WrappedAssetBundle
chloelcdev Apr 27, 2025
6725b01
Add back line I guess I deleted? always use UnityEngine.Object in Wra…
chloelcdev Apr 27, 2025
ebf3657
take away try/catch
chloelcdev Apr 27, 2025
bfe572d
Fix quotation marks in csproj
chloelcdev Apr 27, 2025
80fa207
Update AssetLoader.cs
chloelcdev Apr 30, 2025
4cd97fd
Create UpdateBepInExBundleManager.bat
chloelcdev May 1, 2025
464a8b6
Have batch file wrap #if IL2CPPBEPINEX tags
chloelcdev May 1, 2025
721012f
Add downloaded BE.Il2CppAssetBundleManager
chloelcdev May 1, 2025
86cdf11
Merge branch 'bleeding-edge' into AssetBundles-bleedingedge
chloelcdev May 2, 2025
451726d
fix: Some code style changes
MaxtorCoder May 2, 2025
16dac4e
Rename back to AssetLoader
MaxtorCoder May 2, 2025
43d40c0
Merge branch 'bleeding-edge' into AssetBundles-bleedingedge
MaxtorCoder May 4, 2025
86dc403
fix: Fix for BepInEx building
MaxtorCoder May 4, 2025
ada9cdd
fix: Add AssetBundle caching and fix `overrideAssembly` parameter
MaxtorCoder May 4, 2025
61e991d
Merge pull request #77 from chloelcdev/AssetBundles-bleedingedge
MaxtorCoder May 4, 2025
0067999
Merge branch 'bleeding-edge' into pr-verification
MaxtorCoder May 4, 2025
90fa8c2
fix: Add missing XML documentation for WrappedAssetBundle
MaxtorCoder May 4, 2025
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
132 changes: 132 additions & 0 deletions S1API/AssetBundles/AssetLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Reflection;

#if IL2CPPBEPINEX || IL2CPPMELON
using System.IO;
#endif

using UnityEngine;
using Object = UnityEngine.Object;

using S1API.Logging;

namespace S1API.AssetBundles
{
/// <summary>
/// The asset bundle manager
/// </summary>
public static class AssetLoader
{
private static readonly Log _logger = new Log("AssetLoader");
private static readonly Dictionary<string, WrappedAssetBundle> _cachedAssetBundles = new Dictionary<string, WrappedAssetBundle>();

#if IL2CPPMELON || IL2CPPBEPINEX
/// <summary>
/// Loads an Il2Cpp AssetBundle from an embedded resource stream by name.
/// </summary>
/// <param name="fullResourceName">The full embedded resource name (including namespace path).</param>
/// <param name="overrideAssembly">The assembly to load the embedded resource from.</param>
/// <returns>The loaded Il2CppAssetBundle, or throws on failure.</returns>
public static WrappedAssetBundle GetAssetBundleFromStream(string fullResourceName, Assembly overrideAssembly)
{
if (_cachedAssetBundles.TryGetValue(fullResourceName, out WrappedAssetBundle cachedWrappedAssetBundle))

Check warning on line 33 in S1API/AssetBundles/AssetLoader.cs

View workflow job for this annotation

GitHub Actions / Verify Successful Build

Converting null literal or possible null value to non-nullable type.
return cachedWrappedAssetBundle;

// Attempt to find the embedded resource in the executing assembly
using Stream? stream = overrideAssembly.GetManifestResourceStream(fullResourceName);
if (stream == null)
throw new Exception($"Embedded resource '{fullResourceName}' not found in {overrideAssembly.FullName}."); // hoping these throws will be melon/bepinex-agnostic

// Read the stream into a byte array
byte[] data = new byte[stream.Length];
_ = stream.Read(data, 0, data.Length);

// Load the AssetBundle from memory
Il2CppAssetBundle bundle = Il2CppAssetBundleManager.LoadFromMemory(data);
if (bundle == null)
throw new Exception($"Failed to load AssetBundle from memory: {fullResourceName}");

WrappedAssetBundle wrappedAssetBundle = new WrappedAssetBundle(bundle);
_cachedAssetBundles.TryAdd(fullResourceName, wrappedAssetBundle);
return wrappedAssetBundle;
}
#elif MONOMELON || MONOBEPINEX
/// <summary>
/// Load a <see cref="WrappedAssetBundle"/> instance by <see cref="string"/> resource name.
/// </summary>
/// <param name="fullResourceName">The full embedded resource name (including namespace path);</param>
/// <param name="overrideAssembly">The assembly to load the embedded resource from.</param>
/// <returns>The loaded AssetBundle instance</returns>
public static WrappedAssetBundle GetAssetBundleFromStream(string fullResourceName, Assembly overrideAssembly)
{
// Attempt to retrieve the cached asset bundle
if (_cachedAssetBundles.TryGetValue(fullResourceName, out WrappedAssetBundle cachedWrappedAssetBundle))
return cachedWrappedAssetBundle;

// Attempt to find the embedded resource in the executing assembly
var stream = overrideAssembly.GetManifestResourceStream(fullResourceName);

WrappedAssetBundle wrappedAssetBundle = new WrappedAssetBundle(AssetBundle.LoadFromStream(stream));
_cachedAssetBundles.TryAdd(fullResourceName, wrappedAssetBundle);
return wrappedAssetBundle;
}
#endif

/// <summary>
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using the executing assembly.
/// </summary>
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
public static T EasyLoad<T>(string bundleName, string objectName) where T : Object
{
return EasyLoad<T>(bundleName, objectName, Assembly.GetExecutingAssembly(), out _);
}

/// <summary>
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using the executing assembly and outputs the loaded bundle.
/// </summary>
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
/// <param name="bundle">The output parameter containing the loaded <see cref="WrappedAssetBundle"/>.</param>
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
public static T EasyLoad<T>(string bundleName, string objectName, out WrappedAssetBundle bundle) where T : Object
{
return EasyLoad<T>(bundleName, objectName, Assembly.GetExecutingAssembly(), out bundle);
}

/// <summary>
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using a specified assembly.
/// </summary>
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
/// <param name="assemblyOverride">The assembly from which to load the embedded AssetBundle resource.</param>
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
public static T EasyLoad<T>(string bundleName, string objectName, Assembly assemblyOverride) where T : Object
{
return EasyLoad<T>(bundleName, objectName, assemblyOverride, out _);
}

/// <summary>
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using a specified assembly and outputs the loaded bundle.
/// </summary>
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
/// <param name="assemblyOverride">The assembly from which to load the embedded AssetBundle resource.</param>
/// <param name="bundle">The output parameter containing the loaded <see cref="WrappedAssetBundle"/>.</param>
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
public static T EasyLoad<T>(string bundleName, string objectName, Assembly assemblyOverride, out WrappedAssetBundle bundle) where T : Object
{
// Get the asset bundle from the assembly
bundle = GetAssetBundleFromStream($"{assemblyOverride.GetName().Name}.{bundleName}", assemblyOverride);

// Load the asset from the bundle
return bundle.LoadAsset<T>(objectName);
}
}
}
Loading
Loading