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 CruiserTunes v1.3.7
LC_CruiserTunes.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("LC_CruiserTunes")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("LC_CruiserTunes")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("98830a3d-1b1a-47c1-bd5a-429e781a4830")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] public class CarPatch { [CompilerGenerated] private sealed class <AudioSourceListener>d__17 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public AudioSource radio; public VehicleController instance; private AudioClip <clip>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AudioSourceListener>d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <clip>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)instance == (Object)null) { return false; } break; case 1: <>1__state = -1; if (instance.vehicleID == 0 && (Object)(object)<clip>5__1 != (Object)(object)radio.clip) { if (!CruiserTunesMod.DoRandomTime.Value) { radio.time = 0f; } if (CruiserTunesMod.GoodQuality.Value) { radio.volume = 1f; instance.radioInterference.volume = 0f; } instance.radioAudio.loop = CruiserTunesMod.DoLoop.Value; ((MonoBehaviour)instance).StartCoroutine(PlayNotification(instance)); } break; } <clip>5__1 = radio.clip; <>2__current = null; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayNotification>d__18 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public VehicleController instance; private AudioClip <clip>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayNotification>d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <clip>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!CruiserTunesMod.DoMessage.Value) { return false; } if ((Object)(object)instance == (Object)null) { return false; } <clip>5__1 = instance.radioAudio.clip; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)<clip>5__1 == (Object)(object)instance.radioAudio.clip && (Object)(object)<clip>5__1 != (Object)null && Vector3.Distance(((Component)StartOfRound.Instance.localPlayerController).transform.position, ((Component)instance).transform.position) < 10f) { HUDManager.Instance.DisplayTip("Now Playing:", ((Object)<clip>5__1).name.Replace("Radio_", "") + " - " + FormatLength(<clip>5__1.length), false, false, "LC_Tip1"); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static AudioClip[] tunes; public static int[] playOrder; private static VehicleController _car; public static float checkTimer; public static Type type = typeof(VehicleController); public static FieldInfo radioOnField = type.GetField("radioOn", BindingFlags.Instance | BindingFlags.NonPublic); public static VehicleController GetCar { get { if ((Object)(object)_car == (Object)null) { _car = Object.FindObjectOfType<VehicleController>(); } return _car; } } [HarmonyPatch(typeof(VehicleController), "Awake")] [HarmonyPostfix] public static void AwakePatch(VehicleController __instance) { if (CruiserTunesMod.HasSongs) { AudioClip[] source = ((!CruiserTunesMod.IncludeOriginal.Value) ? CruiserTunesMod.CustomSongs : __instance.radioClips.Concat(CruiserTunesMod.CustomSongs).ToArray()); source = source.OrderByDescending((AudioClip str) => GetAsciiSum(((Object)str).name)).ToArray(); tunes = source; __instance.radioClips = tunes; if (__instance.vehicleID == 0) { __instance.radioAudio.loop = CruiserTunesMod.DoLoop.Value; } ((MonoBehaviour)__instance).StartCoroutine(AudioSourceListener(__instance.radioAudio, __instance)); } static int GetAsciiSum(string str) { return str.Sum((char c) => c); } } public static void UpdateLooping(object sender, EventArgs e) { VehicleController getCar = GetCar; if ((Object)(object)getCar != (Object)null && getCar.vehicleID == 0) { getCar.radioAudio.loop = CruiserTunesMod.DoLoop.Value; } } public static void ChangeVolume(object sender, EventArgs e) { VehicleController getCar = GetCar; if ((Object)(object)getCar != (Object)null && getCar.vehicleID == 0) { getCar.radioAudio.volume = GetVolume(); } } private static float GetVolume() { return Mathf.Clamp(CruiserTunesMod.Volume.Value, 0f, 1.25f); } [HarmonyPatch(typeof(VehicleController), "ChangeRadioStation")] [HarmonyPostfix] public static void ChangeRadioStationPatch(VehicleController __instance) { if (!CruiserTunesMod.DoRandomTime.Value && !((Object)(object)__instance == (Object)null)) { __instance.radioAudio.time = 0f; } } [HarmonyPatch(typeof(VehicleController), "SetRadioOnLocalClient")] [HarmonyPrefix] public static void SetOnClientPatch(VehicleController __instance) { if (!((Object)(object)__instance == (Object)null)) { Type type = ((object)__instance).GetType(); FieldInfo field = type.GetField("currentRadioClip", BindingFlags.Instance | BindingFlags.NonPublic); field.SetValue(__instance, (int)field.GetValue(__instance) % __instance.radioClips.Length); if (!CruiserTunesMod.DoRandomTime.Value) { __instance.radioAudio.time = 0f; } } } [HarmonyPatch(typeof(VehicleController), "SetRadioValues")] [HarmonyPrefix] public static void SetRadioValuesPatch(VehicleController __instance) { if (!((Object)(object)__instance == (Object)null) && __instance.vehicleID == 0 && CruiserTunesMod.GoodQuality.Value) { __instance.radioAudio.volume = GetVolume(); __instance.radioInterference.volume = 0f; } } [HarmonyPatch(typeof(VehicleController), "SwitchRadio")] [HarmonyPrefix] public static void SwitchRadioPatch(VehicleController __instance) { if (!((Object)(object)__instance == (Object)null) && !CruiserTunesMod.DoRandomTime.Value) { __instance.radioAudio.time = 0f; } } [HarmonyPatch(typeof(VehicleController), "SetRadioStationClientRpc")] [HarmonyPostfix] public static void SetRadioStationPatch(ref int radioStation, VehicleController __instance) { if (!((Object)(object)__instance == (Object)null)) { __instance.radioAudio.clip = __instance.radioClips[radioStation]; __instance.radioAudio.Play(); } } [IteratorStateMachine(typeof(<AudioSourceListener>d__17))] public static IEnumerator AudioSourceListener(AudioSource radio, VehicleController instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AudioSourceListener>d__17(0) { radio = radio, instance = instance }; } [IteratorStateMachine(typeof(<PlayNotification>d__18))] public static IEnumerator PlayNotification(VehicleController instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayNotification>d__18(0) { instance = instance }; } public static string FormatLength(float lengthInSeconds) { int num = Mathf.FloorToInt(lengthInSeconds / 3600f); int num2 = Mathf.FloorToInt(lengthInSeconds % 3600f / 60f); int num3 = Mathf.FloorToInt(lengthInSeconds % 60f); return $"{num:00}:{num2:00}:{num3:00}"; } public static void ChangeRadioStationWithoutServer(VehicleController instance) { Type type = ((object)instance).GetType(); FieldInfo field = type.GetField("radioSignalDecreaseThreshold", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("radioSignalQuality", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field3 = type.GetField("currentRadioClip", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field4 = type.GetField("currentSongTime", BindingFlags.Instance | BindingFlags.NonPublic); int num = ((int)field3.GetValue(instance) + 1) % instance.radioClips.Length; field3.SetValue(instance, num); instance.radioAudio.clip = instance.radioClips[num]; instance.radioAudio.time = Mathf.Clamp((float)field4.GetValue(instance) % instance.radioAudio.clip.length, 0.01f, instance.radioAudio.clip.length - 0.1f); instance.radioAudio.Play(); float num2 = 10f; float num3 = (float)field2.GetValue(instance); switch ((int)Mathf.Round(num3)) { case 3: num3 = 1f; num2 = 10f; break; case 0: num3 = 3f; num2 = 90f; break; case 1: num3 = 2f; num2 = 70f; break; case 2: num3 = 1f; num2 = 30f; break; } field2.SetValue(instance, num3); field.SetValue(instance, num2); ChangeRadioStationPatch(instance); } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] public static void EnterMoon() { VehicleController getCar = GetCar; if (!((Object)(object)getCar == (Object)null) && CruiserTunesMod.DoRandomSorting.Value) { playOrder = new int[tunes.Length]; for (int i = 0; i < playOrder.Length; i++) { playOrder[i] = i; } Random r = new Random(StartOfRound.Instance.randomMapSeed); playOrder = playOrder.OrderBy((int x) => r.Next()).ToArray(); SortMusic(); } } public static void SortMusic() { VehicleController getCar = GetCar; if ((Object)(object)getCar == (Object)null || playOrder == null || tunes == null || tunes.Length == 0) { return; } if (playOrder.Length != tunes.Length) { CruiserTunesMod.mls.LogError((object)"Play order length does not match number of songs"); return; } AudioClip[] array = (AudioClip[])(object)new AudioClip[tunes.Length]; for (int i = 0; i < tunes.Length; i++) { array[i] = tunes[playOrder[i]]; } getCar.radioClips = array; CruiserTunesMod.mls.LogInfo((object)"printing order"); for (int j = 0; j < playOrder.Length; j++) { CruiserTunesMod.mls.LogInfo((object)playOrder[j]); } } } [BepInPlugin("Mellowdy.CruiserTunes", "CruiserTunes", "1.3.0")] public class CruiserTunesMod : BaseUnityPlugin { [CompilerGenerated] private sealed class <EndOfPatch>d__21 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private bool <finishedLoading>5__1; private bool[] <>s__2; private int <>s__3; private bool <loading>5__4; private string <currentDirectory>5__5; private string <path>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EndOfPatch>d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>s__2 = null; <currentDirectory>5__5 = null; <path>5__6 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; mls.LogInfo((object)("Loading " + instance.loadingList.Length + " songs")); <finishedLoading>5__1 = false; break; case 1: <>1__state = -1; break; } while (!<finishedLoading>5__1) { <finishedLoading>5__1 = true; <>s__2 = instance.loadingList; for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++) { <loading>5__4 = <>s__2[<>s__3]; if (!<loading>5__4) { <finishedLoading>5__1 = false; break; } } <>s__2 = null; if (!<finishedLoading>5__1) { <>2__current = null; <>1__state = 1; return true; } } instance.loadingList = null; mls.LogInfo((object)("Finished loading songs, final song count at:" + instance.SongList.Count)); if (instance.SongList.Count == 0) { <currentDirectory>5__5 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); <path>5__6 = Path.Combine(<currentDirectory>5__5, instance.folderName).Replace("\\", "/"); mls.LogError((object)"No songs found in folder"); mls.LogError((object)("Make sure to add any .mp3 or .wav or .ogg files you want as songs to: '" + <path>5__6 + "'")); <currentDirectory>5__5 = null; <path>5__6 = null; } CustomSongs = instance.SongList.ToArray(); instance.SongList.Clear(); HasSongs = CustomSongs.Length != 0 || IncludeOriginal.Value; mls.LogInfo((object)"CruiserTunes has been loaded"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadAudioClip>d__22 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string filePath; public int index; public string fileType; private float <loadingTime>5__1; private float <maxLoading>5__2; private string <fileName>5__3; private AudioType <audioType>5__4; private UnityWebRequest <loader>5__5; private AudioClip <content>5__6; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAudioClip>d__22(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <fileName>5__3 = null; <loader>5__5 = null; <content>5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_0071: 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_0083: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <loadingTime>5__1 = Time.time; <maxLoading>5__2 = 5f; <fileName>5__3 = Path.GetFileName(filePath); mls.LogInfo((object)("Loading " + <fileName>5__3)); <audioType>5__4 = GetAudioType(fileType); <loader>5__5 = UnityWebRequestMultimedia.GetAudioClip(filePath, <audioType>5__4); <>1__state = -3; <loader>5__5.SendWebRequest(); break; case 1: <>1__state = -3; break; } if (!<loader>5__5.isDone) { if (<loadingTime>5__1 + <maxLoading>5__2 < Time.time) { mls.LogError((object)("Error loading clip from path: " + <fileName>5__3)); instance.loadingList[index] = true; result = false; goto IL_01c7; } <>2__current = null; <>1__state = 1; result = true; } else { instance.loadingList[index] = true; if (<loader>5__5.error != null) { mls.LogError((object)("Error loading clip from path: " + <fileName>5__3 + "\n" + <loader>5__5.error)); result = false; goto IL_01c7; } <content>5__6 = DownloadHandlerAudioClip.GetContent(<loader>5__5); ((Object)<content>5__6).name = <fileName>5__3; instance.SongList.Add(<content>5__6); <content>5__6 = null; <>m__Finally1(); <loader>5__5 = null; result = false; } goto end_IL_0000; IL_01c7: <>m__Finally1(); end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<loader>5__5 != null) { ((IDisposable)<loader>5__5).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string modGUID = "Mellowdy.CruiserTunes"; private const string modName = "CruiserTunes"; private const string modVersion = "1.3.0"; private readonly Harmony harmony = new Harmony("Mellowdy.CruiserTunes"); public static ManualLogSource mls; public static CruiserTunesMod instance; public static ConfigEntry<bool> IncludeOriginal; public static ConfigEntry<bool> DoMessage; public static ConfigEntry<bool> DoLoop; public static ConfigEntry<bool> DoRandomTime; public static ConfigEntry<bool> GoodQuality; public static ConfigEntry<float> Volume; public static ConfigEntry<bool> DoRandomSorting; public static bool HasSongs; public static AudioClip[] CustomSongs; private const string supportedAudioFileTypes = ".mp3 or .wav or .ogg"; private string folderName = "CustomSongs"; private string altFolderName = "Custom Songs"; private List<AudioClip> SongList = new List<AudioClip>(); private bool[] loadingList; private void Awake() { if ((Object)(object)instance == (Object)null) { instance = this; } mls = Logger.CreateLogSource("Mellowdy.CruiserTunes"); mls.LogInfo((object)"Loading..."); Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; IncludeOriginal = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Include Original Songs", true, "The radio is able to play the orignal songs"); DoMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Notify When New Song", true, "The radio notifies nearby players what song is now playing"); DoLoop = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Loop", false, "The radio loops songs upon completion"); DoLoop.SettingChanged += CarPatch.UpdateLooping; DoRandomTime = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Random Start Time", false, "The randomly picks a point in the song to start playing when switching channels"); GoodQuality = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Always have good quality", true, "When switching between channels the quality will remain good"); Volume = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Volume", 0.75f, "Volume of the radio (does not require restart)"); Volume.SettingChanged += CarPatch.ChangeVolume; DoRandomSorting = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Do Random Sorting", false, "Should songs be randomly sorted when entering a moon?"); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, folderName); List<string> list = new List<string>(); List<string> list2 = new List<string>(); string text2 = Path.Combine(Directory.GetParent(directoryName).FullName, folderName); string text3 = Path.Combine(Directory.GetParent(directoryName).FullName, altFolderName); if (Directory.Exists(text2)) { list.Add(text2); } else if (Directory.Exists(text3)) { list.Add(text3); } string text4 = Path.Combine(Directory.GetParent(directoryName).Parent.FullName, altFolderName); if (Directory.Exists(text4)) { list.Add(text4); } string[] directories = Directory.GetDirectories(Directory.GetParent(directoryName).FullName); foreach (string path in directories) { string text5 = Path.Combine(path, folderName); if (Directory.Exists(text5)) { list.Add(text5); } } if (list.Count == 0) { Directory.CreateDirectory(text); mls.LogWarning((object)("Folder not found. One has been created at: '" + text + "'")); return; } foreach (string item in list) { list2.AddRange(Directory.GetFiles(item)); } list2 = RemoveDuplicateFiles(list2); bool flag = false; loadingList = new bool[list2.Count]; for (int j = 0; j < list2.Count; j++) { string text6 = list2[j]; loadingList[j] = false; string fileName = Path.GetFileName(text6); string text7 = Path.GetExtension(text6).ToLower(); if (text7 == ".mp3" || text7 == ".wav" || text7 == ".ogg") { ((MonoBehaviour)this).StartCoroutine(LoadAudioClip(text6, j, text7)); continue; } loadingList[j] = true; if (text7 != ".old") { mls.LogWarning((object)(fileName + " is of invalid extention. Must be a .mp3 or .wav or .ogg file or .old file")); if (!flag) { mls.LogWarning((object)".old files ignore this message being printed."); } flag = true; } } if (loadingList.Length == 0) { mls.LogError((object)"No songs found"); } harmony.PatchAll(); harmony.PatchAll(typeof(CarPatch)); ((MonoBehaviour)this).StartCoroutine(EndOfPatch()); } [IteratorStateMachine(typeof(<EndOfPatch>d__21))] private static IEnumerator EndOfPatch() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EndOfPatch>d__21(0); } [IteratorStateMachine(typeof(<LoadAudioClip>d__22))] private static IEnumerator LoadAudioClip(string filePath, int index, string fileType) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAudioClip>d__22(0) { filePath = filePath, index = index, fileType = fileType }; } public static AudioType GetAudioType(string fileType) { //IL_0030: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) return (AudioType)(fileType switch { ".mp3" => 13, ".wav" => 20, ".ogg" => 14, _ => 13, }); } public static List<string> RemoveDuplicateFiles(List<string> filePaths) { HashSet<string> hashSet = new HashSet<string>(); List<string> list = new List<string>(); foreach (string filePath in filePaths) { string fileName = Path.GetFileName(filePath); if (!hashSet.Contains(fileName)) { hashSet.Add(fileName); list.Add(filePath); } } return list; } }