Decompiled source of RadioPlus v1.0.0

RadioPlus.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RadioPlus")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+11ff202d8a61f880a82902b780d183bc232704c2")]
[assembly: AssemblyProduct("RadioPlus")]
[assembly: AssemblyTitle("RadioPlus")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RadioPlus
{
	[HarmonyPatch(typeof(AudioLoader), "LoadAudio")]
	public static class LoadAudioPatch
	{
		private static readonly HashSet<string> Known = new HashSet<string>
		{
			".mp3", ".wav", ".ogg", ".flac", ".aiff", ".aif", ".m4a", ".opus", ".mod", ".it",
			".s3m", ".xm"
		};

		private static readonly HashSet<string> Skip = new HashSet<string>
		{
			".meta", ".txt", ".ini", ".json", ".jpg", ".jpeg", ".png", ".gif", ".pdf", ".zip",
			".rar", ".7z", ".exe", ".dll", ".lnk", ".db", ".url", ".cue", ".log", ".m3u",
			".m3u8"
		};

		private static bool Prefix(AudioLoader __instance, string path, ref IEnumerator __result)
		{
			__result = Replacement(__instance, path);
			return false;
		}

		private static IEnumerator Replacement(AudioLoader loader, string path)
		{
			string fileName = Path.GetFileName(path);
			string ext = Path.GetExtension(path).ToLowerInvariant();
			if (ext.Length == 0 || Skip.Contains(ext))
			{
				Plugin.Log.LogInfo((object)("Ignoring " + fileName));
				yield break;
			}
			if (!Known.Contains(ext))
			{
				Plugin.Log.LogInfo((object)("Trying " + fileName + " (unrecognized extension)"));
			}
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip("file://" + path, GuessType(ext));
			try
			{
				((DownloadHandlerAudioClip)req.downloadHandler).streamAudio = true;
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					Plugin.Log.LogWarning((object)("Skipping " + fileName + ": " + req.error));
					yield break;
				}
				AudioClip clip = DownloadHandlerAudioClip.GetContent(req);
				if ((Object)(object)clip == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Skipping " + fileName + ": no clip"));
					yield break;
				}
				((Object)clip).name = fileName;
				loader.tracks.Add(clip);
				Plugin.Log.LogInfo((object)$"Loaded {fileName} — {clip.length:F2}s, {clip.samples} samples, {clip.frequency}Hz, {clip.channels}ch, state={clip.loadState}");
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		private static AudioType GuessType(string ext)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			return (AudioType)(ext switch
			{
				".mp3" => 13, 
				".ogg" => 14, 
				".wav" => 20, 
				_ => 0, 
			});
		}
	}
	[BepInPlugin("com.figrindan.radioplus", "Radio Plus", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Shuffle;

		internal static ConfigEntry<bool> UnlockCustom;

		private void Awake()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Shuffle = ((BaseUnityPlugin)this).Config.Bind<bool>("Radio", "Shuffle", true, "Shuffle the custom radio playlist.");
			UnlockCustom = ((BaseUnityPlugin)this).Config.Bind<bool>("Radio", "UnlockCustomStation", true, "Give the custom radio station (88.1) full signal from the start, without activating the radio tower. Note, driving next to towers that haven't yet been activated will interrupt your listening :)");
			new Harmony("com.figrindan.radioplus").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Radio Plus loaded");
		}
	}
	[HarmonyPatch(typeof(RadioChannel), "GetRandomizedClone")]
	public static class ShufflePatch
	{
		private static readonly Random rng = new Random();

		private static void Postfix(AudioClip[] __result)
		{
			if (Plugin.Shuffle.Value && __result != null && __result.Length >= 2)
			{
				for (int num = __result.Length - 1; num > 0; num--)
				{
					int num2 = rng.Next(num + 1);
					ref AudioClip reference = ref __result[num];
					ref AudioClip reference2 = ref __result[num2];
					AudioClip val = __result[num2];
					AudioClip val2 = __result[num];
					reference = val;
					reference2 = val2;
				}
			}
		}
	}
	[HarmonyPatch(typeof(sRadioSystem), "GetStartTimeAndClip")]
	public static class StartTimePatch
	{
		private static readonly ConditionalWeakTable<AudioClip[], object> lengthCache = new ConditionalWeakTable<AudioClip[], object>();

		private static bool Prefix(RadioChannel channel, ref AudioClip clip, ref float __result)
		{
			if ((Object)(object)channel == (Object)null || channel.queue == null || channel.queue.Length == 0)
			{
				clip = null;
				__result = -1f;
				return false;
			}
			AudioClip[] queue = channel.queue;
			float num;
			if (lengthCache.TryGetValue(queue, out var value))
			{
				num = (float)value;
			}
			else
			{
				num = 0f;
				for (int i = 0; i < queue.Length; i++)
				{
					num += queue[i].length;
				}
				lengthCache.Add(queue, num);
			}
			if (num <= 0f)
			{
				clip = null;
				__result = -1f;
				return false;
			}
			float num2 = Time.unscaledTime % num;
			for (int j = 0; j < queue.Length; j++)
			{
				if (num2 <= queue[j].length)
				{
					clip = queue[j];
					__result = num2;
					return false;
				}
				num2 -= queue[j].length;
			}
			clip = null;
			__result = -1f;
			return false;
		}
	}
	[HarmonyPatch(typeof(RadioSignalManager), "CheckStation")]
	public static class UnlockPatch
	{
		private static void Postfix(RadioSignalManager __instance, int index)
		{
			if (!Plugin.UnlockCustom.Value)
			{
				return;
			}
			object? value = AccessTools.Field(typeof(RadioSignalManager), "radio").GetValue(__instance);
			sRadioSystem val = (sRadioSystem)((value is sRadioSystem) ? value : null);
			if (!((Object)(object)val == (Object)null) && index < val.channels.Count)
			{
				RadioChannel val2 = val.channels[index];
				if (val2.externalTracks != null && val2.externalTracks.Count != 0)
				{
					val2.signal = 1f;
				}
			}
		}
	}
}