Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MusicManager v1.1.1
plugins/MusicSwapper.dll
Decompiled 2 months 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 MusicSwapper.Extras; using On.EntityStates.SolusWing2; using On.RoR2; using RoR2; using RoR2.EntitlementManagement; using RoR2.ExpansionManagement; using RoR2.WwiseUtils; 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+fde86df21dfcb9c6bb6e17b03a18894742d4c399")] [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.1.1")] public class MusicSwapperPlugin : BaseUnityPlugin { public const string GUID = "groovesalad.MusicManager"; public const string NAME = "MusicManager"; public const string VERSION = "1.1.1"; 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"); TracksConfig.SaveOnConfigSet = false; ExtrasConfig = GetConfigFile("groovesalad.MusicManager.Extras.cfg"); ExtrasConfig.SaveOnConfigSet = false; MusicSwapperSystem.Init(); TeleporterAudioAdjuster.Init(); SolutionalHauntMusic.Init(); ContinueTeleporterMusic.Init(); ExtrasConfig.Save(); ExtrasConfig.SaveOnConfigSet = true; } 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(); MusicSwapperPlugin.TracksConfig.Save(); MusicSwapperPlugin.TracksConfig.SaveOnConfigSet = true; 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 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"); } } } } namespace MusicSwapper.Extras { public static class ContinueTeleporterMusic { [CompilerGenerated] private static class <>O { public static hook_UpdateTeleporterParameters <0>__MusicController_UpdateTeleporterParameters; } 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>("Teleporter Music", "Continue After Charged", false, "After charging the Teleporter, continue playing the Teleporter track until you leave the stage."); if (val.Value) { MusicSwapperPlugin.Logger.LogMessage((object)"ContinueTeleporterMusic extra is active"); 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); bool flag = (Object.op_Implicit((Object)(object)teleporter) && teleporter.isInFinalSequence) || (Object.op_Implicit((Object)(object)Run.instance) && Run.instance.inSceneTransition); self.stBossStatus.valueId = (flag ? CommonWwiseIds.dead : CommonWwiseIds.alive); } } 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); } } }