Decompiled source of CruiserTunes v1.3.3

LC_CruiserTunes.dll

Decompiled 3 weeks ago
using 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;
	}
}