From 127f48fb1f8560f29a29c6e5e89f595accc00aae Mon Sep 17 00:00:00 2001 From: js6pak Date: Wed, 31 Jul 2024 00:16:11 +0200 Subject: [PATCH] Add support for asset bundles without an architecture suffix Unity requires specifying the architecture when building asset bundles as part of BuildTarget. While compatibility between targets isn't guaranteed, in practice there are no differences between architectures. --- Reactor.Assets/Assets/Build.cs | 8 +- ...ault-win-x86.bundle => default-win.bundle} | Bin Reactor/Utilities/AssetBundleManager.cs | 94 ++++++++++++------ 3 files changed, 67 insertions(+), 35 deletions(-) rename Reactor/Assets/{default-win-x86.bundle => default-win.bundle} (100%) diff --git a/Reactor.Assets/Assets/Build.cs b/Reactor.Assets/Assets/Build.cs index 7d47946..f214338 100644 --- a/Reactor.Assets/Assets/Build.cs +++ b/Reactor.Assets/Assets/Build.cs @@ -69,14 +69,14 @@ internal static class Build } } - private static string GetTargetName(BuildTarget target) + private static string GetTargetName(BuildTarget target, bool includeArchitecture = false) { return target switch { - BuildTarget.StandaloneWindows => "win-x86", - BuildTarget.StandaloneWindows64 => "win-x64", + BuildTarget.StandaloneWindows => includeArchitecture ? "win-x86" : "win", + BuildTarget.StandaloneWindows64 => includeArchitecture ? "win-x64" : "win", BuildTarget.Android => "android", - BuildTarget.StandaloneLinux64 => "linux-x64", + BuildTarget.StandaloneLinux64 => includeArchitecture ? "linux-x64" : "linux", _ => throw new ArgumentOutOfRangeException(nameof(target), target, null), }; } diff --git a/Reactor/Assets/default-win-x86.bundle b/Reactor/Assets/default-win.bundle similarity index 100% rename from Reactor/Assets/default-win-x86.bundle rename to Reactor/Assets/default-win.bundle diff --git a/Reactor/Utilities/AssetBundleManager.cs b/Reactor/Utilities/AssetBundleManager.cs index 6645864..afc86cd 100644 --- a/Reactor/Utilities/AssetBundleManager.cs +++ b/Reactor/Utilities/AssetBundleManager.cs @@ -3,8 +3,8 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using Il2CppInterop.Runtime.InteropTypes.Arrays; -using MonoMod.Utils; using Reactor.Utilities.Extensions; using UnityEngine; @@ -23,38 +23,48 @@ public static class AssetBundleManager /// /// Gets the target name of the current system. /// - public static string TargetName { get; } + [Obsolete("Use AssetBundleManager#GetTargetName instead")] + public static string TargetName { get; } = GetTargetName(true); - static AssetBundleManager() + /// + /// Gets the target name of the current system. + /// + /// A value indicating whether to include the process architecture. + /// Target name of the current system. + public static string GetTargetName(bool includeArchitecture) { - if (PlatformHelper.Is(Platform.Android)) + string operatingSystem; + + if (OperatingSystem.IsWindows()) { - TargetName = "android"; + operatingSystem = "win"; + } + else if (OperatingSystem.IsLinux()) + { + operatingSystem = "linux"; + } + else if (OperatingSystem.IsAndroid()) + { + operatingSystem = "android"; } else { - if (PlatformHelper.Is(Platform.Windows)) - { - TargetName = "win"; - } - else if (PlatformHelper.Is(Platform.Linux)) - { - TargetName = "linux"; - } - else - { - throw new PlatformNotSupportedException(); - } - - if (PlatformHelper.Is(Platform.ARM)) - { - TargetName += Environment.Is64BitProcess ? "-arm64" : "-arm"; - } - else - { - TargetName += Environment.Is64BitProcess ? "-x64" : "-x86"; - } + throw new PlatformNotSupportedException(); } + + if (!includeArchitecture) + { + return operatingSystem; + } + + return $"{operatingSystem}-{RuntimeInformation.ProcessArchitecture switch + { + Architecture.X86 => "x86", + Architecture.X64 => "x64", + Architecture.Arm => "arm", + Architecture.Arm64 => "arm64", + _ => throw new PlatformNotSupportedException(), + }}"; } /// @@ -62,7 +72,16 @@ public static class AssetBundleManager /// /// The name of the asset bundle. /// File name of the asset bundle. - public static string GetFileName(string assetBundleName) => $"{assetBundleName}-{TargetName}{BundleExtension}"; + [Obsolete("Use the overload with includeArchitecture instead")] + public static string GetFileName(string assetBundleName) => GetFileName(assetBundleName, true); + + /// + /// Gets the file name for an asset bundle named . + /// + /// The name of the asset bundle. + /// A value indicating whether to include the process architecture. + /// File name of the asset bundle. + public static string GetFileName(string assetBundleName, bool includeArchitecture) => $"{assetBundleName}-{GetTargetName(includeArchitecture)}{BundleExtension}"; private static bool TryFindFile(Assembly assembly, string fileName, [NotNullWhen(true)] out string? path) { @@ -72,6 +91,7 @@ public static class AssetBundleManager var filePath = Path.Combine(pluginDirectoryPath, fileName); if (File.Exists(filePath)) { + Debug($"Loading an asset bundle from {filePath}"); path = filePath; return true; } @@ -86,6 +106,8 @@ public static class AssetBundleManager var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName, StringComparison.Ordinal)); if (resourceName != null) { + Debug($"Loading an asset bundle from {resourceName}"); + using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException("Resource stream was null"); var length = (int) stream.Length; @@ -119,8 +141,13 @@ public static class AssetBundleManager /// Couldn't find an assetbundle named . public static AssetBundle Load(Assembly assembly, string name) { - var fileName = GetFileName(name); + return TryLoad(assembly, GetFileName(name, includeArchitecture: true)) + ?? TryLoad(assembly, GetFileName(name, includeArchitecture: false)) + ?? throw new AssetBundleNotFoundException(name); + } + private static AssetBundle? TryLoad(Assembly assembly, string fileName) + { if (TryFindFile(assembly, fileName, out var filePath)) { return AssetBundle.LoadFromFile(filePath); @@ -131,7 +158,7 @@ public static class AssetBundleManager return AssetBundle.LoadFromMemory(data); } - throw new AssetBundleNotFoundException(name); + return null; } /// @@ -154,8 +181,13 @@ public static class AssetBundleManager /// Couldn't find an assetbundle named . public static AssetBundleCreateRequest LoadAsync(Assembly assembly, string name) { - var fileName = GetFileName(name); + return TryLoadAsync(assembly, GetFileName(name, includeArchitecture: true)) + ?? TryLoadAsync(assembly, GetFileName(name, includeArchitecture: false)) + ?? throw new AssetBundleNotFoundException(name); + } + private static AssetBundleCreateRequest? TryLoadAsync(Assembly assembly, string fileName) + { if (TryFindFile(assembly, fileName, out var filePath)) { return AssetBundle.LoadFromFileAsync(filePath); @@ -166,7 +198,7 @@ public static class AssetBundleManager return AssetBundle.LoadFromMemoryAsync(data); } - throw new AssetBundleNotFoundException(name); + return null; } }