using System; using System.Buffers; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using System.Threading.Tasks; using AssetHelperLib; using AssetHelperLib.BundleTools; using AssetHelperLib.IO; using AssetHelperLib.PreloadTable; using AssetHelperLib.Repacking; using AssetsTools.NET; using AssetsTools.NET.Extra; using BepInEx; using BepInEx.Logging; using DataDrivenConstants.Marker; using HarmonyLib; using Md.StartManager; using Microsoft.CodeAnalysis; using MonoDetour; using MonoDetour.Cil; using MonoDetour.DetourTypes; using MonoDetour.HookGen; using MonoDetour.Reflection.Unspeakable; using MonoMod.RuntimeDetour; using MonoMod.Utils; using Newtonsoft.Json; using Silksong.AssetHelper.CatalogTools; using Silksong.AssetHelper.Core; using Silksong.AssetHelper.Internal; using Silksong.AssetHelper.Plugin; using Silksong.AssetHelper.Plugin.LoadingPage; using Silksong.AssetHelper.Plugin.Tasks; using TeamCherry.Localization; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.ResourceManagement.Util; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MonoDetourTargets(typeof(StartManager))] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AssetHelper")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Library for helping with loading vanilla Silksong assets.")] [assembly: AssemblyFileVersion("1.3.2.0")] [assembly: AssemblyInformationalVersion("1.3.2+cdd9cae110fc2313b117652474be58605ce40dba")] [assembly: AssemblyProduct("AssetHelper")] [assembly: AssemblyTitle("AssetHelper")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/silksong-modding/Silksong.AssetHelper")] [assembly: NeutralResourcesLanguage("EN")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyList : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { int ICollection.Count => _items.Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => _items.Count; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Count; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyList(List items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return _items.Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { _items.CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return _items.IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator { object IEnumerator.Current => _item; T IEnumerator.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => 1; T IReadOnlyList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection.Count => 1; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return EqualityComparer.Default.Equals(_item, item); } void ICollection.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { if (!EqualityComparer.Default.Equals(_item, item)) { return -1; } return 0; } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Md.StartManager { internal static class _Start_d__8 { internal static class MoveNext { public delegate void PrefixSignature(object self); public delegate void PostfixSignature(object self, ref bool returnValue); public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).Hook(Target(), (Delegate)hook, config, applyByDefault); } public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).Hook(Target(), (Delegate)hook, config, applyByDefault); } public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault); } public static MethodBase Target() { return (Type.GetType("StartManager+d__8, Assembly-CSharp") ?? throw new Exception("Missing Type: 'StartManager+d__8'")).GetMethod("MoveNext", (BindingFlags)(-1), null, Array.Empty(), null) ?? throw new MissingMethodException("StartManager+d__8", "MoveNext"); } } } internal static class Start { public delegate void PrefixSignature(StartManager self); public delegate void PostfixSignature(StartManager self, ref IEnumerator returnValue); public delegate void PrefixMoveNextSignature(SpeakableEnumerator self); public delegate void PostfixMoveNextSignature(SpeakableEnumerator self, ref bool continueEnumeration); public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).Hook(Target(), (Delegate)hook, config, applyByDefault); } public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).Hook(Target(), (Delegate)hook, config, applyByDefault); } public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault); } public static MonoDetourHook PrefixMoveNext(PrefixMoveNextSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).Hook((MethodBase)StateMachineTarget(), (Delegate)hook, config, applyByDefault); } public static MonoDetourHook PostfixMoveNext(PostfixMoveNextSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).Hook((MethodBase)StateMachineTarget(), (Delegate)hook, config, applyByDefault); } public static MonoDetourHook ILHookMoveNext(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null) { return (manager ?? DefaultMonoDetourManager.Instance).ILHook((MethodBase)StateMachineTarget(), manipulator, config, applyByDefault); } public static MethodBase Target() { return typeof(StartManager).GetMethod("Start", (BindingFlags)(-1), null, Array.Empty(), null) ?? throw new MissingMethodException("StartManager", "Start"); } public static MethodInfo StateMachineTarget() { return Extensions.GetStateMachineTarget((MethodInfo)Target()); } } } namespace MonoDetour.HookGen { internal static class DefaultMonoDetourManager { internal static MonoDetourManager Instance { get; } = New(); internal static MonoDetourManager New() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return new MonoDetourManager(typeof(DefaultMonoDetourManager).Assembly.GetName().Name); } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)] internal class MonoDetourTargetsAttribute : Attribute, IMonoDetourTargets { public Type? TargetType { get; } public bool IncludeNestedTypes { get; set; } public string[]? Members { get; set; } public string[]? MemberNamePrefixes { get; set; } public string[]? MemberNameSuffixes { get; set; } public bool GenerateControlFlowVariants { get; set; } public MonoDetourTargetsAttribute(Type? targetType = null) { TargetType = targetType; IncludeNestedTypes = true; base..ctor(); } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.Embedded] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] [Microsoft.CodeAnalysis.Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace DataDrivenConstants.Marker { [AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)] internal sealed class DataInjectAttribute : Attribute { public string Prefix { get; set; } = "Get"; } [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] internal sealed class JsonDataAttribute : Attribute { public string ValuePath { get; } public string[] FileGlobs { get; } public JsonDataAttribute(string valuePath, params string[] fileGlobs) { ValuePath = valuePath; FileGlobs = (string[])fileGlobs.Clone(); } } internal enum NameStyle { PascalCase, CamelCase, SnakeCase, UpperSnakeCase } [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] internal sealed class NameGenerationStyleAttribute : Attribute { public NameStyle NameStyle { get; } public NameGenerationStyleAttribute(NameStyle nameStyle) { NameStyle = nameStyle; } } internal enum ReplacementKind { Normal, Regex } [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] internal sealed class ReplacementRuleAttribute : Attribute { public string OldString { get; } public string NewString { get; } public ReplacementKind ReplacementKind { get; } public ReplacementRuleAttribute(string oldString, string newString, ReplacementKind replacementKind = ReplacementKind.Normal) { OldString = oldString; NewString = newString; ReplacementKind = replacementKind; } } } namespace Silksong.AssetHelper { [AttributeUsage(AttributeTargets.Class)] internal class ModMenuIgnoreAttribute : Attribute { } [BepInDependency(/*Could not decode attribute arguments.*/)] [ModMenuIgnore] [BepInPlugin("org.silksong-modding.assethelper", "AssetHelper", "1.3.2")] public class AssetHelperPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__13 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; AssetRequestAPI.CloseRequestAPI(); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } if (!AddressablesData.TryLoadBundleKeys()) { <>2__current = null; <>1__state = 2; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string Id = "org.silksong-modding.assethelper"; public static AssetHelperPlugin Instance { get; private set; } internal static ManualLogSource InstanceLogger { get; private set; } public static string Name => "AssetHelper"; public static string Version => "1.3.2"; public static event Action? OnQuitApplication; private void Awake() { Instance = this; InstanceLogger = ((BaseUnityPlugin)this).Logger; InitLibLogging(); AssetsToolsPatch.Init(); AddressablesData.InvokeAfterAddressablesLoaded(BundleMetadata.Setup); StartupOverrideManager.Hook(); Addressables.ResourceManager.ResourceProviders.Add((IResourceProvider)(object)new ChildGameObjectProvider()); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Silksong version: " + VersionData.SilksongVersion + " // OS String: " + AssetPaths.OSFolderName)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (org.silksong-modding.assethelper) has loaded!")); } private static void InitLibLogging() { ManualLogSource @object = Logger.CreateLogSource("AssetHelper.Lib"); Logging.OnLog += @object.LogInfo; Logging.OnLogWarning += @object.LogWarning; Logging.OnLogError += @object.LogError; } [IteratorStateMachine(typeof(d__13))] private IEnumerator Start() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0); } private void OnApplicationQuit() { Delegate[] array = AssetHelperPlugin.OnQuitApplication?.GetInvocationList() ?? Array.Empty(); for (int i = 0; i < array.Length; i++) { ActionUtil.SafeInvoke((Action)array[i]); } } } internal static class AssetsToolsPatch { private static Hook? _atCopyHook; public static void Init() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown _atCopyHook = new Hook((MethodBase)typeof(Net35Polyfill).GetMethod("CopyToCompat"), (Delegate)new Action, Stream, Stream, long, int>(PatchC2C)); } private static void PatchC2C(Action orig, Stream input, Stream output, long bytes, int bufferSize) { byte[] array = ArrayPool.Shared.Rent(bufferSize); if (bytes == -1) { bytes = long.MaxValue; } int num; while (bytes > 0 && (num = input.Read(array, 0, (int)Math.Min(array.Length, bytes))) > 0) { output.Write(array, 0, num); bytes -= num; } ArrayPool.Shared.Return(array); } } } namespace Silksong.AssetHelper.Plugin { internal class AssetRequest { public Dictionary> SceneAssets { get; set; } = new Dictionary>(); [JsonConverter(typeof(DictListConverter, Type>))] public Dictionary<(string bundleName, string assetName), Type> NonSceneAssets { get; set; } = new Dictionary<(string, string), Type>(); [JsonIgnore] public bool AnyRequestMade { get { if (SceneAssets.Count <= 0) { return NonSceneAssets.Count > 0; } return true; } } } public static class AssetRequestAPI { internal static DelayedAction AfterBundleCreationComplete; internal static AssetRequest Request { get; private set; } private static string SerializedRequestPath => Path.Combine(AssetPaths.CacheDirectory, "accumulated_request.json"); internal static bool RequestApiAvailable { get; private set; } public static IResourceLocator? SceneAssetLocator { get; internal set; } public static IResourceLocator? NonSceneAssetLocator { get; internal set; } static AssetRequestAPI() { RequestApiAvailable = true; AfterBundleCreationComplete = new DelayedAction(); if (JsonExtensions.TryLoadFromFile(SerializedRequestPath, out AssetRequest obj)) { Request = obj; } else { Request = new AssetRequest(); } } internal static void CloseRequestAPI() { RequestApiAvailable = false; Request.SerializeToFile(SerializedRequestPath); } private static void VerifyRequest([CallerMemberName] string? caller = null) { if (!RequestApiAvailable) { throw new InvalidOperationException("Requests made through " + caller + " should be made during a plugin's Awake method!"); } } public static void InvokeAfterBundleCreation(Action a) { AfterBundleCreationComplete.Subscribe(a); } public static void RequestSceneAssets(string sceneName, IEnumerable assetPaths) { VerifyRequest("RequestSceneAssets"); sceneName = sceneName.ToLowerInvariant(); HashSet value; HashSet hashSet = (Request.SceneAssets.TryGetValue(sceneName, out value) ? value : new HashSet()); hashSet.UnionWith(assetPaths); Request.SceneAssets[sceneName] = hashSet; } public static void RequestSceneAsset(string sceneName, string assetPath) { RequestSceneAssets(sceneName, new <>z__ReadOnlySingleElementList(assetPath)); } public static void RequestSceneAssets(Dictionary> assetData) { foreach (var (sceneName, assetPaths) in assetData) { RequestSceneAssets(sceneName, assetPaths); } } public static void RequestNonSceneAsset(string bundleName, string assetName) { RequestNonSceneAsset(bundleName, assetName, typeof(T)); } public static void RequestNonSceneAsset(string bundleName, string assetName, Type assetType) { VerifyRequest("RequestNonSceneAsset"); bundleName = bundleName.ToLowerInvariant(); if (bundleName.EndsWith(".bundle")) { string text = bundleName; bundleName = text.Substring(0, text.Length - 7); } if (Request.NonSceneAssets.TryGetValue((bundleName, assetName), out Type value) && value != assetType) { AssetHelperPlugin.InstanceLogger.LogError((object)("Asset " + bundleName + " - " + assetName + " requested with both " + value.Name + " and " + assetType.Name)); } Request.NonSceneAssets[(bundleName, assetName)] = assetType; } public static void RequestNonSceneAssets(string bundleName, IEnumerable assetNames) where T : Object { foreach (string assetName in assetNames) { RequestNonSceneAsset(bundleName, assetName); } } } public abstract class BaseStartupTask { public abstract IEnumerator Run(ILoadingScreen loadingScreen); } public static class CatalogKeys { public static string SceneCatalogId => "AssetHelper-RepackedScenes"; public static string NonSceneCatalogId => "AssetHelper-BundleAssets"; public static string GetKeyForSceneAsset(string sceneName, string objPath) { return SceneCatalogId + "/Assets/" + sceneName.ToLowerInvariant() + "/" + objPath; } public static string GetKeyForNonSceneAsset(string assetName) { return NonSceneCatalogId + "/" + assetName; } internal static string GetKeyForAssetAtTransform(string sceneName, long tPathId) { return $"{SceneCatalogId}/RepackedTransforms/{sceneName}/t{tPathId}.prefab"; } } internal class CatalogMetadata { [JsonProperty(/*Could not decode attribute arguments.*/)] [DefaultValue(null)] public CachedFileMetadata Metadata { get; set; } = CachedFileMetadata.CreateNew(); } internal class SceneCatalogMetadata : CatalogMetadata { } internal class NonSceneCatalogMetadata : CatalogMetadata { [JsonConverter(typeof(DictListConverter, Type>))] public Dictionary<(string bundleName, string assetName), Type> CatalogAssets { get; set; } = new Dictionary<(string, string), Type>(); } internal class CustomCatalogBuilder { [CompilerGenerated] private sealed class d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private float <>2__current; public string catalogId; public CustomCatalogBuilder <>4__this; private List 5__2; private IEnumerator 5__3; float IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { bool result; try { int num = <>1__state; CustomCatalogBuilder CS$<>8__locals0 = <>4__this; switch (num) { default: result = false; goto end_IL_0000; case 0: { <>1__state = -1; if (catalogId == null) { catalogId = CS$<>8__locals0._primaryKeyPrefix; } List list = new List(); list.AddRange(CS$<>8__locals0._includedBaseBundles.Select((string x) => CS$<>8__locals0._baseBundleEntries[x])); list.AddRange(CS$<>8__locals0._addedEntries); 5__2 = list; 5__3 = CatalogUtils.WriteCatalogRoutine(5__2, catalogId); <>1__state = -3; break; } case 1: <>1__state = -3; break; } if (5__3.MoveNext()) { <>2__current = (float)5__3.Current / (float)5__2.Count; <>1__state = 1; result = true; } else { result = false; <>m__Finally1(); } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (5__3 != null) { 5__3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private readonly string _primaryKeyPrefix; private readonly Dictionary _baseBundleEntries; private readonly HashSet _includedBaseBundles = new HashSet(); private readonly Dictionary _basePrimaryKeys = new Dictionary(); private readonly List _addedEntries = new List(); public CustomCatalogBuilder(string primaryKeyPrefix = "AssetHelper") { _primaryKeyPrefix = primaryKeyPrefix; _baseBundleEntries = new Dictionary(); foreach (string key in AddressablesData.BundleKeys.Keys) { if (AddressablesData.TryGetLocation(key, out IResourceLocation location) && !(location.ResourceType != typeof(IAssetBundleResource)) && !location.PrimaryKey.StartsWith("scenes_scenes_scenes") && AddressablesData.TryStrip(location.PrimaryKey, out string stripped)) { string text = _primaryKeyPrefix + "/DependencyBundles/" + stripped; ContentCatalogDataEntry value = CatalogEntryUtils.CreateEntryFromLocation(location, new List(1) { text }); _baseBundleEntries.Add(stripped, value); _basePrimaryKeys.Add(stripped, text); } } } public bool TryDeclareBundleDep(string bundleName, [NotNullWhen(true)] out string? primaryKey) { string text = bundleName.ToLowerInvariant().Replace(".bundle", ""); if (!_basePrimaryKeys.TryGetValue(text, out primaryKey)) { return false; } _includedBaseBundles.Add(text); return true; } public void AddRepackedSceneData(string sceneName, RepackedBundleData data, SceneCatalogInfo info, string bundlePath, string? serializedBundlePath = null) { string text = _primaryKeyPrefix + "/SceneBundles/" + sceneName; ContentCatalogDataEntry item = CatalogEntryUtils.CreateBundleEntry(text, bundlePath, data.BundleName, new List(), serializedBundlePath); _addedEntries.Add(item); List list = new List(1) { text }; foreach (string item4 in BundleMetadata.DetermineCatalogDeps("scenes_scenes_scenes/" + sceneName + ".bundle")) { if (!TryDeclareBundleDep(item4, out string primaryKey)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Error adding asset from scene " + sceneName + " with alien dep " + item4)); } else { list.Add(primaryKey); } } foreach (SceneCatalogInfo.GameObjectInfo rootGameObject in info.RootGameObjects) { ContentCatalogDataEntry item2 = CatalogEntryUtils.CreateAssetEntry(rootGameObject.ContainerPath, typeof(GameObject), list, new List(2) { _primaryKeyPrefix + "/Assets/" + sceneName + "/" + rootGameObject.ObjPath, CatalogKeys.GetKeyForAssetAtTransform(sceneName, rootGameObject.TransformPathId) }); _addedEntries.Add(item2); } foreach (SceneCatalogInfo.ChildGameObjectInfo childGameObject in info.ChildGameObjects) { ContentCatalogDataEntry item3 = CatalogEntryUtils.CreateChildGameObjectEntry(CatalogKeys.GetKeyForAssetAtTransform(sceneName, childGameObject.AncestorTransformPathId), childGameObject.RelativePath, new List(2) { _primaryKeyPrefix + "/Assets/" + sceneName + "/" + childGameObject.ObjPath, CatalogKeys.GetKeyForAssetAtTransform(sceneName, childGameObject.TransformPathId) }); _addedEntries.Add(item3); } } public void AddAssets(string bundle, List<(string asset, Type assetType)> data) { if (!TryDeclareBundleDep(bundle, out string primaryKey)) { throw new ArgumentException("Error adding assets from bundle " + bundle + ": bundle not recognized"); } List list = new List(1) { primaryKey }; foreach (string item4 in BundleMetadata.DetermineTransitiveDeps(bundle)) { if (!TryDeclareBundleDep(item4, out string primaryKey2)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Error adding asset from " + bundle + ": unrecognized T-dep " + item4)); } else { list.Add(primaryKey2); } } foreach (var datum in data) { string item = datum.asset; Type item2 = datum.assetType; ContentCatalogDataEntry item3 = CatalogEntryUtils.CreateAssetEntry(item, item2, list, new List(1) { _primaryKeyPrefix + "/" + item }); _addedEntries.Add(item3); } } public void AddCatalogEntry(ContentCatalogDataEntry entry) { _addedEntries.Add(entry); } [IteratorStateMachine(typeof(d__10))] public IEnumerator BuildRoutine(string? catalogId = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { <>4__this = this, catalogId = catalogId }; } } internal sealed class RepackedSceneBundleData { [JsonProperty(/*Could not decode attribute arguments.*/)] [DefaultValue(null)] public CachedFileMetadata Metadata { get; init; } = CachedFileMetadata.CreateNew(); public required string SceneName { get; init; } public string? BundleHash { get; init; } public RepackedBundleData? Data { get; set; } public SceneCatalogInfo? CatalogInfo { get; set; } } internal static class StartupOverrideManager { [CompilerGenerated] private sealed class d__4 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator original; private LoadingScreen 5__2; private bool 5__3; private List.Enumerator <>7__wrap3; private BaseStartupTask 5__5; private IEnumerator 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap3 = default(List.Enumerator); 5__5 = null; 5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown try { bool flag; switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil((Func)(() => AddressablesData.IsAddressablesLoaded)); <>1__state = 1; return true; case 1: <>1__state = -1; RentedFileArray.Pool = ArrayPool.Create(262144000, 5); 5__2 = LoadingScreenExtensions.Create(); 5__3 = false; <>7__wrap3 = _tasks.GetEnumerator(); <>1__state = -3; goto IL_0161; case 2: <>1__state = -3; goto IL_00d6; case 3: <>1__state = -1; <>2__current = original; <>1__state = 4; return true; case 4: { <>1__state = -1; return false; } IL_0161: if (<>7__wrap3.MoveNext()) { 5__5 = <>7__wrap3.Current; 5__6 = 5__5.Run(5__2); goto IL_00d6; } goto IL_0171; IL_00d6: try { flag = 5__6.MoveNext(); } catch (Exception ex) { AssetHelperPlugin.InstanceLogger.LogError((object)($"Error during startup task of type {5__5.GetType()}\n" + ex)); 5__3 = true; goto IL_014b; } if (flag) { <>2__current = 5__6.Current; <>1__state = 2; return true; } goto IL_014b; IL_0171: <>m__Finally1(); <>7__wrap3 = default(List.Enumerator); if (!5__3) { AssetHelperPlugin.InstanceLogger.LogInfo((object)"AssetHelper prep complete!"); AssetRequestAPI.AfterBundleCreationComplete.Activate(); _startupRun = true; 5__2.SetProgress(1f); } else { AssetHelperPlugin.InstanceLogger.LogWarning((object)"An error occurred during startup, and AssetHelper did not finish."); } Object.Destroy((Object)(object)5__2); RentedFileArray.Pool = null; <>2__current = null; <>1__state = 3; return true; IL_014b: if (!5__3) { 5__6 = null; 5__5 = null; goto IL_0161; } goto IL_0171; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap3).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool _startupRun = false; private static List _tasks = new List(3) { new BundleDepsPrecompute(), new SceneRepacking(), new NonSceneCatalog() }; internal static void Hook() { Start.Postfix(PrependStartManagerStart); } private static void PrependStartManagerStart(StartManager self, ref IEnumerator returnValue) { if (!_startupRun && AssetRequestAPI.Request.AnyRequestMade) { returnValue = WrapStartManagerStart(self, returnValue); } } [IteratorStateMachine(typeof(d__4))] private static IEnumerator WrapStartManagerStart(StartManager self, IEnumerator original) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0) { original = original }; } } } namespace Silksong.AssetHelper.Plugin.Tasks { internal class BundleDepsPrecompute : BaseStartupTask { [CompilerGenerated] private sealed class d__0 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ILoadingScreen loadingScreen; private Stopwatch 5__2; private List 5__3; private int 5__4; private int 5__5; private List.Enumerator <>7__wrap5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; <>7__wrap5 = default(List.Enumerator); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (AssetRequestAPI.Request.NonSceneAssets.Count == 0) { return false; } loadingScreen.SetText("COMPUTING_BUNDLE_DEPS".GetLocalized()); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; AssetHelperPlugin.InstanceLogger.LogInfo((object)"Computing bundle deps"); 5__2 = Stopwatch.StartNew(); 5__3 = AddressablesData.BundleKeys.Keys.Where((string x) => !x.Contains("scenes_scenes_scenes")).ToList(); loadingScreen.SetProgress(0f); 5__4 = 0; 5__5 = 0; <>7__wrap5 = 5__3.GetEnumerator(); <>1__state = -3; break; case 2: <>1__state = -3; break; } while (<>7__wrap5.MoveNext()) { BundleMetadata.DetermineDirectDepsInternal(<>7__wrap5.Current, out var cacheHit); 5__4++; loadingScreen.SetProgress((float)5__4 / (float)5__3.Count); if (!cacheHit) { 5__5++; if (5__5 % 5 == 0) { <>2__current = null; <>1__state = 2; return true; } } } <>m__Finally1(); <>7__wrap5 = default(List.Enumerator); 5__2.Stop(); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Computed bundle deps in {5__2.ElapsedMilliseconds} ms."); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(d__0))] public override IEnumerator Run(ILoadingScreen loadingScreen) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(0) { loadingScreen = loadingScreen }; } } internal class NonSceneCatalog : BaseStartupTask { [CompilerGenerated] private sealed class d__3 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public NonSceneCatalog <>4__this; public ILoadingScreen bar; private IEnumerator 5__2; private AsyncOperationHandle 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) 5__2 = null; 5__3 = default(AsyncOperationHandle); <>1__state = -2; } private bool MoveNext() { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; NonSceneCatalog nonSceneCatalog = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = nonSceneCatalog.CreateNonSceneAssetCatalog(bar); bar.SetText("BUILDING_NON_SCENE".GetLocalized()); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; goto IL_0090; case 2: <>1__state = -1; goto IL_0090; case 3: <>1__state = -1; if (File.Exists(NonSceneCatalogPath) && AssetRequestAPI.Request.NonSceneAssets.Count > 0) { bar.SetText("LOADING_NON_SCENE".GetLocalized()); <>2__current = null; <>1__state = 4; return true; } goto IL_0161; case 4: <>1__state = -1; AssetHelperPlugin.InstanceLogger.LogInfo((object)"Loading non-scene catalog"); 5__3 = Addressables.LoadContentCatalogAsync(NonSceneCatalogPath, (string)null); <>2__current = 5__3; <>1__state = 5; return true; case 5: <>1__state = -1; AssetRequestAPI.NonSceneAssetLocator = 5__3.Result; 5__3 = default(AsyncOperationHandle); goto IL_0161; case 6: { <>1__state = -1; return false; } IL_0161: <>2__current = null; <>1__state = 6; return true; IL_0090: if (5__2.MoveNext()) { <>2__current = null; <>1__state = 2; return true; } <>2__current = null; <>1__state = 3; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__4 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ILoadingScreen screen; private string 5__2; private NonSceneCatalogMetadata 5__3; private CustomCatalogBuilder 5__4; private int 5__5; private IEnumerator 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 2) { try { } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; 5__4 = null; 5__6 = null; <>1__state = -2; } private bool MoveNext() { bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: { <>1__state = -1; 5__2 = Path.ChangeExtension(NonSceneCatalogPath, ".json"); AssetHelperPlugin.InstanceLogger.LogInfo((object)"Creating NS catalog"); Dictionary<(string, string), Type> dictionary = new Dictionary<(string, string), Type>(); bool flag = false; if (JsonExtensions.TryLoadFromFile(5__2, out NonSceneCatalogMetadata obj) && obj.Metadata != null && obj.Metadata.SilksongVersion == VersionData.SilksongVersion && VersionData.EarliestAcceptableNonSceneCatalogVersion.AllowCachedData(obj.Metadata.PluginVersion) && obj.Metadata.OSFolderName == AssetPaths.OSFolderName) { dictionary = obj.CatalogAssets; } (string, string) key; Type value; foreach (KeyValuePair<(string, string), Type> nonSceneAsset in AssetRequestAPI.Request.NonSceneAssets) { nonSceneAsset.Deconstruct(out key, out value); (string, string) tuple = key; Type type = value; if (!dictionary.ContainsKey(tuple)) { dictionary.Add(tuple, type); flag = true; } else if (dictionary[tuple] != type) { AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Replacing {tuple} :: {dictionary[tuple]} -> {type}"); dictionary[tuple] = type; flag = true; } } if (!flag) { AssetHelperPlugin.InstanceLogger.LogInfo((object)"Not writing non-scene catalog: no new assets added"); result = false; } else { 5__3 = new NonSceneCatalogMetadata(); 5__4 = new CustomCatalogBuilder(CatalogKeys.NonSceneCatalogId); foreach (KeyValuePair<(string, string), Type> nonSceneAsset2 in AssetRequestAPI.Request.NonSceneAssets) { nonSceneAsset2.Deconstruct(out key, out value); (string, string) tuple2 = key; string item = tuple2.Item1; string item2 = tuple2.Item2; Type type2 = value; 5__4.AddAssets(item, new List<(string, Type)>(1) { (item2, type2) }); 5__3.CatalogAssets.Add((item, item2), type2); } <>2__current = null; <>1__state = 1; result = true; } goto end_IL_0000; } case 1: <>1__state = -1; AssetHelperPlugin.InstanceLogger.LogInfo((object)"Writing catalog"); 5__5 = 0; 5__6 = 5__4.BuildRoutine(); <>1__state = -3; break; case 2: <>1__state = -3; break; } while (true) { if (5__6.MoveNext()) { float current = 5__6.Current; 5__5++; if (5__5 % 10 == 0) { screen.SetProgress(current); <>2__current = null; <>1__state = 2; result = true; break; } continue; } 5__3.SerializeToFile(5__2); result = false; <>m__Finally1(); break; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (5__6 != null) { 5__6.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static string NonSceneCatalogPath => Path.Combine(AssetPaths.CatalogFolder, CatalogKeys.NonSceneCatalogId + ".bin"); public override IEnumerator Run(ILoadingScreen loadingScreen) { return CreateAndLoadCatalog(loadingScreen); } [IteratorStateMachine(typeof(d__3))] private IEnumerator CreateAndLoadCatalog(ILoadingScreen bar) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(0) { <>4__this = this, bar = bar }; } [IteratorStateMachine(typeof(d__4))] private IEnumerator CreateNonSceneAssetCatalog(ILoadingScreen screen) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0) { screen = screen }; } } internal class SceneCatalogInfo { public record GameObjectInfo(string ObjPath, string ContainerPath, long TransformPathId); public record ChildGameObjectInfo(string ObjPath, long TransformPathId, string AncestorObjPath, string RelativePath, long AncestorTransformPathId); public List RootGameObjects { get; init; } = new List(); public List ChildGameObjects { get; init; } = new List(); public IEnumerable LoadableAssets { get { List list = new List(); list.AddRange(RootGameObjects.Select((GameObjectInfo x) => x.ObjPath)); list.AddRange(ChildGameObjects.Select((ChildGameObjectInfo x) => x.ObjPath)); return new <>z__ReadOnlyList(list); } } } internal class SceneRepacking : BaseStartupTask { [CompilerGenerated] private static class <>O { public static CabResolver <0>__ResolveCab; } [CompilerGenerated] private sealed class d__5 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public SceneRepacking <>4__this; public ILoadingScreen loadingScreen; private List 5__2; private AsyncOperationHandle 5__3; private IDisposable 5__4; private SceneRepacker 5__5; private Stopwatch 5__6; private int 5__7; private int 5__8; private List.Enumerator <>7__wrap8; private CustomCatalogBuilder 5__10; private IEnumerator 5__11; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { case -3: case 2: try { } finally { <>m__Finally1(); } break; case -4: case 6: try { } finally { <>m__Finally2(); } break; } 5__2 = null; 5__3 = default(AsyncOperationHandle); 5__4 = null; 5__5 = null; 5__6 = null; <>7__wrap8 = default(List.Enumerator); 5__10 = null; 5__11 = null; <>1__state = -2; } private bool MoveNext() { //IL_072c: Unknown result type (might be due to invalid IL or missing references) //IL_0731: Unknown result type (might be due to invalid IL or missing references) //IL_0738: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown try { int num = <>1__state; SceneRepacking CS$<>8__locals0 = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; if (AssetRequestAPI.Request.SceneAssets.Count == 0) { AssetHelperPlugin.InstanceLogger.LogInfo((object)"Not running scene repack operation: no scenes in request"); } if (JsonExtensions.TryLoadFromFile>(AssetPaths.RepackedSceneBundleMetadataPath, out Dictionary obj2)) { CS$<>8__locals0._repackData = obj2; } else { CS$<>8__locals0._repackData = new Dictionary(); } CS$<>8__locals0._repackData = (from kvp in CS$<>8__locals0._repackData where kvp.Value.CatalogInfo != null && kvp.Value.Data != null where !MetadataMismatch(kvp.Key, kvp.Value) where File.Exists(GetBundlePathForScene(kvp.Key)) where CS$<>8__locals0.CanLoadAll(kvp.Value.CatalogInfo, kvp.Key) select kvp).ToDictionary((KeyValuePair kvp) => kvp.Key, (KeyValuePair kvp) => kvp.Value); loadingScreen.Reset(); loadingScreen.SetText("REPACKING_SCENE".GetLocalized()); <>2__current = null; <>1__state = 1; return true; } case 1: { <>1__state = -1; CachedObject> cachedObject = CachedObject>.CreateSynced("container_pointer_preloads_cache.json", () => new Dictionary(), mutable: true, out 5__4); object obj = <>O.<0>__ResolveCab; if (obj == null) { CabResolver val = ResolveCab; <>O.<0>__ResolveCab = val; obj = (object)val; } ContainerPointerPreloads val2 = new ContainerPointerPreloads((CabResolver)obj); val2.set_Cache(cachedObject.Value); ContainerPointerPreloads item = val2; PreloadTableResolver val3 = new PreloadTableResolver(new List(2) { (BasePreloadTableResolver)new DefaultPreloadTableResolver(), (BasePreloadTableResolver)(object)item }); 5__5 = (SceneRepacker)new StrippedSceneRepacker((BasePreloadTableResolver)(object)val3); 5__2 = AssetRequestAPI.Request.SceneAssets.Keys.Where((string x) => !CS$<>8__locals0._repackData.ContainsKey(x)).ToList(); 5__6 = Stopwatch.StartNew(); 5__7 = 5__2.Count; 5__8 = 0; AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Repacking {5__7} scenes"); <>7__wrap8 = 5__2.GetEnumerator(); <>1__state = -3; goto IL_03a6; } case 2: <>1__state = -3; goto IL_03a6; case 3: <>1__state = -1; 5__4 = null; 5__5 = null; 5__6 = null; if (5__2.Count > 0 || CS$<>8__locals0.MustWriteCatalog()) { loadingScreen.Reset(); loadingScreen.SetText("BULDING_SCENE".GetLocalized()); <>2__current = null; <>1__state = 4; return true; } AssetHelperPlugin.InstanceLogger.LogInfo((object)"Not creating catalog"); goto IL_06c9; case 4: <>1__state = -1; AssetHelperPlugin.InstanceLogger.LogInfo((object)"Creating catalog"); 5__6 = Stopwatch.StartNew(); 5__10 = new CustomCatalogBuilder(CatalogKeys.SceneCatalogId); foreach (var (sceneName, repackedSceneBundleData2) in CS$<>8__locals0._repackData) { if (repackedSceneBundleData2.Data != null && repackedSceneBundleData2.CatalogInfo != null) { string bundlePathForScene = GetBundlePathForScene(sceneName); string fileName = Path.GetFileName(bundlePathForScene); string serializedBundlePath = GetSerializedBundleDirPrefix() + "/" + fileName; 5__10.AddRepackedSceneData(sceneName, repackedSceneBundleData2.Data, repackedSceneBundleData2.CatalogInfo, bundlePathForScene, serializedBundlePath); } } 5__6.Stop(); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Prepared catalog in {5__6.ElapsedMilliseconds} ms"); loadingScreen.SetText("WRITING_SCENE".GetLocalized()); loadingScreen.SetProgress(0f); <>2__current = null; <>1__state = 5; return true; case 5: <>1__state = -1; 5__6 = Stopwatch.StartNew(); 5__8 = 0; 5__11 = 5__10.BuildRoutine(); <>1__state = -4; goto IL_0652; case 6: <>1__state = -4; goto IL_0652; case 7: <>1__state = -1; loadingScreen.SetText("LOADING_SCENE".GetLocalized()); <>2__current = null; <>1__state = 8; return true; case 8: <>1__state = -1; AssetHelperPlugin.InstanceLogger.LogInfo((object)"Loading scene catalog"); 5__3 = Addressables.LoadContentCatalogAsync(SceneCatalogPath, (string)null); <>2__current = 5__3; <>1__state = 9; return true; case 9: <>1__state = -1; AssetRequestAPI.SceneAssetLocator = 5__3.Result; <>2__current = null; <>1__state = 10; return true; case 10: { <>1__state = -1; return false; } IL_0652: while (5__11.MoveNext()) { float current = 5__11.Current; 5__8++; if (5__8 % 10 == 0) { loadingScreen.SetProgress(current); <>2__current = null; <>1__state = 6; return true; } } 5__6.Stop(); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Finished writing catalog in {5__6.ElapsedMilliseconds} ms"); new SceneCatalogMetadata().SerializeToFile(CatalogMetadataPath); <>m__Finally2(); 5__6 = null; 5__10 = null; 5__11 = null; goto IL_06c9; IL_06c9: <>2__current = null; <>1__state = 7; return true; IL_03a6: if (<>7__wrap8.MoveNext()) { string current2 = <>7__wrap8.Current; HashSet hashSet = AssetRequestAPI.Request.SceneAssets[current2]; Stopwatch stopwatch = Stopwatch.StartNew(); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Repacking {hashSet.Count} objects in scene {current2}"); loadingScreen.SetSubtext(current2); RepackedSceneBundleData value = CS$<>8__locals0.DoRepack(current2, hashSet, 5__5); stopwatch.Stop(); CS$<>8__locals0._repackData[current2] = value; CS$<>8__locals0._repackData.SerializeToFile(AssetPaths.RepackedSceneBundleMetadataPath); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Repacked {current2} in {stopwatch.ElapsedMilliseconds} ms"); 5__8++; loadingScreen.SetProgress((float)5__8 / (float)5__7); <>2__current = null; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap8 = default(List.Enumerator); 5__6.Stop(); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Finished scene repacking after {5__6.ElapsedMilliseconds} ms"); loadingScreen.Reset(); 5__4?.Dispose(); <>2__current = null; <>1__state = 3; return true; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap8).Dispose(); } private void <>m__Finally2() { <>1__state = -1; if (5__11 != null) { 5__11.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private Dictionary _repackData = new Dictionary(); private static string SceneCatalogPath => Path.Combine(AssetPaths.CatalogFolder, CatalogKeys.SceneCatalogId + ".bin"); private static string CatalogMetadataPath => Path.ChangeExtension(SceneCatalogPath, ".json"); [IteratorStateMachine(typeof(d__5))] public override IEnumerator Run(ILoadingScreen loadingScreen) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0) { <>4__this = this, loadingScreen = loadingScreen }; } private RepackedSceneBundleData DoRepack(string scene, HashSet request, SceneRepacker repacker) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown HashSet request2 = request; Dictionary>> transformSeqs = null; string containerPrefix = "AssetHelper/" + scene; RepackingParams val = new RepackingParams { SceneBundlePath = AssetPaths.GetScenePath(scene), ObjectNames = request2.ToList(), ContainerPrefix = containerPrefix, OutBundlePath = GetBundlePathForScene(scene), LateCallback = delegate(RepackingContext ctx, RepackedBundleData data) { transformSeqs = BuildTransformSequences(ctx, data, request2); } }; RepackedBundleData val2 = repacker.Repack(val); string bundleHash = null; if (AddressablesData.TryGetLocationForScene(scene, out IResourceLocation location)) { object data2 = location.Data; AssetBundleRequestOptions val3 = (AssetBundleRequestOptions)((data2 is AssetBundleRequestOptions) ? data2 : null); if (val3 != null) { bundleHash = val3.Hash; } } SceneCatalogInfo catalogInfo = BuildSceneCatalogInfo(val2, transformSeqs, containerPrefix); return new RepackedSceneBundleData { SceneName = scene, BundleHash = bundleHash, Data = val2, CatalogInfo = catalogInfo }; } private SceneCatalogInfo BuildSceneCatalogInfo(RepackedBundleData repackData, Dictionary>> transformSeqs, string containerPrefix) { string containerPrefix2 = containerPrefix; SceneCatalogInfo sceneCatalogInfo = new SceneCatalogInfo(); HashSet hashSet = repackData.GameObjectAssets?.Values.Distinct().ToHashSet() ?? new HashSet(); Dictionary rootTransformPathIds = new Dictionary(); foreach (string rootGo in hashSet) { foreach (List transformSeq in transformSeqs[rootGo]) { string key = repackData.GameObjectAssets.First((KeyValuePair kvp) => kvp.Key.StartsWith($"{containerPrefix2}/{transformSeq[0]}") && kvp.Value == rootGo).Key; sceneCatalogInfo.RootGameObjects.Add(new SceneCatalogInfo.GameObjectInfo(rootGo, key, transformSeq[0])); rootTransformPathIds.Add(transformSeq[0], rootGo); } } foreach (string key2 in transformSeqs.Keys) { if (hashSet.Contains(key2)) { continue; } foreach (List item in transformSeqs[key2]) { long num = item.FirstOrDefault((long x) => rootTransformPathIds.ContainsKey(x)); if (num == 0L) { throw new Exception($"Unexpectedly failed to find ancestor for {key2} [{item[0]}]"); } string text = rootTransformPathIds[num]; if (!key2.StartsWith(text + "/")) { throw new Exception("Object " + key2 + " unexpectedly matched ancestor " + text); } string relativePath = key2.Substring(text.Length + 1); sceneCatalogInfo.ChildGameObjects.Add(new SceneCatalogInfo.ChildGameObjectInfo(key2, item[0], text, relativePath, num)); } } return sceneCatalogInfo; } private Dictionary>> BuildTransformSequences(RepackingContext ctx, RepackedBundleData data, HashSet request) { GameObjectLookup val = ctx.GameObjLookup ?? GameObjectLookup.CreateFromFile(ctx.SceneAssetsManager, ctx.MainAssetsFileInstance); Dictionary>> dictionary = new Dictionary>>(); HashSet hashSet = new HashSet(); foreach (string item in request) { hashSet.Add(item); } IEnumerable enumerable = data.GameObjectAssets?.Values; foreach (string item2 in enumerable ?? Enumerable.Empty()) { hashSet.Add(item2); } List list2 = default(List); foreach (string item3 in hashSet) { List> list = new List>(); if (!val.TryLookupName(item3, ref list2)) { throw new Exception("Failed to find " + item3 + " in bundle"); } foreach (GameObjectInfo item4 in list2) { GameObjectInfo val2 = item4; List list3 = new List(); long transformPathId = val2.TransformPathId; list3.Add(transformPathId); while (val2.ParentPathId != 0L) { val2 = val.LookupTransform(val2.ParentPathId); list3.Add(val2.TransformPathId); } list.Add(list3); } dictionary[item3] = list; } return dictionary; } private bool MustWriteCatalog() { if (!JsonExtensions.TryLoadFromFile(CatalogMetadataPath, out SceneCatalogMetadata obj) || obj.Metadata == null || obj.Metadata.SilksongVersion != VersionData.SilksongVersion || !VersionData.EarliestAcceptableSceneRepackVersion.AllowCachedData(obj.Metadata.PluginVersion) || obj.Metadata.OSFolderName != AssetPaths.OSFolderName) { return true; } if (!File.Exists(SceneCatalogPath)) { return true; } return false; } private static bool MetadataMismatch(string scene, RepackedSceneBundleData existingData) { if (existingData.Metadata == null) { return true; } if (!VersionData.EarliestAcceptableSceneRepackVersion.AllowCachedData(existingData.Metadata.PluginVersion)) { return true; } if (existingData.Metadata.OSFolderName != AssetPaths.OSFolderName) { return true; } if (existingData.Metadata.SilksongVersion == VersionData.SilksongVersion) { return false; } if (AddressablesData.TryGetLocationForScene(scene, out IResourceLocation location)) { object data = location.Data; AssetBundleRequestOptions val = (AssetBundleRequestOptions)((data is AssetBundleRequestOptions) ? data : null); if (val != null && !string.IsNullOrEmpty(val.Hash) && !string.IsNullOrEmpty(existingData.BundleHash) && val.Hash == existingData.BundleHash) { return false; } } return true; } private bool CanLoadAll(SceneCatalogInfo catalogInfo, string sceneName) { HashSet other = new HashSet(catalogInfo.LoadableAssets); if (!AssetRequestAPI.Request.SceneAssets.TryGetValue(sceneName, out HashSet value)) { return true; } return value.IsSubsetOf(other); } private static string GetSerializedBundleDirPrefix() { return "{Silksong.AssetHelper.Core.AssetPaths.RepackedSceneBundleDir}"; } private static string GetBundlePathForScene(string sceneName) { return Path.Combine(AssetPaths.RepackedSceneBundleDir, "repacked_" + sceneName + ".bundle"); } private static bool ResolveCab(string cabName, out string? bundlePath) { bundlePath = null; if (cabName.Contains("unity")) { return true; } if (!BundleMetadata.CabLookup.TryGetValue(cabName.ToLowerInvariant(), out string value)) { return false; } if (value.Contains("monoscripts") || value.Contains("builtinassets")) { return true; } bundlePath = Path.Combine(AssetPaths.BundleFolder, value); return true; } } } namespace Silksong.AssetHelper.Plugin.LoadingPage { public interface ILoadingScreen { void SetText(string text); void SetSubtext(string text); void SetProgress(float progress); void SetVisible(bool visible); } internal static class LoadingScreenExtensions { public static T Create() where T : MonoBehaviour, ILoadingScreen { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("AssetHelper LoadingScreen"); T result = val.AddComponent(); val.SetActive(true); return result; } public static void Reset(this ILoadingScreen self) { self.SetText(string.Empty); self.SetSubtext(string.Empty); self.SetProgress(0f); self.SetVisible(visible: true); } } internal class LoadingScreen : MonoBehaviour, ILoadingScreen { private RectTransform _fillImageRect; private GameObject _canvasObject; private CanvasGroup _canvasGroup; private Text _statusText; private Text _subText; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Expected O, but got Unknown //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) _canvasObject = new GameObject("LoadingCanvas"); Canvas obj = _canvasObject.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 999; _canvasObject.AddComponent(); _canvasObject.AddComponent(); _canvasGroup = _canvasObject.AddComponent(); _canvasGroup.interactable = false; _canvasGroup.blocksRaycasts = true; GameObject val = new GameObject("Background"); val.transform.SetParent(_canvasObject.transform); Image obj2 = val.AddComponent(); ((Graphic)obj2).color = Color.black; RectTransform rectTransform = ((Graphic)obj2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.sizeDelta = Vector2.zero; rectTransform.anchoredPosition = Vector2.zero; GameObject val2 = new GameObject("Outline"); val2.transform.SetParent(_canvasObject.transform); Image obj3 = val2.AddComponent(); ((Graphic)obj3).color = Color.white; RectTransform rectTransform2 = ((Graphic)obj3).rectTransform; rectTransform2.anchorMin = new Vector2(0.5f, 0.5f); rectTransform2.anchorMax = new Vector2(0.5f, 0.5f); rectTransform2.pivot = new Vector2(0.5f, 0.5f); rectTransform2.sizeDelta = new Vector2(500f, 66f); rectTransform2.anchoredPosition = Vector2.zero; GameObject val3 = new GameObject("InnerBG"); val3.transform.SetParent(val2.transform); Image obj4 = val3.AddComponent(); ((Graphic)obj4).color = Color.black; RectTransform rectTransform3 = ((Graphic)obj4).rectTransform; rectTransform3.anchorMin = Vector2.zero; rectTransform3.anchorMax = Vector2.one; rectTransform3.sizeDelta = new Vector2(-4f, -4f); rectTransform3.anchoredPosition = Vector2.zero; GameObject val4 = new GameObject("Fill"); val4.transform.SetParent(val3.transform); Image val5 = val4.AddComponent(); ((Graphic)val5).color = Color.white; _fillImageRect = ((Graphic)val5).rectTransform; _fillImageRect.anchorMin = new Vector2(0f, 0f); _fillImageRect.anchorMax = new Vector2(0f, 1f); _fillImageRect.pivot = new Vector2(0f, 0.5f); _fillImageRect.sizeDelta = Vector2.zero; _fillImageRect.anchoredPosition = Vector2.zero; GameObject val6 = new GameObject("StatusText"); val6.transform.SetParent(_canvasObject.transform); _statusText = val6.AddComponent(); _statusText.font = Resources.GetBuiltinResource("Arial.ttf"); _statusText.text = string.Empty; _statusText.fontSize = 30; _statusText.alignment = (TextAnchor)4; ((Graphic)_statusText).color = Color.white; RectTransform rectTransform4 = ((Graphic)_statusText).rectTransform; rectTransform4.anchorMin = new Vector2(0.5f, 0.5f); rectTransform4.anchorMax = new Vector2(0.5f, 0.5f); rectTransform4.pivot = new Vector2(0.5f, 0f); rectTransform4.sizeDelta = new Vector2(800f, 50f); rectTransform4.anchoredPosition = new Vector2(0f, 60f); GameObject val7 = new GameObject("SubText"); val7.transform.SetParent(_canvasObject.transform); _subText = val7.AddComponent(); _subText.font = Resources.GetBuiltinResource("Arial.ttf"); _subText.text = string.Empty; _subText.fontSize = 20; _subText.alignment = (TextAnchor)4; ((Graphic)_subText).color = Color.white; RectTransform rectTransform5 = ((Graphic)_subText).rectTransform; rectTransform5.anchorMin = new Vector2(0.5f, 0.5f); rectTransform5.anchorMax = new Vector2(0.5f, 0.5f); rectTransform5.pivot = new Vector2(0.5f, 1f); rectTransform5.sizeDelta = new Vector2(800f, 50f); rectTransform5.anchoredPosition = new Vector2(0f, -45f); _statusText.text = "Loading..."; } public void SetProgress(float progress) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) progress = Mathf.Clamp01(progress); _fillImageRect.anchorMax = new Vector2(progress, 1f); } public void SetVisible(bool visible) { _canvasGroup.alpha = (visible ? 1f : 0f); } public void SetText(string text) { _statusText.text = text; } public void SetSubtext(string text) { _subText.text = text; } private void OnDestroy() { if ((Object)(object)_canvasObject != (Object)null) { Object.Destroy((Object)(object)_canvasObject); } } } [RequireComponent(typeof(Text))] internal class MemoryWatcher : MonoBehaviour { private long maxSoFar; private Text _text; private void Awake() { _text = ((Component)this).GetComponent(); } private void Update() { long totalMemory = GC.GetTotalMemory(forceFullCollection: false); maxSoFar = ((totalMemory > maxSoFar) ? totalMemory : maxSoFar); _text.text = $"Memory: {totalMemory:E}\nMax {maxSoFar:E}"; } } } namespace Silksong.AssetHelper.ManagedAssets { public interface IManagedAsset { object? Load(); void Unload(); } public class ManagedAsset : ManagedAssetBase { public string Key { get; } protected internal override string Identifier => Key; public ManagedAsset(string key) { Key = key; base..ctor(); } public static ManagedAsset FromSceneAsset(string sceneName, string objPath) { if (typeof(T) != typeof(GameObject)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)"ManagedAsset instances for scene assets should have GameObject as the type argument!"); } HashSet value; if (AssetRequestAPI.RequestApiAvailable) { AssetRequestAPI.RequestSceneAsset(sceneName, objPath); } else if (!AssetRequestAPI.Request.SceneAssets.TryGetValue(sceneName.ToLowerInvariant(), out value) || !value.Contains(objPath)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Constructing managed asset from scene " + sceneName + ", " + objPath + " after Awake may not work unless the asset has been requested first!")); } return new ManagedAsset(CatalogKeys.GetKeyForSceneAsset(sceneName, objPath)); } public static ManagedAsset FromNonSceneAsset(string assetName, string? bundleName = null) { if (AssetRequestAPI.RequestApiAvailable && !string.IsNullOrEmpty(bundleName)) { AssetRequestAPI.RequestNonSceneAsset(bundleName, assetName); } else if (!string.IsNullOrEmpty(bundleName) && !AssetRequestAPI.Request.NonSceneAssets.ContainsKey((bundleName, assetName))) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Constructing managed asset " + assetName + " from non-scene bundle " + bundleName + " after Awake may not work unless the asset has been requested first!")); } return new ManagedAsset(CatalogKeys.GetKeyForNonSceneAsset(assetName)); } protected override AsyncOperationHandle DoLoad() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Addressables.LoadAssetAsync((object)Key); } public ManagedAsset Clone() { return new ManagedAsset(Key); } } public abstract class ManagedAssetBase : IManagedAsset { private AsyncOperationHandle? _handle; protected internal abstract string Identifier { get; } public AsyncOperationHandle Handle { get { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!_handle.HasValue) { throw new InvalidOperationException("Addressable asset with identifier " + Identifier + " must be loaded before accessing the handle!"); } return _handle.Value; } } public bool IsLoaded { get { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (HasBeenLoaded) { return Handle.IsDone; } return false; } } public bool HasBeenLoaded => _handle.HasValue; public AsyncOperationHandle Load() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!_handle.HasValue) { _handle = DoLoad(); } return Handle; } protected abstract AsyncOperationHandle DoLoad(); object? IManagedAsset.Load() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Load(); } public void Unload() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (_handle.HasValue) { Addressables.Release(_handle.Value); _handle = null; } } } public class ManagedAssetBundle : ManagedAssetBase { public string BundleName { get; } protected internal override string Identifier => BundleName; public ManagedAssetBundle(string bundleName) { BundleName = bundleName; base..ctor(); } protected override AsyncOperationHandle DoLoad() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return Addressables.LoadAssetAsync((object)AddressablesData.ToBundleKey(BundleName)); } public ManagedAssetBundle Clone() { return new ManagedAssetBundle(BundleName); } } public static class ManagedAssetExtensions { public static T InstantiateAsset(this ManagedAsset asset) where T : Object { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!asset.IsLoaded) { throw new InvalidOperationException("The asset has not finished loading!"); } return Object.Instantiate(asset.Handle.Result); } public static void EnsureLoaded(this ManagedAssetBase asset) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!asset.HasBeenLoaded) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("EnsureLoaded has been called on " + asset.Identifier + " before loading the asset!")); asset.Load(); } if (!asset.IsLoaded) { asset.Handle.WaitForCompletion(); } if (asset.Handle.OperationException != null) { AssetHelperPlugin.InstanceLogger.LogError((object)("Operation exception when loading asset " + asset.Identifier + "\n" + asset.Handle.OperationException)); } } [EditorBrowsable(EditorBrowsableState.Never)] public static void EnsureLoaded(this ManagedAsset asset) { ((ManagedAssetBase)asset).EnsureLoaded(); } public static T InstantiateAsset(this ManagedAssetGroup group, string key) where T : Object { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!group.IsLoaded) { throw new InvalidOperationException("The group has not finished loading!"); } return Object.Instantiate(group[key].Result); } public static T InstantiateAsset(this ManagedAssetList asset, Func predicate) where T : Object { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (!asset.IsLoaded) { throw new InvalidOperationException("The asset has not finished loading!"); } foreach (T item in asset.Handle.Result) { if (predicate(item)) { return Object.Instantiate(item); } } throw new ArgumentException("No matching asset for managed asset list with key " + asset.Key + " was found!"); } } public class ManagedAssetGroup : IManagedAsset { public record SceneAssetInfo(string SceneName, string ObjPath); public record NonSceneAssetInfo(string BundleName, string AssetName); private readonly Dictionary _keyLookup; private Dictionary>? _handles; public AsyncOperationHandle this[string name] { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (_handles == null) { throw new InvalidOperationException("Handles can not be accessed until this instance has started loading"); } return _handles[name]; } } public bool IsLoaded { get { if (HasBeenLoaded) { return _handles.Values.All((AsyncOperationHandle x) => x.IsDone); } return false; } } public bool HasBeenLoaded => _handles != null; public ManagedAssetGroup(Dictionary keyLookup) { _keyLookup = keyLookup; } public static ManagedAssetGroup RequestAndCreate(Dictionary? sceneAssets = null, Dictionary? nonSceneAssets = null) { Dictionary dictionary = new Dictionary(); string key; if (sceneAssets != null) { if (typeof(T) != typeof(GameObject)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)"ManagedAssetGroup instances for scene assets should have GameObject as the type argument!"); } foreach (KeyValuePair sceneAsset in sceneAssets) { sceneAsset.Deconstruct(out key, out var value); string key2 = key; SceneAssetInfo sceneAssetInfo = value; HashSet value2; if (AssetRequestAPI.RequestApiAvailable) { AssetRequestAPI.RequestSceneAsset(sceneAssetInfo.SceneName, sceneAssetInfo.ObjPath); } else if (!AssetRequestAPI.Request.SceneAssets.TryGetValue(sceneAssetInfo.SceneName.ToLowerInvariant(), out value2) || !value2.Contains(sceneAssetInfo.ObjPath)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Constructing managed asset from scene " + sceneAssetInfo.SceneName + ", " + sceneAssetInfo.ObjPath + " after Awake may not work unless the asset has been requested first!")); } dictionary.Add(key2, CatalogKeys.GetKeyForSceneAsset(sceneAssetInfo.SceneName, sceneAssetInfo.ObjPath)); } } if (nonSceneAssets != null) { foreach (KeyValuePair nonSceneAsset in nonSceneAssets) { nonSceneAsset.Deconstruct(out key, out var value3); string key3 = key; NonSceneAssetInfo nonSceneAssetInfo = value3; if (AssetRequestAPI.RequestApiAvailable) { AssetRequestAPI.RequestNonSceneAsset(nonSceneAssetInfo.BundleName, nonSceneAssetInfo.AssetName); } else if (!AssetRequestAPI.Request.NonSceneAssets.ContainsKey((nonSceneAssetInfo.BundleName, nonSceneAssetInfo.AssetName))) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Constructing managed asset " + nonSceneAssetInfo.AssetName + " from non-scene bundle " + nonSceneAssetInfo.BundleName + " after Awake may not work unless the asset has been requested first!")); } dictionary.Add(key3, CatalogKeys.GetKeyForNonSceneAsset(nonSceneAssetInfo.AssetName)); } } return new ManagedAssetGroup(dictionary); } public CustomYieldInstruction GetYieldInstruction() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (_handles == null) { throw new InvalidOperationException("This ManagedAssetGroup must be loaded before awaiting!"); } return (CustomYieldInstruction)new WaitUntil((Func)(() => IsLoaded)); } public CustomYieldInstruction Load() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (_handles != null) { return GetYieldInstruction(); } _handles = new Dictionary>(); foreach (var (key, text3) in _keyLookup) { _handles[key] = Addressables.LoadAssetAsync((object)text3); } return GetYieldInstruction(); } object? IManagedAsset.Load() { return Load(); } public Task GetTask() { if (_handles == null) { throw new InvalidOperationException("This ManagedAssetGroup must be loaded before awaiting!"); } return Task.WhenAll(_handles.Values.Select((AsyncOperationHandle x) => x.Task)); } public ManagedAsset GetIndividualAsset(string name) { return new ManagedAsset(_keyLookup[name]); } public void Unload() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (_handles == null) { return; } foreach (AsyncOperationHandle value in _handles.Values) { Addressables.Release(value); } _handles = null; } } public class ManagedAssetList : ManagedAssetBase> { public string Key { get; } protected internal override string Identifier => Key; public ManagedAssetList(string key) { Key = key; base..ctor(); } protected override AsyncOperationHandle> DoLoad() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return Addressables.LoadAssetsAsync(Key, (Action)null); } public ManagedAssetList Clone() { return new ManagedAssetList(Key); } public static ManagedAssetList FromSceneAsset(string sceneName, string objPath) { if (typeof(T) != typeof(GameObject)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)"ManagedAssetList instances for scene assets should have GameObject as the type argument!"); } HashSet value; if (AssetRequestAPI.RequestApiAvailable) { AssetRequestAPI.RequestSceneAsset(sceneName, objPath); } else if (!AssetRequestAPI.Request.SceneAssets.TryGetValue(sceneName.ToLowerInvariant(), out value) || !value.Contains(objPath)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Constructing managed asset list from scene " + sceneName + ", " + objPath + " after Awake may not work unless the asset has been requested first!")); } return new ManagedAssetList(CatalogKeys.GetKeyForSceneAsset(sceneName, objPath)); } } public class ManagedResourceLocation : IManagedAsset { private AsyncOperationHandle? _handle; public IResourceLocation Location { get; } public AsyncOperationHandle Handle { get { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!_handle.HasValue) { throw new InvalidOperationException("Addressable asset with location " + Location.InternalId + " must be loaded before accessing the handle!"); } return _handle.Value; } } public bool IsLoaded { get { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (HasBeenLoaded) { return Handle.IsDone; } return false; } } public bool HasBeenLoaded => _handle.HasValue; public ManagedResourceLocation(IResourceLocation location) { Location = location; base..ctor(); } public AsyncOperationHandle Load() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!_handle.HasValue) { _handle = Addressables.LoadAssetAsync(Location); } return Handle; } object? IManagedAsset.Load() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Load(); } public void Unload() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (_handle.HasValue) { Addressables.Release(_handle.Value); _handle = null; } } } } namespace Silksong.AssetHelper.Internal { internal static class ActionUtil { private static readonly ManualLogSource Log = Logger.CreateLogSource("AssetHelper.ActionUtil"); public static void SafeInvoke(Action? a) { if (a == null) { return; } try { a(); } catch (Exception ex) { Log.LogError((object)("Error invoking action " + a.Method.Name + "\n" + ex)); } } public static void SafeInvoke(Action? a, T arg) { if (a == null) { return; } try { a(arg); } catch (Exception ex) { Log.LogError((object)("Error invoking action " + a.Method.Name + "\n" + ex)); } } } internal class CachedFileMetadata { public required string SilksongVersion { get; init; } public required string PluginVersion { get; init; } public required string OSFolderName { get; init; } public static CachedFileMetadata CreateNew() { return new CachedFileMetadata { SilksongVersion = VersionData.SilksongVersion, PluginVersion = AssetHelperPlugin.Version, OSFolderName = AssetPaths.OSFolderName }; } } internal class CachedObject where T : class { [JsonProperty(/*Could not decode attribute arguments.*/)] [DefaultValue(null)] public required CachedFileMetadata Metadata { get; init; } [JsonProperty] public required T Value { get; set; } private CachedObject() { } private bool IsValid() { if (Metadata == null || Metadata.SilksongVersion == null || Metadata.PluginVersion == null) { return false; } if (Metadata.OSFolderName != AssetPaths.OSFolderName) { return false; } if (VersionData.SilksongVersion != Metadata.SilksongVersion) { return false; } if (!VersionData.EarliestAcceptableGeneralVersion.AllowCachedData(Metadata.PluginVersion)) { return false; } return true; } public static CachedObject CreateSynced(string filename, Func createDefault, bool mutable, out IDisposable? syncHandle) { syncHandle = null; string text = Path.Combine(AssetPaths.CacheDirectory, filename); if (JsonExtensions.TryLoadFromFile>(text, out CachedObject obj) && obj.Value != null && obj.IsValid()) { if (mutable) { syncHandle = new F2DD635EBDE083CBD17FC2C9D7D25FDDFBD73B1716C77C87C4A78F37A6C77FBC9__CachedObjectSyncHandle(obj, text); } return obj; } CachedObject cachedObject = new CachedObject { Metadata = CachedFileMetadata.CreateNew(), Value = createDefault() }; cachedObject.SerializeToFile(text); if (mutable) { syncHandle = new F2DD635EBDE083CBD17FC2C9D7D25FDDFBD73B1716C77C87C4A78F37A6C77FBC9__CachedObjectSyncHandle(cachedObject, text); } return cachedObject; } } internal class F2DD635EBDE083CBD17FC2C9D7D25FDDFBD73B1716C77C87C4A78F37A6C77FBC9__CachedObjectSyncHandle : IDisposable where T : class { private CachedObject _obj; private string _filepath; public F2DD635EBDE083CBD17FC2C9D7D25FDDFBD73B1716C77C87C4A78F37A6C77FBC9__CachedObjectSyncHandle(CachedObject obj, string filepath) { _obj = obj; _filepath = filepath; AssetHelperPlugin.OnQuitApplication += SyncObj; } private void SyncObj() { _obj.SerializeToFile(_filepath); } public void Dispose() { SyncObj(); AssetHelperPlugin.OnQuitApplication -= SyncObj; } } internal class DelayedAction { private List _subscribers = new List(); public bool Activated { get; private set; } public void Activate() { if (Activated) { return; } Activated = true; foreach (Action subscriber in _subscribers) { ActionUtil.SafeInvoke(subscriber); } _subscribers.Clear(); } public void Subscribe(Action toInvoke) { if (Activated) { ActionUtil.SafeInvoke(toInvoke); } else { _subscribers.Add(toInvoke); } } } internal class DictListConverter : JsonConverter> { public override Dictionary? ReadJson(JsonReader reader, Type objectType, Dictionary? existingValue, bool hasExistingValue, JsonSerializer serializer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)reader.TokenType == 11) { return null; } return serializer.Deserialize>(reader)?.ToDictionary(((T, U) x) => x.Item1, ((T, U) x) => x.Item2); } public override void WriteJson(JsonWriter writer, Dictionary? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } List<(T, U)> list = value.Select, (T, U)>((KeyValuePair kvp) => (kvp.Key, kvp.Value)).ToList(); serializer.Serialize(writer, (object)list); } public DictListConverter() { ((JsonConverter, ?>>)(object)this)..ctor(); } } internal static class EnumeratorExtensions { public static void Consume(this IEnumerator self) { while (self.MoveNext()) { } } } internal static class JsonExtensions { public static void SerializeToFile(this T self, string filePath) { string contents = JsonConvert.SerializeObject((object)self, (Formatting)1); File.WriteAllText(filePath, contents); } public static void SerializeToFileInBackground(this T self, string filePath) { T self2 = self; string filePath2 = filePath; Task.Run(delegate { self2.SerializeToFile(filePath2); }); } public static bool TryLoadFromFile(string filePath, [NotNullWhen(true)] out T? obj) { obj = default(T); if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) { return false; } try { string text = File.ReadAllText(filePath); obj = JsonConvert.DeserializeObject(text); return obj != null; } catch (Exception) { return false; } } } [JsonData("$.*~", new string[] { "**/languages/en.json" })] internal static class LanguageKeys { public const string BUILDING_NON_SCENE = "BUILDING_NON_SCENE"; public const string BULDING_SCENE = "BULDING_SCENE"; public const string COMPUTING_BUNDLE_DEPS = "COMPUTING_BUNDLE_DEPS"; public const string LOADING_NON_SCENE = "LOADING_NON_SCENE"; public const string LOADING_SCENE = "LOADING_SCENE"; public const string REPACKING_SCENE = "REPACKING_SCENE"; public const string WRITING_SCENE = "WRITING_SCENE"; public static string GetLocalized(this string key) { return Language.Get(key, "Mods.org.silksong-modding.assethelper"); } } internal static class VersionData { private static string? _silksongVersion; public static string SilksongVersion { get { if (_silksongVersion == null) { _silksongVersion = GetSilksongVersion(); } return _silksongVersion; } } internal static Version EarliestAcceptableGeneralVersion { get; } = Version.Parse("1.3.0"); internal static Version EarliestAcceptableSceneRepackVersion { get; } = Version.Parse("1.3.0"); internal static Version EarliestAcceptableNonSceneCatalogVersion { get; } = Version.Parse("1.3.0"); private static string GetSilksongVersion() { return (AccessTools.Field(typeof(Constants), "GAME_VERSION")?.GetRawConstantValue() as string) ?? "UNKNOWN"; } internal static bool AllowCachedData(this Version earliest, string cachedPluginVersion) { if (!Version.TryParse(cachedPluginVersion, out Version result)) { return false; } if (result > Version.Parse(AssetHelperPlugin.Version)) { return false; } if (result < earliest) { return false; } return true; } } } namespace Silksong.AssetHelper.Dev { public static class DebugTools { private class LocatorInfo { public string? LocatorID { get; init; } public Dictionary> Infos { get; init; } = new Dictionary>(); } private class AddressablesAssetInfo { public string? InternalId { get; init; } public string? ProviderId { get; init; } public int DependencyCount { get; init; } public List? Dependencies { get; init; } public string? PrimaryKey { get; init; } public Type? ResourceType { get; init; } public Type? AuxDataType { get; init; } public static AddressablesAssetInfo FromLocation(IResourceLocation loc, bool includeDependencyNames) { List dependencies = ((!includeDependencyNames) ? null : (loc.Dependencies?.Select((IResourceLocation x) => "[" + ((x != null) ? x.PrimaryKey : null) + " | " + ((x != null) ? x.InternalId : null) + "]").ToList() ?? new List())); return new AddressablesAssetInfo { InternalId = loc.InternalId, ProviderId = loc.ProviderId, DependencyCount = (loc.Dependencies?.Count ?? 0), Dependencies = dependencies, PrimaryKey = loc.PrimaryKey, ResourceType = loc.ResourceType, AuxDataType = loc.Data?.GetType() }; } } public class LoadedBundleNames { public List VanillaBundleNames; public List RepackedSceneBundles; public List Unknown; public LoadedBundleNames(List names, List repacked, List unknown) { VanillaBundleNames = names; RepackedSceneBundles = repacked; Unknown = unknown; base..ctor(); } } private static readonly ManualLogSource Log = Logger.CreateLogSource("AssetHelper.DebugTools"); private static string _debugDataDir = Path.Combine(AssetPaths.AssemblyFolder, "DebugData"); private static Dictionary? _bundleNameLookup; private static Dictionary? _repackBundleNameLookup = null; public static string DebugDataDir { get { if (!Directory.Exists(_debugDataDir)) { Directory.CreateDirectory(_debugDataDir); } return _debugDataDir; } } public static void DumpAddressablesKeys() { string dumpFile = Path.Combine(DebugDataDir, "bundle_keys.json"); AddressablesData.InvokeAfterAddressablesLoaded(delegate { AddressablesData.BundleKeys.SerializeToFileInBackground(dumpFile); }); } public static void DumpAllAssetNames() { AddressablesData.InvokeAfterAddressablesLoaded(DumpAllAssetNamesInternal); } private static void DumpAllAssetNamesInternal() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) string filePath = Path.Combine(DebugDataDir, "asset_names.json"); Dictionary> dictionary = new Dictionary>(); Dictionary> dictionary2 = new Dictionary>(); Stopwatch stopwatch = Stopwatch.StartNew(); foreach (KeyValuePair bundleKey in AddressablesData.BundleKeys) { bundleKey.Deconstruct(out var key, out var value); string key2 = key; AsyncOperationHandle val = Addressables.LoadAssetAsync((object)value); AssetBundle assetBundle = val.WaitForCompletion().GetAssetBundle(); string[] allScenePaths = assetBundle.GetAllScenePaths(); if (allScenePaths.Length != 0) { dictionary2[key2] = allScenePaths.ToList(); } string[] allAssetNames = assetBundle.GetAllAssetNames(); if (allAssetNames.Length != 0) { dictionary[key2] = allAssetNames.ToList(); } Addressables.Release(val); } stopwatch.Stop(); Log.LogInfo((object)$"Determined asset names in {stopwatch.ElapsedMilliseconds} ms"); new Dictionary>> { ["assets"] = dictionary, ["scenes"] = dictionary2 }.SerializeToFileInBackground(filePath); } public static void DumpAllAddressableAssets() { AddressablesData.InvokeAfterAddressablesLoaded(DumpAllAddressableAssetsInternal); } private static void DumpAllAddressableAssetsInternal() { if (AddressablesData.MainLocator != null) { DumpAllAddressableAssets(AddressablesData.MainLocator, "addressables_main.json"); } } public static void DumpAllAddressableAssets(IResourceLocator locator, string fileName, bool includeDependencyNames = false) { Dictionary> dictionary = new Dictionary>(); IList source = default(IList); foreach (string item in locator.Keys.OfType()) { if (locator.Locate((object)item, (Type)null, ref source)) { dictionary[item] = source.Select((IResourceLocation x) => AddressablesAssetInfo.FromLocation(x, includeDependencyNames)).ToList(); } } new LocatorInfo { LocatorID = locator.LocatorId, Infos = dictionary }.SerializeToFileInBackground(Path.Combine(DebugDataDir, fileName)); } private static Dictionary GenerateBundleNameLookup() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (KeyValuePair bundleKey in AddressablesData.BundleKeys) { bundleKey.Deconstruct(out var key, out var value); string value2 = key; AsyncOperationHandle val = Addressables.LoadAssetAsync((object)value); val.WaitForCompletion(); dictionary[((Object)val.Result.GetAssetBundle()).name] = value2; Addressables.Release(val); } return dictionary; } public static LoadedBundleNames GetLoadedBundleNames() { if (!AddressablesData.IsAddressablesLoaded) { throw new InvalidOperationException("GetLoadedBundleNames cannot be called until Addressables is loaded!"); } if (_bundleNameLookup == null) { _bundleNameLookup = CachedObject>.CreateSynced("bundle_name_lookup.json", GenerateBundleNameLookup, mutable: false, out IDisposable _).Value; } List list = new List(); List list2 = new List(); List list3 = new List(); foreach (string item in from b in AssetBundle.GetAllLoadedAssetBundles() select ((Object)b).name) { if (_bundleNameLookup.TryGetValue(item, out string value)) { list.Add(value + ".bundle"); } else { list3.Add(item); } } if (list3.Count > 0) { if (_repackBundleNameLookup == null) { _repackBundleNameLookup = CreateRepackBundleNameLookup(); } List list4 = new List(); foreach (string item2 in list3) { if (_repackBundleNameLookup.TryGetValue(item2, out string value2)) { list2.Add(value2); } else { list4.Add(item2); } } list3 = list4; } return new LoadedBundleNames(list, list2, list3); } private static Dictionary CreateRepackBundleNameLookup() { Dictionary dictionary = new Dictionary(); if (JsonExtensions.TryLoadFromFile>(AssetPaths.RepackedSceneBundleMetadataPath, out Dictionary obj)) { foreach (RepackedSceneBundleData value in obj.Values) { RepackedBundleData? data = value.Data; if (((data != null) ? data.BundleName : null) != null) { dictionary[value.Data.BundleName] = value.SceneName; } } } return dictionary; } public static void DumpLoadedBundleNames() { GetLoadedBundleNames().SerializeToFile(Path.Combine(DebugDataDir, "loaded_bundle_names.json")); } public static void DumpGameObjectPaths(string sceneName, bool compressed) { string path = "paths_" + sceneName + (compressed ? "_compressed.json" : ".json"); string filePath = Path.Combine(DebugDataDir, path); AssetsManager val = BundleUtils.CreateDefaultManager(); string scenePath = AssetPaths.GetScenePath(sceneName); using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(scenePath)); BundleFileInstance val2 = val.LoadBundleFile((Stream)memoryStream, scenePath, true); SceneBundleInfo val3 = default(SceneBundleInfo); if (!BundleUtils.TryFindAssetsFiles(val, val2, ref val3)) { return; } AssetsFileInstance val4 = val.LoadAssetsFileFromBundle(val2, val3.mainAfileInstIndex, false); List list = GameObjectLookupExtensions.TraverseOrdered(GameObjectLookup.CreateFromFile(val, val4)).ToList(); if (!compressed) { list.SerializeToFile(filePath); return; } list.Select((GameObjectInfo x) => $"{x.GameObjectName} [{x.GameObjectPathId}, {x.TransformPathId}]").ToList().SerializeToFile(filePath); val.UnloadAll(false); } public static void SerializeAssetRequest(string filename = "asset_request.json") { AssetRequestAPI.Request.SerializeToFile(Path.Combine(DebugDataDir, filename)); } } } namespace Silksong.AssetHelper.Core { public static class AddressablesData { private static readonly ManualLogSource Log = Logger.CreateLogSource("AssetHelper.AddressablesData"); private static Dictionary? _bundleKeys; private static DelayedAction _afterAddressablesLoaded = new DelayedAction(); private static readonly string BundleSuffix = "_[0-9a-fA-F]{32}\\.bundle+$"; private static readonly Regex BundleSuffixRegex = new Regex(BundleSuffix, RegexOptions.Compiled); public static IResourceLocator? MainLocator { get; private set; } public static IReadOnlyDictionary? BundleKeys { get { if (_bundleKeys != null) { return new ReadOnlyDictionary(_bundleKeys); } return null; } } public static bool IsAddressablesLoaded => _bundleKeys != null; public static bool TryGetLocation(string bundleName, [NotNullWhen(true)] out IResourceLocation? location) { string text = ToBundleKey(bundleName); IList source = Array.Empty(); IResourceLocator? mainLocator = MainLocator; if (mainLocator != null && !mainLocator.Locate((object)text, typeof(IAssetBundleResource), ref source)) { location = null; return false; } location = source.FirstOrDefault(); return location != null; } public static bool TryGetLocationForScene(string sceneName, [NotNullWhen(true)] out IResourceLocation? location) { return TryGetLocation("scenes_scenes_scenes/" + sceneName.ToLowerInvariant(), out location); } public static void InvokeAfterAddressablesLoaded(Action a) { _afterAddressablesLoaded.Subscribe(a); } internal static bool TryStrip(string key, [MaybeNullWhen(false)] out string stripped) { if (BundleSuffixRegex.IsMatch(key)) { stripped = BundleSuffixRegex.Replace(key, ""); return true; } stripped = key; return false; } internal static bool TryLoadBundleKeys() { Dictionary dictionary = new Dictionary(); Stopwatch stopwatch = Stopwatch.StartNew(); MainLocator = Addressables.ResourceLocators.FirstOrDefault((Func)((IResourceLocator x) => x.Keys.Any())); if (MainLocator == null) { Log.LogWarning((object)"Addressables not loaded yet"); return false; } foreach (string item in MainLocator.Keys.OfType()) { if (TryStrip(item, out string stripped)) { dictionary[stripped] = item; } } stopwatch.Stop(); Log.LogInfo((object)$"Loaded {dictionary.Count} bundle locations in {stopwatch.ElapsedMilliseconds} ms"); if (dictionary.Count == 0) { return false; } _bundleKeys = dictionary; _afterAddressablesLoaded.Activate(); return true; } public static string ToBundleKey(string name) { if (_bundleKeys == null) { Log.LogWarning((object)"ToBundleKey called before addressables loaded"); return name; } if (TryStrip(name, out string stripped)) { name = stripped; } else if (name.EndsWith(".bundle")) { string text = name; name = text.Substring(0, text.Length - 7); } if (_bundleKeys.TryGetValue(name, out string value)) { return value; } throw new Exception("Bundle " + name + " not found in lookup."); } } public static class AssetPaths { public static string OSFolderName { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 RuntimePlatform platform = Application.platform; if ((int)platform != 1) { if ((int)platform != 2) { if ((int)platform == 13) { return "StandaloneLinux64"; } return ""; } return "StandaloneWindows64"; } return "StandaloneOSX"; } } public static string BundleFolder => Path.Combine(Application.streamingAssetsPath, "aa", OSFolderName); private static string CacheSubfolder => "AssetHelper"; public static string CacheDirectory => Path.Combine(Paths.CachePath, CacheSubfolder).CreateIfNeeded(); public static string RepackedSceneBundleDir => Path.Combine(CacheDirectory, "repacked_scenes").CreateIfNeeded(); internal static string RepackedSceneBundleMetadataPath => Path.Combine(RepackedSceneBundleDir, "repack_data.json"); internal static string CatalogFolder => Path.Combine(CacheDirectory, "Catalogs").CreateIfNeeded(); internal static string AssemblyFolder => Directory.GetParent(typeof(AssetPaths).Assembly.Location).FullName; private static string CreateIfNeeded(this string path) { Directory.CreateDirectory(path); return path; } public static string GetScenePath(string sceneName) { return Path.Combine(BundleFolder, "scenes_scenes_scenes", sceneName.ToLowerInvariant() + ".bundle"); } } public static class BundleMetadata { public static IReadOnlyDictionary CabLookup { get; private set; } private static CachedObject>> DirectDependencyLookup { get; set; } internal static void Setup() { CabLookup = CachedObject>.CreateSynced("cabs.json", GenerateCabLookup, mutable: false, out IDisposable syncHandle).Value; DirectDependencyLookup = CachedObject>>.CreateSynced("direct_deps.json", () => new Dictionary>(), mutable: true, out syncHandle); } private static Dictionary GenerateCabLookup() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown Stopwatch stopwatch = Stopwatch.StartNew(); AssetsManager val = new AssetsManager(); string bundleFolder = AssetPaths.BundleFolder; Dictionary dictionary = new Dictionary(); foreach (string key in AddressablesData.BundleKeys.Keys) { string text = key.Replace("\\", "/"); if (!text.EndsWith(".bundle")) { text += ".bundle"; } string text2 = Path.Combine(bundleFolder, text); if (!File.Exists(text2)) { AssetHelperPlugin.InstanceLogger.LogError((object)("Bundle not found! Resolved key " + text + "\nThis may cause errors down the line")); continue; } string text3 = val.LoadBundleFile(text2, true).file.GetFileName(0).Split(".")[0].ToLowerInvariant(); if (dictionary.ContainsKey(text3)) { AssetHelperPlugin.InstanceLogger.LogWarning((object)("Duplicate cab detected! " + text3 + ": " + dictionary[text3] + " -> " + text)); } else { dictionary[text3] = text; } val.UnloadAll(false); } stopwatch.Stop(); AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Generated CAB lookup in {stopwatch.ElapsedMilliseconds} ms"); return dictionary; } public static List DetermineDirectDeps(string bundleName) { bool cacheHit; return DetermineDirectDepsInternal(bundleName, out cacheHit); } internal static List DetermineDirectDepsInternal(string bundleName, out bool cacheHit) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown string text = bundleName; if (!text.EndsWith(".bundle")) { text += ".bundle"; } if (DirectDependencyLookup.Value.TryGetValue(text, out List value)) { cacheHit = true; return value.ToList(); } cacheHit = false; AssetsManager val = new AssetsManager(); string text2 = Path.Combine(AssetPaths.BundleFolder, text); RentedFileArray val2 = new RentedFileArray(text2); try { BundleFileInstance val3 = val.LoadBundleFile((Stream)val2.Stream, text2, true); AssetsFile file = val.LoadAssetsFileFromBundle(val3, 0, false).file; List list = new List(); foreach (AssetsFileExternal external in file.Metadata.Externals) { string key = external.OriginalPathName.Split('/')[^1].Split(".")[0].ToLowerInvariant(); if (CabLookup.TryGetValue(key, out string value2)) { list.Add(value2); } } DirectDependencyLookup.Value[text] = list.ToList(); val.UnloadAll(false); return list; } finally { ((IDisposable)val2)?.Dispose(); } } public static List DetermineTransitiveDeps(string bundleName) { string text = bundleName; if (!text.EndsWith(".bundle")) { text += ".bundle"; } HashSet hashSet = new HashSet { text }; Queue queue = new Queue(); queue.Enqueue(text); string result; while (queue.TryDequeue(out result)) { foreach (string item in DetermineDirectDeps(result)) { if (hashSet.Add(item)) { queue.Enqueue(item); } } } hashSet.Remove(text); return hashSet.ToList(); } public static List DetermineCatalogDeps(string sceneBundle) { sceneBundle = sceneBundle.Replace(".bundle", ""); if (!sceneBundle.StartsWith("scenes_scenes_scenes/")) { sceneBundle = "scenes_scenes_scenes/" + sceneBundle; } string sceneName = sceneBundle.Substring("scenes_scenes_scenes/".Length); if (AddressablesData.MainLocator == null) { throw new InvalidOperationException("Cannot inspect catalog until after Addressables has loaded"); } string text = (from s in AddressablesData.MainLocator.Keys.OfType() where s.StartsWith("Scenes/") && s.Substring(7).Equals(sceneName, StringComparison.InvariantCultureIgnoreCase) select s).First(); IList source = default(IList); AddressablesData.MainLocator.Locate((object)text, typeof(SceneInstance), ref source); IResourceLocation obj = source.First(); List list = new List(); foreach (IResourceLocation dependency in obj.Dependencies) { AddressablesData.TryStrip(dependency.PrimaryKey, out string stripped); if (!(stripped == sceneBundle)) { list.Add(stripped + ".bundle"); } } return list; } } } namespace Silksong.AssetHelper.CatalogTools { internal static class BackgroundSerialize { [CompilerGenerated] private sealed class <>c__DisplayClass0_0 { public uint[] locationIds; public Func <>9__0; internal uint b__0(int num4) { return locationIds[num4]; } } [CompilerGenerated] private sealed class d__0 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private int <>2__current; public ContentCatalogData contentCatalogData; public Writer writer; private <>c__DisplayClass0_0 <>8__1; private IList 5__2; private Dictionary> 5__3; private uint 5__4; private int 5__5; int IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Expected O, but got Unknown //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; <>8__1 = new <>c__DisplayClass0_0(); 5__2 = contentCatalogData.m_Entries; 5__3 = new Dictionary>(); for (int i = 0; i < 5__2.Count; i++) { foreach (object key in 5__2[i].Keys) { if (!5__3.TryGetValue(key, out List value)) { 5__3.Add(key, value = new List()); } value.Add(i); } } uint num5 = writer.Reserve
(); 5__4 = writer.Reserve((uint)5__3.Count); Header val = default(Header); val.magic = ContentCatalogData.kMagic; val.version = 2; val.keysOffset = 5__4; val.idOffset = writer.WriteString(contentCatalogData.ProviderId, '\0'); val.instanceProvider = writer.WriteObject((object)contentCatalogData.InstanceProviderData, false); val.sceneProvider = writer.WriteObject((object)contentCatalogData.SceneProviderData, false); val.initObjectsArray = writer.WriteObjects((IEnumerable)contentCatalogData.m_ResourceProviderData, false); val.buildResultHash = writer.WriteString(contentCatalogData.BuildResultHash, '\0'); Header val2 = val; writer.Write
(num5, ref val2); <>8__1.locationIds = new uint[5__2.Count]; 5__5 = 0; break; } case 1: <>1__state = -1; 5__5++; break; } if (5__5 < 5__2.Count) { <>8__1.locationIds[5__5] = writer.WriteObject((object)new ContentCatalogDataEntrySerializationContext { entry = 5__2[5__5], allEntries = 5__2, keyToEntryIndices = 5__3 }, false); <>2__current = 5__5 + 1; <>1__state = 1; return true; } int num6 = 0; KeyData[] array = (KeyData[])(object)new KeyData[5__3.Count]; foreach (KeyValuePair> item in 5__3) { uint[] array2 = item.Value.Select((int num4) => <>8__1.locationIds[num4]).ToArray(); array[num6++] = new KeyData { keyNameOffset = writer.WriteObject(item.Key, true), locationSetOffset = writer.Write(array2, true) }; } writer.Write(5__4, array, true); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(d__0))] public static IEnumerator SerializeRoutine(this Serializer self, Writer writer, ContentCatalogData contentCatalogData) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(0) { writer = writer, contentCatalogData = contentCatalogData }; } } internal static class CatalogEntryUtils { public static ContentCatalogDataEntry CreateBundleEntry(string primaryKey, string bundlePath, string internalBundleName, List dependencyKeys, string? serializedBundlePath = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown AssetBundleRequestOptions val = new AssetBundleRequestOptions(); val.AssetLoadMode = (AssetLoadMode)0; val.BundleName = internalBundleName; val.ChunkedTransfer = false; val.RetryCount = 0; val.RedirectLimit = 32; val.Timeout = 0; val.BundleSize = 0L; val.ClearOtherCachedVersionsWhenLoaded = false; val.Crc = 0u; val.UseCrcForCachedBundle = true; val.BundleSize = new FileInfo(bundlePath).Length; return new ContentCatalogDataEntry(typeof(IAssetBundleResource), serializedBundlePath ?? bundlePath, "UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider", (IEnumerable)new object[1] { primaryKey }, (IEnumerable)dependencyKeys, (object)val); } public static ContentCatalogDataEntry CreateAssetEntry(string internalId, Type assetType, List dependencyKeys, out string primaryKey) { primaryKey = internalId; return CreateAssetEntry(internalId, assetType, dependencyKeys, new List(1) { primaryKey }); } public static ContentCatalogDataEntry CreateAssetEntry(string internalId, Type assetType, List dependencyKeys, List primaryKeys) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown object[] array = dependencyKeys.Cast().ToArray(); object[] array2 = primaryKeys.Cast().ToArray(); return new ContentCatalogDataEntry(assetType, internalId, "UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider", (IEnumerable)array2, (IEnumerable)array, (object)null); } public static ContentCatalogDataEntry CreateChildGameObjectEntry(string parentPrimaryKey, string relativePath, out string primaryKey) { int num = parentPrimaryKey.LastIndexOf('.'); int num2 = parentPrimaryKey.LastIndexOf('/'); if (num != -1 && num > num2) { string text = parentPrimaryKey.Substring(0, num); string text2 = parentPrimaryKey.Substring(num); primaryKey = text + "/" + relativePath + text2; } else if (parentPrimaryKey.EndsWith('/')) { primaryKey = parentPrimaryKey + relativePath; } else { primaryKey = parentPrimaryKey + "/" + relativePath; } return CreateChildGameObjectEntry(parentPrimaryKey, relativePath, new List(1) { primaryKey }); } public static ContentCatalogDataEntry CreateChildGameObjectEntry(string parentPrimaryKey, string relativePath, List primaryKeys) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown object[] array = new object[1] { parentPrimaryKey }; object[] array2 = primaryKeys.Cast().ToArray(); return new ContentCatalogDataEntry(typeof(GameObject), relativePath + "/" + ChildGameObjectProvider.InternalIdSeparator + "/" + parentPrimaryKey, ChildGameObjectProvider.ClassProviderId, (IEnumerable)array2, (IEnumerable)array, (object)null); } public static ContentCatalogDataEntry CreateEntryFromLocation(IResourceLocation location, out string primaryKey) { primaryKey = "AssetHelper:" + location.PrimaryKey; return CreateEntryFromLocation(location, new List(1) { primaryKey }); } public static ContentCatalogDataEntry CreateEntryFromLocation(IResourceLocation location, List primaryKeys) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown object[] array = primaryKeys.Cast().ToArray(); return new ContentCatalogDataEntry(location.ResourceType, location.InternalId, location.ProviderId, (IEnumerable)array, (IEnumerable)null, location.Data); } } internal static class CatalogUtils { [CompilerGenerated] private sealed class d__1 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private int <>2__current; public string catalogId; public List locationEntries; private Writer 5__2; private IEnumerator 5__3; int IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: { <>1__state = -1; string text = catalogId; if (!text.StartsWith("AssetHelper")) { text = "AssetHelper-" + catalogId; } ContentCatalogData val = new ContentCatalogData(text); val.m_Entries = locationEntries; Serializer val2 = new Serializer(); new BinaryStorageBuffer(); 5__2 = new Writer(1048576, (ISerializationAdapter[])(object)new ISerializationAdapter[1] { (ISerializationAdapter)val2 }); 5__3 = val2.SerializeRoutine(5__2, val); <>1__state = -3; break; } case 1: <>1__state = -3; break; } if (5__3.MoveNext()) { <>2__current = 5__3.Current; <>1__state = 1; result = true; } else { byte[] array = 5__2.SerializeToByteArray(); Hash128 val3 = Hash(array); File.WriteAllBytes(Path.Combine(AssetPaths.CatalogFolder, catalogId + ".bin"), array); File.WriteAllText(Path.Combine(AssetPaths.CatalogFolder, catalogId + ".hash"), ((object)(Hash128)(ref val3)).ToString()); result = false; <>m__Finally1(); } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (5__3 != null) { 5__3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private unsafe static Hash128 Hash(byte[] catalogByteArray) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) ulong u64_ = default(Hash128).u64_0; ulong u64_2 = default(Hash128).u64_1; fixed (byte* ptr = catalogByteArray) { void* ptr2 = ptr; SpookyHash.Hash(ptr2, (ulong)catalogByteArray.Length, &u64_, &u64_2); } return new Hash128(u64_, u64_2); } [IteratorStateMachine(typeof(d__1))] public static IEnumerator WriteCatalogRoutine(List locationEntries, string catalogId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(0) { locationEntries = locationEntries, catalogId = catalogId }; } } internal class ChildGameObjectProvider : ResourceProviderBase { public static string ClassProviderId => "Silksong.AssetHelper.CatalogTools.ChildObjectProvider"; public static string InternalIdSeparator => "AssetHelper-ChildGameObject-Split"; public override string ProviderId => ClassProviderId; public override Type GetDefaultType(IResourceLocation location) { return typeof(GameObject); } public override void Provide(ProvideHandle provideHandle) { List list = new List(); ((ProvideHandle)(ref provideHandle)).GetDependencies((IList)list); string text = ((ProvideHandle)(ref provideHandle)).Location.InternalId.Split("/" + InternalIdSeparator + "/").First(); GameObject dependency = ((ProvideHandle)(ref provideHandle)).GetDependency(0); if ((Object)(object)dependency != (Object)null) { Transform val = dependency.transform.Find(text); if ((Object)(object)val != (Object)null) { ((ProvideHandle)(ref provideHandle)).Complete(((Component)val).gameObject, true, (Exception)null); } else { ((ProvideHandle)(ref provideHandle)).Complete((GameObject)null, false, new Exception("Child '" + text + "' not found in " + ((Object)dependency).name)); } } else { ((ProvideHandle)(ref provideHandle)).Complete((GameObject)null, false, new Exception("Parent dependency failed to load or is not a GameObject.")); } } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ConstantExpectedAttribute : Attribute { public object? Min { get; set; } public object? Max { get; set; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ExperimentalAttribute : Attribute { public string DiagnosticId { get; } public string? UrlFormat { get; set; } public ExperimentalAttribute(string diagnosticId) { DiagnosticId = diagnosticId; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SetsRequiredMembersAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class StringSyntaxAttribute : Attribute { public const string CompositeFormat = "CompositeFormat"; public const string DateOnlyFormat = "DateOnlyFormat"; public const string DateTimeFormat = "DateTimeFormat"; public const string EnumFormat = "EnumFormat"; public const string GuidFormat = "GuidFormat"; public const string Json = "Json"; public const string NumericFormat = "NumericFormat"; public const string Regex = "Regex"; public const string TimeOnlyFormat = "TimeOnlyFormat"; public const string TimeSpanFormat = "TimeSpanFormat"; public const string Uri = "Uri"; public const string Xml = "Xml"; public string Syntax { get; } public object?[] Arguments { get; } public StringSyntaxAttribute(string syntax) { Syntax = syntax; Arguments = new object[0]; } public StringSyntaxAttribute(string syntax, params object?[] arguments) { Syntax = syntax; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class UnscopedRefAttribute : Attribute { } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiresPreviewFeaturesAttribute : Attribute { public string? Message { get; } public string? Url { get; set; } public RequiresPreviewFeaturesAttribute() { } public RequiresPreviewFeaturesAttribute(string? message) { Message = message; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CollectionBuilderAttribute : Attribute { public Type BuilderType { get; } public string MethodName { get; } public CollectionBuilderAttribute(Type builderType, string methodName) { BuilderType = builderType; MethodName = methodName; } } [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CompilerFeatureRequiredAttribute : Attribute { public const string RefStructs = "RefStructs"; public const string RequiredMembers = "RequiredMembers"; public string FeatureName { get; } public bool IsOptional { get; set; } public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute { public string[] Arguments { get; } public InterpolatedStringHandlerArgumentAttribute(string argument) { Arguments = new string[1] { argument }; } public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) { Arguments = arguments; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal static class IsExternalInit { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ModuleInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class OverloadResolutionPriorityAttribute : Attribute { public int Priority { get; } public OverloadResolutionPriorityAttribute(int priority) { Priority = priority; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] [ExcludeFromCodeCoverage] internal sealed class ParamCollectionAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiredMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal sealed class RequiresLocationAttribute : Attribute { } [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SkipLocalsInitAttribute : Attribute { } }