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.2.0
plugins/MusicSwapper.dll
Decompiled 16 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 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.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.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("MusicSwapper")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+fa3b8b266b7485cb8ae399d6b9daf9237b4dcae4")] [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] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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.2.0")] public class MusicSwapperPlugin : BaseUnityPlugin { public const string GUID = "groovesalad.MusicManager"; public const string NAME = "MusicManager"; public const string VERSION = "1.2.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"); TracksConfig.SaveOnConfigSet = false; ExtrasConfig = GetConfigFile("groovesalad.MusicManager.Extras.cfg"); ExtrasConfig.SaveOnConfigSet = false; MusicSwapperSystem.Init(); TeleporterAudioAdjuster.Init(); ContinueTeleporterMusic.Init(); ExtrasConfig.Save(); ExtrasConfig.SaveOnConfigSet = true; } private ConfigFile GetConfigFile(string relativePath) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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 LoadSceneData(string fileName, out HashSet<string> excludedSceneNames, out HashSet<string> noBossTrackSceneNames) { excludedSceneNames = new HashSet<string>(); noBossTrackSceneNames = new HashSet<string>(); string path = Path.Combine(MusicSwapperPlugin.RuntimeDirectory, fileName); if (!File.Exists(path)) { MusicSwapperPlugin.Logger.LogWarning((object)("Could not find " + fileName + "!")); return; } JSONNode json = JSON.Parse(File.ReadAllText(path)); if (TryToLoadJsonSceneNames("excluded", excludedSceneNames)) { MusicSwapperPlugin.Logger.LogMessage((object)("Excluding scene(s): " + string.Join(", ", excludedSceneNames))); } if (TryToLoadJsonSceneNames("noBossTrack", noBossTrackSceneNames)) { MusicSwapperPlugin.Logger.LogMessage((object)("Not configuring boss tracks for scene(s): " + string.Join(", ", noBossTrackSceneNames))); } bool TryToLoadJsonSceneNames(string jsonKey, HashSet<string> sceneNames) { JSONNode val = json[jsonKey]; if (val == (object)null) { MusicSwapperPlugin.Logger.LogWarning((object)("Failed to find " + jsonKey + " node in " + fileName)); return false; } sceneNames.UnionWith(val.Children.Select((JSONNode x) => x.Value)); return true; } } private static void DoConfiguration() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0034: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0156: 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) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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> val = Addressables.LoadAssetAsync<SceneCollection>((object)RoR2_DLC1_GameModes_InfiniteTowerRun_SceneGroups.sgInfiniteTowerStageX_asset); SceneCollection val2 = val.WaitForCompletion(); if (Object.op_Implicit((Object)(object)val2)) { Enumerator<SceneEntry> enumerator = val2.sceneEntries.GetEnumerator(); try { while (enumerator.MoveNext()) { SceneEntry current = enumerator.Current; infiniteTowerStages.Add(UnityObjectWrapperKey<SceneDef>.op_Implicit(current.sceneDef)); } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } else { MusicSwapperPlugin.Logger.LogError((object)"Failed to load sgInfiniteTowerStageX!"); } LoadSceneData("SceneData.json", out var excludedSceneNames, out var noBossTrackSceneNames); 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 val3 in array2) { EntitlementDef requiredEntitlement = GetRequiredEntitlementFromScene(val3); if (SceneValidForMainTrack(val3)) { RegisterMusicTrack(val3.mainTrack, requiredEntitlement); } if (SceneValidForBossTrack(val3)) { RegisterMusicTrack(val3.bossTrack, requiredEntitlement); } } MusicTrackDef val4 = Addressables.LoadAssetAsync<MusicTrackDef>((object)RoR2_Base_Common_MusicTrackDefs.muNone_asset).WaitForCompletion(); if (Object.op_Implicit((Object)(object)val4)) { RegisterMusicTrack(val4, null); } else { MusicSwapperPlugin.Logger.LogError((object)"Failed to load muNone!"); } trackTitles.SetAllTracks(allMusicTracks); Dictionary<string, string> consistentLanguageDictionary = 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 val5 = null; MusicTrackDef val6 = null; List<SceneDef> list = baseNameSceneGroup.ToList(); if (list.Count > 1) { int num = list.FindIndex((SceneDef x) => x.cachedName == baseNameSceneGroup.Key); if (num >= 0) { SceneDef val7 = list[num]; if (Object.op_Implicit((Object)(object)val7)) { val5 = val7.mainTrack; val6 = val7.bossTrack; sceneMusicConfigurationResult = ConfigureSceneMusic(val7, default(SceneMusicConfigurationResult.TrackResult), default(SceneMusicConfigurationResult.TrackResult)); } list.RemoveAt(num); } } foreach (SceneDef item in list) { ConfigureSceneMusic(item, ((Object)(object)item.mainTrack == (Object)(object)val5) ? sceneMusicConfigurationResult.mainTrack : default(SceneMusicConfigurationResult.TrackResult), ((Object)(object)item.bossTrack == (Object)(object)val6) ? sceneMusicConfigurationResult.bossTrack : default(SceneMusicConfigurationResult.TrackResult)); } } val.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 value)) { value = musicTrack.cachedName; } ConfigEntry<TrackTitle> val8 = CreateMusicTrackConfigEntry(section, key, description, string.Empty, value, parentConfigEntry); if (ShouldApplyMusicTrackConfig(val8, scene, parentConfigEntry, out var chosenMusicTrack)) { MusicSwapperPlugin.Logger.LogMessage((object)("Setting the " + scene.cachedName + " " + key + " to " + chosenMusicTrack.cachedName + " (formerly " + musicTrack.cachedName + ")")); musicTrack = chosenMusicTrack; } return val8; } ConfigEntry<TrackTitle> ConfigureMusicTrackPostLoop(PostLoopMusicManager.IPostLoopTrackData postLoopTrackData, SceneDef scene, string section, string key, [CanBeNull] ConfigEntry<TrackTitle> parentConfigEntry) { ConfigEntry<TrackTitle> val8 = 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(val8, scene, parentConfigEntry, out var chosenMusicTrack)) { MusicSwapperPlugin.Logger.LogMessage((object)("Setting the " + scene.cachedName + " " + ((ConfigEntryBase)val8).Definition.Key + " to " + chosenMusicTrack.cachedName)); postLoopTrackData.RegisterTrack(scene, chosenMusicTrack); } return val8; } SceneMusicConfigurationResult ConfigureSceneMusic(SceneDef scene, SceneMusicConfigurationResult.TrackResult mainTrackParent, SceneMusicConfigurationResult.TrackResult bossTrackParent) { SceneMusicConfigurationResult result = default(SceneMusicConfigurationResult); string section = GetConfigSectionForScene(scene, consistentLanguageDictionary); bool num2 = SceneValidForMainTrack(scene); bool flag = SceneValidForBossTrack(scene); if (num2) { result.mainTrack.configEntry = ConfigureMusicTrack(ref scene.mainTrack, scene, section, "Main Track", "Choose a track for the stage.", mainTrackParent.configEntry); } if (flag) { result.bossTrack.configEntry = ConfigureMusicTrack(ref scene.bossTrack, scene, section, "Teleporter Track", "Choose a track for the Teleporter event.", bossTrackParent.configEntry); } if (num2) { result.mainTrack.postLoopConfigEntry = ConfigureMusicTrackPostLoop(PostLoopMusicManager.mainTrackData, scene, section, "Main Track", mainTrackParent.postLoopConfigEntry); } if (flag) { result.bossTrack.postLoopConfigEntry = ConfigureMusicTrackPostLoop(PostLoopMusicManager.bossTrackData, scene, section, "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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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 text) { text = text.Replace('\'', 'ꞌ'); for (int num2 = text.Length - 1; num2 >= 0; num2--) { if (invalidConfigChars.Contains(text[num2])) { text = text.Remove(num2, 1); } } return text; } string GetConfigSectionForScene(SceneDef scene, Dictionary<string, string> dictionary) { string value; string val8 = ((string.IsNullOrEmpty(scene.nameToken) || !dictionary.TryGetValue(scene.nameToken, out value) || string.IsNullOrWhiteSpace(value)) ? scene.cachedName : (value + " (" + scene.cachedName + ")")); return GetConfigSafeString(val8); } EntitlementDef GetRequiredEntitlementFromScene(SceneDef scene) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) EntitlementDef val8 = (Object.op_Implicit((Object)(object)scene.requiredExpansion) ? scene.requiredExpansion.requiredEntitlement : null); if (!Object.op_Implicit((Object)(object)val8) && infiniteTowerStages.Contains(UnityObjectWrapperKey<SceneDef>.op_Implicit(scene)) && Object.op_Implicit((Object)(object)dlc1)) { val8 = dlc1.requiredEntitlement; } return val8; } void RegisterMusicTrack(MusicTrackDef musicTrack, [CanBeNull] EntitlementDef val8) { //IL_0007: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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) allMusicTracks.Add(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack)); if (!alwaysAvailableMusicTracks.Contains(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack))) { HashSet<UnityObjectWrapperKey<EntitlementDef>> value; if (!Object.op_Implicit((Object)(object)val8) || ((BaseUserEntitlementTracker<LocalUser>)(object)EntitlementManager.localUserEntitlementTracker).AnyUserHasEntitlement(val8)) { alwaysAvailableMusicTracks.Add(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack)); entitlementLockedMusicTracks.Remove(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack)); } else if (entitlementLockedMusicTracks.TryGetValue(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack), out value)) { value.Add(UnityObjectWrapperKey<EntitlementDef>.op_Implicit(val8)); } else { entitlementLockedMusicTracks.Add(UnityObjectWrapperKey<MusicTrackDef>.op_Implicit(musicTrack), new HashSet<UnityObjectWrapperKey<EntitlementDef>> { UnityObjectWrapperKey<EntitlementDef>.op_Implicit(val8) }); } } } bool SceneValidForBossTrack(SceneDef scene) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)scene.bossTrack) && scene.hasAnyDestinations && !infiniteTowerStages.Contains(UnityObjectWrapperKey<SceneDef>.op_Implicit(scene))) { return !noBossTrackSceneNames.Contains(scene.cachedName); } return false; } bool SceneValidForConfig(SceneDef scene) { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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; } if (excludedSceneNames.Contains(scene.cachedName)) { 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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 val8 = GetRequiredEntitlementFromScene(scene); if (!Object.op_Implicit((Object)(object)val8) || !value.Contains(UnityObjectWrapperKey<EntitlementDef>.op_Implicit(val8))) { 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(string trackName) : IPostLoopTrackData { private readonly string trackName = trackName; public Dictionary<UnityObjectWrapperKey<SceneDef>, MusicTrackDef> tracks; public MusicTrackDef mostRecentTrack; public bool setHook; public bool HasTracks { get { if (tracks != null) { return tracks.Count > 0; } return false; } } public void RegisterTrack(SceneDef scene, MusicTrackDef postLoopTrack) { //IL_0019: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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)) ? track : mostRecentTrack)); } } } 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_000a: 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) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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 (!(other is TrackTitle other2)) { if (other is string other3) { return Equals(other3); } return false; } return Equals(other2); } } 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 = list2; List<TrackTitle> list4 = new List<TrackTitle>(list.Count + list3.Count); foreach (string item2 in list) { list4.Add(item2); } foreach (string item3 in list3) { list4.Add(item3); } PrimaryTrackTitles = list4; 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown if (MusicSwapperPlugin.ExtrasConfig.Bind<bool>("Teleporter Music", "Continue After Charged", false, "After charging the Teleporter, continue playing the Teleporter track until you leave the stage.").Value) { MusicSwapperPlugin.Logger.LogMessage((object)"ContinueTeleporterMusic extra is active"); object obj = <>O.<0>__MusicController_UpdateTeleporterParameters; if (obj == null) { hook_UpdateTeleporterParameters val = MusicController_UpdateTeleporterParameters; <>O.<0>__MusicController_UpdateTeleporterParameters = val; obj = (object)val; } 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 TeleporterAudioAdjuster { [CompilerGenerated] private static class <>O { public static hook_UpdateTeleporterParameters <0>__MusicController_UpdateTeleporterParameters; } private static float proximityScalar; public static void Init() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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); } } }