Decompiled source of CybergrindMusicExplorer v2.0.7
plugins/Jukebox/Jukebox.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Xml; using BepInEx; using Discord; using HarmonyLib; using Jukebox.Assets; using Jukebox.Components; using Jukebox.Core.Collections; using Jukebox.Core.Model.Song; using Jukebox.Core.Model.Themes; using Jukebox.Core.Themes; using Jukebox.Input; using Jukebox.UI; using Jukebox.UI.Elements; using Jukebox.UI.Windows; using Jukebox.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SettingsMenu.Components; using SettingsMenu.Components.Pages; using Steamworks; using TMPro; using TagLib; using TagLib.Aac; using TagLib.Aiff; using TagLib.Ape; using TagLib.Asf; using TagLib.Audible; using TagLib.Dsf; using TagLib.Flac; using TagLib.Gif; using TagLib.IFD; using TagLib.IFD.Entries; using TagLib.IFD.Makernotes; using TagLib.IFD.Tags; using TagLib.IIM; using TagLib.Id3v1; using TagLib.Id3v2; using TagLib.Image; using TagLib.Image.NoMetadata; using TagLib.Jpeg; using TagLib.Matroska; using TagLib.Mpeg; using TagLib.Mpeg4; using TagLib.MusePack; using TagLib.NonContainer; using TagLib.Ogg; using TagLib.Ogg.Codecs; using TagLib.Png; using TagLib.Riff; using TagLib.Tiff; using TagLib.Tiff.Arw; using TagLib.Tiff.Cr2; using TagLib.Tiff.Dng; using TagLib.Tiff.Nef; using TagLib.Tiff.Pef; using TagLib.Tiff.Rw2; using TagLib.WavPack; using TagLib.Xmp; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Jukebox")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Jukebox")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("B01B8657-61B6-4BC3-BFAF-F43D4C264B4B")] [assembly: AssemblyFileVersion("2.0.7.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("2.0.7.0")] namespace UnityEngine.UI { [AddComponentMenu("Layout/Auto Expand Grid Layout Group", 152)] public class AutoExpandGridLayoutGroup : LayoutGroup { public enum Corner { UpperLeft, UpperRight, LowerLeft, LowerRight } public enum Axis { Horizontal, Vertical } public enum Constraint { Flexible, FixedColumnCount, FixedRowCount } [SerializeField] protected Corner m_StartCorner; [SerializeField] protected Axis m_StartAxis; [SerializeField] protected Vector2 m_CellSize = new Vector2(100f, 100f); [SerializeField] protected Vector2 m_Spacing = Vector2.zero; [SerializeField] protected Constraint m_Constraint; [SerializeField] protected int m_ConstraintCount = 2; public Corner startCorner { get { return m_StartCorner; } set { ((LayoutGroup)this).SetProperty<Corner>(ref m_StartCorner, value); } } public Axis startAxis { get { return m_StartAxis; } set { ((LayoutGroup)this).SetProperty<Axis>(ref m_StartAxis, value); } } public Vector2 cellSize { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return m_CellSize; } set { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ((LayoutGroup)this).SetProperty<Vector2>(ref m_CellSize, value); } } public Vector2 spacing { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return m_Spacing; } set { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ((LayoutGroup)this).SetProperty<Vector2>(ref m_Spacing, value); } } public Constraint constraint { get { return m_Constraint; } set { ((LayoutGroup)this).SetProperty<Constraint>(ref m_Constraint, value); } } public int constraintCount { get { return m_ConstraintCount; } set { ((LayoutGroup)this).SetProperty<int>(ref m_ConstraintCount, Mathf.Max(1, value)); } } protected AutoExpandGridLayoutGroup() { }//IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) public override void CalculateLayoutInputHorizontal() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) ((LayoutGroup)this).CalculateLayoutInputHorizontal(); int num = 0; int num2 = 0; if (m_Constraint == Constraint.FixedColumnCount) { num = (num2 = m_ConstraintCount); } else if (m_Constraint == Constraint.FixedRowCount) { num = (num2 = Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)m_ConstraintCount - 0.001f)); } else { num = 1; num2 = Mathf.CeilToInt(Mathf.Sqrt((float)((LayoutGroup)this).rectChildren.Count)); } ((LayoutGroup)this).SetLayoutInputForAxis((float)((LayoutGroup)this).padding.horizontal + (cellSize.x + spacing.x) * (float)num - spacing.x, (float)((LayoutGroup)this).padding.horizontal + (cellSize.x + spacing.x) * (float)num2 - spacing.x, -1f, 0); } public override void CalculateLayoutInputVertical() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) int num = 0; if (m_Constraint == Constraint.FixedColumnCount) { num = Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)m_ConstraintCount - 0.001f); } else if (m_Constraint == Constraint.FixedRowCount) { num = m_ConstraintCount; } else { Rect rect = ((LayoutGroup)this).rectTransform.rect; float x = ((Rect)(ref rect)).size.x; int num2 = Mathf.Max(1, Mathf.FloorToInt((x - (float)((LayoutGroup)this).padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))); num = Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)num2); } float num3 = (float)((LayoutGroup)this).padding.vertical + (cellSize.y + spacing.y) * (float)num - spacing.y; ((LayoutGroup)this).SetLayoutInputForAxis(num3, num3, -1f, 1); } public override void SetLayoutHorizontal() { SetCellsAlongAxis(0); } public override void SetLayoutVertical() { SetCellsAlongAxis(1); } private void SetCellsAlongAxis(int axis) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) if (axis == 0) { for (int i = 0; i < ((LayoutGroup)this).rectChildren.Count; i++) { RectTransform val = ((LayoutGroup)this).rectChildren[i]; ((DrivenRectTransformTracker)(ref base.m_Tracker)).Add((Object)(object)this, val, (DrivenTransformProperties)16134); val.anchorMin = Vector2.up; val.anchorMax = Vector2.up; val.sizeDelta = cellSize; } return; } Rect rect = ((LayoutGroup)this).rectTransform.rect; float x = ((Rect)(ref rect)).size.x; rect = ((LayoutGroup)this).rectTransform.rect; float y = ((Rect)(ref rect)).size.y; int num = 1; int num2 = 1; if (m_Constraint == Constraint.FixedColumnCount) { num = m_ConstraintCount; num2 = Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)num - 0.001f); } else if (m_Constraint != Constraint.FixedRowCount) { num = ((!(cellSize.x + spacing.x <= 0f)) ? Mathf.Max(1, Mathf.FloorToInt((x - (float)((LayoutGroup)this).padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x))) : int.MaxValue); num2 = ((!(cellSize.y + spacing.y <= 0f)) ? Mathf.Max(1, Mathf.FloorToInt((y - (float)((LayoutGroup)this).padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y))) : int.MaxValue); } else { num2 = m_ConstraintCount; num = Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)num2 - 0.001f); } int num3 = (int)startCorner % 2; int num4 = (int)startCorner / 2; int num5; int num6; int num7; if (startAxis == Axis.Horizontal) { num5 = num; num6 = Mathf.Clamp(num, 1, ((LayoutGroup)this).rectChildren.Count); num7 = Mathf.Clamp(num2, 1, Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)num5)); } else { num5 = num2; num7 = Mathf.Clamp(num2, 1, ((LayoutGroup)this).rectChildren.Count); num6 = Mathf.Clamp(num, 1, Mathf.CeilToInt((float)((LayoutGroup)this).rectChildren.Count / (float)num5)); } Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)num6 * cellSize.x + (float)(num6 - 1) * spacing.x, (float)num7 * cellSize.y + (float)(num7 - 1) * spacing.y); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(((LayoutGroup)this).GetStartOffset(0, val2.x), ((LayoutGroup)this).GetStartOffset(1, val2.y)); for (int j = 0; j < ((LayoutGroup)this).rectChildren.Count; j++) { int num8; int num9; if (startAxis == Axis.Horizontal) { num8 = j % num5; num9 = j / num5; } else { num8 = j / num5; num9 = j % num5; } if (num3 == 1) { num8 = num6 - 1 - num8; } if (num4 == 1) { num9 = num7 - 1 - num9; } Vector2 val4 = spacing; float num10 = (x - ((Vector2)(ref val4))[0] * (float)(num6 - 1)) / (float)num6; RectTransform obj = ((LayoutGroup)this).rectChildren[j]; float x2 = val3.x; val4 = spacing; ((LayoutGroup)this).SetChildAlongAxis(obj, 0, x2 + (num10 + ((Vector2)(ref val4))[0]) * (float)num8, num10); RectTransform obj2 = ((LayoutGroup)this).rectChildren[j]; float y2 = val3.y; val4 = cellSize; float num11 = ((Vector2)(ref val4))[1]; val4 = spacing; float num12 = y2 + (num11 + ((Vector2)(ref val4))[1]) * (float)num9; val4 = cellSize; ((LayoutGroup)this).SetChildAlongAxis(obj2, 1, num12, ((Vector2)(ref val4))[1]); } } } } namespace Jukebox { [BepInProcess("ULTRAKILL.exe")] [BepInPlugin("dev.flazhik.jukebox", "Jukebox", "2.0.7")] public class JukeboxPlugin : BaseUnityPlugin { [ExternalAsset("Assets/Jukebox/Bootstrap.prefab", typeof(GameObject))] private static GameObject bootstrap; public static string catalogDir; private static Harmony _harmony; private static bool motdShown; private static bool init; static JukeboxPlugin() { catalogDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Assets"); } private void Awake() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_004b: Expected O, but got Unknown Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Addressables.InitializeAsync().WaitForCompletion(); Addressables.LoadContentCatalogAsync(Path.Combine(catalogDir, "catalog.json"), true, (string)null).WaitForCompletion(); _harmony = new Harmony("dev.flazhik.jukebox"); Startup(); } private void Startup() { _harmony.PatchAll(); SceneManager.sceneLoaded += OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (scene != SceneManager.GetActiveScene()) { return; } switch (SceneHelper.CurrentScene) { case "Bootstrap": SetDefaultPrefsValues(); break; case "Main Menu": if (!init) { MonoSingleton<AssetsManager>.Instance.LoadAssets(); MonoSingleton<AssetsManager>.Instance.RegisterPrefabs(); init = true; } break; case "Endless": Object.Instantiate<GameObject>(bootstrap); if (!motdShown) { ((MonoBehaviour)MonoSingleton<JukeboxManager>.Instance).StartCoroutine(Motd()); } break; } } private static void SetDefaultPrefsValues() { foreach (KeyValuePair<string, object> item in new Dictionary<string, object> { { "jukebox.volumeBoost", 0f }, { "jukebox.showTrackPanelIndefinitely", false }, { "jukebox.alwaysPlayIntro", true }, { "jukebox.discordAndSteamIntegration", true }, { "jukebox.enableTracksPreview", true }, { "jukebox.preventDuplicateTracks", false }, { "jukebox.nowPlayingHud", true }, { "jukebox.enableCalmThemes", true }, { "jukebox.songPanelStyle", 0 }, { "jukebox.currentPlaylist", "slot1" }, { "jukebox.calmThemeEnemiesThreshold", 2 }, { "jukebox.effects.parry", null }, { "jukebox.effects.wavecomplete", null }, { "jukebox.effects.gameover", null }, { "jukebox.effects.aww", null }, { "jukebox.effects.terminal-music", null } }) { MonoSingleton<PrefsManager>.Instance.defaultValues.Add(item.Key, item.Value); } } private IEnumerator Motd() { yield return (object)new WaitForSeconds(1.5f); InputAction menu = MonoSingleton<JukeboxInputs>.Instance.Menu; string text = GeneralExtensions.Join<InputBinding>((IEnumerable<InputBinding>)(object)menu.bindings, (Func<InputBinding, string>)((InputBinding binding) => InputExtensions.GetBindingDisplayStringWithoutOverride(menu, binding, (DisplayStringOptions)0)), ", "); MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Jukebox menu is available by pressing <color=orange>" + text + "</color>", "", "", 0, false, false, true); motdShown = true; } } internal static class PluginInfo { public const string GUID = "dev.flazhik.jukebox"; public const string NAME = "Jukebox"; public const string VERSION = "2.0.7"; } [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("Jukebox.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] Jukebox => (byte[])ResourceManager.GetObject("Jukebox", resourceCulture); internal Resources() { } } } namespace Jukebox.Utils { public static class CompositeSongsUtils { private static readonly List<string> SpecialPostfixes = new List<string> { "intro", "loop", "calm", "calmloop", "calmintro" }; public static JukeboxSongMetadata.CompositeProperties GetSongComponents(string guid, SoundtrackSong song) { return new JukeboxSongMetadata.CompositeProperties.Builder().GotIntroAndLoop((Object)(object)song.introClip != (Object)null).GotCalmIntro(val: false).GotCalmLoop(MonoSingleton<JukeboxManager>.Instance.calmThemes.FindCalmClipsFor(guid) != null) .Build; } public static JukeboxSongMetadata.CompositeProperties GetSongComponents(FileInfo fileInfo) { JukeboxSongMetadata.CompositeProperties.Builder builder = new JukeboxSongMetadata.CompositeProperties.Builder(); List<FileInfo> source = (from file in fileInfo.Directory?.GetFiles() where WithoutPostfix(file).Name.Equals(fileInfo.Name) select file).Select(delegate(FileInfo file) { if (HasSpecialPostfix(file, "calmintro")) { builder.GotCalmIntro(val: true); } if (HasSpecialPostfix(file, "calmloop")) { builder.GotCalmLoop(val: true); } if (HasSpecialPostfix(file, "calm")) { builder.GotCalmTheme(val: true); } return file; }).ToList() ?? new List<FileInfo>(); if (source.Any((FileInfo file) => HasSpecialPostfix(file, "intro")) && source.Any((FileInfo file) => HasSpecialPostfix(file, "loop"))) { builder.GotIntroAndLoop(val: true); } return builder.Build; } public static FileInfo WithPostfix(FileInfo path, string postfix) { return new FileInfo(Path.GetDirectoryName(path.FullName) + "\\" + Path.GetFileNameWithoutExtension(path.FullName) + "_" + postfix + path.Extension); } public static FileInfo WithoutPostfix(FileInfo path) { if (HasAnySpecialPostfix(path)) { return new FileInfo(Regex.Replace(path.FullName, "_[a-zA-Z]+\\.[a-zA-Z0-9]+$", path.Extension)); } return path; } public static bool HasValidExtenstion(FileInfo path) { return CustomMusicFileBrowser.extensionTypeDict.Keys.Any((string extension) => path.Extension.ToLower().Equals(extension)); } private static bool HasAnySpecialPostfix(FileInfo path) { return SpecialPostfixes.Any((string postfix) => HasSpecialPostfix(path, postfix)); } private static bool HasSpecialPostfix(FileInfo path, string postfix) { return Path.GetFileNameWithoutExtension(path.Name).EndsWith("_" + postfix); } } public class GenericUtils { public static string FirstNonEmpty(params string[] options) { return options.FirstOrDefault((string option) => !string.IsNullOrEmpty(option)); } } public static class FloatExtensions { public static string SecondsToHumanReadable(this float value) { int num = (int)value; int num2 = num / 60; int num3 = num - num2 * 60; return $"{num2:00}:{num3:00}"; } } public static class IntExtensions { public static int Mod(this int num, int mod) { return (num % mod + mod) % mod; } } public abstract class ReflectionUtils { private const BindingFlags PrivateFields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static object GetPrivate<T>(T instance, Type classType, string field) { return classType.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(instance); } public static void SetPrivate<T, TV>(T instance, Type classType, string field, TV value) { classType.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetField).SetValue(instance, value); } public static IEnumerable<CodeInstruction> IL(params (OpCode, object)[] instructions) { return ((IEnumerable<(OpCode, object)>)instructions).Select((Func<(OpCode, object), CodeInstruction>)(((OpCode, object) i) => new CodeInstruction(i.Item1, i.Item2))).ToList(); } } public static class ScrollingTextUnscaled { public static IEnumerator ShowText(TMP_Text text, string message, float secondsBetweenLetters = 0.005f, AudioSource clickAudio = null) { int currentLetter = 0; text.text = ""; while (currentLetter < message.Length) { int num; if (message[currentLetter] == '<') { while (message[currentLetter] != '>' && currentLetter <= message.Length) { num = currentLetter + 1; currentLetter = num; } } else if (currentLetter < message.Length - 1) { while (currentLetter < message.Length - 1 && message[currentLetter + 1] == ' ') { num = currentLetter + 1; currentLetter = num; } } num = currentLetter + 1; currentLetter = num; text.text = message.Substring(0, currentLetter); if ((Object)(object)clickAudio != (Object)null && message[currentLetter - 1] != '\n' && message[currentLetter - 1] != ' ') { clickAudio.Play(); } yield return (object)new WaitForSecondsRealtime(secondsBetweenLetters); } } public static IEnumerator HideText(TMP_Text text, float secondsBetweenLetters = 0.005f) { int currentLetter = text.text.Length - 1; string message = text.text; while (currentLetter >= 0) { int num; if (text.text[currentLetter] == '>') { while (text.text[currentLetter] != '<' && currentLetter >= 0) { num = currentLetter - 1; currentLetter = num; } } num = currentLetter - 1; currentLetter = num; text.text = message.Substring(0, currentLetter + 1); yield return (object)new WaitForSecondsRealtime(secondsBetweenLetters); } } } public static class StringExtensions { } } namespace Jukebox.UI { public class JukeboxCredits : MonoBehaviour { [SerializeField] private TMP_Text terminalText; [SerializeField] private AudioSource click; [SerializeField] private GameObject firstWindow; [SerializeField] private GameObject secondWindow; [SerializeField] private List<GameObject> lastWindows; private string originalText; private void Awake() { originalText = terminalText.text; } private void OnEnable() { firstWindow.SetActive(false); secondWindow.SetActive(false); foreach (GameObject lastWindow in lastWindows) { lastWindow.SetActive(false); } ((MonoBehaviour)this).StartCoroutine(ScrollingTextUnscaled.ShowText(terminalText, originalText, 0.01f, click)); ((MonoBehaviour)this).StartCoroutine(WindowsRoutine()); } private IEnumerator WindowsRoutine() { yield return (object)new WaitForSecondsRealtime(1f); firstWindow.SetActive(true); yield return (object)new WaitForSecondsRealtime(1f); secondWindow.SetActive(true); yield return (object)new WaitForSecondsRealtime(2f); foreach (GameObject lastWindow in lastWindows) { lastWindow.SetActive(true); } } } public class JukeboxCustomContentButton : CustomContentButton { [SerializeField] public GameObject introAndLoopIcon; [SerializeField] public GameObject calmThemeIcon; } public class JukeboxUI : MonoBehaviour { [SerializeField] public GameObject jukeboxMenuTemplate; [SerializeField] public GameObject playbackMenuTemplate; [SerializeField] public GameObject nowPlayingHudTemplate; [SerializeField] public GameObject nowPlayingHudClassicTemplate; private GameObject jukeboxMenu; private GameObject playbackMenu; private GameObject nowPlayingHud; private GameObject nowPlayingHudClassic; private ReadOnlyCollection<JukeboxWindow> windows; protected void Awake() { InstantiateUI(); windows = new ReadOnlyCollection<JukeboxWindow>(new List<JukeboxWindow> { jukeboxMenu.GetComponent<JukeboxWindow>(), playbackMenu.GetComponent<JukeboxPlaybackWindow>() }); foreach (JukeboxWindow window in windows) { ((Component)window).gameObject.SetActive(false); } } protected void Update() { ManageWindows(); } private void ManageWindows() { if (GameIsPaused()) { return; } if (MonoSingleton<InputManager>.Instance.InputSource.Pause.WasPerformedThisFrame) { foreach (JukeboxWindow window in windows) { if (window.IsOpened()) { window.Close(); } } return; } JukeboxWindow jukeboxWindow = windows.FirstOrDefault((JukeboxWindow w) => w.hotkey.ToInputAction().WasPerformedThisFrame()); if ((Object)(object)jukeboxWindow != (Object)null) { foreach (JukeboxWindow window2 in windows) { if (InputExtensions.IsActionEqual(window2.hotkey.ToInputAction(), jukeboxWindow.hotkey.ToInputAction(), (string)null)) { window2.Toggle(); } else { window2.Close(); } } } if (!windows.Any((JukeboxWindow w) => GameStateManager.Instance.IsStateActive(w.StateKey())) && MonoSingleton<OptionsManager>.Instance.paused) { MonoSingleton<JukeboxPauseManager>.Instance.UnPause(); } } private void InstantiateUI() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) GameObject val = new GameObject { name = "JukeboxCanvas" }; val.AddComponent<Canvas>(); GameObject val2 = GameObject.Find("/Canvas"); Canvas component = val.GetComponent<Canvas>(); component.renderMode = (RenderMode)1; component.sortingOrder = val2.GetComponent<Canvas>().sortingOrder + 1; val.AddComponent<CanvasScaler>(); val.AddComponent<GraphicRaycaster>(); jukeboxMenu = Object.Instantiate<GameObject>(jukeboxMenuTemplate, val2.transform); playbackMenu = Object.Instantiate<GameObject>(playbackMenuTemplate, val2.transform); nowPlayingHud = Object.Instantiate<GameObject>(nowPlayingHudTemplate, GameObject.Find("/Player/Main Camera/HUD Camera/HUD/GunCanvas").transform, false); nowPlayingHudClassic = Object.Instantiate<GameObject>(nowPlayingHudClassicTemplate, val2.transform.Find("Crosshair Filler"), false); } private bool GameIsPaused() { return GameStateManager.Instance.IsStateActive("pause"); } } public class ScrollUIImageUnscaled : MonoBehaviour { private RawImage img; public float xSpeed; public float ySpeed; private void Start() { img = ((Component)this).GetComponent<RawImage>(); } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) Rect uvRect = img.uvRect; Vector2 val = ((Rect)(ref uvRect)).position + new Vector2(xSpeed, ySpeed) * Time.unscaledDeltaTime; while ((double)val.x > 1.0) { val.x -= 1f; } while ((double)val.x < -1.0) { val.x += 1f; } while ((double)val.y > 1.0) { val.y -= 1f; } while ((double)val.y < -1.0) { val.y += 1f; } RawImage obj = img; uvRect = img.uvRect; Vector2 val2 = ((Rect)(ref uvRect)).position + new Vector2(xSpeed, ySpeed) * Time.unscaledDeltaTime; uvRect = img.uvRect; obj.uvRect = new Rect(val2, ((Rect)(ref uvRect)).size); } } } namespace Jukebox.UI.Windows { public class JukeboxMenuWindow : JukeboxWindow { [SerializeField] protected Button[] buttons; [SerializeField] protected GameObject activeBgObject; public override string StateKey() { return "jukeboxMenu"; } protected override void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown base.Awake(); Button[] array = buttons; foreach (Button button in array) { ((UnityEvent)button.onClick).AddListener((UnityAction)delegate { //IL_0046: Unknown result type (might be due to invalid IL or missing references) activeBgObject.transform.SetParent(((Component)button).transform); activeBgObject.transform.SetSiblingIndex(0); activeBgObject.transform.localPosition = Vector3.zero; }); } } } public class JukeboxPlaybackWindow : JukeboxWindow { public override string StateKey() { return "jukeboxPlayback"; } } public abstract class JukeboxWindow : MonoBehaviour { [SerializeField] public InputActionReference hotkey; public abstract string StateKey(); public void Open() { ((Component)this).gameObject.SetActive(true); MonoSingleton<JukeboxPauseManager>.Instance.Pause(StateKey(), ((Component)this).gameObject); } public void Close() { GameStateManager.Instance.PopState(StateKey()); ((Component)this).gameObject.SetActive(false); } public void Toggle() { if (IsOpened()) { Close(); } else { Open(); } } protected virtual void Awake() { if ((Object)(object)hotkey != (Object)null) { hotkey = InputActionReference.Create(MonoSingleton<InputManager>.Instance.InputSource.Actions.asset.FindAction(hotkey.ToInputAction().id)); } } public bool IsOpened() { return ((Component)this).gameObject.activeSelf; } } } namespace Jukebox.UI.Themes { public class ThemeSettingsMenu : MonoBehaviour { [SerializeField] private Counter threshold; [SerializeField] private GameObject enemyTemplate; [SerializeField] private List<AssetReferenceT<SpawnableObject>> enemies; private void Awake() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) JukeboxThemesManager themesManager = MonoSingleton<JukeboxThemesManager>.Instance; threshold.SetDefaultValue(MonoSingleton<PrefsManager>.Instance.GetIntLocal("jukebox.calmThemeEnemiesThreshold", 0)); threshold.OnChanged += OnThresholdChanged; foreach (AssetReferenceT<SpawnableObject> enemy2 in enemies) { AsyncOperationHandle<SpawnableObject> val = enemy2.LoadAssetAsync(); SpawnableObject enemy = val.WaitForCompletion(); Addressables.Release<SpawnableObject>(val); GameObject val2 = Object.Instantiate<GameObject>(enemyTemplate, enemyTemplate.transform.parent); Sprite gridIcon = enemy.gridIcon; ((Component)val2.transform.Find("Icon")).GetComponentInChildren<Image>().sprite = gridIcon; ((Component)val2.transform.Find("Title")).GetComponentInChildren<TMP_Text>().text = enemy.objectName; Counter counter = val2.GetComponentInChildren<Counter>(); Toggle toggle = val2.GetComponentInChildren<Toggle>(); int? thresholdFor = themesManager.GetThresholdFor(enemy.enemyType); if (!thresholdFor.HasValue) { toggle.isOn = false; counter.SetDefaultValue(0); } else { counter.SetDefaultValue(thresholdFor.Value); } counter.OnChanged += delegate(int value) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) toggle.isOn = true; themesManager.SetThresholdFor(enemy.enemyType, value); }; ((UnityEvent<bool>)(object)toggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool on) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (on) { themesManager.SetThresholdFor(enemy.enemyType, counter.Value); } else { themesManager.DisableThresholdFor(enemy.enemyType); } }); val2.SetActive(true); } } private void OnDestroy() { threshold.OnChanged -= OnThresholdChanged; } private static void OnThresholdChanged(int value) { MonoSingleton<PrefsManager>.Instance.SetIntLocal("jukebox.calmThemeEnemiesThreshold", value); } } } namespace Jukebox.UI.SongPanel { public class ClassicSongPanel : SongPanel { protected override SongPanelStyle Style => SongPanelStyle.Classic; protected override IEnumerator FadeIn(JukeboxSongMetadata metadata) { float time = 0f; while ((double)time < (double)panelApproachTime) { time += Time.unscaledDeltaTime; panelGroup.alpha = (active ? (time / panelApproachTime) : 0f); yield return null; } panelGroup.alpha = (active ? 1 : 0); } protected override IEnumerator Await() { float time = panelStayTime; while ((double)time > 0.0 || showIndefinitely) { panelGroup.alpha = (active ? 1 : 0); if ((double)time > 0.0) { time -= Time.unscaledDeltaTime; } yield return null; } } protected override IEnumerator FadeOut() { float time = panelApproachTime; while ((double)time > 0.0) { time -= Time.unscaledDeltaTime; panelGroup.alpha = (active ? (time / panelApproachTime) : 0f); yield return null; } panelGroup.alpha = 0f; } } public class JukeboxSongPanel : SongPanel { [SerializeField] public Vector2 startDimensions; [SerializeField] public Vector2 targetDimensions; private Coroutine rollingTextRoutine; protected override SongPanelStyle Style => SongPanelStyle.Jukebox; protected override IEnumerator FadeIn(JukeboxSongMetadata metadata) { ((Graphic)base.text).color = new Color(1f, 1f, 1f, 1f); RectTransform rect = ((Component)panelGroup).GetComponent<RectTransform>(); rect.sizeDelta = startDimensions; string text = ((!string.IsNullOrEmpty(metadata.Artist)) ? ("<color=#999>" + metadata.Artist + "</color>") : string.Empty); if (rollingTextRoutine != null) { ((MonoBehaviour)this).StopCoroutine(rollingTextRoutine); } base.text.text = string.Empty; rollingTextRoutine = ((MonoBehaviour)this).StartCoroutine(ScrollingTextUnscaled.ShowText(base.text, metadata.Title.ToUpper() + " " + text, 0.022f)); float time = 0f; while (time < panelApproachTime) { panelGroup.alpha = (active ? 1 : 0); time += Time.unscaledDeltaTime; if (time > panelApproachTime) { time = panelApproachTime; } rect.sizeDelta = startDimensions + (targetDimensions - startDimensions) * time / panelApproachTime; yield return null; } } protected override IEnumerator Await() { float time = panelStayTime; while ((double)time > 0.0 || showIndefinitely) { panelGroup.alpha = (active ? 1 : 0); if ((double)time > 0.0) { time -= Time.unscaledDeltaTime; } yield return null; } } protected override IEnumerator FadeOut() { rollingTextRoutine = ((MonoBehaviour)this).StartCoroutine(ScrollingTextUnscaled.HideText(text, 0.022f)); RectTransform rect = ((Component)panelGroup).GetComponent<RectTransform>(); float time = panelApproachTime; yield return (object)new WaitUntil((Func<bool>)(() => text.text.Length <= 20)); while ((double)time > 0.0) { panelGroup.alpha = (active ? 1 : 0); time -= Time.unscaledDeltaTime; if (time < 0f) { time = 0f; } rect.sizeDelta = startDimensions + (targetDimensions - startDimensions) * time / panelApproachTime; yield return null; } panelGroup.alpha = 0f; } } public class PlaylistSelectable : DirectoryTreeBrowser<JukeboxSong> { [SerializeField] public GameObject selectPlaylistPanel; [SerializeField] public string playlistName; [SerializeField] public Button button; [SerializeField] public GameObject empty; protected override int maxPageLength => 6; protected override IDirectoryTree<JukeboxSong> baseDirectory { get { JukeboxPlaylist jukeboxPlaylist; using (StreamReader streamReader = new StreamReader(System.IO.File.Open(JukeboxPlaylist.PathForPlaylist(playlistName), FileMode.OpenOrCreate))) { jukeboxPlaylist = JsonConvert.DeserializeObject<JukeboxPlaylist>(streamReader.ReadToEnd()); } List<SongIdentifier> source = ((jukeboxPlaylist != null) ? ((Playlist)jukeboxPlaylist).ids : new List<SongIdentifier>()); return (IDirectoryTree<JukeboxSong>)(object)new FakeDirectoryTree<JukeboxSong>("Songs", from id in source where (int)id.type != 1 || new FileInfo(id.path).Exists select MonoSingleton<JukeboxSongsLoader>.Instance.Load(id), (IEnumerable<IDirectoryTree<JukeboxSong>>)null, (IDirectoryTree<JukeboxSong>)null); } } private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown ((UnityEvent)button.onClick).AddListener((UnityAction)delegate { MonoSingleton<PrefsManager>.Instance.SetStringLocal("jukebox.currentPlaylist", playlistName); MonoSingleton<JukeboxManager>.Instance.playlistEditor.ReloadPlaylist(); selectPlaylistPanel.SetActive(false); }); } private void OnEnable() { base.currentDirectory = ((DirectoryTreeBrowser<JukeboxSong>)this).baseDirectory; ((DirectoryTreeBrowser<JukeboxSong>)this).Rebuild(true); } protected override Action BuildLeaf(JukeboxSong item, int indexInPage) { GameObject go = Object.Instantiate<GameObject>(base.itemButtonTemplate, base.itemButtonTemplate.transform.parent); go.SetActive(true); go.GetComponent<Image>().sprite = item.Metadata.Icon; return delegate { Object.Destroy((Object)(object)go); }; } public override void Rebuild(bool setToPageZero = true) { base.Rebuild(setToPageZero); Transform itemParent = base.itemParent; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((itemParent is RectTransform) ? itemParent : null)); empty.SetActive(!base.currentDirectory.files.Any()); } } public abstract class SongPanel : MonoBehaviour { [SerializeField] public CanvasGroup panelGroup; [SerializeField] public Sprite defaultIcon; [SerializeField] public float panelApproachTime; [SerializeField] public float panelStayTime; public TMP_Text text; public Image icon; protected bool showIndefinitely; protected bool active; private Coroutine displayRoutine; protected abstract SongPanelStyle Style { get; } protected abstract IEnumerator FadeIn(JukeboxSongMetadata metadata); protected abstract IEnumerator Await(); protected abstract IEnumerator FadeOut(); public void Awake() { PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Combine(PrefsManager.onPrefChanged, new Action<string, object>(OnPrefChanged)); JukeboxMusicPlayer.onNextSong = (Action<JukeboxSong>)Delegate.Combine(JukeboxMusicPlayer.onNextSong, new Action<JukeboxSong>(OnNextSong)); JukeboxMusicPlayer.onStop = (Action)Delegate.Combine(JukeboxMusicPlayer.onStop, new Action(OnStop)); showIndefinitely = MonoSingleton<PrefsManager>.Instance.GetBoolLocal("jukebox.showTrackPanelIndefinitely", false); active = MonoSingleton<PrefsManager>.Instance.GetIntLocal("jukebox.songPanelStyle", 0) == (int)Style; } public void OnDestroy() { PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Remove(PrefsManager.onPrefChanged, new Action<string, object>(OnPrefChanged)); JukeboxMusicPlayer.onNextSong = (Action<JukeboxSong>)Delegate.Remove(JukeboxMusicPlayer.onNextSong, new Action<JukeboxSong>(OnNextSong)); JukeboxMusicPlayer.onStop = (Action)Delegate.Remove(JukeboxMusicPlayer.onStop, new Action(OnStop)); } private IEnumerator ShowPanelRoutine(JukeboxSongMetadata metadata) { string text = ((!string.IsNullOrEmpty(metadata.Artist)) ? ("<color=#999>" + metadata.Artist + "</color>") : string.Empty); this.text.text = metadata.Title.ToUpper() + " " + text; icon.sprite = (((Object)(object)metadata.Icon != (Object)null) ? metadata.Icon : defaultIcon); yield return FadeIn(metadata); yield return Await(); yield return FadeOut(); } private void OnNextSong(JukeboxSong song) { active = MonoSingleton<PrefsManager>.Instance.GetIntLocal("jukebox.songPanelStyle", 0) == (int)Style; if (displayRoutine != null) { ((MonoBehaviour)this).StopCoroutine(displayRoutine); } displayRoutine = ((MonoBehaviour)this).StartCoroutine(ShowPanelRoutine(song.Metadata)); } private void OnStop() { active = false; } private void OnPrefChanged(string key, object value) { if (key.Equals("jukebox.showTrackPanelIndefinitely")) { showIndefinitely = (bool)value; } if (key.Equals("jukebox.songPanelStyle")) { active = (int)value == (int)Style; } } } public class SongPanelOption : MonoBehaviour { private static readonly Color Active = new Color(0.68f, 0.68f, 0.68f, 0.25f); private static readonly Color Inactive = new Color(0f, 0f, 0f, 0.59f); public SongPanelStyle style; private void Start() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) ((Graphic)((Component)this).gameObject.GetComponent<Image>()).color = ((MonoSingleton<PrefsManager>.Instance.GetIntLocal("jukebox.songPanelStyle", 0) == (int)style) ? Active : Inactive); } public void Select() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Button[] componentsInChildren = ((Component)((Component)this).transform.parent).GetComponentsInChildren<Button>(); foreach (Button val in componentsInChildren) { ((Graphic)((Component)val).gameObject.GetComponent<Image>()).color = (((Object)(object)val == (Object)(object)((Component)this).gameObject.GetComponent<Button>()) ? Active : Inactive); } MonoSingleton<PrefsManager>.Instance.SetIntLocal("jukebox.songPanelStyle", (int)style); } } public enum SongPanelStyle { Jukebox, Classic } } namespace Jukebox.UI.Elements { public class Counter : MonoBehaviour { [SerializeField] private TextMeshProUGUI textValue; [SerializeField] private CounterButton increase; [SerializeField] private CounterButton decrease; [SerializeField] private int minValue; [SerializeField] private int maxValue; private int tmpValue; private IEnumerator changeValueRoutine; public int Value { get; set; } public event Action<int> OnChanged; public void Awake() { AddEvents(increase, delegate { tmpValue = ChangeValue((int i) => i + 1); }); AddEvents(decrease, delegate { tmpValue = ChangeValue((int i) => i - 1); }); } public void SetDefaultValue(int defaultValue) { Value = defaultValue; tmpValue = defaultValue; ((TMP_Text)textValue).text = defaultValue.ToString(); } private void AddEvents(CounterButton button, Action<int> callback) { button.OnDown += delegate { changeValueRoutine = ChangeValueRoutine(callback); ((MonoBehaviour)this).StartCoroutine(changeValueRoutine); }; button.OnUp += SaveValue; button.OnExit += SaveValue; } private void SaveValue() { if (changeValueRoutine != null) { ((MonoBehaviour)this).StopCoroutine(changeValueRoutine); } Value = tmpValue; ((TMP_Text)textValue).text = Value.ToString(); this.OnChanged?.Invoke(Value); } private IEnumerator ChangeValueRoutine(Action<int> callback) { callback(tmpValue); yield return (object)new WaitForSecondsRealtime(0.3f); while (true) { callback(tmpValue); yield return (object)new WaitForSecondsRealtime(0.1f); } } private int ChangeValue(Func<int, int> operation) { int result = ValidateOperation(operation); ((TMP_Text)textValue).text = result.ToString(); return result; } private int ValidateOperation(Func<int, int> operation) { int num = operation(tmpValue); if (num >= minValue && num <= maxValue) { return num; } return tmpValue; } } public class CounterButton : Button { public bool pressed; public event Action OnDown; public event Action OnUp; public event Action OnExit; public override void OnPointerDown(PointerEventData eventData) { pressed = true; ((Selectable)this).OnPointerDown(eventData); this.OnDown?.Invoke(); } public override void OnPointerUp(PointerEventData eventData) { pressed = false; ((Selectable)this).OnPointerUp(eventData); this.OnUp?.Invoke(); } public override void OnPointerExit(PointerEventData eventData) { ((Selectable)this).OnPointerExit(eventData); if (pressed) { this.OnExit?.Invoke(); } pressed = false; } } } namespace Jukebox.UI.Effects { public class SoundEffectButton : MonoBehaviour { [SerializeField] private string prefsKey; [SerializeField] private TMP_Text title; [SerializeField] private TMP_Text fileNameText; [SerializeField] private TMP_Text browserWindowTitle; protected void Awake() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown ChangeFileName(MonoSingleton<PrefsManager>.Instance.GetStringLocal(prefsKey, (string)null)); PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Combine(PrefsManager.onPrefChanged, new Action<string, object>(OnPrefChanged)); ((UnityEvent)((Component)this).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { browserWindowTitle.text = "Select file for " + title.text; }); } protected void OnDestroy() { PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Remove(PrefsManager.onPrefChanged, new Action<string, object>(OnPrefChanged)); } private void OnPrefChanged(string key, object value) { if (key.Equals(prefsKey)) { ChangeFileName((string)value); } } private void ChangeFileName(string fileName) { fileNameText.text = ((fileName != null) ? new FileInfo(fileName).Name : "Default"); } } } namespace Jukebox.UI.Decorators { public class ControlBindDecorator : MonoBehaviour { [SerializeField] public InputActionReference action; protected void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) InputAction val = MonoSingleton<InputManager>.Instance.InputSource.Actions.asset.FindAction(action.ToInputAction().id); ((Component)this).GetComponentInChildren<ControlsOptionsKey>().RebuildBindings(val, MonoSingleton<InputManager>.Instance.InputSource.Actions.KeyboardMouseScheme); } } public abstract class UIDecorator<T> : MonoBehaviour where T : MonoBehaviour { [SerializeField] public GameObject hint; protected GameObject control; protected abstract GameObject Template(); protected abstract void Init(); public void Start() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) control = Object.Instantiate<GameObject>(Template(), ((Component)this).transform); control.transform.position = ((Component)this).transform.position; Object.Destroy((Object)(object)hint); Init(); Object.Destroy((Object)(object)((Component)this).GetComponent<T>()); } } public class SliderDecorator : UIDecorator<SliderDecorator> { [AddressableAsset("Assets/Prefabs/UI/Settings/Elements/Slider Button.prefab", typeof(GameObject))] private static GameObject sliderTemplate; [SerializeField] public float minValue; [SerializeField] public float maxValue; [SerializeField] public SliderValueToTextConfig sliderConfig; protected override GameObject Template() { return sliderTemplate; } protected override void Init() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) Slider componentInChildren = ((Component)this).GetComponentInChildren<Slider>(); componentInChildren.minValue = minValue; componentInChildren.maxValue = maxValue; ((SliderValueToText)ReflectionUtils.GetPrivate<SettingsSlider>(((Component)this).GetComponentInChildren<SettingsSlider>(), typeof(SettingsSlider), "sliderValueToText")).ConfigureFrom(sliderConfig); } } } namespace Jukebox.Patches { [HarmonyPatch(typeof(AudioMixerController))] public static class AudioMixerControllerPatch { [HarmonyPostfix] [HarmonyPatch(typeof(AudioMixerController), "Update")] public static void AudioMixerController_Update_Postfix(AudioMixerController __instance) { if (!((Object)(object)MonoSingleton<JukeboxManager>.Instance == (Object)null)) { __instance.musicSound.SetFloat("allVolume", __instance.CalculateVolume(__instance.musicVolume) + MonoSingleton<JukeboxManager>.Instance.player.VolumeBoost); } } } [HarmonyPatch(typeof(DiscordController))] public static class DiscordControllerPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UpdateActivityHandler <>9__0_0; internal void <DiscordController_UpdateWave_Prefix>b__0_0(Result _) { } } [HarmonyPrefix] [HarmonyPatch(typeof(DiscordController), "UpdateWave")] public static bool DiscordController_UpdateWave_Prefix(int wave) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown if (JukeboxMusicPlayer.CurrentSong == null || !MonoSingleton<PrefsManager>.Instance.GetBoolLocal("jukebox.discordAndSteamIntegration", false)) { return true; } if ((Object)(object)DiscordController.Instance == (Object)null) { return false; } bool num = (bool)ReflectionUtils.GetPrivate<DiscordController>(DiscordController.Instance, typeof(DiscordController), "disabled"); Activity val = (Activity)ReflectionUtils.GetPrivate<DiscordController>(DiscordController.Instance, typeof(DiscordController), "cachedActivity"); ActivityManager val2 = (ActivityManager)ReflectionUtils.GetPrivate<DiscordController>(DiscordController.Instance, typeof(DiscordController), "activityManager"); Discord val3 = (Discord)ReflectionUtils.GetPrivate<DiscordController>(DiscordController.Instance, typeof(DiscordController), "discord"); if (num) { return false; } val.Details = $"WAVE: {wave} | \ud83c\udfb5 {JukeboxMusicPlayer.CurrentSong.ArtistAndTrack}"; ReflectionUtils.SetPrivate<DiscordController, Activity>(DiscordController.Instance, typeof(DiscordController), "cachedActivity", val); if (val3 == null || val2 == null) { return false; } Activity val4 = val; object obj = <>c.<>9__0_0; if (obj == null) { UpdateActivityHandler val5 = delegate { }; <>c.<>9__0_0 = val5; obj = (object)val5; } val2.UpdateActivity(val4, (UpdateActivityHandler)obj); return false; } } [HarmonyPatch(typeof(FinalCyberRank))] public static class FinalCyberRankPatch { [HarmonyPrefix] [HarmonyPatch(typeof(FinalCyberRank), "GameOver")] public static bool FinalCyberRank_GameOver_Prefix() { if ((Object)(object)MonoSingleton<JukeboxManager>.Instance.player != (Object)null) { MonoSingleton<JukeboxManager>.Instance.player.Stop(); } return true; } } [HarmonyPatch(typeof(InputActions))] public static class InputActionsPatch { [HarmonyPostfix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] public static void InputActions_Constructor_Postfix(InputActions __instance) { if (__instance.asset.FindActionMap("Jukebox", false) == null) { MergeInputActionAssets(__instance); } } private static void MergeInputActionAssets(InputActions ukInputActions) { if (Resources.FindObjectsOfTypeAll(typeof(InputActionAsset)).Length == 0) { Debug.LogError((object)"Couldn't load InputActionAsset"); return; } string text = "{\r\n \"maps\": [\r\n {\r\n \"name\": \"Jukebox\",\r\n \"id\": \"9dda5277-7734-4ec3-ad76-c8c0e5763d02\",\r\n \"actions\": [\r\n {\r\n \"name\": \"Next Track\",\r\n \"type\": \"Button\",\r\n \"id\": \"09c701ba-74bc-4818-80a7-d1049e88ed97\",\r\n \"expectedControlType\": \"Button\",\r\n \"processors\": \"\",\r\n \"interactions\": \"\",\r\n \"initialStateCheck\": false\r\n },\r\n {\r\n \"name\": \"Jukebox Menu\",\r\n \"type\": \"Button\",\r\n \"id\": \"2031a43b-3913-4384-a334-02669e72c30d\",\r\n \"expectedControlType\": \"Button\",\r\n \"processors\": \"\",\r\n \"interactions\": \"\",\r\n \"initialStateCheck\": false\r\n },\r\n {\r\n \"name\": \"Disable Player\",\r\n \"type\": \"Button\",\r\n \"id\": \"3675ceba-90d0-46f5-b634-d6c13d208ff6\",\r\n \"expectedControlType\": \"Button\",\r\n \"processors\": \"\",\r\n \"interactions\": \"\",\r\n \"initialStateCheck\": false\r\n },\r\n {\r\n \"name\": \"Playback Menu\",\r\n \"type\": \"Button\",\r\n \"id\": \"fa8430f8-91e7-454b-91f7-8b0147642ef9\",\r\n \"expectedControlType\": \"Button\",\r\n \"processors\": \"\",\r\n \"interactions\": \"\",\r\n \"initialStateCheck\": false\r\n }\r\n ],\r\n \"bindings\": [\r\n {\r\n \"name\": \"\",\r\n \"id\": \"8ec3310e-3f25-46a8-9a97-347d624fb616\",\r\n \"path\": \"<Keyboard>/f3\",\r\n \"interactions\": \"\",\r\n \"processors\": \"\",\r\n \"groups\": \"Keyboard & Mouse\",\r\n \"action\": \"Next Track\",\r\n \"isComposite\": false,\r\n \"isPartOfComposite\": false\r\n },\r\n {\r\n \"name\": \"\",\r\n \"id\": \"b6df442f-c08f-4187-940a-9b684fa729c5\",\r\n \"path\": \"<Keyboard>/f4\",\r\n \"interactions\": \"\",\r\n \"processors\": \"\",\r\n \"groups\": \"Keyboard & Mouse\",\r\n \"action\": \"Jukebox Menu\",\r\n \"isComposite\": false,\r\n \"isPartOfComposite\": false\r\n },\r\n {\r\n \"name\": \"\",\r\n \"id\": \"48676d48-feb2-406e-bc66-91f1aa7b11f1\",\r\n \"path\": \"<Keyboard>/backquote\",\r\n \"interactions\": \"\",\r\n \"processors\": \"\",\r\n \"groups\": \"Keyboard & Mouse\",\r\n \"action\": \"Playback Menu\",\r\n \"isComposite\": false,\r\n \"isPartOfComposite\": false\r\n },\r\n {\r\n \"name\": \"\",\r\n \"id\": \"b86c9dc7-c6a1-4490-8aaa-bcb7dc1aa3cd\",\r\n \"path\": \"<Keyboard>/f10\",\r\n \"interactions\": \"\",\r\n \"processors\": \"\",\r\n \"groups\": \"Keyboard & Mouse\",\r\n \"action\": \"Disable Player\",\r\n \"isComposite\": false,\r\n \"isPartOfComposite\": false\r\n }\r\n ]\r\n }\r\n ]\r\n }"; InputActionSetupExtensions.AddActionMap(ukInputActions.asset, InputActionMap.FromJson(text)[0]); } } [HarmonyPatch(typeof(InputManager))] public static class InputManagerPatch { [HarmonyPrefix] [HarmonyPatch(typeof(InputManager), "Rebind")] public static bool InputManager_Rebind_Prefix(InputManager __instance, InputAction action, int? existingIndex, Action onComplete, Action onCancel, InputControlScheme scheme) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (action.actionMap.name != "Jukebox") { return true; } __instance.WaitForButton((Action<string>)delegate(string path) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if (path == "<Mouse>/leftButton") { onComplete?.Invoke(); } else if (((IEnumerable<InputBinding>)(object)action.bindings).Any((InputBinding binding) => InputSystem.FindControl(((InputBinding)(ref binding)).path) == InputSystem.FindControl(path))) { onComplete?.Invoke(); } else { BindingSyntax val = ((!existingIndex.HasValue) ? InputActionSetupExtensions.AddBinding(action, default(InputBinding)) : InputActionSetupExtensions.ChangeBinding(action, existingIndex.GetValueOrDefault())); val = ((BindingSyntax)(ref val)).WithPath(path); ((BindingSyntax)(ref val)).WithGroup(((InputControlScheme)(ref scheme)).bindingGroup); __instance.actionModified?.Invoke(action); if (onComplete != null) { onComplete(); } } }, (Action)delegate { onCancel?.Invoke(); }, ((IEnumerable<DeviceRequirement>)(object)((InputControlScheme)(ref scheme)).deviceRequirements).Select((DeviceRequirement requirement) => ((DeviceRequirement)(ref requirement)).controlPath).ToList()); return false; } } [HarmonyPatch(typeof(ScreenZone))] public static class ScreenZonePatch { private static PreviewHelper helper; private static ScreenZone cgTerminal; [HarmonyPostfix] [HarmonyPatch(typeof(ScreenZone), "Awake")] public static void ScreenZone_Awake_Postfix(ScreenZone __instance) { if (!(((Object)__instance).name != "Cybergrind Shop")) { PreviewHelper previewHelper = default(PreviewHelper); if (!((Component)__instance).TryGetComponent<PreviewHelper>(ref previewHelper)) { ((Component)__instance).gameObject.AddComponent<PreviewHelper>(); } cgTerminal = __instance; } } [HarmonyPrefix] [HarmonyPatch(typeof(ScreenZone), "Update")] public static bool ScreenZone_Update_Prefix(bool ___inZone, ScreenZone __instance) { if ((Object)(object)cgTerminal != (Object)(object)__instance) { return true; } if ((Object)(object)helper == (Object)null) { PreviewHelper previewHelper = default(PreviewHelper); if (!((Component)__instance).TryGetComponent<PreviewHelper>(ref previewHelper)) { return true; } helper = previewHelper; } helper.inZone = ___inZone; return true; } } [HarmonyPatch(typeof(SteamController))] public static class SteamControllerPatch { [HarmonyPrefix] [HarmonyPatch(typeof(SteamController), "UpdateWave")] public static bool SteamController_UpdateWave_Prefix(int wave) { if (JukeboxMusicPlayer.CurrentSong == null || !MonoSingleton<PrefsManager>.Instance.GetBoolLocal("jukebox.discordAndSteamIntegration", false)) { return true; } if (!SteamClient.IsValid) { return false; } SteamFriends.SetRichPresence("wave", $"WAVE: {wave} | \ud83c\udfb5 {JukeboxMusicPlayer.CurrentSong.ArtistAndTrack}"); return false; } } } namespace Jukebox.Input { [ConfigureSingleton(/*Could not decode attribute arguments.*/)] public class JukeboxInputs : MonoSingleton<JukeboxInputs> { private InputActionMap jukeboxActionMap; public InputAction Menu { get; private set; } public InputAction Playback { get; private set; } public InputAction NextTrack { get; private set; } public InputAction DisablePlayer { get; private set; } protected void Awake() { base.Awake(); jukeboxActionMap = MonoSingleton<InputManager>.Instance.InputSource.Actions.asset.FindActionMap("Jukebox", false); Menu = jukeboxActionMap.FindAction("Jukebox Menu", false); Playback = jukeboxActionMap.FindAction("Playback Menu", false); NextTrack = jukeboxActionMap.FindAction("Next Track", false); DisablePlayer = jukeboxActionMap.FindAction("Disable Player", false); ResetM1Bindings(); } private void ResetM1Bindings() { ResetLeftClick(Menu, "<Keyboard>/f4"); ResetLeftClick(Playback, "<Keyboard>/backquote"); ResetLeftClick(NextTrack, "<Keyboard>/f3"); ResetLeftClick(DisablePlayer, "<Keyboard>/f10"); } private void ResetLeftClick(InputAction binding, string defaultBinding) { //IL_0001: 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) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (((IEnumerable<InputBinding>)(object)binding.bindings).Any((InputBinding b) => ((InputBinding)(ref b)).path == "<Mouse>/leftButton")) { BindingSyntax val = InputActionSetupExtensions.ChangeBinding(binding, InputActionRebindingExtensions.GetBindingIndex(Menu, (string)null, (string)null)); val = ((BindingSyntax)(ref val)).WithPath(defaultBinding); ((BindingSyntax)(ref val)).WithGroup("Keyboard & Mouse"); } } } } namespace Jukebox.Core.Themes { [CreateAssetMenu(menuName = "Jukebox/Calm theme")] public class CalmThemeEntry : ScriptableObject { [SerializeField] public AssetReferenceSoundtrackSong reference; [SerializeField] public List<AssetReferenceT<AudioClip>> calmVariationClips; } [CreateAssetMenu(menuName = "Jukebox/Calm Themes Data")] public class SoundtrackCalmThemes : ScriptableObject { [SerializeField] public CalmThemeEntry[] calmClips; public List<AssetReferenceT<AudioClip>> FindCalmClipsFor(string guid) { CalmThemeEntry calmThemeEntry = MonoSingleton<JukeboxManager>.Instance.calmThemes.calmClips.FirstOrDefault((CalmThemeEntry variation) => ((AssetReference)variation.reference).AssetGUID == guid); if (!((Object)(object)calmThemeEntry != (Object)null)) { return null; } return calmThemeEntry.calmVariationClips; } } } namespace Jukebox.Core.Model.Themes { [JsonObject(/*Could not decode attribute arguments.*/)] public class JukeboxThemesConfig { public class CalmThemeConfig { [JsonProperty(/*Could not decode attribute arguments.*/)] public Dictionary<EnemyType, int> SpecialEnemies = new Dictionary<EnemyType, int> { { (EnemyType)19, 1 }, { (EnemyType)5, 1 }, { (EnemyType)26, 1 }, { (EnemyType)2, 1 }, { (EnemyType)7, 2 } }; } [JsonProperty("calmThemeConfig")] public CalmThemeConfig CalmTheme = new CalmThemeConfig(); } } namespace Jukebox.Core.Model.Song { public sealed class JukeboxCustomSong : JukeboxSong { [ExternalAsset("Assets/Jukebox/Textures/music_note.png", typeof(Sprite))] private static Sprite defaultIcon; private readonly List<UnityWebRequest> requests = new List<UnityWebRequest>(); private List<DownloadHandlerAudioClip> handles; protected override Lazy<JukeboxSongMetadata> GetMetadata => new Lazy<JukeboxSongMetadata>(delegate { JukeboxSongMetadata jukeboxSongMetadata = JukeboxSongMetadata.From(new FileInfo(base.Id.path)); if ((Object)(object)jukeboxSongMetadata.Icon == (Object)null) { jukeboxSongMetadata.Icon = defaultIcon; } return jukeboxSongMetadata; }); private JukeboxCustomSong(string path) : base(new SongIdentifier(path, (IdentifierType)1)) { }//IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown ~JukeboxCustomSong() { requests.ForEach(delegate(UnityWebRequest request) { request.Dispose(); }); } public static JukeboxCustomSong Create(string path) { return new JukeboxCustomSong(path); } protected override IEnumerator AcquireInternal(IEnumerator callback) { handles = new List<DownloadHandlerAudioClip>(); if (base.Metadata.Composite.GotIntroAndLoop) { yield return Download(CompositeSongsUtils.WithPostfix(new FileInfo(base.Id.path), "intro"), delegate(AudioClip c) { base.IntroClip = c; }); } yield return Download(base.Metadata.Composite.GotIntroAndLoop ? CompositeSongsUtils.WithPostfix(new FileInfo(base.Id.path), "loop") : new FileInfo(base.Id.path), delegate(AudioClip c) { base.Clips = new List<AudioClip> { c }; }); if (base.Metadata.Composite.GotCalmIntro) { yield return Download(CompositeSongsUtils.WithPostfix(new FileInfo(base.Id.path), "calmintro"), delegate(AudioClip c) { base.CalmIntroClip = c; }); } if (base.Metadata.Composite.GotCalmTheme) { yield return Download(CompositeSongsUtils.WithPostfix(new FileInfo(base.Id.path), "calm"), delegate(AudioClip c) { base.CalmClips = new List<AudioClip> { c }; }); } if (base.Metadata.Composite.GotCalmLoop) { yield return Download(CompositeSongsUtils.WithPostfix(new FileInfo(base.Id.path), "calmloop"), delegate(AudioClip c) { base.CalmClips = new List<AudioClip> { c }; }); } yield return callback; IEnumerator Download(FileSystemInfo path, Action<AudioClip> downloadCallback) { UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(new Uri(path.FullName).AbsoluteUri, CustomMusicFileBrowser.extensionTypeDict[path.Extension.ToLower()]); requests.Add(audioClip); DownloadHandler downloadHandler = audioClip.downloadHandler; DownloadHandlerAudioClip handle = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null); handles.Add(handle); if (handle != null) { handle.streamAudio = true; audioClip.SendWebRequest(); yield return audioClip; downloadCallback(handle.audioClip); } } } protected override void DisposeInternal() { DisposeOfRequests(); DisposeOfHandlers(); handles = null; DestroyClipIfPresent(base.IntroClip); foreach (AudioClip clip in base.Clips) { DestroyClipIfPresent(clip); } } private void DisposeOfRequests() { requests.ForEach(delegate(UnityWebRequest request) { request.Dispose(); }); } private void DisposeOfHandlers() { handles.ForEach(delegate(DownloadHandlerAudioClip request) { ((DownloadHandler)request).Dispose(); }); } private static void DestroyClipIfPresent(AudioClip clip) { if ((Object)(object)clip != (Object)null) { Object.Destroy((Object)(object)clip); } } } public class JukeboxPlaylist : Playlist { public static string currentPath => Path.Combine(Playlist.directory.FullName, MonoSingleton<PrefsManager>.Instance.GetStringLocal("jukebox.currentPlaylist", (string)null) + ".json"); public JukeboxPlaylist() { } public JukeboxPlaylist(IEnumerable<SongIdentifier> passedIds) : base(MonoSingleton<PrefsManager>.Instance.GetBoolLocal("jukebox.preventDuplicateTracks", false) ? passedIds.Distinct() : passedIds) { } public static string PathForPlaylist(string name) { return Path.Combine(Playlist.directory.FullName, name + ".json"); } public void Add(SongIdentifier id) { if (!MonoSingleton<PrefsManager>.Instance.GetBoolLocal("jukebox.preventDuplicateTracks", false) || !((Playlist)this).ids.Contains(id)) { ((Playlist)this).Add(id); } } public void RemoveDuplicates() { List<SongIdentifier> list = ((Playlist)this).ids.Distinct().ToList(); ((Playlist)this).ids.Clear(); foreach (SongIdentifier item in list) { Add(item); } } public void RemoveNonExisting() { List<SongIdentifier> list = ((Playlist)this).ids.Where((SongIdentifier id) => (int)id.type == 0 || new FileInfo(id.path).Exists).ToList(); ((Playlist)this).ids.Clear(); foreach (SongIdentifier item in list) { Add(item); } } } public abstract class JukeboxSong { private readonly Lazy<JukeboxSongMetadata> lazyMetadata; public SongIdentifier Id { get; } public JukeboxSongMetadata Metadata => lazyMetadata.Value; public AudioClip IntroClip { get; protected set; } public AudioClip CalmIntroClip { get; protected set; } public List<AudioClip> Clips { get; protected set; } public List<AudioClip> CalmClips { get; protected set; } public int MaxClipsIfNotRepeating { get; protected set; } public bool IsCustom => (int)Id.type == 1; public string ArtistAndTrack { get { if (Metadata.Artist == null) { return Metadata.Title; } return Metadata.Artist + " — " + Metadata.Title; } } protected abstract Lazy<JukeboxSongMetadata> GetMetadata { get; } protected JukeboxSong(SongIdentifier id) { Id = id; lazyMetadata = GetMetadata; } public IEnumerator Acquire(IEnumerator callback) { yield return AcquireInternal(callback); Dispose(); } private void Dispose() { DisposeInternal(); IntroClip = null; CalmIntroClip = null; Clips = null; CalmClips = null; MaxClipsIfNotRepeating = -1; } protected abstract IEnumerator AcquireInternal(IEnumerator callback); protected abstract void DisposeInternal(); } public static class JukeboxSongFactory { public static JukeboxSong Create(SongIdentifier id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 IdentifierType type = id.type; if ((int)type != 0) { if ((int)type == 1) { return JukeboxCustomSong.Create(id.path); } throw new ArgumentOutOfRangeException(); } return JukeboxSoundtrackSong.Create(id.path); } } public class JukeboxSongMetadata { public class CompositeProperties { public class Builder { public CompositeProperties Build { get; } public Builder() { Build = new CompositeProperties(); } public Builder GotIntroAndLoop(bool val) { Build.GotIntroAndLoop = val; return this; } public Builder GotCalmIntro(bool val) { Build.GotCalmIntro = val; return this; } public Builder GotCalmTheme(bool val) { Build.GotCalmTheme = val; return this; } public Builder GotCalmLoop(bool val) { Build.GotCalmLoop = val; return this; } } public bool GotIntroAndLoop { get; private set; } public bool GotCalmIntro { get; private set; } public bool GotCalmTheme { get; private set; } public bool GotCalmLoop { get; private set; } private CompositeProperties() { } } public readonly CompositeProperties Composite; public Sprite Icon { get; set; } public string Title { get; } public string Artist { get; } private JukeboxSongMetadata(Sprite icon, string title, CompositeProperties composite, string artist = null) { Icon = icon; Title = title; Composite = composite; Artist = artist; } public static JukeboxSongMetadata From(FileInfo srcFile) { CompositeProperties songComponents = CompositeSongsUtils.GetSongComponents(srcFile); FileInfo fileInfo = (songComponents.GotIntroAndLoop ? CompositeSongsUtils.WithPostfix(srcFile, "intro") : srcFile); try { TagLib.Tag tag = TagLib.File.Create(fileInfo.FullName).Tag; return new JukeboxSongMetadata(LoadCover(tag), (!string.IsNullOrEmpty(tag.Title)) ? tag.Title : Path.GetFileNameWithoutExtension(srcFile.Name), songComponents, GenericUtils.FirstNonEmpty(tag.FirstPerformer, tag.FirstComposer, tag.FirstAlbumArtist)); } catch (Exception) { return new JukeboxSongMetadata(null, fileInfo.Name, songComponents); } } public static JukeboxSongMetadata From(AssetReferenceSoundtrackSong reference) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<SoundtrackSong> val = ((AssetReferenceT<SoundtrackSong>)(object)reference).LoadAssetAsync(); val.WaitForCompletion(); SoundtrackSong result = val.Result; return new JukeboxSongMetadata(result.icon, result.songName, CompositeSongsUtils.GetSongComponents(((AssetReference)reference).AssetGUID, result), result.extraLevelBit); } private static Sprite LoadCover(TagLib.Tag tag) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (tag.Pictures.Length == 0) { return null; } using MemoryStream memoryStream = new MemoryStream(tag.Pictures[0].Data.Data); try { memoryStream.Seek(0L, SeekOrigin.Begin); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, memoryStream.ToArray()); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } catch (Exception) { return null; } } } public sealed class JukeboxSoundtrackSong : JukeboxSong { private AsyncOperationHandle<SoundtrackSong> handle; private readonly List<AsyncOperationHandle<AudioClip>> calmClipsHandles = new List<AsyncOperationHandle<AudioClip>>(); protected override Lazy<JukeboxSongMetadata> GetMetadata => new Lazy<JukeboxSongMetadata>(() => JukeboxSongMetadata.From(new AssetReferenceSoundtrackSong(base.Id.path))); private JukeboxSoundtrackSong(string path) : base(new SongIdentifier(path, (IdentifierType)0)) { }//IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown public static JukeboxSoundtrackSong Create(string path) { return new JukeboxSoundtrackSong(path); } protected override IEnumerator AcquireInternal(IEnumerator callback) { handle = Addressables.LoadAssetAsync<SoundtrackSong>((object)base.Id.path); yield return handle; SoundtrackSong addressable = handle.Result; base.IntroClip = addressable.introClip; base.Clips = addressable.clips; List<AssetReferenceT<AudioClip>> list = MonoSingleton<JukeboxManager>.Instance.calmThemes.FindCalmClipsFor(base.Id.path); if (list != null) { base.CalmClips = new List<AudioClip>(); foreach (AsyncOperationHandle<AudioClip> calmClipHandle in list.Select((AssetReferenceT<AudioClip> clip) => Addressables.LoadAssetAsync<AudioClip>((object)((AssetReference)clip).AssetGUID))) { calmClipsHandles.Add(calmClipHandle); yield return calmClipHandle; base.CalmClips.Add(calmClipHandle.Result); } } base.MaxClipsIfNotRepeating = addressable.maxClipsIfNotRepeating; yield return callback; } protected override void DisposeInternal() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) Addressables.Release<SoundtrackSong>(handle); foreach (AsyncOperationHandle<AudioClip> calmClipsHandle in calmClipsHandles) { Addressables.Release<AudioClip>(calmClipsHandle); } calmClipsHandles.Clear(); handle = default(AsyncOperationHandle<SoundtrackSong>); } } } namespace Jukebox.Core.Collections { public class JukeboxFileTree : IDirectoryTree<JukeboxSong>, IDirectoryTree { public string name { get; private set; } public IDirectoryTree<JukeboxSong> parent { get; set; } public IEnumerable<IDirectoryTree<JukeboxSong>> children { get; private set; } public IEnumerable<JukeboxSong> files { get; private set; } private DirectoryInfo RealDirectory { get; } public JukeboxFileTree(string path, IDirectoryTree<JukeboxSong> parent = null) { RealDirectory = new DirectoryInfo(path); this.parent = parent; Refresh(); } private JukeboxFileTree(DirectoryInfo realDirectory, IDirectoryTree<JukeboxSong> parent = null) { RealDirectory = realDirectory; this.parent = parent; Refresh(); } public void Refresh() { RealDirectory.Create(); name = RealDirectory.Name; children = from dir in RealDirectory.GetDirectories() select new JukeboxFileTree(dir, this); files = (from file in RealDirectory.GetFiles().Where(CompositeSongsUtils.HasValidExtenstion) group file by CompositeSongsUtils.WithoutPostfix(file).FullName into @group select MonoSingleton<JukeboxSongsLoader>.Instance.Load(new SongIdentifier(@group.Key, (IdentifierType)1))).ToList(); } public override bool Equals(object obj) { if (obj != null && !(GetType() != obj.GetType())) { return string.Equals(RealDirectory.FullName, (obj as DirectoryInfo)?.FullName, StringComparison.InvariantCultureIgnoreCase); } return false; } public override int GetHashCode() { return RealDirectory.GetHashCode(); } public IEnumerable<JukeboxSong> GetFilesRecursive() { return children.SelectMany((IDirectoryTree<JukeboxSong> child) => child.GetFilesRecursive()).Concat(files); } } } namespace Jukebox.Components { public class CybergrindEffectsChanger : MonoBehaviour { private const string TerminalPath = "/FirstRoom/Room/Cybergrind Shop/Music"; private CrowdReactions crowdReactions; private PrefsManager prefsManager; private AudioClip awwDefault; private AudioClip cheerDefault; private AudioClip cheerLongDefault; private AudioClip terminalMusicDefault; private AudioClip gameOverDefault; private static AudioSource EndMusicAudioSource { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).GetRootGameObjects().First((GameObject o) => ((Object)o).name == "EndMusic").GetComponent<AudioSource>(); } } private static AudioSource MenuMusicAudioSource => GameObject.Find("/FirstRoom/Room/Cybergrind Shop/Music").GetComponent<AudioSource>(); private void Awake() { crowdReactions = MonoSingleton<CrowdReactions>.Instance; prefsManager = MonoSingleton<PrefsManager>.Instance; awwDefault = Object.Instantiate<AudioClip>(crowdReactions.aww, ((Component)this).gameObject.transform); cheerDefault = Object.Instantiate<AudioClip>(crowdReactions.cheer, ((Component)this).gameObject.transform); cheerLongDefault = Object.Instantiate<AudioClip>(crowdReactions.cheerLong, ((Component)this).gameObject.transform); terminalMusicDefault = Object.Instantiate<AudioClip>(MenuMusicAudioSource.clip, ((Component)this).gameObject.transform); gameOverDefault = Object.Instantiate<AudioClip>(EndMusicAudioSource.clip, ((Component)this).gameObject.transform); ((MonoBehaviour)this).StartCoroutine(Setup()); PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Combine(PrefsManager.onPrefChanged, new Action<string, object>(OnPrefChanged)); } private void OnDestroy() { PrefsManager.onPrefChanged = (Action<string, object>)Delegate.Remove(PrefsManager.onPrefChanged, new Action<string, object>(OnPrefChanged)); } private IEnumerator Setup() { yield return PrepareParrySfx(); yield return PrepareWaveCompleteSfx(); yield return PrepareAwwSfx(); yield return PrepareGameOverSfx(); yield return PrepareTerminalMusic(); } private IEnumerator PrepareParrySfx() { yield return PrepareClip(prefsManager.GetStringLocal("jukebox.effects.parry", (string)null), delegate(AudioClip clip) { crowdReactions.cheer = clip; }, cheerDefault); } private IEnumerator PrepareWaveCompleteSfx() { yield return PrepareClip(prefsManager.GetStringLocal("jukebox.effects.wavecomplete", (string)null), delegate(AudioClip clip) { crowdReactions.cheerLong = clip; }, cheerLongDefault); } private IEnumerator PrepareAwwSfx() { yield return PrepareClip(prefsManager.GetStringLocal("jukebox.effects.aww", (string)null), delegate(AudioClip clip) { crowdReactions.aww = clip; }, awwDefault); } private IEnumerator PrepareGameOverSfx() { yield return PrepareClip(prefsManager.GetStringLocal("jukebox.effects.gameover", (string)null), delegate(AudioClip clip) { EndMusicAudioSource.clip = clip; }, gameOverDefault); } private IEnumerator PrepareTerminalMusic() { AudioSource terminalMusic = MenuMusicAudioSource; yield return PrepareClip(prefsManager.GetStringLocal("jukebox.effects.terminal-music", (string)null), delegate(AudioClip clip) { terminalMusic.Stop(); terminalMusic.volume = 1f; terminalMusic.clip = clip; terminalMusic.Play(); }, terminalMusicDefault); } private IEnumerator PrepareClip(string path, Action<AudioClip> callback, AudioClip fallback) { if (path != null) { yield return Download(new FileInfo(path), callback); } else { callback(fallback); } } private IEnumerator Download(FileSystemInfo path, Action<AudioClip> callback) { DownloadHandlerAudioClip handler = new DownloadHandlerAudioClip(new Uri(path.FullName).AbsoluteUri, CustomMusicFileBrowser.extensionTypeDict[path.Extension.ToLower()]); UnityWebRequest wr = new UnityWebRequest(new Uri(path.FullName).AbsoluteUri, "GET", (DownloadHandler)(object)handler, (UploadHandler)null); try { yield return wr.SendWebRequest(); if (wr.responseCode == 200) { callback(handler.audioClip); } } finally { ((IDisposable)wr)?.Dispose(); } } private void OnPrefChanged(string key, object value) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) switch (key) { case "jukebox.effects.wavecomplete": ((MonoBehaviour)this).StartCoroutine(PrepareWaveCompleteSfx()); break; case "jukebox.effects.aww": ((MonoBehaviour)this).StartCoroutine(PrepareAwwSfx()); break; case "jukebox.effects.gameover": ((MonoBehaviour)this).StartCoroutine(PrepareGameOverSfx()); break; case "jukebox.effects.terminal-music": ((MonoBehaviour)this).StartCoroutine(PrepareTerminalMusic()); break; case "jukebox.effects.parry": ((AudioSource)ReflectionUtils.GetPrivate<CrowdReactions>(crowdReactions, typeof(CrowdReactions), "aud")).Stop(); ((MonoBehaviour)this).StartCoroutine(PrepareParrySfx()); break; } } } public class JukeboxEffectsBrowser : DirectoryTreeBrowser<FileInfo> { private static readonly DirectoryInfo EffectsDirectory = new DirectoryInfo(Path.Combine(Directory.GetParent(Application.dataPath).FullName, "Cybergrind", "Effects")); [SerializeField] private JukeboxTerminalPanel navigator; [SerializeField] private GameObject effectsMenu; private string currentPrefKey; protected override int maxPageLength => 3; protected override IDirectoryTree<FileInfo> baseDirectory => (IDirectoryTree<FileInfo>)new FileDirectoryTree(EffectsDirectory, (IDirectoryTree<FileInfo>)null); public void NextPage() { base.SetPage((base.currentPage != base.maxPages - 1) ? (base.currentPage + 1) : 0); } public void PreviousPage() { base.SetPage((base.currentPage == 0) ? (base.maxPages - 1) : (base.currentPage - 1)); } public void SetCurrentPrefKey(string key) { currentPrefKey = key; } public void ResetToDefault() { MonoSingleton<PrefsManager>.Instance.SetStringLocal(currentPrefKey, (string)null); } protected override Action BuildLeaf(FileInfo item, int indexInPage) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown GameObject go = Object.Instantiate<GameObject>(base.itemButtonTemplate, base.itemParent); CustomContentButton component = go.GetComponent<CustomContentButton>(); component.text.text = item.Name; go.SetActive(true); ((UnityEvent)component.button.onClick).AddListener((UnityAction)delegate { MonoSingleton<PrefsManager>.Instance.SetStringLocal(currentPrefKey, item.FullName); navigator.GoToNoMenu(effectsMenu); }); return delegate { Object.Destroy((Object)(object)go); }; } public void OpenEffectsFolder() { Application.OpenURL(new Uri(EffectsDirectory.FullName).AbsoluteUri); } public override void Rebuild(bool setToPageZero = true) { Transform itemParent = base.itemParent; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((itemParent is RectTransform) ? itemParent : null)); base.Rebuild(setToPageZero); } } public class JukeboxMusicChanger : MonoBehaviour { private enum ThemeVariation { Battle, Calm } private const int FadeSpeed = 1; public AudioSource clean; public AudioSource battle; private JukeboxThemesManager themesManager; private Coroutine updateRoutine; private ThemeVariation currentTheme; private static bool CalmThemesAllowed => MonoSingleton<PrefsManager>.Instance.GetBoolLocal("jukebox.enableCalmThemes", false); public void Awake() { themesManager = MonoSingleton<JukeboxThemesManager>.Instance; } private void Update() { if (!((Object)(object)clean.clip == (Object)null)) { if (currentTheme == ThemeVariation.Calm) { clean.volume = Mathf.MoveTowards(clean.volume, 1f, 1f * Time.deltaTime); battle.volume = Mathf.MoveTowards(battle.volume, 0f, 1f * Time.deltaTime); } else { clean.volume = Mathf.MoveTowards(clean.volume, 0f, 1f * Time.deltaTime); battle.volume = Mathf.MoveTowards(battle.volume, 1f, 1f * Time.deltaTime); } } } public void ChangeTo(AudioClip battleTheme, AudioClip calmTheme) { if (updateRoutine != null) { ((MonoBehaviour)this).StopCoroutine(updateRoutine); } battle.time = 0f; clean.time = 0f; clean.clip = calmTheme; battle.clip = battleTheme; battle.Play(); battle.volume = 1f; if ((Object)(object)clean.clip != (Object)null) { clean.Play(); if (CalmThemesAllowed && themesManager.FewEnemies) { clean.volume = 1f; battle.volume = 0f; } } updateRoutine = ((MonoBehaviour)this).StartCoroutine(SlowUpdate()); } private IEnumerator SlowUpdate() { while (true) { if (CalmThemesAllowed && themesManager.FewEnemies) { PlayCalmTheme(); } else { PlayBattleTheme(); } yield return (object)new WaitForSecondsRealtime(0.1f); } } private void PlayBattleTheme() { if (currentTheme != 0) { currentTheme = ThemeVariation.Battle; if ((Object)(object)clean.clip != (Object)null) { battle.timeSamples = clean.timeSamples; } } } private void PlayCalmTheme() { if (currentTheme != ThemeVariation.Calm) { currentTheme = ThemeVariation.Calm; if ((Object)(object)clean.clip != (Object)null) { clean.timeSamples = battle.timeSamples; } } } } public class JukeboxThemesManager : MonoSingleton<JukeboxThemesManager> { private static readonly string PreferencesPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, "Preferences", "JukeboxThemes.json"); private PrefsManager prefsManager; private EnemyTracker enemyTracker; private JukeboxThemesConfig preferences = new JukeboxThemesConfig(); private bool isDirty; public bool FewEnemies { get { if (EnemiesAlive <= CalmThemeThreshold) { return SpecialEnemiesThresholdReached(); } return false; } } private int CalmThemeThreshold => prefsManager.GetIntLocal("jukebox.calmThemeEnemiesThreshold", 0); private int EnemiesAlive => enemyTracker.enemies.Count((EnemyIdentifier enemy) => !enemy.dead); protected override void Awake() { base.Awake(); prefsManager = MonoSingleton<PrefsManager>.Instance; enemyTracker = MonoSingleton<EnemyTracker>.Instance; LoadPreferences(); ((MonoBehaviour)this).InvokeRepeating("SlowUpdate", 0f, 3f); } private void SlowUpdate() { if (isDirty) { SavePreferences(); isDirty = false; } } protected override void OnDestroy() { SavePreferences(); isDirty = false; base.OnDestroy(); } public int? GetThresholdFor(EnemyType type) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!preferences.CalmTheme.SpecialEnemies.ContainsKey(type)) { return null; } return preferences.CalmTheme.SpecialEnemies[type]; } public void SetThresholdFor(EnemyType type, int value) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) preferences.CalmTheme.SpecialEnemies[type] = value; isDirty = true; } public void DisableThresholdFor(EnemyType type) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (preferences.CalmTheme.SpecialEnemies.ContainsKey(type)) { preferences.CalmTheme.SpecialEnemies.Remove(type); isDirty = true; } } private bool SpecialEnemiesThresholdReached() { return (from enemy in enemyTracker.enemies where !enemy.dead select enemy.enemyType into type group type by type).All((IGrouping<EnemyType, EnemyType> group) => !preferences.CalmTheme.SpecialEnemies.ContainsKey(group.Key) || preferences.CalmTheme.SpecialEnemies[group.Key] >= group.Count()); } private void LoadPreferences() { JukeboxThemesConfig jukeboxThemesConfig; using (StreamReader streamReader = new StreamReader(System.IO.File.Open(PreferencesPath, FileMode.OpenOrCreate))) { jukeboxThemesConfig = JsonConvert.DeserializeObject<JukeboxThemesConfig>(streamReader.ReadToEnd()); } if (jukeboxThemesConfig?.CalmTheme == null) { SavePreferences(); } else { preferences = jukeboxThemesConfig; } } private void SavePreferences() { System.IO.File.WriteAllText(PreferencesPath, JsonConvert.SerializeObject((object)preferences)); } } public class DeckShuffled<T> : IEnumerable<T>, IEnumerable { private List<T> current; public DeckShuffled(IEnumerable<T> target) { current = Randomize(target).ToList(); } public void Reshuffle() { if (current.Count > 1) { IEnumerable<T> source = current.Take(Mathf.FloorToInt((float)(current.Count / 2))); IEnumerable<T> source2 = current.Skip(Mathf.FloorToInt((float)(current.Count / 2))); current = Randomize(source).Concat(Randomize(source2)).ToList(); } } private static IEnumerable<T> Randomize(IEnumerable<T> source) { T[] arr = source.ToArray(); int i = arr.Length - 1; while (i > 0) { int swapIndex = Random.Range(0, i + 1); yield return arr[swapIndex]; arr[swapIndex] = arr[i]; int num = i - 1; i = num; } yield return arr[0]; } public IEnumerator<T> GetEnumerator() { return current.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return current.GetEnumerator(); } } public class JukeboxFileBrowser : DirectoryTreeBrowser<JukeboxSong> { private static readonly string MusicPath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, "CyberGrind", "Music"); [SerializeField] private JukeboxTerminalPanel navigator; [SerializeField] private JukeboxPlaylistEditor playlistEditorLogic; [SerializeField] private GameObject playlistEditor; [Header("Load all warning")] [SerializeField] private TMP_Text loadAllWarningText; [SerializeField] private GameObject yesAndNoButtons; [SerializeField] private GameObject imADumbassButton; protected override int maxPageLength => 4; protected override IDirectoryTree<JukeboxSong> baseDirectory => new JukeboxFileTree(MusicPath); public void NextPage() { base.SetPage((base.currentPage != base.maxPages - 1) ? (base.currentPage + 1) : 0); } public void PreviousPage() { base.SetPage((base.currentPage == 0) ? (base.maxPages - 1) : (base.currentPage - 1)); } public void LoadAllFromCurrentFolder() { foreach (JukeboxSong file in base.currentDirectory.files) { playlistEditorLogic.playlist.Add(file.Id); } ((DirectoryTreeBrowser<JukeboxSong>)playlistEditorLogic).Rebuild(true); } public void SetWarningText() { if (!base.currentDirectory.files.Any()) { yesAndNoButtons.SetActive(false); imADumbassButton.SetActive(true); loadAllWarningText.text = ((!base.currentDirectory.children.Any()) ? "Oh, I get it. \"Yes, I would like to add a whopping total of 0 songs\". Very funny." : "This folder contains no songs."); } else if (base.currentDirectory.files.Count() == 1) { loadAllWarningText.text = "It's a single song in there, but ok. Would you like me to add it?"; } else { loadAllWarningText.text = $"Do you want to add <color=green>{base.currentDirectory.files.Count()}</color> tracks " + "from the folder <color=yellow>" + base.currentDirectory.name + "</color> to your playlist?"; } } protected override Action BuildLeaf(JukeboxSong song, int indexInPage) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown GameObject go = Object.Instantiate<GameObject>(base.itemButtonTemplate, base.itemParent, false); JukeboxCustomContentButton component = go.GetComponent<JukeboxCustomContentButton>(); JukeboxSongMetadata metadata = song.Metadata; ((Un