Decompiled source of SonicOST v0.0.3

SonicCustomOST/CustomSoundtrack.dll

Decompiled 4 hours ago
using 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 System.Threading;
using BepInEx;
using EntityStates.MeridianEvent;
using EntityStates.Missions.BrotherEncounter;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using Newtonsoft.Json;
using On.EntityStates.MeridianEvent;
using On.EntityStates.Missions.BrotherEncounter;
using On.RoR2;
using RoR2;
using RoR2.ConVar;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomSoundtrack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+890e9cce56011104b4fce7bf625bc2a076e9c112")]
[assembly: AssemblyProduct("CustomSoundtrack")]
[assembly: AssemblyTitle("CustomSoundtrack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace CustomSoundtrack;

[BepInPlugin("com.penumbrah.customsoundtrack", "CustomSoundtrack", "2025.5.18")]
public class CustomSoundtrack : BaseUnityPlugin
{
	private enum GameState
	{
		Normal,
		BossFight,
		PostBoss
	}

	private string playbackMode = "next";

	private string trackPath;

	private Dictionary<string, List<string>> bossPlaylists = new Dictionary<string, List<string>>();

	private Dictionary<string, List<string>> postBossPlaylists = new Dictionary<string, List<string>>();

	private Dictionary<string, List<string>> playlists = new Dictionary<string, List<string>>();

	private GameState currentState;

	private string currentScene = "";

	private List<string> currentPlaylist = new List<string>();

	private string currentTrack = "";

	private bool paused;

	private bool start;

	private AudioFileReader currentAudioFileReader;

	private FadeInOutSampleProvider currentFadeInOutSampleProvider;

	private WaveOutEvent player = new WaveOutEvent();

	private bool logging;

	private string logPath = "log.txt";

	private bool locked;

	public void Awake()
	{
		//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b2: Expected O, but got Unknown
		//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d4: Expected O, but got Unknown
		//IL_05db: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e5: Expected O, but got Unknown
		//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f6: Expected O, but got Unknown
		//IL_05fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0607: Expected O, but got Unknown
		//IL_060e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0618: Expected O, but got Unknown
		//IL_061f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0629: Expected O, but got Unknown
		//IL_0630: Unknown result type (might be due to invalid IL or missing references)
		//IL_063a: Expected O, but got Unknown
		string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		logPath = Path.Combine(directoryName, logPath);
		trackPath = directoryName;
		if (!File.Exists(logPath))
		{
			logging = true;
		}
		Settings settings = null;
		try
		{
			settings = JsonConvert.DeserializeObject<Settings>(File.ReadAllText(Path.Combine(directoryName, "settings.json")));
		}
		catch (Exception ex)
		{
			log("could not parse settings.json: " + Environment.NewLine + ex);
		}
		if (settings != null)
		{
			if (settings.trackPath != null && settings.trackPath != "")
			{
				trackPath = settings.trackPath;
			}
			if (settings.playbackMode != null)
			{
				playbackMode = settings.playbackMode;
			}
			if (settings.playlists != null)
			{
				foreach (Dictionary<string, List<string>> playlist in settings.playlists)
				{
					if (!playlist.ContainsKey("scenes"))
					{
						continue;
					}
					foreach (string item in playlist["scenes"])
					{
						if (!playlists.Keys.Contains(item))
						{
							playlists.Add(item, new List<string>());
						}
						if (playlist.ContainsKey("tracks"))
						{
							foreach (string item2 in playlist["tracks"])
							{
								playlists[item].Add(Path.Combine(trackPath, item2));
							}
						}
						if (!bossPlaylists.Keys.Contains(item))
						{
							bossPlaylists.Add(item, new List<string>());
						}
						if (playlist.ContainsKey("bossTracks"))
						{
							foreach (string item3 in playlist["bossTracks"])
							{
								bossPlaylists[item].Add(Path.Combine(trackPath, item3));
							}
						}
						if (!postBossPlaylists.Keys.Contains(item))
						{
							postBossPlaylists.Add(item, new List<string>());
						}
						if (!playlist.ContainsKey("postBossTracks"))
						{
							continue;
						}
						foreach (string item4 in playlist["postBossTracks"])
						{
							postBossPlaylists[item].Add(Path.Combine(trackPath, item4));
						}
					}
				}
			}
		}
		playlists.Add("_default", new List<string>());
		foreach (string item5 in from fileName in Directory.GetFiles(trackPath, "*", SearchOption.AllDirectories)
			where fileName.ToLower().EndsWith(".aiff") || fileName.ToLower().EndsWith(".mp3") || fileName.ToLower().EndsWith(".wav")
			select fileName)
		{
			playlists["_default"].Add(item5);
		}
		if (logging)
		{
			log("track directory: " + trackPath);
			log("playback mode: " + playbackMode);
			log("playlists: ");
			foreach (string key in playlists.Keys)
			{
				log("    " + key + ": ");
				foreach (string item6 in playlists[key])
				{
					log("        " + item6);
				}
			}
			log("boss playlists: ");
			foreach (string key2 in bossPlaylists.Keys)
			{
				log("    " + key2 + ": ");
				foreach (string item7 in bossPlaylists[key2])
				{
					log("        " + item7);
				}
			}
			log("tp playlists: ");
			foreach (string key3 in postBossPlaylists.Keys)
			{
				log("    " + key3 + ": ");
				foreach (string item8 in postBossPlaylists[key3])
				{
					log("        " + item8);
				}
			}
		}
		SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "splash")
			{
				start = true;
			}
			if (start && currentScene != ((Scene)(ref scene)).name)
			{
				currentState = GameState.Normal;
				currentPlaylist = playlists["_default"];
				currentScene = ((Scene)(ref scene)).name;
				nextPlaylist();
			}
			if (logging)
			{
				log("loaded scene: " + ((Scene)(ref scene)).name);
			}
		};
		TeleporterInteraction.RpcClientOnActivated += (hook_RpcClientOnActivated)delegate(orig_RpcClientOnActivated orig, TeleporterInteraction self, GameObject activator)
		{
			orig.Invoke(self, activator);
			if (currentState != GameState.BossFight && currentState != GameState.PostBoss)
			{
				currentState = GameState.BossFight;
				nextPlaylist();
			}
			if (logging)
			{
				log("activated teleporter");
			}
		};
		TeleporterInteraction.onTeleporterChargedGlobal += delegate
		{
			if (currentState != GameState.PostBoss)
			{
				currentState = GameState.PostBoss;
				nextPlaylist();
			}
			if (logging)
			{
				log("tp event over");
			}
		};
		Phase1.OnEnter += (hook_OnEnter)delegate(orig_OnEnter orig, Phase1 self)
		{
			orig.Invoke(self);
			if (currentState != GameState.BossFight)
			{
				currentState = GameState.BossFight;
				nextPlaylist();
			}
			if (logging)
			{
				log("started mithrix fight");
			}
		};
		BossDeath.OnEnter += (hook_OnEnter)delegate(orig_OnEnter orig, BossDeath self)
		{
			orig.Invoke(self);
			if (currentState != GameState.PostBoss)
			{
				currentState = GameState.PostBoss;
				nextPlaylist();
			}
			if (logging)
			{
				log("finished mithrix fight");
			}
		};
		Phase1.OnEnter += (hook_OnEnter)delegate(orig_OnEnter orig, Phase1 self)
		{
			orig.Invoke(self);
			if (currentState != GameState.BossFight)
			{
				currentState = GameState.BossFight;
				nextPlaylist();
			}
			if (logging)
			{
				log("started false son fight");
			}
		};
		Phase3.OnExit += (hook_OnExit)delegate(orig_OnExit orig, Phase3 self)
		{
			orig.Invoke(self);
			if (currentState != 0)
			{
				currentState = GameState.Normal;
				nextPlaylist();
			}
			if (logging)
			{
				log("finished false son fight");
			}
		};
		AudioFocusedOnlyConVar.OnApplicationFocus += (hook_OnApplicationFocus)delegate(orig_OnApplicationFocus orig, BaseConVar self, bool isFocussed)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			orig.Invoke(self, isFocussed);
			if (isFocussed && (int)player.PlaybackState == 2)
			{
				paused = false;
				if (!locked)
				{
					player.Play();
				}
			}
			if (!isFocussed && (int)player.PlaybackState == 1)
			{
				paused = true;
				if (!locked)
				{
					player.Pause();
				}
			}
		};
		MusicController.PickCurrentTrack += new hook_PickCurrentTrack(disableOriginalSoundtrack);
		MusicTrackOverride.PickMusicTrack += new hook_PickMusicTrack(disableOriginalSoundtrack);
	}

	private void disableOriginalSoundtrack(orig_PickMusicTrack orig, MusicController self, ref MusicTrackDef track)
	{
		orig.Invoke(self, ref track);
		track = null;
	}

	private void disableOriginalSoundtrack(orig_PickCurrentTrack orig, MusicController self, ref MusicTrackDef track)
	{
		orig.Invoke(self, ref track);
		track = null;
	}

	public void Update()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		if (start && !locked && (int)player.PlaybackState == 0)
		{
			nextTrack();
		}
		applyVolume();
	}

	private void nextPlaylist()
	{
		switch (currentState)
		{
		case GameState.Normal:
			if (playlists.ContainsKey(currentScene) && playlists[currentScene].Count > 0)
			{
				currentPlaylist = playlists[currentScene];
			}
			break;
		case GameState.BossFight:
			if (bossPlaylists.ContainsKey(currentScene) && bossPlaylists[currentScene].Count > 0)
			{
				currentPlaylist = bossPlaylists[currentScene];
				break;
			}
			return;
		case GameState.PostBoss:
			if (postBossPlaylists.ContainsKey(currentScene) && postBossPlaylists[currentScene].Count > 0)
			{
				currentPlaylist = postBossPlaylists[currentScene];
			}
			break;
		}
		if (playbackMode == "next")
		{
			nextTrack();
			return;
		}
		Random randomizer = new Random();
		currentPlaylist = currentPlaylist.OrderBy((string _) => randomizer.Next()).ToList();
		if (playbackMode == "shuffle")
		{
			nextTrack();
			return;
		}
		currentPlaylist = currentPlaylist.GetRange(0, 1);
		nextTrack();
	}

	private void nextTrack()
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Expected O, but got Unknown
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		if (currentPlaylist.Count <= 0)
		{
			return;
		}
		string text = currentPlaylist[0];
		if (!(text != currentTrack) && (int)player.PlaybackState != 0)
		{
			return;
		}
		FadeInOutSampleProvider val = currentFadeInOutSampleProvider;
		currentTrack = text;
		currentAudioFileReader = new AudioFileReader(currentTrack);
		currentFadeInOutSampleProvider = new FadeInOutSampleProvider((ISampleProvider)(object)currentAudioFileReader, false);
		currentPlaylist.Add(currentTrack);
		currentPlaylist.RemoveAt(0);
		applyVolume();
		if (logging)
		{
			log("current track: " + currentTrack);
			log("current playlist: ");
			foreach (string item in currentPlaylist)
			{
				log("    " + item);
			}
		}
		if (locked)
		{
			return;
		}
		locked = true;
		FadeInOutSampleProvider newTrack = currentFadeInOutSampleProvider;
		FadeInOutSampleProvider oldTrack = val;
		new Thread((ThreadStart)delegate
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)player.PlaybackState != 0)
			{
				oldTrack.BeginFadeOut(1500.0);
				Thread.Sleep(1500);
				player.Stop();
			}
			WaveExtensionMethods.Init((IWavePlayer)(object)player, (ISampleProvider)(object)newTrack, false);
			if (!paused)
			{
				player.Play();
			}
			locked = false;
		}).Start();
	}

	private void applyVolume()
	{
		if (currentAudioFileReader != null)
		{
			float.TryParse(((BaseConVar)AudioManager.cvVolumeMaster).GetString(), out var result);
			float.TryParse(((BaseConVar)AudioManager.cvVolumeMsx).GetString(), out var result2);
			result /= 100f;
			result2 /= 100f;
			currentAudioFileReader.Volume = result * result2;
		}
	}

	private void log(string message)
	{
		File.AppendAllText(logPath, "[" + DateTime.Now.ToString("hh:mm:ss") + "] " + message + Environment.NewLine);
	}
}
public class Settings
{
	public string playbackMode { get; set; }

	public string trackPath { get; set; }

	public List<Dictionary<string, List<string>>> playlists { get; set; }
}