Skip to content

Commit b35d2fa

Browse files
authored
Merge pull request #82 from KaBooMa/pr-verification
PR Verification BepInEx
2 parents 1f05dfa + 90fa8c2 commit b35d2fa

File tree

12 files changed

+949
-0
lines changed

12 files changed

+949
-0
lines changed

S1API/AssetBundles/AssetLoader.cs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Reflection;
4+
5+
#if IL2CPPBEPINEX || IL2CPPMELON
6+
using System.IO;
7+
#endif
8+
9+
using UnityEngine;
10+
using Object = UnityEngine.Object;
11+
12+
using S1API.Logging;
13+
14+
namespace S1API.AssetBundles
15+
{
16+
/// <summary>
17+
/// The asset bundle manager
18+
/// </summary>
19+
public static class AssetLoader
20+
{
21+
private static readonly Log _logger = new Log("AssetLoader");
22+
private static readonly Dictionary<string, WrappedAssetBundle> _cachedAssetBundles = new Dictionary<string, WrappedAssetBundle>();
23+
24+
#if IL2CPPMELON || IL2CPPBEPINEX
25+
/// <summary>
26+
/// Loads an Il2Cpp AssetBundle from an embedded resource stream by name.
27+
/// </summary>
28+
/// <param name="fullResourceName">The full embedded resource name (including namespace path).</param>
29+
/// <param name="overrideAssembly">The assembly to load the embedded resource from.</param>
30+
/// <returns>The loaded Il2CppAssetBundle, or throws on failure.</returns>
31+
public static WrappedAssetBundle GetAssetBundleFromStream(string fullResourceName, Assembly overrideAssembly)
32+
{
33+
if (_cachedAssetBundles.TryGetValue(fullResourceName, out WrappedAssetBundle cachedWrappedAssetBundle))
34+
return cachedWrappedAssetBundle;
35+
36+
// Attempt to find the embedded resource in the executing assembly
37+
using Stream? stream = overrideAssembly.GetManifestResourceStream(fullResourceName);
38+
if (stream == null)
39+
throw new Exception($"Embedded resource '{fullResourceName}' not found in {overrideAssembly.FullName}."); // hoping these throws will be melon/bepinex-agnostic
40+
41+
// Read the stream into a byte array
42+
byte[] data = new byte[stream.Length];
43+
_ = stream.Read(data, 0, data.Length);
44+
45+
// Load the AssetBundle from memory
46+
Il2CppAssetBundle bundle = Il2CppAssetBundleManager.LoadFromMemory(data);
47+
if (bundle == null)
48+
throw new Exception($"Failed to load AssetBundle from memory: {fullResourceName}");
49+
50+
WrappedAssetBundle wrappedAssetBundle = new WrappedAssetBundle(bundle);
51+
_cachedAssetBundles.TryAdd(fullResourceName, wrappedAssetBundle);
52+
return wrappedAssetBundle;
53+
}
54+
#elif MONOMELON || MONOBEPINEX
55+
/// <summary>
56+
/// Load a <see cref="WrappedAssetBundle"/> instance by <see cref="string"/> resource name.
57+
/// </summary>
58+
/// <param name="fullResourceName">The full embedded resource name (including namespace path);</param>
59+
/// <param name="overrideAssembly">The assembly to load the embedded resource from.</param>
60+
/// <returns>The loaded AssetBundle instance</returns>
61+
public static WrappedAssetBundle GetAssetBundleFromStream(string fullResourceName, Assembly overrideAssembly)
62+
{
63+
// Attempt to retrieve the cached asset bundle
64+
if (_cachedAssetBundles.TryGetValue(fullResourceName, out WrappedAssetBundle cachedWrappedAssetBundle))
65+
return cachedWrappedAssetBundle;
66+
67+
// Attempt to find the embedded resource in the executing assembly
68+
var stream = overrideAssembly.GetManifestResourceStream(fullResourceName);
69+
70+
WrappedAssetBundle wrappedAssetBundle = new WrappedAssetBundle(AssetBundle.LoadFromStream(stream));
71+
_cachedAssetBundles.TryAdd(fullResourceName, wrappedAssetBundle);
72+
return wrappedAssetBundle;
73+
}
74+
#endif
75+
76+
/// <summary>
77+
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using the executing assembly.
78+
/// </summary>
79+
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
80+
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
81+
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
82+
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
83+
public static T EasyLoad<T>(string bundleName, string objectName) where T : Object
84+
{
85+
return EasyLoad<T>(bundleName, objectName, Assembly.GetExecutingAssembly(), out _);
86+
}
87+
88+
/// <summary>
89+
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using the executing assembly and outputs the loaded bundle.
90+
/// </summary>
91+
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
92+
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
93+
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
94+
/// <param name="bundle">The output parameter containing the loaded <see cref="WrappedAssetBundle"/>.</param>
95+
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
96+
public static T EasyLoad<T>(string bundleName, string objectName, out WrappedAssetBundle bundle) where T : Object
97+
{
98+
return EasyLoad<T>(bundleName, objectName, Assembly.GetExecutingAssembly(), out bundle);
99+
}
100+
101+
/// <summary>
102+
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using a specified assembly.
103+
/// </summary>
104+
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
105+
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
106+
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
107+
/// <param name="assemblyOverride">The assembly from which to load the embedded AssetBundle resource.</param>
108+
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
109+
public static T EasyLoad<T>(string bundleName, string objectName, Assembly assemblyOverride) where T : Object
110+
{
111+
return EasyLoad<T>(bundleName, objectName, assemblyOverride, out _);
112+
}
113+
114+
/// <summary>
115+
/// Loads an asset of type <typeparamref name="T"/> from an embedded AssetBundle using a specified assembly and outputs the loaded bundle.
116+
/// </summary>
117+
/// <typeparam name="T">The type of asset to load (must derive from UnityEngine.Object).</typeparam>
118+
/// <param name="bundleName">The name of the embedded AssetBundle resource.</param>
119+
/// <param name="objectName">The name of the asset to load within the AssetBundle.</param>
120+
/// <param name="assemblyOverride">The assembly from which to load the embedded AssetBundle resource.</param>
121+
/// <param name="bundle">The output parameter containing the loaded <see cref="WrappedAssetBundle"/>.</param>
122+
/// <returns>The loaded asset of type <typeparamref name="T"/>.</returns>
123+
public static T EasyLoad<T>(string bundleName, string objectName, Assembly assemblyOverride, out WrappedAssetBundle bundle) where T : Object
124+
{
125+
// Get the asset bundle from the assembly
126+
bundle = GetAssetBundleFromStream($"{assemblyOverride.GetName().Name}.{bundleName}", assemblyOverride);
127+
128+
// Load the asset from the bundle
129+
return bundle.LoadAsset<T>(objectName);
130+
}
131+
}
132+
}

0 commit comments

Comments
 (0)