Please disclose if your mod was created primarily 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 PidoryMusic v1.0.8
LC_CruiserTunes.dll
Decompiled 9 months 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 { public static float checkTimer; public static Type type = typeof(VehicleController); public static FieldInfo radioOnField = type.GetField("radioOn", BindingFlags.Instance | BindingFlags.NonPublic); [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(); __instance.radioClips = source; __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) { Object.FindObjectOfType<VehicleController>().radioAudio.loop = CruiserTunesMod.DoLoop.Value; } public static void ChangeVolume(object sender, EventArgs e) { Object.FindObjectOfType<VehicleController>().radioAudio.volume = Mathf.Clamp(CruiserTunesMod.Volume.Value, 0f, 1.25f); } [HarmonyPatch(typeof(VehicleController), "ChangeRadioStation")] [HarmonyPostfix] public static void ChangeRadioStationPatch(VehicleController __instance) { if (!CruiserTunesMod.DoRandomTime.Value) { __instance.radioAudio.time = 0f; } } [HarmonyPatch(typeof(VehicleController), "SetRadioOnLocalClient")] [HarmonyPrefix] public static void SetOnClientPatch(VehicleController __instance) { 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 (CruiserTunesMod.GoodQuality.Value) { __instance.radioAudio.volume = 1f; __instance.radioInterference.volume = 0f; } } [HarmonyPatch(typeof(VehicleController), "SwitchRadio")] [HarmonyPrefix] public static void SwitchRadioPatch(VehicleController __instance) { if (!CruiserTunesMod.DoRandomTime.Value) { __instance.radioAudio.time = 0f; } } [HarmonyPatch(typeof(VehicleController), "SetRadioStationClientRpc")] [HarmonyPostfix] public static void SetRadioStationPatch(ref int radioStation, VehicleController __instance) { __instance.radioAudio.clip = __instance.radioClips[radioStation]; __instance.radioAudio.Play(); } public static IEnumerator AudioSourceListener(AudioSource radio, VehicleController instance) { while (true) { AudioClip clip = radio.clip; instance.radioAudio.loop = CruiserTunesMod.DoLoop.Value; yield return null; if ((Object)(object)clip != (Object)(object)radio.clip) { if (!CruiserTunesMod.DoRandomTime.Value) { radio.time = 0f; } if (CruiserTunesMod.GoodQuality.Value) { radio.volume = 1f; instance.radioInterference.volume = 0f; } ((MonoBehaviour)instance).StartCoroutine(PlayNotification(instance)); } } } public static IEnumerator PlayNotification(VehicleController instance) { if (CruiserTunesMod.DoMessage.Value) { AudioClip clip = instance.radioAudio.clip; yield return (object)new WaitForSeconds(2f); if ((Object)(object)clip == (Object)(object)instance.radioAudio.clip && Vector3.Distance(((Component)StartOfRound.Instance.localPlayerController).transform.position, ((Component)instance).transform.position) < 10f) { HUDManager.Instance.DisplayTip("Now Playing:", ((Object)clip).name.Replace("Radio_", "") + " - " + FormatLength(clip.length), false, false, "LC_Tip1"); } } } 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); } } [BepInPlugin("Mellowdy.CruiserTunes", "CruiserTunes", "1.3.0")] public class CruiserTunesMod : BaseUnityPlugin { 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 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; 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()); } private static IEnumerator EndOfPatch() { mls.LogInfo((object)("Loading " + instance.loadingList.Length + " songs")); bool finishedLoading = false; while (!finishedLoading) { finishedLoading = true; bool[] array = instance.loadingList; for (int i = 0; i < array.Length; i++) { if (!array[i]) { finishedLoading = false; break; } } if (!finishedLoading) { yield return null; } } instance.loadingList = null; mls.LogInfo((object)("Finished loading songs, final song count at:" + instance.SongList.Count)); if (instance.SongList.Count == 0) { string currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string path = Path.Combine(currentDirectory, 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 + "'")); } CustomSongs = instance.SongList.ToArray(); instance.SongList.Clear(); HasSongs = CustomSongs.Length != 0 || IncludeOriginal.Value; mls.LogInfo((object)"CruiserTunes has been loaded"); } private static IEnumerator LoadAudioClip(string filePath, int index, string fileType) { float loadingTime = Time.time; float maxLoading = 5f; string fileName = Path.GetFileName(filePath); mls.LogInfo((object)("Loading " + fileName)); AudioType audioType = GetAudioType(fileType); UnityWebRequest loader = UnityWebRequestMultimedia.GetAudioClip(filePath, audioType); try { loader.SendWebRequest(); while (!loader.isDone) { if (loadingTime + maxLoading < Time.time) { mls.LogError((object)("Error loading clip from path: " + fileName)); instance.loadingList[index] = true; yield break; } yield return null; } instance.loadingList[index] = true; if (loader.error != null) { mls.LogError((object)("Error loading clip from path: " + fileName + "\n" + loader.error)); yield break; } AudioClip content = DownloadHandlerAudioClip.GetContent(loader); ((Object)content).name = fileName; instance.SongList.Add(content); } finally { ((IDisposable)loader)?.Dispose(); } } 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; } }