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 BoomboxPlaylists.Managers;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BoomboxPlaylists")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BoomboxPlaylists")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("020a0457-0d96-492e-ad0f-548bc97b9557")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BoomboxPlaylists
{
[BepInPlugin("Batres3.BoomboxPlaylists", "Boombox Playlists", "1.0.0")]
public class BoomboxPlaylistsBase : BaseUnityPlugin
{
private const string modGUID = "Batres3.BoomboxPlaylists";
private const string modName = "Boombox Playlists";
private const string modVersion = "1.0.0";
private readonly Harmony harmony = new Harmony("Batres3.BoomboxPlaylists");
private static BoomboxPlaylistsBase Instance;
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
if (!Directory.Exists(Path.Combine(Paths.BepInExRootPath, "Custom Playlists")))
{
Directory.CreateDirectory(Path.Combine(Paths.BepInExRootPath, "Custom Playlists"));
LogError("No custom playlists detected, they must be in the 'Custom Playlists' folder");
}
else
{
harmony.PatchAll();
AudioManager.Load();
LogInfo("Boombox Playlists Loaded!");
}
}
internal static void LogInfo(string message)
{
Instance.Log(message, (LogLevel)16);
}
internal static void LogError(string message)
{
Instance.Log(message, (LogLevel)2);
}
private void Log(string message, LogLevel logLevel)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
((BaseUnityPlugin)this).Logger.Log(logLevel, (object)message);
}
}
}
namespace BoomboxPlaylists.Utils
{
internal class SharedCoroutineStarter : MonoBehaviour
{
private static SharedCoroutineStarter _instance;
public static Coroutine StartCoroutine(IEnumerator routine)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_instance == (Object)null)
{
_instance = new GameObject("Shared Coroutine Starter").AddComponent<SharedCoroutineStarter>();
Object.DontDestroyOnLoad((Object)(object)_instance);
}
return ((MonoBehaviour)_instance).StartCoroutine(routine);
}
}
}
namespace BoomboxPlaylists.Patches
{
[HarmonyPatch(typeof(BoomboxItem))]
internal class BoomboxItemPatch
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void Start_Postfix(BoomboxItem __instance)
{
if (AudioManager.finishedLoading)
{
AudioManager.ApplyClips(ref __instance);
return;
}
AudioManager.OnAllSongsLoaded += delegate
{
AudioManager.ApplyClips(ref __instance);
};
AudioManager.SetTooltip(ref __instance);
}
[HarmonyPatch("StartMusic")]
[HarmonyPostfix]
private static void StartMusic_Postfix(BoomboxItem __instance, bool startMusic)
{
AudioManager.SetVolume(ref __instance);
AudioManager.NextSong(ref __instance, ref startMusic);
}
[HarmonyPatch("PocketItem")]
[HarmonyPostfix]
private static void PocketItem_Postfix(BoomboxItem __instance)
{
AudioManager.ApplyClips(ref __instance);
AudioManager.SetTooltip(ref __instance);
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
private static void Update_Postfix(BoomboxItem __instance)
{
if (((GrabbableObject)__instance).isHeld)
{
if (((KeyboardShortcut)(ref AudioManager.lowerVolume)).IsPressed())
{
AudioManager.ModifyVolume(increase: false, ref __instance);
}
else if (((KeyboardShortcut)(ref AudioManager.increaseVolume)).IsPressed())
{
AudioManager.ModifyVolume(increase: true, ref __instance);
}
}
}
}
}
namespace BoomboxPlaylists.Managers
{
internal static class AudioManager
{
public static List<PlaylistManager> playlistManagers = new List<PlaylistManager>();
public static int currentPlaylistID;
public static bool finishedLoading = false;
public static int currentSongID = 0;
private static readonly string directory = Path.Combine(Paths.BepInExRootPath, "Custom Playlists");
private static readonly string[] defaultTooltip = new string[3] { "Toggle Music : [LMB]", "Playlist : ", "Change Volume : [Ctrl]+[Shift]+[K]/[J]" };
private static KeyCode[] conditionKeys = (KeyCode[])(object)new KeyCode[2]
{
(KeyCode)304,
(KeyCode)306
};
public static KeyboardShortcut lowerVolume = new KeyboardShortcut((KeyCode)106, conditionKeys);
public static KeyboardShortcut increaseVolume = new KeyboardShortcut((KeyCode)107, conditionKeys);
public static float volume = 1f;
public static event Action OnAllSongsLoaded;
public static void Load()
{
if (playlistManagers.Count != 0)
{
return;
}
string[] array = Directory.GetDirectories(directory).Select(Path.GetFileName).ToArray();
if (array.Length == 0)
{
BoomboxPlaylistsBase.LogError("No playlists detected");
return;
}
string[] array2 = array;
foreach (string playlistname in array2)
{
playlistManagers.Add(new PlaylistManager(playlistname));
}
int num = 0;
foreach (PlaylistManager playlistManager in playlistManagers)
{
array2 = playlistManager.playlistSongsPaths;
for (int i = 0; i < array2.Length; i++)
{
LoadAudioClip(array2[i], num);
}
BoomboxPlaylistsBase.LogInfo("Loaded playlist " + playlistManager.playlistName);
num++;
}
}
private static void LoadAudioClip(string filePath, int playlistID)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Invalid comparison between Unknown and I4
if ((int)GetAudioType(filePath) == 0)
{
BoomboxPlaylistsBase.LogError("Failed to load AudioClip from " + filePath + "!");
return;
}
UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(filePath, GetAudioType(filePath));
audioClip.SendWebRequest();
while (!audioClip.isDone)
{
}
if (audioClip.error != null)
{
BoomboxPlaylistsBase.LogError("Error loading clip from path: " + filePath);
BoomboxPlaylistsBase.LogError(audioClip.error);
return;
}
AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
if (Object.op_Implicit((Object)(object)content) && (int)content.loadState == 2)
{
((Object)content).name = Path.GetFileName(filePath);
BoomboxPlaylistsBase.LogInfo("Loaded song " + ((Object)content).name);
playlistManagers[playlistID].clips.Add(content);
}
else
{
BoomboxPlaylistsBase.LogError("Failed to load clip at: " + filePath + "\nThis might be due to an mismatch between the audio codec and the file extension!");
}
}
private static IEnumerator WaitForAllClips(List<Coroutine> coroutines, int playlistID)
{
foreach (Coroutine coroutine in coroutines)
{
yield return coroutine;
}
playlistManagers[playlistID].clips.Sort((AudioClip first, AudioClip second) => ((Object)first).name.CompareTo(((Object)second).name));
finishedLoading = true;
AudioManager.OnAllSongsLoaded?.Invoke();
AudioManager.OnAllSongsLoaded = null;
}
private static AudioType GetAudioType(string filePath)
{
string extension = Path.GetExtension(filePath);
switch (extension)
{
case ".wav":
return (AudioType)20;
case ".ogg":
return (AudioType)14;
case ".mp3":
return (AudioType)13;
default:
BoomboxPlaylistsBase.LogError("Unsupported extesion type: " + extension);
return (AudioType)0;
}
}
public static void ApplyClips(ref BoomboxItem __istance)
{
currentPlaylistID++;
if (currentPlaylistID >= playlistManagers.Count)
{
currentPlaylistID = 0;
}
currentSongID = 0;
__istance.musicAudios = playlistManagers[currentPlaylistID].clips.ToArray();
}
public static void SetTooltip(ref BoomboxItem __instance)
{
string[] array = new string[3];
Array.Copy(defaultTooltip, array, defaultTooltip.Length);
array[1] += playlistManagers[currentPlaylistID].playlistName;
((GrabbableObject)__instance).itemProperties.toolTips = array;
}
public static void ModifyVolume(bool increase, ref BoomboxItem __instance)
{
if (increase)
{
volume = Mathf.Clamp(volume + 0.01f, 0f, 1f);
SetVolume(ref __instance);
}
else
{
volume = Mathf.Clamp(volume - 0.01f, 0f, 1f);
SetVolume(ref __instance);
}
}
public static void SetVolume(ref BoomboxItem __instance)
{
__instance.boomboxAudio.volume = volume;
}
public static void NextSong(ref BoomboxItem __instance, ref bool startMusic)
{
if (startMusic)
{
currentSongID++;
if (currentSongID >= playlistManagers[currentPlaylistID].clips.Count)
{
currentSongID = 0;
}
__instance.boomboxAudio.clip = __instance.musicAudios[currentSongID];
__instance.boomboxAudio.pitch = 1f;
__instance.boomboxAudio.Play();
startMusic = false;
}
}
}
internal class PlaylistManager
{
public string[] playlistSongsPaths;
public List<AudioClip> clips = new List<AudioClip>();
private readonly string playlistPath;
public string playlistName;
public bool hasNoSongs => playlistSongsPaths.Length == 0;
internal PlaylistManager(string playlistname)
{
playlistName = playlistname;
playlistPath = Path.Combine(Paths.BepInExRootPath, "Custom Playlists", playlistName);
playlistSongsPaths = Directory.GetFiles(playlistPath);
if (hasNoSongs)
{
BoomboxPlaylistsBase.LogError("No songs found for playlist " + playlistName);
}
}
}
}