Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of MusicManager v1.0.0
plugins/MusicSwapper.dll
Decompiled 11 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates.SolusWing2; using HG; using HG.Reflection; using IL.RoR2; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using On.EntityStates.SolusWing2; using On.RoR2; using RoR2; using RoR2.EntitlementManagement; using RoR2.ExpansionManagement; using RoR2BepInExPack.GameAssetPathsBetter; using SimpleJSON; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MusicSwapper")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+57d1654b71976cb5cfc3381312ad6009a9ad915f")] [assembly: AssemblyProduct("MusicSwapper")] [assembly: AssemblyTitle("MusicSwapper")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 MusicSwapper { public class ConsistentLanguageInstance : IDisposable { private List<KeyValuePair<string, string>> consistentTokenStringPairs; public ConsistentLanguageInstance() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Language.LoadAllTokensFromFolders += new hook_LoadAllTokensFromFolders(Language_LoadAllTokensFromFolders); } private void Language_LoadAllTokensFromFolders(orig_LoadAllTokensFromFolders orig, IEnumerable<string> folders, List<KeyValuePair<string, string>> output) { orig.Invoke(folders, output); Language val = Language.FindLanguageByName("en"); if (val != null && folders == val.folders) { consistentTokenStringPairs = output; } } public Dictionary<string, string> BuildConsistentLanguageDictionary() { Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (consistentTokenStringPairs == null) { MusicSwapperPlugin.Logger.LogWarning((object)"Failed to cache consistentTokenStringPairs - generating them from the language folders!"); if (Language.english == null) { return dictionary; } consistentTokenStringPairs = new List<KeyValuePair<string, string>>(); Language.LoadAllTokensFromFolders((IEnumerable<string>)Language.english.folders, consistentTokenStringPairs); } foreach (KeyValuePair<string, string> consistentTokenStringPair in consistentTokenStringPairs) { dictionary.TryAdd(consistentTokenStringPair.Key, consistentTokenStringPair.Value); } return dictionary; } public void Dispose() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown Language.LoadAllTokensFromFolders -= new hook_LoadAllTokensFromFolders(Language_LoadAllTokensFromFolders); } } public static class Constants { public const string VALUE_DEFAULT = "default"; public const string VALUE_INHERIT = "inherit"; public const string TRACK_NAME_NONE = "None"; public const string MAIN_TRACK = "Main Track"; public const string BOSS_TRACK = "Teleporter Track"; } public class HiddenAcceptableValueList<T> : AcceptableValueList<T> where T : IEquatable<T> { public virtual HashSet<T> HiddenAcceptableValues { get; } public HiddenAcceptableValueList(T[] acceptableValues, HashSet<T> hiddenAcceptableValues) { HiddenAcceptableValues = hiddenAcceptableValues; base..ctor(acceptableValues); } public override bool IsValid(object value) { if (value is T item && HiddenAcceptableValues.Contains(item)) { return true; } return base.IsValid(value); } } [BepInPlugin("groovesalad.MusicManager", "MusicManager", "1.0.0")] public class MusicSwapperPlugin : BaseUnityPlugin { public const string GUID = "groovesalad.MusicManager"; public const string NAME = "MusicManager"; public const string VERSION = "1.0.0"; public static ManualLogSource Logger { get; private set; } public static string RuntimeDirectory { get; private set; } public static string ConfigDirectory { get; private set; } public static string DefaultConfigDirectory { get; private set; } public static ConfigFile TracksConfig { get; private set; } public static ConfigFile ExtrasConfig { get; private set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; RuntimeDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); ConfigDirectory = Path.Combine(Paths.ConfigPath, "MusicManager"); DefaultConfigDirectory = Path.Combine(RuntimeDirectory, "defaultconfig"); TracksConfig = GetConfigFile("groovesalad.MusicManager.Tracks.cfg"); ExtrasConfig = GetConfigFile("groovesalad.MusicManager.Extras.cfg"); MusicSwapperSystem.Init(); TeleporterAudioAdjuster.Init(); SolutionalHauntMusic.Init(); } private ConfigFile GetConfigFile(string relativePath) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown string text = Path.Combine(ConfigDirectory, relativePath); if (!File.Exists(text)) { string text2 = Path.Combine(DefaultConfigDirectory, relativePath); if (File.Exists(text2)) { Logger.LogMessage((object)("Regenerating the config file " + relativePath + " from the default config file")); Directory.CreateDirectory(Path.GetDirectoryName(text)); File.Copy(text2, text); } } return new ConfigFile(text, true, ((BaseUnityPlugin)this).Info.Metadata); } } public static class MusicSwapperSystem { private struct SceneMusicConfigurationResult { public struct TrackResult { public ConfigEntry<TrackTitle> configEntry; public ConfigEntry<TrackTitle> postLoopConfigEntry; } public TrackResult mainTrack; public TrackResult bossTrack; } private static TrackTitlesInstance trackTitles; private static ConsistentLanguageInstance consistentLanguage; public static void Init() { trackTitles = new TrackTitlesInstance("TrackTitles.json"); consistentLanguage = new ConsistentLanguageInstance(); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnLoad)); } private static void OnLoad() { DoConfiguration(); PostLoopMusicManager.Init(); trackTitles = null; consistentLanguage.Dispose(); consistentLanguage = null; } private static void DoConfiguration() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0031: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) ExpansionDef dlc1 = Addressables.LoadAssetAsync<ExpansionDef>((object)RoR2_DLC1_Common.DLC1_asset).WaitForCompletion(); HashSet<UnityObjectWrapperKey<SceneDef>> infiniteTowerStages = new HashSet<UnityObjectWrapperKey<SceneDef>>(); AsyncOperationHandle<SceneCollection> val2 = Addressables.LoadAssetAsync<SceneCollection>((object)RoR2_DLC1_GameModes_InfiniteTowerRun_SceneGroups.sgInfiniteTowerStageX_asset); SceneCollection val3 = val2.WaitForCompletion(); if (Object.op_Implicit((Object)(object)val3)) { Enumerator<SceneEntry> enumerator = val3.sceneEntries.GetEnumerator(); try { while (enumerator.MoveNext()) { SceneEntry current = enumerator.Current; infiniteTowerStages.Add(UnityObjectWrapperKey<SceneDef>.op_Implicit(current.sceneDef)); } } finally { ((IDisposable)enumerator).Dispose(); } } else { MusicSwapperPlugin.Logger.LogError((object)"Failed to load sgInfiniteTowerStageX!"); } SceneDef[] array = ((IEnumerable<SceneDef>)(object)SceneCatalog.allSceneDefs).Where(SceneValidForConfig).ToArray(); HashSet<UnityObjectWrapperKey<MusicTrackDef>> allMusicTracks = new HashSet<UnityObjectWrapperKey<MusicTrackDef>>(); HashSet<UnityObjectWrapperKey<MusicTrackDef>> alwaysAvailableMusicTracks = new HashSet<UnityObjectWrapperKey<MusicTrackDef>>(); Dictionary<UnityObjectWrapperKey<MusicTrackDef>, HashSet<UnityObjectWrapperKey<EntitlementDef>>> entitlementLockedMusicTracks = new Dictionary<UnityObjectWrapperKey<MusicTrackDef>, HashSet<UnityObjectWrapperKey<EntitlementDef>>>(); SceneDef[] array2 = array; foreach (SceneDef val4 in array2) { EntitlementDef requiredEntitlement2 = GetRequiredEntitlementFromScene(val4); if (SceneValidForMainTrack(val4)) { RegisterMusicTrack(val4.mainTrack, requiredEntitlement2); } if (SceneValidForBossTrack(val4)) { RegisterMusicTrack(val4.bossTrack, requiredEntitlement2); } } MusicTrackDef val5 = Addressables.LoadAssetAsync<MusicTrackDef>((object)RoR2_Base_Common_MusicTrackDefs.muNone_asset).WaitForCompletion(); if (Object.op_Implicit((Object)(object)val5)) { RegisterMusicTrack(val5, null); } else { MusicSwapperPlugin.Logger.LogError((object)"Failed to load muNone!"); } trackTitles.SetAllTracks(allMusicTracks); Dictionary<string, string> consistentLanguageDictionary2 = consistentLanguage.BuildConsistentLanguageDictionary(); HashSet<char> invalidConfigChars = new HashSet<char> { '=', '\n', '\t', '\\', '"', '\'', '[', ']' }; foreach (IGrouping<string, SceneDef> baseNameSceneGroup in from x in array group x by x.baseSceneName) { SceneMusicConfigurationResult sceneMusicConfigurationResult = default(SceneMusicConfigurationResult); MusicTrackDef val6 = null; MusicTrackDef val7 = null; List<SceneDef> list = baseNameSceneGroup.ToList(); if (list.Count > 1) { int num = list.FindIndex((SceneDef x) => x.cachedName == baseNameSceneGroup.Key); if (num >= 0) { SceneDef val8 = list[num]; if (Object.op_Implicit((Object)(object)val8)) { val6 = val8.mainTrack; val7 = val8.bossTrack; sceneMusicConfigurationResult = ConfigureSceneMusic(val8, default(SceneMusicConfigurationResult.TrackResult), default(SceneMusicConfigurationResult.TrackResult)); } list.RemoveAt(num); } } foreach (SceneDef item in list) { ConfigureSceneMusic(item, ((Object)(object)item.mainTrack == (Object)(object)val6) ? sceneMusicConfigurationResult.mainTrack : default(SceneMusicConfigurationResult.TrackResult), ((Object)(object)item.bossTrack == (Object)(object)val7) ? sceneMusicConfigurationResult.bossTrack : default(SceneMusicConfigurationResult.TrackResult)); } } val2.Release(); invalidConfigChars = null; ConfigEntry<TrackTitle> ConfigureMusicTrack(ref MusicTrackDef musicTrack, SceneDef scene, string section, string key, string description, [CanBeNull] ConfigEntry<TrackTitle> parentConfigEntry) { if (!trackTitles.InternalNameToAlbumName.TryGetValue(musicTrack.cachedName, out var value2)) { value2 = musicTrack.cachedName; } ConfigEntry<TrackTitle> val10 = CreateMusicTrackConfigEntry(section, key, description, string.Empty, value2, parentConfigEntry); if (ShouldApplyMusicTrackConfig(val10, scene, parentConfigEntry, out var chosenMusicTrack3)) { MusicSwapperPlugin.Logger.LogMessage((object)("Setting the " + scene.cachedName + " " + key + " to " + chosenMusicTrack3.cachedName + " (formerly " + musicTrack.cachedName + ")")); musicTrack = chosenMusicTrack3; } return val10; } ConfigEntry<TrackTitle> ConfigureMusicTrackPostLoop(PostLoopMusicManager.IPostLoopTrackData postLoopTrackData, SceneDef scene, string section, string key, [CanBeNull] ConfigEntry<TrackTitle> parentConfigEntry) { ConfigEntry<TrackTitle> val9 = CreateMusicTrackConfigEntry(section, "Post-Loop " + key, "Choose a track to override the " + key + " after looping once.", "\nChoose \"default\" to disable this feature.", "default", parentConfigEntry); if (ShouldApplyMusicTrackConfig(val9, scene, parentConfigEntry, out var chosenMusicTrack2)) { MusicSwapperPlugin.Logger.LogMessage((object)("Setting the " + scene.cachedName + " " + ((ConfigEntryBase)val9).Definition.Key + " to " + chosenMusicTrack2.cachedName)); postLoopTrackData.RegisterTrack(scene, chosenMusicTrack2); } return val9; } SceneMusicConfigurationResult ConfigureSceneMusic(SceneDef scene, SceneMusicConfigurationResult.TrackResult mainTrackParent, SceneMusicConfigurationResult.TrackResult bossTrackParent) { SceneMusicConfigurationResult result = default(SceneMusicConfigurationResult); string configSectionForScene = GetConfigSectionForScene(scene, consistentLanguageDictionary2); bool flag = SceneValidForMainTrack(scene); bool flag2 = SceneValidForBossTrack(scene); if (flag) { result.mainTrack.configEntry = ConfigureMusicTrack(ref scene.mainTrack, scene, configSectionForScene, "Main Track", "Choose a track for the stage.", mainTrackParent.configEntry); } if (flag2) { result.bossTrack.configEntry = ConfigureMusicTrack(ref scene.bossTrack, scene, configSectionForScene, "Teleporter Track", "Choose a track for the Teleporter event.", bossTrackParent.configEntry); } if (flag) { result.mainTrack.postLoopConfigEntry = ConfigureMusicTrackPostLoop(PostLoopMusicManager.mainTrackData, scene, configSectionForScene, "Main Track", mainTrackParent.postLoopConfigEntry); } if (flag2) { result.bossTrack.postLoopConfigEntry = ConfigureMusicTrackPostLoop(PostLoopMusicManager.bossTrackData, scene, configSectionForScene, "Teleporter Track", bossTrackParent.postLoopConfigEntry); } return result; } static ConfigEntry<TrackTitle> CreateMusicTrackConfigEntry(string section, string key, string desc, string specialValuesDesc, string defaultValue, [CanBeNull] ConfigEntry<TrackTitle> parentConfigEntry) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown List<TrackTitle> list2 = trackTitles.PrimaryTrackTitles.ToList(); if (parentConfigEntry != null) { if (!list2.Contains(defaultValue)) { list2.Insert(0, defaultValue); } defaultValue = "inherit"; specialValuesDesc = "\nChoose \"inherit\" to use the same " + key + " as " + ((ConfigEntryBase)parentConfigEntry).Definition.Section + "." + specialValuesDesc; } list2.Remove(defaultValue); list2.Insert(0, defaultValue); desc += " Some tracks require DLC."; if (!string.IsNullOrEmpty(specialValuesDesc)) { desc = desc + "\nSpecial Values:" + specialValuesDesc; } return MusicSwapperPlugin.TracksConfig.Bind<TrackTitle>(section, key, (TrackTitle)defaultValue, new ConfigDescription(desc, (AcceptableValueBase)(object)new HiddenAcceptableValueList<TrackTitle>(list2.ToArray(), trackTitles.AllTrackTitles), Array.Empty<object>())); } string GetConfigSafeString(string val) { val = val.Replace('\'', 'ꞌ'); for (int num2 = val.Length - 1; num2 >= 0; num2--) { if (invalidConfigChars.Contains(val[num2])) { val = val.Remove(num2, 1); } } return val; } string GetConfigSectionForScene(SceneDef scene, Dictionary<string, string> consistentLanguageDictionary) { string value3; string val11 = ((string.IsNullOrEmpty(scene.nameToken) || !consistentLanguageDictionary.TryGetValue(scene.nameToken, out value3) || string.IsNullOrWhiteSpace(value3)) ? scene.cachedName : (value3 + " (" + scene.cachedName + ")")); return GetConfigSafeString(val11); } EntitlementDef GetRequiredEntitlementFromScene(SceneDef scene) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) EntitlementDef val12 = (Object.op_Implicit((Object)(object)scene.requiredExpansion) ? scene.requiredExpansion.requiredEntitlement : null); if (!Object.op_Implicit((Object)(object)val12) && infiniteTowerStages.Contains(UnityObjectWrapperKey<SceneDef>.op_Implicit(scene)) && Object.op_Implicit((Object)(object)dlc1)) { val12 = dlc1.requiredEntitlement; } return val12; } void RegisterMusicTrack(MusicTrackDef musicTrack, [CanBeNull] EntitlementDef requiredEntitlement) { //IL_0008: 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) //IL_0076: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) allMusicTracks.Add(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack)); if (!alwaysAvailableMusicTracks.Contains(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack))) { HashSet<UnityObjectWrapperKey<EntitlementDef>> value4; if (!Object.op_Implicit((Object)(object)requiredEntitlement) || ((BaseUserEntitlementTracker<LocalUser>)(object)EntitlementManager.localUserEntitlementTracker).AnyUserHasEntitlement(requiredEntitlement)) { alwaysAvailableMusicTracks.Add(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack)); entitlementLockedMusicTracks.Remove(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack)); } else if (entitlementLockedMusicTracks.TryGetValue(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack), out value4)) { value4.Add(UnityObjectWrapperKey<EntitlementDef>.op_Implicit(requiredEntitlement)); } else { entitlementLockedMusicTracks.Add(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack), new HashSet<UnityObjectWrapperKey<EntitlementDef>> { UnityObjectWrapperKey<EntitlementDef>.op_Implicit(requiredEntitlement) }); } } } bool SceneValidForBossTrack(SceneDef scene) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) return Object.op_Implicit((Object)(object)scene.bossTrack) && scene.hasAnyDestinations && !infiniteTowerStages.Contains(UnityObjectWrapperKey<SceneDef>.op_Implicit(scene)); } static bool SceneValidForConfig(SceneDef scene) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 if (scene.isOfflineScene) { return false; } SceneType sceneType = scene.sceneType; if ((int)sceneType != 1 && (int)sceneType != 2 && (int)sceneType != 4 && (int)sceneType != 5) { return false; } return true; } static bool SceneValidForMainTrack(SceneDef scene) { return Object.op_Implicit((Object)(object)scene.mainTrack); } bool ShouldApplyMusicTrackConfig(ConfigEntry<TrackTitle> configEntry, SceneDef scene, [CanBeNull] ConfigEntry<TrackTitle> parentConfigEntry, out MusicTrackDef chosenMusicTrack) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) chosenMusicTrack = null; if (string.Equals(configEntry.Value, "inherit")) { if (parentConfigEntry != null) { return ShouldApplyMusicTrackConfig(parentConfigEntry, scene, null, out chosenMusicTrack); } return false; } if (string.Equals(configEntry.Value, (TrackTitle)((ConfigEntryBase)configEntry).DefaultValue)) { return false; } if (string.Equals(configEntry.Value, "default")) { return false; } if (!trackTitles.TrackNameToMusicTrackDef.TryGetValue(configEntry.Value, out chosenMusicTrack)) { return false; } if (entitlementLockedMusicTracks.TryGetValue(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(chosenMusicTrack), out var value)) { EntitlementDef requiredEntitlementFromScene = GetRequiredEntitlementFromScene(scene); if (!Object.op_Implicit((Object)(object)requiredEntitlementFromScene) || !value.Contains(UnityObjectWrapperKey<EntitlementDef>.op_Implicit(requiredEntitlementFromScene))) { MusicSwapperPlugin.Logger.LogWarning((object)("The " + scene.cachedName + " " + ((ConfigEntryBase)configEntry).Definition.Key + " cannot be set to " + chosenMusicTrack.cachedName + " because the track's entitlement requirements are not met")); return false; } } return true; } } } public static class PostLoopMusicManager { public interface IPostLoopTrackData { void RegisterTrack(SceneDef scene, MusicTrackDef postLoopTrack); } public class PostLoopTrackData : IPostLoopTrackData { private readonly string trackName; public Dictionary<UnityObjectWrapperKey<SceneDef>, MusicTrackDef> tracks; public MusicTrackDef mostRecentTrack; public bool setHook; public bool HasTracks => tracks != null && tracks.Count > 0; public PostLoopTrackData(string trackName) { this.trackName = trackName; base..ctor(); } public void RegisterTrack(SceneDef scene, MusicTrackDef postLoopTrack) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) (tracks ?? (tracks = new Dictionary<UnityObjectWrapperKey<SceneDef>, MusicTrackDef>()))[UnityObjectWrapperKey<SceneDef>.op_Implicit(scene)] = postLoopTrack; } public void Init() { if (HasTracks) { SceneCatalog.onMostRecentSceneDefChanged += OnMostRecentSceneDefChanged; } } private void OnMostRecentSceneDefChanged(SceneDef mostRecentSceneDef) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown mostRecentTrack = null; if (Object.op_Implicit((Object)(object)Run.instance) && Run.instance.loopClearCount > 0 && tracks.TryGetValue(UnityObjectWrapperKey<SceneDef>.op_Implicit(mostRecentSceneDef), out mostRecentTrack) && !setHook) { MusicSwapperPlugin.Logger.LogMessage((object)("Setting a hook to override " + trackName + " post loop")); setHook = true; MusicController.PickCurrentTrack += new Manipulator(OverrideTrackPostLoop); } } private void OverrideTrackPostLoop(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); while (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchLdfld<SceneDef>(x, trackName) })) { val.EmitDelegate<Func<MusicTrackDef, MusicTrackDef>>((Func<MusicTrackDef, MusicTrackDef>)((MusicTrackDef track) => Object.op_Implicit((Object)(object)mostRecentTrack) ? mostRecentTrack : track)); } } } public static readonly PostLoopTrackData mainTrackData = new PostLoopTrackData("mainTrack"); public static readonly PostLoopTrackData bossTrackData = new PostLoopTrackData("bossTrack"); public static void Init() { mainTrackData.Init(); bossTrackData.Init(); } } public static class SolutionalHauntMusic { [CompilerGenerated] private static class <>O { public static hook_OnEnter <0>__Mission5Death_OnEnter; } public static void Init() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown ConfigEntry<bool> val = MusicSwapperPlugin.ExtrasConfig.Bind<bool>("Solutional Haunt", "Restart Music After Fight", false, "After the Solus Wing fight, resume playing the main track of Solutional Haunt."); if (val.Value) { MusicSwapperPlugin.Logger.LogMessage((object)"SolutionalHauntMusic extra is active"); object obj = <>O.<0>__Mission5Death_OnEnter; if (obj == null) { hook_OnEnter val2 = Mission5Death_OnEnter; <>O.<0>__Mission5Death_OnEnter = val2; obj = (object)val2; } Mission5Death.OnEnter += (hook_OnEnter)obj; } } private static void Mission5Death_OnEnter(orig_OnEnter orig, Mission5Death self) { orig.Invoke(self); if (Object.op_Implicit((Object)(object)((SolusWing2BaseMissionState)self).solutionalHauntReferences) && Object.op_Implicit((Object)(object)((SolusWing2BaseMissionState)self).solutionalHauntReferences.PostFightMusic)) { ((SolusWing2BaseMissionState)self).solutionalHauntReferences.PostFightMusic.AddComponent<DestroyOnTimer>().duration = 10f; } } } public static class TeleporterAudioAdjuster { [CompilerGenerated] private static class <>O { public static hook_UpdateTeleporterParameters <0>__MusicController_UpdateTeleporterParameters; } private static float proximityScalar; public static void Init() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown ConfigEntry<float> val = MusicSwapperPlugin.ExtrasConfig.Bind<float>("Teleporter Hum", "Volume Multiplier", 1f, new ConfigDescription("Reduce this value to dampen the volume of Teleporter hum (the Teleporter hum emits from the Teleporter and plays along with a stage's main track).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); if (val.Value != 1f) { MusicSwapperPlugin.Logger.LogMessage((object)"TeleporterAudioAdjuster extra is active"); proximityScalar = Mathf.Clamp01(val.Value); object obj = <>O.<0>__MusicController_UpdateTeleporterParameters; if (obj == null) { hook_UpdateTeleporterParameters val2 = MusicController_UpdateTeleporterParameters; <>O.<0>__MusicController_UpdateTeleporterParameters = val2; obj = (object)val2; } MusicController.UpdateTeleporterParameters += (hook_UpdateTeleporterParameters)obj; } } private static void MusicController_UpdateTeleporterParameters(orig_UpdateTeleporterParameters orig, MusicController self, TeleporterInteraction teleporter, Transform cameraTransform, CharacterBody targetBody) { orig.Invoke(self, teleporter, cameraTransform, targetBody); float value = self.rtpcTeleporterProximityValue.value; self.rtpcTeleporterProximityValue.value = Util.Remap(value, 0f, 10000f, 10000f - 10000f * proximityScalar, 10000f); } } public readonly struct TrackTitle : IEquatable<TrackTitle> { public string Value { get; } public TrackTitle(string value) { Value = value; } static TrackTitle() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown TomlTypeConverter.AddConverter(typeof(TrackTitle), new TypeConverter { ConvertToString = (object obj, Type type) => obj.ToString(), ConvertToObject = (string str, Type type) => new TrackTitle(str) }); } public override string ToString() { return Value; } public static implicit operator TrackTitle(string value) { return new TrackTitle(value); } public static implicit operator string(TrackTitle trackTitle) { return trackTitle.Value; } public override int GetHashCode() { return Value?.GetHashCode() ?? 0; } public bool Equals(string other) { return string.Equals(Value, other); } public bool Equals(TrackTitle other) { return Equals(other.Value); } public override bool Equals(object other) { if (1 == 0) { } bool result = ((other is TrackTitle other2) ? Equals(other2) : (other is string other3 && Equals(other3))); if (1 == 0) { } return result; } } public class TrackTitlesInstance { public Dictionary<string, string> InternalNameToAlbumName { get; private set; } public List<TrackTitle> PrimaryTrackTitles { get; private set; } public HashSet<TrackTitle> AllTrackTitles { get; private set; } public Dictionary<string, MusicTrackDef> TrackNameToMusicTrackDef { get; private set; } public TrackTitlesInstance(string fileName) { InternalNameToAlbumName = new Dictionary<string, string>(); string path = Path.Combine(MusicSwapperPlugin.RuntimeDirectory, fileName); if (!File.Exists(path)) { MusicSwapperPlugin.Logger.LogWarning((object)("Could not find " + fileName + "!")); return; } JSONNode val = JSON.Parse(File.ReadAllText(path)); foreach (string key in val.Keys) { string value = val[key].Value; InternalNameToAlbumName.Add(key, value); } MusicSwapperPlugin.Logger.LogMessage((object)$"Loaded {val.Count} track titles from {fileName}"); } public void SetAllTracks(HashSet<UnityObjectWrapperKey<MusicTrackDef>> allTracks) { AllTrackTitles = new HashSet<TrackTitle>(); TrackNameToMusicTrackDef = new Dictionary<string, MusicTrackDef>(); List<string> list = new List<string>(); List<string> list2 = new List<string>(); foreach (MusicTrackDef item in allTracks.Select((UnityObjectWrapperKey<MusicTrackDef> x) => x.value)) { string cachedName = item.cachedName; if (InternalNameToAlbumName.TryGetValue(cachedName, out var value)) { if (!list.Contains(value)) { list.Add(value); } AllTrackTitles.Add(value); TrackNameToMusicTrackDef.TryAdd(value, item); } else if (!list2.Contains(cachedName)) { list2.Add(cachedName); } AllTrackTitles.Add(cachedName); TrackNameToMusicTrackDef.TryAdd(cachedName, item); } list.Sort(); list2.Sort(); List<string> list3 = list; List<string> list4 = list2; List<TrackTitle> list5 = new List<TrackTitle>(list3.Count + list4.Count); foreach (string item2 in list3) { list5.Add(item2); } foreach (string item3 in list4) { list5.Add(item3); } PrimaryTrackTitles = list5; if (PrimaryTrackTitles.Remove("None")) { PrimaryTrackTitles.Add("None"); } } } }