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 YakuzaRadio v1.0.2
LC_CruiserTunes.dll
Decompiled 2 years 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); } } [HarmonyPatch(typeof(VehicleController), "Update")] [HarmonyPostfix] public static void UpdatePatch(VehicleController __instance) { if (CruiserTunesMod.DoLoop.Value) { return; } if (!__instance.radioAudio.isPlaying && checkTimer <= 0f) { if ((bool)radioOnField.GetValue(__instance)) { ChangeRadioStationWithoutServer(__instance); } else { checkTimer = 1f; } } else { checkTimer -= Time.deltaTime; } } [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; } } 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.0.1")] public class CruiserTunesMod : BaseUnityPlugin { private const string modGUID = "Mellowdy.CruiserTunes"; private const string modName = "CruiserTunes"; private const string modVersion = "1.0.1"; 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 bool HasSongs; public static AudioClip[] CustomSongs; private string folderName = "CustomSongs"; 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..."); 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"); 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"); 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); if (Directory.Exists(text2)) { list.Add(text2); } string[] directories = Directory.GetDirectories(Directory.GetParent(directoryName).FullName); foreach (string path in directories) { string text3 = Path.Combine(path, folderName); if (Directory.Exists(text3)) { list.Add(text3); } } 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)); } bool flag = false; loadingList = new bool[list2.Count]; for (int j = 0; j < list2.Count; j++) { string text4 = list2[j]; loadingList[j] = false; string fileName = Path.GetFileName(text4); string text5 = Path.GetExtension(text4).ToLower(); if (text5 == ".mp3") { ((MonoBehaviour)this).StartCoroutine(LoadAudioClip(text4, j)); continue; } loadingList[j] = true; if (text5 != ".old") { mls.LogWarning((object)(fileName + " is of invalid extention. Must be a .mp3 file or .old file")); if (!flag) { mls.LogWarning((object)".old files ignore this message being printed."); } flag = true; } } ((MonoBehaviour)this).StartCoroutine(EndOfPatch()); } private IEnumerator EndOfPatch() { bool finishedLoading = false; while (!finishedLoading) { finishedLoading = true; bool[] array = loadingList; for (int i = 0; i < array.Length; i++) { if (!array[i]) { finishedLoading = false; break; } } yield return null; } loadingList = null; mls.LogInfo((object)("Finished loading songs, final song count at:" + SongList.Count)); if (SongList.Count == 0) { string currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string path = Path.Combine(currentDirectory, folderName).Replace("\\", "/"); mls.LogError((object)"No songs found in folder"); mls.LogError((object)("Make sure to add any .mp3 files you want as songs to: '" + path + "'")); } CustomSongs = SongList.ToArray(); SongList.Clear(); HasSongs = CustomSongs.Length != 0 || IncludeOriginal.Value; harmony.PatchAll(); harmony.PatchAll(typeof(CarPatch)); mls.LogInfo((object)"CruiserTunes has been loaded"); } private IEnumerator LoadAudioClip(string filePath, int index) { string fileName = Path.GetFileName(filePath); mls.LogInfo((object)("Loading " + fileName)); UnityWebRequest loader = UnityWebRequestMultimedia.GetAudioClip(filePath, (AudioType)13); loader.SendWebRequest(); while (!loader.isDone) { yield return null; } 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; SongList.Add(content); } }