Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BoomboxCartUpgrade v1.3.2
BoomBoxCartUpgradeMod.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.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BoomBoxCartMod.Patches; using BoomBoxCartMod.Util; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("BoomboxCartUpgrade")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BoomboxCartUpgrade")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("37e852e0-b511-4315-8182-68c0a54e1ba9")] [assembly: AssemblyFileVersion("1.3.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BoomBoxCartMod { public class Boombox : MonoBehaviourPunCallbacks { [Serializable] private class SharedBoomboxState { public int version; public string key; public bool isPlaying; public bool pendingPlaybackStart; public float absVolume; public bool loopQueue; public int currentSongIndex = -1; public int playbackStartTimestamp; public int playbackTime; public string[] queueTitles = Array.Empty<string>(); public string[] queueUrls = Array.Empty<string>(); public int[] queueStartTimes = Array.Empty<int>(); public SharedAudioEntry[] queue = Array.Empty<SharedAudioEntry>(); } [Serializable] private class SharedAudioEntry { public string title; public string url; public int startTime; } public class BoomboxData { public string key = Guid.NewGuid().ToString(); public AudioEntry currentSong = null; public List<AudioEntry> playbackQueue = new List<AudioEntry>(); public bool isPlaying = false; public float absVolume = 0.6f; public float personalVolumePercentage = 0.35f; public bool loopQueue = false; public bool underglowEnabled = false; public bool visualizerEnabled = true; public bool pendingPlaybackStart = false; public int stateVersion = 0; public int playbackTime = 0; public int playbackStartTimestamp = 0; } public class AudioEntry { public string Title; public string Url; public int StartTime = 0; public AudioEntry(string title, string url) { Title = title; Url = url; } public int PeekStartTime(Boombox boombox) { if (boombox.data != null && boombox.data.playbackTime != 0) { return boombox.data.playbackTime; } return StartTime; } public int UseStartTime(Boombox boombox) { int result = PeekStartTime(boombox); if (boombox.data != null && boombox.data.playbackTime != 0) { boombox.data.playbackTime = 0; } else if (Instance.UseTimeStampOnce.Value) { StartTime = 0; } return result; } public AudioClip GetAudioClip() { return DownloadHelper.downloadedClips.ContainsKey(Url) ? DownloadHelper.downloadedClips[Url] : null; } } private static BoomBoxCartMod Instance = BoomBoxCartMod.instance; public PhotonView photonView; public AudioSource audioSource; public Visualizer visualizer; public DownloadHelper downloadHelper = null; private bool syncFinished = false; public float minDistance = 3f; public float maxDistanceBase = 15f; public float maxDistanceAddition = 30f; public bool isAwaitingSyncPlayback = false; public bool startPlayBackOnDownload = true; public BoomboxData data = new BoomboxData(); private AudioLowPassFilter lowPassFilter; public static int qualityLevel = 4; private static bool mutePressed = false; private const string SharedStatePropertyPrefix = "boomboxState."; private bool isApplyingSharedState = false; private string lastSharedStateJson = null; private string pendingCurrentSongDownloadUrl = null; private int lastAppliedSharedStateVersion = -1; private float monsterAttractTimer = 0f; private float monsterAttractInterval = 1f; private static bool applyQualityToDownloads = false; private static bool monstersCanHearMusic = false; private static ManualLogSource Logger => Instance.logger; public static bool ApplyQualityToDownloads { get { return applyQualityToDownloads; } set { applyQualityToDownloads = value; } } public static bool MonstersCanHearMusic { get { return monstersCanHearMusic; } set { monstersCanHearMusic = value; } } public bool LoopQueue { get { return data.loopQueue; } set { data.loopQueue = value; } } private void Awake() { audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource.volume = 0.15f; audioSource.spatialBlend = 1f; audioSource.playOnAwake = false; audioSource.rolloffMode = (AudioRolloffMode)2; audioSource.spread = 90f; audioSource.dopplerLevel = 0f; audioSource.reverbZoneMix = 1f; audioSource.spatialize = true; audioSource.loop = false; audioSource.mute = Instance.baseListener.audioMuted; lowPassFilter = ((Component)this).gameObject.AddComponent<AudioLowPassFilter>(); ((Behaviour)lowPassFilter).enabled = false; downloadHelper = ((Component)this).gameObject.AddComponent<DownloadHelper>(); UpdateAudioRangeBasedOnVolume(audioSource.volume); photonView = ((Component)this).GetComponent<PhotonView>(); isAwaitingSyncPlayback = data.pendingPlaybackStart; if ((Object)(object)photonView == (Object)null) { Logger.LogError((object)"PhotonView not found on Boombox object."); return; } if ((Object)(object)((Component)this).GetComponent<BoomboxController>() == (Object)null) { ((Component)this).gameObject.AddComponent<BoomboxController>(); } if ((Object)(object)((Component)this).GetComponent<Visualizer>() == (Object)null) { visualizer = ((Component)this).gameObject.AddComponent<Visualizer>(); visualizer.audioSource = audioSource; } PersistentData.SetBoomboxViewInitialized(photonView.ViewID); Logger.LogInfo((object)$"Boombox initialized on this cart. AudioSource: {audioSource}, PhotonView: {photonView}"); } private void Start() { ApplyVisualStateFromData(); LoadSharedStateFromRoom(); } private void Update() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient && data.isPlaying && MonstersCanHearMusic && (Object)(object)EnemyDirector.instance != (Object)null) { monsterAttractTimer += Time.deltaTime; if (monsterAttractTimer >= monsterAttractInterval) { EnemyDirector.instance.SetInvestigate(((Component)this).transform.position, 5f, false); monsterAttractTimer = 0f; } } else { monsterAttractTimer = 0f; } if (Instance.baseListener.audioMuted != audioSource.mute) { audioSource.mute = Instance.baseListener.audioMuted; } bool flag = (Object)(object)audioSource.clip != (Object)null && audioSource.time >= Math.Max(0f, audioSource.clip.length - 0.05f); if (!(syncFinished && data.isPlaying && !audioSource.isPlaying && flag) || !PhotonNetwork.IsMasterClient) { return; } int currentSongIndex = GetCurrentSongIndex(); if (currentSongIndex == -1) { DismissQueueLocal(); } else if (currentSongIndex + 1 >= data.playbackQueue.Count) { if (LoopQueue && data.playbackQueue.Count > 0) { SelectSongIndex(0); return; } data.currentSong = null; data.isPlaying = false; SetPlaybackReferenceFromSeconds(0f); PublishSharedState(); } else { SelectSongIndex(currentSongIndex + 1); } } public void TogglePlaying(bool value) { data.isPlaying = value; } public static long GetCurrentTimeMilliseconds() { return PhotonNetwork.ServerTimestamp; } public long GetRelativePlaybackMilliseconds() { return GetCurrentTimeMilliseconds() - (long)Math.Round(GetTrackedPlaybackSeconds() * 1000f); } public static string GetSongTitle(string url) { if (DownloadHelper.songTitles.ContainsKey(url)) { return DownloadHelper.songTitles[url]; } return null; } public int GetCurrentSongIndex() { if (data.currentSong == null) { return -1; } return data.playbackQueue.IndexOf(data.currentSong); } private string GetSharedStatePropertyKey() { return "boomboxState." + photonView.ViewID; } private SharedBoomboxState CreateSharedState() { return new SharedBoomboxState { version = data.stateVersion, key = data.key, isPlaying = (data.currentSong != null && data.isPlaying), pendingPlaybackStart = (data.currentSong != null && data.pendingPlaybackStart), absVolume = data.absVolume, loopQueue = data.loopQueue, currentSongIndex = GetCurrentSongIndex(), playbackStartTimestamp = data.playbackStartTimestamp, playbackTime = data.playbackTime, queueTitles = data.playbackQueue.Select((AudioEntry entry) => entry.Title).ToArray(), queueUrls = data.playbackQueue.Select((AudioEntry entry) => entry.Url).ToArray(), queueStartTimes = data.playbackQueue.Select((AudioEntry entry) => entry.StartTime).ToArray(), queue = data.playbackQueue.Select((AudioEntry entry) => new SharedAudioEntry { title = entry.Title, url = entry.Url, startTime = entry.StartTime }).ToArray() }; } private List<AudioEntry> CreateQueueFromState(SharedBoomboxState state) { if (state.queueUrls != null && state.queueUrls.Length != 0) { List<AudioEntry> list = new List<AudioEntry>(state.queueUrls.Length); for (int i = 0; i < state.queueUrls.Length; i++) { string text = state.queueUrls[i]; string text2 = ((state.queueTitles != null && i < state.queueTitles.Length && !string.IsNullOrWhiteSpace(state.queueTitles[i])) ? state.queueTitles[i] : "Unknown Title"); int startTime = ((state.queueStartTimes != null && i < state.queueStartTimes.Length) ? state.queueStartTimes[i] : 0); if (!string.IsNullOrWhiteSpace(text) && !DownloadHelper.songTitles.ContainsKey(text)) { DownloadHelper.songTitles[text] = text2; } list.Add(new AudioEntry(text2, text) { StartTime = startTime }); } return list; } if (state.queue == null) { return new List<AudioEntry>(); } return state.queue.Select(delegate(SharedAudioEntry entry) { string text3 = (string.IsNullOrWhiteSpace(entry.title) ? "Unknown Title" : entry.title); string url = entry.url; if (!string.IsNullOrWhiteSpace(url) && !DownloadHelper.songTitles.ContainsKey(url)) { DownloadHelper.songTitles[url] = text3; } return new AudioEntry(text3, url) { StartTime = entry.startTime }; }).ToList(); } private void LoadSharedStateFromRoom() { if (PhotonNetwork.IsConnected && PhotonNetwork.CurrentRoom != null && !((Object)(object)photonView == (Object)null)) { if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)GetSharedStatePropertyKey(), out object value) && value is string text && !string.IsNullOrWhiteSpace(text)) { ApplySharedStateJson(text); } else if (PhotonNetwork.IsMasterClient) { PublishSharedState(force: true); } } } public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { ((MonoBehaviourPunCallbacks)this).OnRoomPropertiesUpdate(propertiesThatChanged); if (!((Object)(object)photonView == (Object)null) && propertiesThatChanged != null && ((Dictionary<object, object>)(object)propertiesThatChanged).TryGetValue((object)GetSharedStatePropertyKey(), out object value) && value is string text && !string.IsNullOrWhiteSpace(text)) { ApplySharedStateJson(text); } } private void ApplySharedStateJson(string json) { SharedBoomboxState sharedBoomboxState; try { sharedBoomboxState = JsonUtility.FromJson<SharedBoomboxState>(json); } catch (Exception ex) { ManualLogSource logger = Logger; PhotonView obj = photonView; logger.LogError((object)$"Failed to deserialize boombox state for cart {((obj != null) ? new int?(obj.ViewID) : null)}: {ex.Message}"); return; } if (sharedBoomboxState != null && sharedBoomboxState.version >= lastAppliedSharedStateVersion) { lastSharedStateJson = json; lastAppliedSharedStateVersion = sharedBoomboxState.version; ApplySharedState(sharedBoomboxState); } } private void ApplySharedState(SharedBoomboxState state) { int currentSongIndex = GetCurrentSongIndex(); string text = data.currentSong?.Url; isApplyingSharedState = true; try { data.key = (string.IsNullOrWhiteSpace(state.key) ? data.key : state.key); data.stateVersion = Math.Max(data.stateVersion, state.version); data.playbackQueue = CreateQueueFromState(state); data.absVolume = Mathf.Clamp01(state.absVolume); data.loopQueue = state.loopQueue; data.playbackTime = Math.Max(0, state.playbackTime); data.playbackStartTimestamp = state.playbackStartTimestamp; if (state.currentSongIndex >= 0 && state.currentSongIndex < data.playbackQueue.Count) { data.currentSong = data.playbackQueue[state.currentSongIndex]; } else { data.currentSong = null; } data.pendingPlaybackStart = data.currentSong != null && state.pendingPlaybackStart; data.isPlaying = data.currentSong != null && state.isPlaying; float volume = data.absVolume * data.personalVolumePercentage; audioSource.volume = volume; UpdateAudioRangeBasedOnVolume(volume); ApplyVisualStateFromData(); bool songChanged = currentSongIndex != state.currentSongIndex || text != data.currentSong?.Url; ApplySharedPlaybackState(songChanged); ((Component)this).GetComponent<BoomboxUI>()?.UpdateDataFromBoomBox(); UpdateStatusFromState(); syncFinished = true; } finally { isApplyingSharedState = false; } } private void ApplySharedPlaybackState(bool songChanged) { if (data.currentSong?.Url == null) { isAwaitingSyncPlayback = false; data.pendingPlaybackStart = false; StopLocalPlayback(updateSharedFlag: false); UpdateUIStatus("Ready to play music! Enter a Video URL"); return; } AudioClip audioClip = data.currentSong.GetAudioClip(); if ((Object)(object)audioClip == (Object)null) { StopLocalPlayback(updateSharedFlag: false); isAwaitingSyncPlayback = data.pendingPlaybackStart; startPlayBackOnDownload = data.pendingPlaybackStart; if (songChanged || data.pendingPlaybackStart) { UpdateUIStatus("Loading: " + data.currentSong.Title); } if (!data.pendingPlaybackStart) { EnsureCurrentSongDownloaded(); } return; } isAwaitingSyncPlayback = data.pendingPlaybackStart; if ((Object)(object)audioSource.clip != (Object)(object)audioClip) { audioSource.clip = audioClip; SetQuality(qualityLevel); UpdateAudioRangeBasedOnVolume(audioSource.volume); } SetPlaybackTime(data.playbackStartTimestamp); if (data.pendingPlaybackStart) { if (audioSource.isPlaying) { audioSource.Pause(); } UpdateUIStatus("Loading: " + data.currentSong.Title); } else if (data.isPlaying) { if (!audioSource.isPlaying) { audioSource.Play(); } UpdateUIStatus("Now playing: " + data.currentSong.Title); } else { if (audioSource.isPlaying) { audioSource.Pause(); } UpdateUIStatus("Ready to play: " + data.currentSong.Title); } } public void ApplyVisualStateFromData() { VisualEffects visualEffects = ((Component)this).GetComponent<VisualEffects>(); if ((Object)(object)visualEffects == (Object)null) { visualEffects = ((Component)this).gameObject.AddComponent<VisualEffects>(); } visualEffects.SetLights(data.underglowEnabled); Visualizer visualizer = ((Component)this).GetComponent<Visualizer>(); if (data.visualizerEnabled) { if ((Object)(object)visualizer == (Object)null) { visualizer = ((Component)this).gameObject.AddComponent<Visualizer>(); } visualizer.audioSource = audioSource; this.visualizer = visualizer; } else if ((Object)(object)visualizer != (Object)null) { Object.Destroy((Object)(object)visualizer); this.visualizer = null; } } private async void EnsureCurrentSongDownloaded() { string url = data.currentSong?.Url; if (string.IsNullOrWhiteSpace(url) || (Object)(object)downloadHelper == (Object)null || DownloadHelper.downloadedClips.ContainsKey(url) || pendingCurrentSongDownloadUrl == url) { return; } pendingCurrentSongDownloadUrl = url; try { await downloadHelper.StartAudioDownload(url); } finally { if (pendingCurrentSongDownloadUrl == url) { pendingCurrentSongDownloadUrl = null; } } if (!((Object)(object)this == (Object)null) && !(data.currentSong?.Url != url)) { ApplySharedPlaybackState(songChanged: false); } } private void UpdateStatusFromState() { if (data.currentSong == null) { UpdateUIStatus("Ready to play music! Enter a Video URL"); } else if (data.pendingPlaybackStart) { UpdateUIStatus("Loading: " + data.currentSong.Title); } else if (data.isPlaying) { UpdateUIStatus("Now playing: " + data.currentSong.Title); } else { UpdateUIStatus("Ready to play: " + data.currentSong.Title); } } public void PublishSharedState(bool force = false) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ad: Expected O, but got Unknown if (isApplyingSharedState || !PhotonNetwork.IsConnected || PhotonNetwork.CurrentRoom == null || (Object)(object)photonView == (Object)null) { return; } if (PhotonNetwork.IsMasterClient) { data.stateVersion++; } SharedBoomboxState sharedBoomboxState = CreateSharedState(); string text = JsonUtility.ToJson((object)sharedBoomboxState); if (!force && text == lastSharedStateJson) { if (PhotonNetwork.IsMasterClient) { data.stateVersion--; } return; } Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)GetSharedStatePropertyKey(), (object)text); Hashtable val2 = val; PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); lastSharedStateJson = text; syncFinished = true; if (PhotonNetwork.IsMasterClient) { lastAppliedSharedStateVersion = sharedBoomboxState.version; ApplySharedPlaybackState(songChanged: false); ((Component)this).GetComponent<BoomboxUI>()?.UpdateDataFromBoomBox(); UpdateStatusFromState(); } } private void StopLocalPlayback(bool updateSharedFlag) { if (audioSource.isPlaying) { audioSource.Stop(); } if (updateSharedFlag) { TogglePlaying(value: false); } audioSource.clip = null; } private void SetPlaybackReferenceFromSeconds(float seconds) { data.playbackStartTimestamp = (int)((double)GetCurrentTimeMilliseconds() - Math.Round(Math.Max(0f, seconds) * 1000f)); } private float GetTrackedPlaybackSeconds() { AudioSource obj = audioSource; if ((Object)(object)((obj != null) ? obj.clip : null) != (Object)null) { return audioSource.time; } return Math.Max(0f, (float)(GetCurrentTimeMilliseconds() - data.playbackStartTimestamp) / 1000f); } private void CleanupCurrentPlayback() { StopLocalPlayback(updateSharedFlag: true); } private bool ShouldRequestMasterMutation() { return PhotonNetwork.IsConnected && PhotonNetwork.CurrentRoom != null && !PhotonNetwork.IsMasterClient; } public void StartPlayBack() { AudioClip val = data.currentSong?.GetAudioClip(); if ((Object)(object)val == (Object)null) { Logger.LogError((object)"Clip not found for current song"); CleanupCurrentPlayback(); return; } if ((Object)(object)audioSource.clip != (Object)(object)val) { CleanupCurrentPlayback(); audioSource.clip = val; SetQuality(qualityLevel); UpdateAudioRangeBasedOnVolume(audioSource.volume); audioSource.Play(); } audioSource.Play(); TogglePlaying(value: true); } public void PausePlayBack() { audioSource.Pause(); TogglePlaying(value: false); } public void SetPlaybackTime(long startTimeMillis) { audioSource.time = Math.Max(0f, GetCurrentTimeMilliseconds() - startTimeMillis) / 1000f; } public void EnqueueSongLocal(string url, int seconds) { if (string.IsNullOrWhiteSpace(url)) { return; } if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestEnqueueSong", (RpcTarget)2, url, seconds, PhotonNetwork.LocalPlayer.ActorNumber); return; } string title = (DownloadHelper.songTitles.ContainsKey(url) ? DownloadHelper.songTitles[url] : "Unknown Title"); AudioEntry audioEntry = new AudioEntry(title, url) { StartTime = seconds }; data.playbackQueue.Add(audioEntry); if (data.currentSong == null) { data.currentSong = audioEntry; data.isPlaying = false; data.pendingPlaybackStart = true; isAwaitingSyncPlayback = PhotonNetwork.IsMasterClient; startPlayBackOnDownload = true; SetPlaybackReferenceFromSeconds(audioEntry.PeekStartTime(this)); } PublishSharedState(); if (PhotonNetwork.IsMasterClient) { downloadHelper.EnqueueDownload(url); downloadHelper.StartDownloadJob(); } } public void CommitPlaybackSeek() { if (data.currentSong != null) { if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestCommitPlaybackSeek", (RpcTarget)2, audioSource.time, PhotonNetwork.LocalPlayer.ActorNumber); } else { SetPlaybackReferenceFromSeconds(audioSource.time); PublishSharedState(); } } } public void SetPlaybackStateLocal(bool startPlaying) { if (data.currentSong != null) { if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestSetPlaybackState", (RpcTarget)2, startPlaying, PhotonNetwork.LocalPlayer.ActorNumber); } else if ((Object)(object)data.currentSong.GetAudioClip() == (Object)null) { startPlayBackOnDownload = startPlaying; data.isPlaying = false; data.pendingPlaybackStart = startPlaying; isAwaitingSyncPlayback = PhotonNetwork.IsMasterClient && data.pendingPlaybackStart; PublishSharedState(); } else { SetPlaybackReferenceFromSeconds(GetTrackedPlaybackSeconds()); data.isPlaying = startPlaying; data.pendingPlaybackStart = false; PublishSharedState(); } } } public void JumpPlaybackBySeconds(float seconds) { if (data.currentSong == null) { return; } if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestJumpPlaybackBySeconds", (RpcTarget)2, seconds, PhotonNetwork.LocalPlayer.ActorNumber); return; } float num = Math.Max(0f, GetTrackedPlaybackSeconds() + seconds); AudioSource obj = audioSource; if ((Object)(object)((obj != null) ? obj.clip : null) != (Object)null) { num = Math.Min(num, Math.Max(0f, audioSource.clip.length - 0.05f)); } SetPlaybackReferenceFromSeconds(num); data.pendingPlaybackStart = false; PublishSharedState(); } public void SelectSongIndex(int index) { if (index < 0 || index >= data.playbackQueue.Count) { return; } if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestSelectSongIndex", (RpcTarget)2, index, PhotonNetwork.LocalPlayer.ActorNumber); return; } data.currentSong = data.playbackQueue[index]; data.isPlaying = false; data.pendingPlaybackStart = true; isAwaitingSyncPlayback = PhotonNetwork.IsMasterClient; startPlayBackOnDownload = true; SetPlaybackReferenceFromSeconds(data.currentSong.PeekStartTime(this)); PublishSharedState(); if (PhotonNetwork.IsMasterClient) { downloadHelper.DismissDownloadQueue(); downloadHelper.DownloadQueue(index); } } public void SetVolumeLocal(float volume) { if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestSetVolume", (RpcTarget)2, volume, PhotonNetwork.LocalPlayer.ActorNumber); } else { data.absVolume = Mathf.Clamp01(volume); float volume2 = data.absVolume * data.personalVolumePercentage; audioSource.volume = volume2; UpdateAudioRangeBasedOnVolume(volume2); PublishSharedState(); } } public void SetLoopQueueLocal(bool loop) { if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestSetLoopQueue", (RpcTarget)2, loop, PhotonNetwork.LocalPlayer.ActorNumber); } else { data.loopQueue = loop; PublishSharedState(); } } public void SetUnderglowEnabledLocal(bool enabled) { data.underglowEnabled = enabled; ApplyVisualStateFromData(); ((Component)this).GetComponent<BoomboxUI>()?.UpdateDataFromBoomBox(); } public void SetVisualizerEnabledLocal(bool enabled) { data.visualizerEnabled = enabled; ApplyVisualStateFromData(); ((Component)this).GetComponent<BoomboxUI>()?.UpdateDataFromBoomBox(); } public void DismissQueueLocal() { if (!PhotonNetwork.IsMasterClient && Instance.MasterClientDismissQueue.Value) { return; } if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestDismissQueue", (RpcTarget)2, PhotonNetwork.LocalPlayer.ActorNumber); return; } StopLocalPlayback(updateSharedFlag: false); data.playbackQueue.Clear(); data.currentSong = null; data.isPlaying = false; data.pendingPlaybackStart = false; data.playbackTime = 0; SetPlaybackReferenceFromSeconds(0f); PublishSharedState(); if (PhotonNetwork.IsMasterClient) { downloadHelper.DismissDownloadQueue(); downloadHelper.ForceCancelDownload(); } UpdateUIStatus("Ready to play music! Enter a Video URL"); } public void MoveQueueItemLocal(int index, int newIndex) { if (index >= 0 && index < data.playbackQueue.Count && newIndex >= 0 && newIndex < data.playbackQueue.Count && index != newIndex) { if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestMoveQueueItem", (RpcTarget)2, index, newIndex, PhotonNetwork.LocalPlayer.ActorNumber); } else { AudioEntry item = data.playbackQueue[index]; data.playbackQueue.RemoveAt(index); data.playbackQueue.Insert(newIndex, item); PublishSharedState(); } } } public void RemoveQueueItemLocal(int index) { if (index < 0 || index >= data.playbackQueue.Count) { return; } if (ShouldRequestMasterMutation()) { BaseListener.RPC(photonView, "RequestRemoveQueueItem", (RpcTarget)2, index, PhotonNetwork.LocalPlayer.ActorNumber); return; } AudioEntry audioEntry = data.playbackQueue[index]; bool flag = audioEntry == data.currentSong; data.playbackQueue.RemoveAt(index); if (flag) { if (data.playbackQueue.Count == 0) { data.currentSong = null; data.isPlaying = false; data.pendingPlaybackStart = false; SetPlaybackReferenceFromSeconds(0f); } else { int index2 = Math.Min(index, data.playbackQueue.Count - 1); if (index >= data.playbackQueue.Count && LoopQueue) { index2 = 0; } data.currentSong = data.playbackQueue[index2]; data.isPlaying = false; data.pendingPlaybackStart = true; isAwaitingSyncPlayback = PhotonNetwork.IsMasterClient; startPlayBackOnDownload = true; SetPlaybackReferenceFromSeconds(data.currentSong.PeekStartTime(this)); } } if (PhotonNetwork.IsMasterClient && data.currentSong?.Url != null) { downloadHelper.DismissDownloadQueue(); downloadHelper.DownloadQueue(GetCurrentSongIndex()); } PublishSharedState(); } public void FinalizePendingPlaybackStart(bool startPlaying) { if (data.currentSong != null) { isAwaitingSyncPlayback = false; data.pendingPlaybackStart = false; data.isPlaying = startPlaying; SetPlaybackReferenceFromSeconds(data.currentSong.UseStartTime(this)); startPlayBackOnDownload = true; PublishSharedState(force: true); } } [PunRPC] public void RequestEnqueueSong(string url, int seconds, int requesterId) { if (PhotonNetwork.IsMasterClient) { EnqueueSongLocal(url, seconds); } } [PunRPC] public void RequestCommitPlaybackSeek(float playbackSeconds, int requesterId) { if (PhotonNetwork.IsMasterClient && data.currentSong != null) { SetPlaybackReferenceFromSeconds(playbackSeconds); PublishSharedState(); } } [PunRPC] public void RequestSetPlaybackState(bool startPlaying, int requesterId) { if (PhotonNetwork.IsMasterClient) { SetPlaybackStateLocal(startPlaying); } } [PunRPC] public void RequestJumpPlaybackBySeconds(float seconds, int requesterId) { if (PhotonNetwork.IsMasterClient) { JumpPlaybackBySeconds(seconds); } } [PunRPC] public void RequestSelectSongIndex(int index, int requesterId) { if (PhotonNetwork.IsMasterClient) { SelectSongIndex(index); } } [PunRPC] public void RequestSetVolume(float volume, int requesterId) { if (PhotonNetwork.IsMasterClient) { SetVolumeLocal(volume); } } [PunRPC] public void RequestSetLoopQueue(bool loop, int requesterId) { if (PhotonNetwork.IsMasterClient) { SetLoopQueueLocal(loop); } } [PunRPC] public void RequestDismissQueue(int requesterId) { if (PhotonNetwork.IsMasterClient) { DismissQueueLocal(); } } [PunRPC] public void RequestMoveQueueItem(int index, int newIndex, int requesterId) { if (PhotonNetwork.IsMasterClient) { MoveQueueItemLocal(index, newIndex); } } [PunRPC] public void RequestRemoveQueueItem(int index, int requesterId) { if (PhotonNetwork.IsMasterClient) { RemoveQueueItemLocal(index); } } public void HandleDownloadedCurrentSong() { if (!((Object)(object)data.currentSong?.GetAudioClip() == (Object)null)) { ApplySharedPlaybackState(songChanged: false); } } public void SetQuality(int level) { qualityLevel = Mathf.Clamp(level, 0, 4); switch (qualityLevel) { case 0: ((Behaviour)lowPassFilter).enabled = true; lowPassFilter.cutoffFrequency = 1500f; break; case 1: ((Behaviour)lowPassFilter).enabled = true; lowPassFilter.cutoffFrequency = 3000f; break; case 2: ((Behaviour)lowPassFilter).enabled = true; lowPassFilter.cutoffFrequency = 4500f; break; case 3: ((Behaviour)lowPassFilter).enabled = true; lowPassFilter.cutoffFrequency = 6000f; break; case 4: ((Behaviour)lowPassFilter).enabled = false; break; } } private void UpdateAudioRangeBasedOnVolume(float volume) { //IL_004c: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown float num = Mathf.Lerp(maxDistanceBase, maxDistanceBase + maxDistanceAddition, volume); audioSource.minDistance = minDistance; audioSource.maxDistance = num; AnimationCurve val = new AnimationCurve((Keyframe[])(object)new Keyframe[3] { new Keyframe(0f, 1f), new Keyframe(minDistance, 0.9f), new Keyframe(num, 0f) }); audioSource.SetCustomCurve((AudioSourceCurveType)0, val); } public void UpdateUIStatus(string message) { if (!((Object)(object)this == (Object)null)) { BoomboxUI component = ((Component)this).GetComponent<BoomboxUI>(); if ((Object)(object)component != (Object)null && component.IsUIVisible()) { component.UpdateStatus(message); } } } public override void OnPlayerEnteredRoom(Player newPlayer) { ((MonoBehaviourPunCallbacks)this).OnPlayerEnteredRoom(newPlayer); if (PhotonNetwork.IsMasterClient && !Instance.modDisabled) { PhotonView obj = ((MonoBehaviourPun)Instance.baseListener).photonView; if (obj != null) { obj.RPC("ModFeedbackCheck", newPlayer, new object[2] { "1.3.2", PhotonNetwork.LocalPlayer.ActorNumber }); } } } private void OnDisable() { PersistentData.RemoveBoomboxViewInitialized(photonView.ViewID); data.playbackTime = (int)Math.Round(audioSource.time); } private void OnDestroy() { Instance.data.GetAllBoomboxes().Remove(this); Object.Destroy((Object)(object)((Component)this).GetComponent<BoomboxUI>()); Object.Destroy((Object)(object)visualizer); Object.Destroy((Object)(object)lowPassFilter); Object.Destroy((Object)(object)audioSource); Object.Destroy((Object)(object)downloadHelper); Object.Destroy((Object)(object)((Component)this).gameObject.GetComponent<BoomboxController>()); photonView.RefreshRpcMonoBehaviourCache(); } public void ResetData() { if (PhotonNetwork.IsMasterClient) { Logger.LogInfo((object)$"Resetting Boombox {photonView.ViewID}"); isAwaitingSyncPlayback = false; startPlayBackOnDownload = true; data.pendingPlaybackStart = false; UpdateUIStatus("Ready to play music! Enter a Video URL"); CleanupCurrentPlayback(); downloadHelper.DismissDownloadQueue(); List<BoomboxData> boomboxData = Instance.data.GetBoomboxData(); int index = boomboxData.Count; if (boomboxData.Contains(data)) { index = boomboxData.IndexOf(data); boomboxData.Remove(data); } data = new BoomboxData(); ApplyVisualStateFromData(); if (Instance.RestoreBoomboxes.Value) { boomboxData.Insert(index, data); } PublishSharedState(force: true); } } } public class BoomboxController : MonoBehaviourPun { private static BoomBoxCartMod Instance = BoomBoxCartMod.instance; private PhysGrabCart cart; private BoomboxUI boomboxUI; private Boombox boombox; private int currentControllerId = -1; private static ManualLogSource Logger => Instance.logger; private void Awake() { cart = ((Component)this).GetComponent<PhysGrabCart>(); boombox = ((Component)this).GetComponent<Boombox>(); if ((Object)(object)cart == (Object)null) { Logger.LogError((object)"BoomboxController: PhysGrabCart component not found!"); } else if ((Object)(object)boombox == (Object)null) { Logger.LogError((object)"BoomboxController: Boombox component not found!"); } } private bool IsLocalPlayerGrabbingCart() { return PlayerGrabbingTracker.IsLocalPlayerGrabbingCart(((Component)this).gameObject); } public void RequestBoomboxControl() { if (IsLocalPlayerGrabbingCart()) { int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; BaseListener.RPC(((MonoBehaviourPun)this).photonView, "RequestControl", (RpcTarget)2, actorNumber); } } [PunRPC] private void RequestControl(int requesterId) { if (PhotonNetwork.IsMasterClient) { bool flag = true; if (requesterId == PhotonNetwork.LocalPlayer.ActorNumber) { flag = PlayerGrabbingTracker.IsLocalPlayerGrabbingCart(((Component)this).gameObject); } if ((currentControllerId == -1 || !Instance.baseListener.GetAllModUsers().Contains(requesterId)) && flag) { BaseListener.RPC(((MonoBehaviourPun)this).photonView, "SetController", (RpcTarget)0, requesterId); } } } [PunRPC] private void SetController(int controllerId) { try { currentControllerId = controllerId; if (controllerId == PhotonNetwork.LocalPlayer.ActorNumber) { EnsureBoomboxUIExists(); if ((Object)(object)boomboxUI != (Object)null) { boomboxUI.ShowUI(); } else { Logger.LogError((object)"Failed to create BoomboxUI component"); } } else if ((Object)(object)boomboxUI != (Object)null && boomboxUI.IsUIVisible()) { boomboxUI.HideUI(); } } catch (Exception ex) { Logger.LogError((object)("Error in SetController: " + ex.Message + "\n" + ex.StackTrace)); } } private void EnsureBoomboxUIExists() { if ((Object)(object)boomboxUI == (Object)null) { boomboxUI = ((Component)this).gameObject.GetComponent<BoomboxUI>(); if ((Object)(object)boomboxUI == (Object)null) { boomboxUI = ((Component)this).gameObject.AddComponent<BoomboxUI>(); } } } public void ReleaseControl() { if (currentControllerId == PhotonNetwork.LocalPlayer.ActorNumber) { BaseListener.RPC(((MonoBehaviourPun)this).photonView, "RequestRelease", (RpcTarget)2, PhotonNetwork.LocalPlayer.ActorNumber); } } [PunRPC] private void RequestRelease(int releaserId) { if (PhotonNetwork.IsMasterClient && currentControllerId == releaserId) { BaseListener.RPC(((MonoBehaviourPun)this).photonView, "SetController", (RpcTarget)0, -1); } } private void OnPlayerReleasedCart(int playerActorNumber) { if (playerActorNumber == currentControllerId && PhotonNetwork.IsMasterClient) { BaseListener.RPC(((MonoBehaviourPun)this).photonView, "SetController", (RpcTarget)0, -1); } } public void LocalPlayerReleasedCart() { int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; if (currentControllerId == actorNumber) { ReleaseControl(); } } } public class BoomboxUI : MonoBehaviourPun { private static BoomBoxCartMod Instance = BoomBoxCartMod.instance; public PhotonView photonView; public static bool anyUISHown = false; public bool showUI = false; private string urlInput = ""; private bool isTimeSliderBeingDragged = false; private int songIndexForTime = -2; private float songTimePerc = 0f; private float lastSentSongTimePerc = -1f; private float lastSentVolume = 0.3f; private bool isVolumeSliderBeingDragged = false; private bool isIndividualVolumeBeingDragged = false; private int qualityLevel = 3; private string[] qualityLabels = new string[5] { "REALLY Low (You Freak)", "Low", "Medium-Low", "Medium-High", "High" }; private bool isQualitySliderBeingDragged = false; private int lastSentQualityLevel = 3; private Rect windowRect; private Boombox boombox; private BoomboxController controller; private VisualEffects visualEffects; private Visualizer visualizer; private GUIStyle windowStyle; private GUIStyle headerStyle; private GUIStyle buttonStyle; private GUIStyle smallButtonStyle; private GUIStyle textFieldStyle; private GUIStyle labelStyle; private GUIStyle sliderStyle; private GUIStyle statusStyle; private GUIStyle scrollViewStyle; private GUIStyle queueHeaderStyle; private GUIStyle queueEntryStyle; private GUIStyle currentSongStyle; private Texture2D backgroundTexture; private Texture2D buttonTexture; private Texture2D sliderBackgroundTexture; private Texture2D sliderThumbTexture; private Texture2D textFieldBackgroundTexture; private Vector2 urlScrollPosition = Vector2.zero; private float textFieldVisibleWidth = 350f; private string errorMessage = ""; private float errorMessageTime = 0f; public string statusMessage = ""; private CursorLockMode previousLockMode; private bool previousCursorVisible; private bool stylesInitialized = false; private Vector2 scrollPosition = Vector2.zero; private Vector2 queueScrollPosition = Vector2.zero; private const float refreshHoldTime = 5f; private const int maxRefreshSymbols = 5; private float? refreshObjectStart = null; private bool refreshObjectSent = false; private string lastUrl = null; private static ManualLogSource Logger => Instance.logger; private void Awake() { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) try { boombox = ((Component)this).GetComponent<Boombox>(); if ((Object)(object)boombox != (Object)null) { photonView = boombox.photonView; } else { Logger.LogError((object)"BoomboxUI: Failed to find Boombox component"); photonView = ((Component)this).GetComponent<PhotonView>(); } controller = ((Component)this).GetComponent<BoomboxController>(); visualEffects = ((Component)this).GetComponent<VisualEffects>(); if ((Object)(object)visualEffects == (Object)null) { visualEffects = ((Component)this).gameObject.AddComponent<VisualEffects>(); } visualizer = ((Component)this).GetComponent<Visualizer>(); boombox?.ApplyVisualStateFromData(); RefreshVisualComponentRefs(); if ((Object)(object)photonView == (Object)null) { Logger.LogError((object)"BoomboxUI: Failed to find PhotonView component"); } windowRect = new Rect((float)(Screen.width / 2 - 400), (float)(Screen.height / 2 - 175), 800f, 550f); } catch (Exception ex) { Logger.LogError((object)("Error in BoomboxUI.Awake: " + ex.Message + "\n" + ex.StackTrace)); } } private void Update() { if (Time.time > errorMessageTime && !string.IsNullOrEmpty(errorMessage)) { errorMessage = ""; } if (showUI && Keyboard.current != null && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame) { if ((Object)(object)controller != (Object)null) { controller.ReleaseControl(); } else { HideUI(); } } if (isTimeSliderBeingDragged && ((Mouse.current != null && Mouse.current.leftButton.wasReleasedThisFrame) || songIndexForTime != boombox.GetCurrentSongIndex())) { isTimeSliderBeingDragged = false; SendTimeUpdate(); songIndexForTime = -2; songTimePerc = 0f; lastSentSongTimePerc = -1f; } if (isVolumeSliderBeingDragged && Mouse.current != null && Mouse.current.leftButton.wasReleasedThisFrame) { isVolumeSliderBeingDragged = false; SendVolumeUpdate(); } if (isIndividualVolumeBeingDragged && Mouse.current != null && Mouse.current.leftButton.wasReleasedThisFrame) { isIndividualVolumeBeingDragged = false; } if (isQualitySliderBeingDragged && Mouse.current != null && Mouse.current.leftButton.wasReleasedThisFrame) { isQualitySliderBeingDragged = false; SendQualityUpdate(); } if (refreshObjectStart.HasValue && Mouse.current != null && Mouse.current.leftButton.wasReleasedThisFrame) { refreshObjectStart = null; refreshObjectSent = false; } } public void ShowUI() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!showUI) { if ((Object)(object)boombox == (Object)null || (Object)(object)photonView == (Object)null) { Logger.LogError((object)"Cannot show UI - boombox or photonView is null"); return; } anyUISHown = true; showUI = true; previousLockMode = Cursor.lockState; previousCursorVisible = Cursor.visible; Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; UpdateDataFromBoomBox(); UpdateStatusFromBoombox(); } } public void UpdateDataFromBoomBox() { if ((Object)(object)boombox != (Object)null) { lastSentVolume = boombox.data.absVolume; qualityLevel = Boombox.qualityLevel; lastSentQualityLevel = qualityLevel; RefreshVisualComponentRefs(); } } private void RefreshVisualComponentRefs() { visualEffects = ((Component)this).GetComponent<VisualEffects>(); visualizer = ((Component)this).GetComponent<Visualizer>(); } public void UpdateStatusFromBoombox() { if ((Object)(object)boombox != (Object)null) { if (YoutubeDL.IsUpdatingResources) { statusMessage = YoutubeDL.ResourceUpdateStatus; } else if (boombox.downloadHelper.IsProcessingQueue() && boombox.data.currentSong != null && (Object)(object)boombox.data.currentSong.GetAudioClip() == (Object)null) { statusMessage = "Downloading audio from " + boombox.downloadHelper.GetCurrentDownloadUrl() + "..."; } else if (boombox.data.currentSong != null && boombox.data.pendingPlaybackStart) { statusMessage = "Loading: " + boombox.data.currentSong.Title; } else if (boombox.data.currentSong != null && boombox.data.isPlaying) { statusMessage = "Now playing: " + boombox.data.currentSong.Title; } else if (!string.IsNullOrEmpty(boombox.data.currentSong?.Url)) { statusMessage = "Ready to play: " + boombox.data.currentSong.Title; } else { statusMessage = "Ready to play music! Enter a Video URL"; } } } private void SendTimeUpdate() { if (songTimePerc == lastSentSongTimePerc) { return; } lastSentSongTimePerc = songTimePerc; if (boombox?.GetCurrentSongIndex() == songIndexForTime && songIndexForTime != -1) { Boombox obj = boombox; object obj2; if (obj == null) { obj2 = null; } else { AudioSource audioSource = obj.audioSource; obj2 = ((audioSource != null) ? audioSource.clip : null); } if ((Object)obj2 != (Object)null && boombox.audioSource.clip.length > 0f) { float time = Math.Max(0f, Math.Min(songTimePerc * boombox.audioSource.clip.length, boombox.audioSource.clip.length - 0.05f)); boombox.audioSource.time = time; boombox.CommitPlaybackSeek(); return; } } if (songIndexForTime != boombox.GetCurrentSongIndex()) { UpdateDataFromBoomBox(); } } private void SendVolumeUpdate() { if (boombox.data.absVolume != lastSentVolume) { lastSentVolume = boombox.data.absVolume; if ((Object)(object)boombox.audioSource != (Object)null) { float volume = boombox.data.absVolume * boombox.data.personalVolumePercentage; boombox.audioSource.volume = volume; } boombox.SetVolumeLocal(boombox.data.absVolume); } } private void SendQualityUpdate() { if (qualityLevel != lastSentQualityLevel) { lastSentQualityLevel = qualityLevel; if ((Object)(object)boombox != (Object)null) { boombox.SetQuality(qualityLevel); } } } public void HideUI() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (showUI) { anyUISHown = false; showUI = false; Cursor.lockState = previousLockMode; Cursor.visible = previousCursorVisible; } } public bool IsUIVisible() { return showUI; } public void UpdateStatus(string message) { statusMessage = message; } private Texture2D CreateColorTexture(Color color) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(1, 1); val.SetPixel(0, 0, color); val.Apply(); return val; } private void InitializeStyles() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown //IL_0179: 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_01a7: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Expected O, but got Unknown //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Expected O, but got Unknown //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Expected O, but got Unknown //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Expected O, but got Unknown //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Expected O, but got Unknown //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Expected O, but got Unknown //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Expected O, but got Unknown //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Expected O, but got Unknown //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Expected O, but got Unknown //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Expected O, but got Unknown //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Expected O, but got Unknown //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Expected O, but got Unknown //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Expected O, but got Unknown //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Expected O, but got Unknown //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Expected O, but got Unknown //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0552: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Expected O, but got Unknown //IL_057c: Unknown result type (might be due to invalid IL or missing references) //IL_0597: Unknown result type (might be due to invalid IL or missing references) if (!stylesInitialized) { backgroundTexture = CreateColorTexture(new Color(0.1f, 0.1f, 0.1f, 0.9f)); buttonTexture = CreateColorTexture(new Color(0.2f, 0.2f, 0.3f, 1f)); sliderBackgroundTexture = CreateColorTexture(new Color(0.15f, 0.15f, 0.2f, 1f)); sliderThumbTexture = CreateColorTexture(new Color(0.7f, 0.7f, 0.8f, 1f)); textFieldBackgroundTexture = CreateColorTexture(new Color(0.15f, 0.17f, 0.2f, 1f)); windowStyle = new GUIStyle(GUI.skin.window); windowStyle.normal.background = backgroundTexture; windowStyle.onNormal.background = backgroundTexture; windowStyle.border = new RectOffset(10, 10, 10, 10); windowStyle.padding = new RectOffset(15, 15, 20, 15); headerStyle = new GUIStyle(GUI.skin.label); headerStyle.fontSize = 18; headerStyle.fontStyle = (FontStyle)1; headerStyle.normal.textColor = Color.white; headerStyle.alignment = (TextAnchor)4; headerStyle.margin = new RectOffset(0, 0, 10, 20); buttonStyle = new GUIStyle(GUI.skin.button); buttonStyle.normal.background = buttonTexture; buttonStyle.hover.background = CreateColorTexture(new Color(0.3f, 0.3f, 0.4f, 1f)); buttonStyle.active.background = CreateColorTexture(new Color(0.4f, 0.4f, 0.5f, 1f)); buttonStyle.normal.textColor = Color.white; buttonStyle.hover.textColor = Color.white; buttonStyle.active.textColor = Color.white; buttonStyle.fontSize = 14; buttonStyle.padding = new RectOffset(15, 15, 8, 8); buttonStyle.margin = new RectOffset(5, 5, 5, 5); buttonStyle.alignment = (TextAnchor)4; smallButtonStyle = new GUIStyle(buttonStyle); smallButtonStyle.padding = new RectOffset(8, 8, 4, 4); smallButtonStyle.fontSize = 12; textFieldStyle = new GUIStyle(GUI.skin.textField); textFieldStyle.normal.background = textFieldBackgroundTexture; textFieldStyle.normal.textColor = new Color(1f, 1f, 1f); textFieldStyle.fontSize = 14; textFieldStyle.padding = new RectOffset(10, 10, 8, 8); scrollViewStyle = new GUIStyle(GUI.skin.scrollView); scrollViewStyle.normal.background = textFieldBackgroundTexture; scrollViewStyle.border = new RectOffset(2, 2, 2, 2); scrollViewStyle.padding = new RectOffset(0, 0, 0, 0); labelStyle = new GUIStyle(GUI.skin.label); labelStyle.normal.textColor = Color.white; labelStyle.fontSize = 14; labelStyle.margin = new RectOffset(0, 0, 10, 5); statusStyle = new GUIStyle(GUI.skin.label); statusStyle.normal.textColor = Color.cyan; statusStyle.fontSize = 14; statusStyle.wordWrap = true; statusStyle.alignment = (TextAnchor)4; sliderStyle = new GUIStyle(GUI.skin.horizontalSlider); sliderStyle.normal.background = sliderBackgroundTexture; queueHeaderStyle = new GUIStyle(headerStyle); queueHeaderStyle.fontSize = 16; queueHeaderStyle.alignment = (TextAnchor)3; queueHeaderStyle.margin = new RectOffset(5, 0, 10, 5); queueEntryStyle = new GUIStyle(textFieldStyle); queueEntryStyle.normal.background = CreateColorTexture(new Color(0.1f, 0.1f, 0.1f, 0.7f)); queueEntryStyle.hover.background = CreateColorTexture(new Color(0.2f, 0.2f, 0.2f, 0.8f)); queueEntryStyle.alignment = (TextAnchor)3; currentSongStyle = new GUIStyle(queueEntryStyle); currentSongStyle.normal.background = CreateColorTexture(new Color(0.1f, 0.3f, 0.1f, 0.9f)); currentSongStyle.normal.textColor = Color.yellow; currentSongStyle.hover.background = currentSongStyle.normal.background; stylesInitialized = true; } } private void OnGUI() { //IL_0027: 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_004d: Expected O, but got Unknown //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) if (showUI) { if (!stylesInitialized) { InitializeStyles(); } windowRect = GUILayout.Window(0, windowRect, new WindowFunction(DrawUI), "Boombox Controller", windowStyle, Array.Empty<GUILayoutOption>()); } } private void DrawUI(int windowID) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (boombox?.data == null) { return; } object obj; if (!Instance.baseListener.audioMuted) { obj = ""; } else { Key value = Instance.GlobalMuteKey.Value; obj = " - MUTED(" + ((object)(Key)(ref value)).ToString() + ")"; } GUILayout.Label("Control The Boombox In The Cart" + (string?)obj, headerStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(400f) }); DrawMainPanel(boombox); GUILayout.EndVertical(); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(420f), GUILayout.ExpandHeight(true) }); DrawQueue(boombox); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button("Close", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(300f), GUILayout.Height(36f) })) { if ((Object)(object)controller != (Object)null) { controller.ReleaseControl(); } else { HideUI(); } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUI.DragWindow(); } private void DrawMainPanel(Boombox boombox) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_06cb: Unknown result type (might be due to invalid IL or missing references) //IL_063d: Unknown result type (might be due to invalid IL or missing references) //IL_065f: Unknown result type (might be due to invalid IL or missing references) //IL_06d2: Unknown result type (might be due to invalid IL or missing references) //IL_06d7: Unknown result type (might be due to invalid IL or missing references) //IL_06e0: Unknown result type (might be due to invalid IL or missing references) //IL_080a: Unknown result type (might be due to invalid IL or missing references) //IL_0811: Unknown result type (might be due to invalid IL or missing references) //IL_0816: Unknown result type (might be due to invalid IL or missing references) //IL_081f: Unknown result type (might be due to invalid IL or missing references) //IL_0906: Unknown result type (might be due to invalid IL or missing references) //IL_090d: Unknown result type (might be due to invalid IL or missing references) //IL_0912: Unknown result type (might be due to invalid IL or missing references) //IL_091b: Unknown result type (might be due to invalid IL or missing references) scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, false, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) }); GUILayout.Space(10f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Enter Video URL:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button("Clear", smallButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) })) { urlInput = ""; GUI.FocusControl((string)null); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); urlScrollPosition = GUILayout.BeginScrollView(urlScrollPosition, false, false, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(60f) }); urlInput = GUILayout.TextField(urlInput, textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }); urlInput = Regex.Replace(urlInput, "\\s+", ""); GUILayout.EndScrollView(); GUILayout.EndHorizontal(); float num = 0f; float num2 = 0f; float num3 = 0f; string text = "??"; int num4; if ((Object)(object)boombox != (Object)null) { AudioSource audioSource = boombox.audioSource; num4 = (((Object)(object)((audioSource != null) ? audioSource.clip : null) != (Object)null) ? 1 : 0); } else { num4 = 0; } bool flag = (byte)num4 != 0; if (flag) { num = boombox.audioSource.time; num2 = boombox.audioSource.clip.length; if (num2 > 0f) { num3 = num / num2; text = PrintTime(num2); } else { flag = false; } } GUILayout.Label(PrintTime(num) + " / " + text, labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Rect lastRect; if (flag && (int)Event.current.type == 0) { lastRect = GUILayoutUtility.GetLastRect(); if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition)) { isTimeSliderBeingDragged = true; } } float num5 = GUILayout.HorizontalSlider(num3, 0f, 1f, sliderStyle, GUI.skin.horizontalSliderThumb, Array.Empty<GUILayoutOption>()); int currentSongIndex = boombox.GetCurrentSongIndex(); if (flag && currentSongIndex != -1 && num5 != num3) { if (!isTimeSliderBeingDragged) { isTimeSliderBeingDragged = true; } if (songIndexForTime == -2) { songIndexForTime = currentSongIndex; } if (songIndexForTime == currentSongIndex) { float time = Math.Max(0f, Math.Min(num5 * num2, boombox.audioSource.clip.length - 0.05f)); boombox.audioSource.time = time; songTimePerc = num5; } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("<<", smallButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(40f) }) && (Object)(object)boombox != (Object)null && boombox.data.currentSong != null) { boombox.JumpPlaybackBySeconds(-10f); } string text2 = ((boombox?.data != null && boombox.data.playbackQueue.Count > 0) ? "+ ENQUEUE" : "▶ PLAY"); if (GUILayout.Button(text2, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { var (text3, seconds) = IsValidVideoUrl(urlInput); if (string.IsNullOrEmpty(text3)) { ShowErrorMessage("Invalid Video URL!"); } else if (lastUrl != text3) { lastUrl = text3; boombox.EnqueueSongLocal(text3, seconds); GUI.FocusControl((string)null); } } string text4 = ((boombox.data.currentSong == null) ? "..." : (boombox.data.isPlaying ? "▌▌ PAUSE" : "▶ RESUME")); if (GUILayout.Button(text4, buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }) && boombox.data.currentSong != null) { boombox.SetPlaybackStateLocal(!boombox.data.isPlaying); } if (GUILayout.Button(">>", smallButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(40f), GUILayout.Height(40f) }) && (Object)(object)boombox != (Object)null && boombox.data.currentSong != null) { boombox.JumpPlaybackBySeconds(10f); } GUILayout.EndHorizontal(); if ((Object)(object)boombox != (Object)null && boombox.downloadHelper.IsProcessingQueue() && (Object)(object)boombox.data.currentSong?.GetAudioClip() == (Object)null && boombox.downloadHelper.GetCurrentDownloadUrl() != null) { GUILayout.Space(10f); GUILayout.Label("Download in progress...", statusStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button("Force Cancel Download", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(200f), GUILayout.Height(30f) })) { boombox.downloadHelper.ForceCancelDownload(); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } GUILayout.Space(15f); if (!string.IsNullOrEmpty(statusMessage)) { GUILayout.Label(statusMessage, statusStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); } if (!string.IsNullOrEmpty(errorMessage)) { GUI.color = Color.red; GUILayout.Label(errorMessage, labelStyle, Array.Empty<GUILayoutOption>()); GUI.color = Color.white; GUILayout.Space(5f); } GUILayout.Space(15f); float num6 = boombox.data.absVolume * 100f; GUILayout.Label($"Volume: {Mathf.Round(num6)}%", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if ((int)Event.current.type == 0) { lastRect = GUILayoutUtility.GetLastRect(); if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition)) { isVolumeSliderBeingDragged = true; } } float num7 = GUILayout.HorizontalSlider(boombox.data.absVolume, 0f, 1f, sliderStyle, GUI.skin.horizontalSliderThumb, Array.Empty<GUILayoutOption>()); if (num7 != boombox.data.absVolume) { if (!isVolumeSliderBeingDragged) { isVolumeSliderBeingDragged = true; } if ((Object)(object)boombox != (Object)null && (Object)(object)boombox.audioSource != (Object)null) { float volume = boombox.data.absVolume * boombox.data.personalVolumePercentage; boombox.audioSource.volume = volume; } boombox.data.absVolume = num7; } GUILayout.EndHorizontal(); GUILayout.Space(15f); GUILayout.Label($"Personal Volume Multiplier: {Mathf.Round(boombox.data.personalVolumePercentage * 100.001f)}%", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if ((int)Event.current.type == 0) { lastRect = GUILayoutUtility.GetLastRect(); if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition)) { isIndividualVolumeBeingDragged = true; } } float num8 = GUILayout.HorizontalSlider(boombox.data.personalVolumePercentage, 0f, 1f, sliderStyle, GUI.skin.horizontalSliderThumb, Array.Empty<GUILayoutOption>()); if (num8 != boombox.data.personalVolumePercentage) { isIndividualVolumeBeingDragged = true; boombox.data.personalVolumePercentage = num8; boombox.audioSource.volume = boombox.data.absVolume * boombox.data.personalVolumePercentage; } GUILayout.EndHorizontal(); GUILayout.Space(15f); GUILayout.Label("Audio Quality: " + qualityLabels[qualityLevel], labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if ((int)Event.current.type == 0) { lastRect = GUILayoutUtility.GetLastRect(); if (((Rect)(ref lastRect)).Contains(Event.current.mousePosition)) { isQualitySliderBeingDragged = true; } } float num9 = GUILayout.HorizontalSlider((float)qualityLevel, 0f, 4f, sliderStyle, GUI.skin.horizontalSliderThumb, Array.Empty<GUILayoutOption>()); int num10 = Mathf.RoundToInt(num9); if (num10 != qualityLevel && !isQualitySliderBeingDragged) { isQualitySliderBeingDragged = true; } qualityLevel = num10; if ((Object)(object)boombox != (Object)null) { boombox.SetQuality(qualityLevel); } GUILayout.EndHorizontal(); GUILayout.Space(10f); bool applyQualityToDownloads = Boombox.ApplyQualityToDownloads; bool flag2 = GUILayout.Toggle(applyQualityToDownloads, "Apply Quality Setting to Downloads", Array.Empty<GUILayoutOption>()); if (flag2 != applyQualityToDownloads) { Boombox.ApplyQualityToDownloads = flag2; } GUILayout.Space(10f); bool monstersCanHearMusic = Boombox.MonstersCanHearMusic; bool flag3 = GUILayout.Toggle(monstersCanHearMusic, "Monsters can hear audio", Array.Empty<GUILayoutOption>()); if (flag3 != monstersCanHearMusic) { Boombox.MonstersCanHearMusic = flag3; } GUILayout.Space(10f); bool loopQueue = boombox.LoopQueue; bool flag4 = GUILayout.Toggle(loopQueue, "Loop queue", Array.Empty<GUILayoutOption>()); if (flag4 != loopQueue && PhotonNetwork.IsMasterClient) { boombox.SetLoopQueueLocal(flag4); } GUILayout.Space(10f); bool underglowEnabled = boombox.data.underglowEnabled; bool flag5 = GUILayout.Toggle(underglowEnabled, "RGB Underglow enabled", Array.Empty<GUILayoutOption>()); if (flag5 != underglowEnabled) { boombox.SetUnderglowEnabledLocal(flag5); UpdateDataFromBoomBox(); } GUILayout.Space(10f); bool visualizerEnabled = boombox.data.visualizerEnabled; bool flag6 = GUILayout.Toggle(visualizerEnabled, "Audio Visualizer enabled", Array.Empty<GUILayoutOption>()); if (flag6 != visualizerEnabled) { boombox.SetVisualizerEnabledLocal(flag6); UpdateDataFromBoomBox(); } GUILayout.EndScrollView(); } private void DrawQueue(Boombox boombox) { //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(" Playback Queue", queueHeaderStyle, Array.Empty<GUILayoutOption>()); if (PhotonNetwork.IsMasterClient) { float num = Time.time - (refreshObjectStart ?? Time.time); int num2 = 1 + (int)Mathf.Floor(num / 1f); string text = ((num > 0f && num <= 5f) ? (new string('!', num2) + new string('.', Math.Max(0, 5 - num2))) : "RESET"); if (GUILayout.RepeatButton(text, smallButtonStyle, Array.Empty<GUILayoutOption>())) { if (!refreshObjectStart.HasValue) { refreshObjectStart = Time.time; } else if (!refreshObjectSent && num >= 5f) { boombox.ResetData(); lastUrl = null; refreshObjectSent = true; } } } if (GUILayout.Button("Dismiss Queue", smallButtonStyle, Array.Empty<GUILayoutOption>())) { boombox.DismissQueueLocal(); lastUrl = null; } GUILayout.EndHorizontal(); queueScrollPosition = GUILayout.BeginScrollView(queueScrollPosition, false, true, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) }); List<Boombox.AudioEntry> playbackQueue = boombox.data.playbackQueue; int currentSongIndex = boombox.GetCurrentSongIndex(); if (playbackQueue.Count == 0) { GUILayout.Label(" Queue is empty and no song is playing.", labelStyle, Array.Empty<GUILayoutOption>()); } for (int i = 0; i < playbackQueue.Count; i++) { Boombox.AudioEntry audioEntry = playbackQueue[i]; bool flag = i == currentSongIndex; GUIStyle val = (flag ? currentSongStyle : queueEntryStyle); string text2 = (flag ? "▶ " : $"{i - ((currentSongIndex != -1) ? currentSongIndex : 0)}. "); string text3 = ClipText(text2 + audioEntry.Title, 280f, val); GUILayout.BeginHorizontal(val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }); if (GUILayout.Button(text3, val, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(32f) }) && !flag) { boombox.SelectSongIndex(i); } if (!flag) { if (i > 0) { if (GUILayout.Button("▲", smallButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(25f), GUILayout.Height(28f) })) { boombox.MoveQueueItemLocal(i, i - 1); } } else { GUILayout.Space(30f); } if (i + 1 < playbackQueue.Count) { if (GUILayout.Button("▼", smallButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(25f), GUILayout.Height(28f) })) { boombox.MoveQueueItemLocal(i, i + 1); } } else { GUILayout.Space(30f); } if (GUILayout.Button("X", smallButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(25f), GUILayout.Height(28f) })) { boombox.RemoveQueueItemLocal(i); } } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); } private string ClipText(string text, float maxWidth, GUIStyle style) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Vector2 val = style.CalcSize(new GUIContent(text)); string text2 = text; int length = text.Length; while (val.x > maxWidth) { text2 = text2.Substring(0, text2.Length - 4) + "..."; val = style.CalcSize(new GUIContent(text2)); } return text2; } private string PrintTime(float time) { return $"{(int)Math.Floor(time / 60f)}:{(int)(time % 60f)}"; } private (string cleanedUrl, int seconds) IsValidVideoUrl(string url) { return DownloadHelper.IsValidVideoUrl(url); } private void ShowErrorMessage(string message) { errorMessage = message; errorMessageTime = Time.time + 3f; } private void OnDestroy() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (showUI) { anyUISHown = false; showUI = false; Cursor.lockState = previousLockMode; Cursor.visible = previousCursorVisible; } if ((Object)(object)backgroundTexture != (Object)null) { Object.Destroy((Object)(object)backgroundTexture); } if ((Object)(object)buttonTexture != (Object)null) { Object.Destroy((Object)(object)buttonTexture); } if ((Object)(object)sliderBackgroundTexture != (Object)null) { Object.Destroy((Object)(object)sliderBackgroundTexture); } if ((Object)(object)sliderThumbTexture != (Object)null) { Object.Destroy((Object)(object)sliderThumbTexture); } if ((Object)(object)textFieldBackgroundTexture != (Object)null) { Object.Destroy((Object)(object)textFieldBackgroundTexture); } } } public class DownloadHelper : MonoBehaviourPunCallbacks { [CompilerGenerated] private sealed class <>c__DisplayClass33_0 { public string url; internal bool <MasterClientInitiateSync>b__0(Boombox.AudioEntry entry) { return entry.Url == url; } } [CompilerGenerated] private sealed class <DownloadTimeoutCoroutine>d__34 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string requestId; public string url; public DownloadHelper <>4__this; private List<int>.Enumerator <>s__1; private int <player>5__2; private string <timeoutMessage>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DownloadTimeoutCoroutine>d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>s__1 = default(List<int>.Enumerator); <timeoutMessage>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(40f); <>1__state = 1; return true; case 1: <>1__state = -1; if (<>4__this.currentRequestId == requestId && <>4__this.isProcessingQueue) { Logger.LogWarning((object)("Download timeout for url: " + url)); Logger.LogInfo((object)"Master client initiating timeout recovery"); <>4__this.isTimeoutRecovery = true; <>s__1 = Instance.baseListener.GetAllModUsers().GetEnumerator(); try { while (<>s__1.MoveNext()) { <player>5__2 = <>s__1.Current; if (!downloadsReady[url].Contains(<player>5__2)) { if (!downloadErrors.ContainsKey(url)) { downloadErrors[url] = new HashSet<int>(); } downloadErrors[url].Add(<player>5__2); Logger.LogWarning((object)$"Player {<player>5__2} timed out during download"); } } } finally { ((IDisposable)<>s__1).Dispose(); } <>s__1 = default(List<int>.Enumerator); if (downloadsReady.ContainsKey(url) && downloadsReady[url].Count > 0) { <timeoutMessage>5__3 = $"Some players timed out. Continuing playback for {downloadsReady[url].Count} players."; BaseListener.RPC(((MonoBehaviourPun)<>4__this).photonView, "NotifyPlayersOfErrors", (RpcTarget)0, <timeoutMessage>5__3); if (<>4__this.boomboxParent.isAwaitingSyncPlayback && <>4__this.boomboxParent.data.currentSong?.Url == url) { <>4__this.boomboxParent.FinalizePendingPlaybackStart(<>4__this.boomboxParent.startPlayBackOnDownload); } <timeoutMessage>5__3 = null; } else { BaseListener.RPC(((MonoBehaviourPun)<>4__this).photonView, "NotifyPlayersOfErrors", (RpcTarget)0, "Download timed out for all players."); } <>4__this.currentDownloadUrl = null; <>4__this.currentRequestId = null; <>4__this.isTimeoutRecovery = false; } <>4__this.timeoutCoroutines.Remove(requestId); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MasterClientInitiateSync>d__33 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string url; public DownloadHelper <>4__this; private <>c__DisplayClass33_0 <>8__1; private string <requestId>5__2; private Coroutine <coroutine>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MasterClientInitiateSync>d__33(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <requestId>5__2 = null; <coroutine>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass33_0(); <>8__1.url = url; if (!<>4__this.boomboxParent.data.playbackQueue.Any((Boombox.AudioEntry entry) => entry.Url == <>8__1.url)) { return false; } <requestId>5__2 = Guid.NewGuid().ToString(); <>4__this.currentDownloadUrl = <>8__1.url; <>4__this.currentRequestId = <requestId>5__2; if (downloadsReady.ContainsKey(<>8__1.url)) { if (downloadsReady[<>8__1.url].Count >= Instance.baseListener.GetAllModUsers().Count) { if (!<>4__this.boomboxParent.data.isPlaying && !<>4__this.boomboxParent.audioSource.isPlaying && <>4__this.boomboxParent.isAwaitingSyncPlayback && <>8__1.url == <>4__this.boomboxParent.data.currentSong?.Url) { <>4__this.boomboxParent.FinalizePendingPlaybackStart(<>4__this.boomboxParent.startPlayBackOnDownload); } return false; } downloadsReady[<>8__1.url].Clear(); } else { downloadsReady[<>8__1.url] = new HashSet<int>(); } if (downloadErrors.ContainsKey(<>8__1.url)) { downloadErrors[<>8__1.url].Clear(); } else { downloadErrors[<>8__1.url] = new HashSet<int>(); } BaseListener.RPC(((MonoBehaviourPun)<>4__this).photonView, "StartDownloadAndSync", (RpcTarget)0, <>8__1.url, PhotonNetwork.LocalPlayer.ActorNumber); <>4__this.timeoutCoroutines[<requestId>5__2] = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.DownloadTimeoutCoroutine(<requestId>5__2, <>8__1.url)); <>2__current = <>4__this.WaitForPlayersReadyOrFailed(<>8__1.url); <>1__state = 1; return true; case 1: { <>1__state = -1; Dictionary<string, Coroutine> timeoutCoroutines = <>4__this.timeoutCoroutines; if (timeoutCoroutines != null && timeoutCoroutines.TryGetValue(<requestId>5__2, out <coroutine>5__3) && <coroutine>5__3 != null) { ((MonoBehaviour)<>4__this).StopCoroutine(<coroutine>5__3); <>4__this.timeoutCoroutines.Remove(<requestId>5__2); } if (<>4__this.currentDownloadUrl != <>8__1.url) { return false; } <>4__this.currentDownloadUrl = null; <>4__this.currentRequestId = null; Logger.LogInfo((object)("Consensus finished for " + <>8__1.url + ", Starting Playback.")); Boombox boomboxParent = <>4__this.boomboxParent; if (boomboxParent != null && boomboxParent.isAwaitingSyncPlayback && <>8__1.url == <>4__this.boomboxParent.data.currentSong?.Url) { <>4__this.boomboxParent.FinalizePendingPlaybackStart(<>4__this.boomboxParent.startPlayBackOnDownload); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ProcessDownloadQueue>d__32 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public DownloadHelper <>4__this; private string <url>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ProcessDownloadQueue>d__32(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <url>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.isProcessingQueue = true; Logger.LogInfo((object)"Master Client Download Queue Processor started."); break; case 1: <>1__state = -1; if ((Object)(object)<>4__this == (Object)null) { return false; } <url>5__1 = null; break; } if (<>4__this.downloadJobQueue.Count > 0 && <>4__this.isProcessingQueue) { <url>5__1 = <>4__this.downloadJobQueue.Dequeue(); <>2__current = <>4__this.MasterClientInitiateSync(<url>5__1); <>1__state = 1; return true; } if ((Object)(object)<>4__this == (Object)null) { return false; } <>4__this.isProcessingQueue = false; <>4__this.currentDownloadUrl = null; Logger.LogInfo((object)"Master Client Download Queue Processor finished."); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <WaitForPlayersReadyOrFailed>d__37 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string url; public DownloadHelper <>4__this; private int <totalPlayers>5__1; private int <readyCount>5__2; private int <errorCount>5__3; private float <waitTime>5__4; private float? <partialConsensusStartTime>5__5; private bool <allAccountedFor>5__6; private bool <partialConsensus>5__7; private bool <timeOutReached>5__8; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForPlayersReadyOrFailed>d__37(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <totalPlayers>5__1 = Instance.baseListener.GetAllModUsers().Count; <readyCount>5__2 = 0; <errorCount>5__3 = 0; <waitTime>5__4 = 0.1f; <partialConsensusStartTime>5__5 = null; break; case 1: <>1__state = -1; break; } if ((Object)(object)<>4__this != (Object)null) { <readyCount>5__2 = (downloadsReady.ContainsKey(url) ? downloadsReady[url].Count : 0); <errorCount>5__3 = (downloadErrors.ContainsKey(url) ? downloadErrors[url].Count : 0); <allAccountedFor>5__6 = <readyCount>5__2 + <errorCount>5__3 >= <totalPlayers>5__1; <partialConsensus>5__7 = <readyCount>5__2 > 0 && <errorCount>5__3 > 0; <timeOutReached>5__8 = false; if (!<partialConsensus>5__7) { <partialConsensusStartTime>5__5 = null; } else if (!<partialConsensusStartTime>5__5.HasValue) { <partialConsensusStartTime>5__5 = Time.time; } else { <timeOutReached>5__8 = Time.time - <partialConsensusStartTime>5__5.Value >= 10f; } if (!(<allAccountedFor>5__6 | <timeOutReached>5__8)) { <>2__current = (object)new WaitForSeconds(<waitTime>5__4); <>1__state = 1; return true; } } if ((Object)(object)<>4__this != (Object)null) { Logger.LogInfo((object)$"Ready to proceed with playback. Ready: {<readyCount>5__2}, Errors: {<errorCount>5__3}, Total: {<totalPlayers>5__1} for url: {url}"); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static BoomBoxCartMod Instance = BoomBoxCartMod.instance; private Boombox boomboxParent = null; public static Dictionary<string, AudioClip> downloadedClips = new Dictionary<string, AudioClip>(); public static Dictionary<string, string> songTitles = new Dictionary<string, string>(); public static Dictionary<string, HashSet<int>> downloadsReady = new Dictionary<string, HashSet<int>>(); public static Dictionary<string, HashSet<int>> downloadErrors = new Dictionary<string, HashSet<int>>(); private const float DOWNLOAD_TIMEOUT = 40f; private const float TIMEOUT_THRESHOLD = 10f; private Dictionary<string, Coroutine> timeoutCoroutines = new Dictionary<string, Coroutine>(); private Queue<string> downloadJobQueue = new Queue<string>(); private bool isProcessingQueue = false; private string currentRequestId = null; private string currentDownloadUrl = null; private bool isTimeoutRecovery = false; private Coroutine processingCoroutine; private static readonly Regex[] supportedVideoUrlRegexes = new Regex[5] { new Regex("^(?<CleanedUrl>((?:https?:)?\\/\\/)?(((?:www|m)\\.)?((?:youtube(?:-nocookie)?\\.com|youtu\\.be))|music\\.youtube\\.com)(\\/(?:[\\w\\-]+\\?v=|embed\\/|live\\/|v\\/)?)([\\w\\-]+))(?<TrailingParams>(&(\\S+&)*?(t=(?<TimeStamp>(?<Seconds>\\d+)))\\S*)?\\S*?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), new Regex("^(?<CleanedUrl>((?:https?:)?\\/\\/)?((?:www)?\\.?)(rutube\\.ru)(\\/video\\/)([\\w\\-]+))(?<TrailingParams>(\\?(?:\\S+&)*?(t=(?<TimeStamp>(?<Seconds>\\d+)))\\S*)?\\S*?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), new Regex("^(?<CleanedUrl>((?:https?:)?\\/\\/)?((?:www)?\\.?)(music\\.yandex\\.ru)(\\/album\\/\\d+\\/track\\/)([\\w\\-]+))(?<TrailingParams>(?:\\?(\\S+&)*?(t=(?<TimeStamp>(?<Seconds>\\d+)))\\S*)?\\S*?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), new Regex("^(?<CleanedUrl>((?:https?:)?\\/\\/)?((?:www|m)\\.)?(bilibili\\.com)(\\/video\\/)([\\w\\-]+))(?<TrailingParams>(\\?(?:\\S+&)*?(t=(?<TimeStamp>(?<Seconds>\\d+)))\\S*)?\\S*?)$", RegexOptions.IgnoreCase | RegexOptions.Compiled), new Regex("^(?<CleanedUrl>((?:https?:)?\\/\\/)?((?:www|m)\\.)?(soundcloud\\.com|snd\\.sc)\\/([\\w\\-]+\\/[\\w\\-]+))(?<TrailingParams>(?:\\?(?:\\S+&*?#)*?t=(?<TimeStamp>(?<Minutes>\\d+)(?:\\/|(?:%3A))(?<Seconds>\\d{1,2})))?\\S*)?$", RegexOptions.IgnoreCase | RegexOptions.Compiled) }; private static ManualLogSource Logger => Instance.logger; private void Awake() { boomboxParent = ((Component)this).gameObject.GetComponent<Boombox>(); } private void OnDestroy() { downloadJobQueue.Clear(); foreach (Coroutine value in timeoutCoroutines.Values) { if (value != null) { ((MonoBehaviour)this).StopCoroutine(value); } } timeoutCoroutines.Clear(); } public bool IsProcessingQueue() { return isProcessingQueue; } public string GetCurrentDownloadUrl() { return currentDownloadUrl; } public static (string cleanedUrl, int seconds) IsValidVideoUrl(string url) { if (!string.IsNullOrWhiteSpace(url)) { Regex[] array = supportedVideoUrlRegexes; foreach (Regex regex in array) { Match match = regex.Match(url); if (!match.Success) { continue; } Group group = match.Groups["CleanedUrl"]; if (!group.Success) { continue; } Group group2 = match.Groups["TimeStamp"]; int num = 0; if (group2.Success) { Group group3 = match.Groups["Seconds"]; Group group4 = match.Groups["Minutes"]; if (group3.Success && int.TryParse(group3.Value, out var result)) { num = result; } if (group4.Success && int.TryParse(group4.Value, out var result2)) { num += result2 * 60; } } return (group.Value, num); } } return (null, 0); } public static int CheckDownloadCount(string url, bool includeErrors = false) { if (string.IsNullOrEmpty(url)) { return 0; } int num = 0; if (downloadsReady.ContainsKey(url)) { num += downloadsReady[url].Count; } if (downloadErrors.ContainsKey(url)) { num += downloadErrors[url].Count; } return num; } public void EnqueueDownload(string Url) { downloadJobQueue.Enqueue(Url); } public void DismissDownloadQueue() { downloadJobQueue.Clear(); } public void StartDownloadJob() { if (!isProcessingQueue) { processingCoroutine = ((MonoBehaviour)this).StartCoroutine(ProcessDownloadQueue()); } } public static float EstimateDownloadTimeSeconds(float songLength) { return 1.5f * songLength / 60f / 1.25f; } public void DownloadQueue(int startIndex) { if (startIndex < 0 || startIndex >= boomboxParent.data.playbackQueue.Count) { startIndex = 0; } for (int i = startIndex; i < boomboxParent.data.playbackQueue.Count; i++) { downloadJobQueue.Enqueue(boomboxParent.data.playbackQueue.ElementAt(i).Url); } for (int j = 0; j < startIndex; j++) { downloadJobQueue.Enqueue(boomboxParent.data.playbackQueue.ElementAt(j).Url); } StartDownloadJob(); } [PunRPC] public void NotifyPlayersOfErrors(string message) { Logger.LogWarning((object)message); boomboxParent.UpdateUIStatus(message); } [PunRPC] public void ReportDownloadError(int actorNumber, string url, string errorMessage) { if (actorNumber == PhotonNetwork.LocalPlayer.ActorNumber) { boomboxParent.UpdateUIStatus("Error: " + errorMessage); } if (PhotonNetwork.IsMasterClient) { Logger.LogError((object)$"Player {actorNumber} reported download error for {url}: {errorMessage}"); if (!downloadErrors.ContainsKey(url)) { downloadErrors[url] = new HashSet<int>(); } downloadErrors[url].Add(actorNumber); } } [PunRPC] public void SetSongTitle(string url, string title) { if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(title)) { return; } songTitles[url] = title; bool flag = false; if (boomboxParent?.data?.playbackQueue != null) { foreach (Boombox.AudioEntry item in boomboxParent.data.playbackQueue.FindAll((Boombox.AudioEntry entry) => entry.Url == url)) { if (item.Title != title) { item.Title = title; flag = true; } } } if (boomboxParent?.data?.currentSong != null && boomboxParent.data.currentSong.Url == url) { boomboxParent.data.currentSong.Title = title; if (boomboxParent.data.pendingPlaybackStart) { boomboxParent.UpdateUIStatus("Loading: " + title); } else if ((Object)(object)boomboxParent.data.currentSong.GetAudioClip() != (Object)null && boomboxParent.data.isPlaying) { boomboxParent.UpdateUIStatus("Now playing: " + title); } else if ((Object)(object)boomboxParent.data.currentSong.GetAudioClip() != (Object)null) { boomboxParent.UpdateUIStatus("Ready to play: " + title); } else { boomboxParent.UpdateUIStatus("Loading: " + title); } } if (flag) { Boombox boombox = boomboxParent; if (boombox != null) { ((Component)boombox).GetComponent<BoomboxUI>()?.UpdateDataFromBoomBox(); } if (PhotonNetwork.IsMasterClient) { boomboxParent.PublishSharedState(); } } } [IteratorStateMachine(typeof(<ProcessDownloadQueue>d__32))] private IEnumerator ProcessDownloadQueue() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ProcessDownloadQueue>d__32(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<MasterClientInitiateSync>d__33))] private IEnumerator MasterClientInitiateSync(string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MasterClientInitiateSync>d__33(0) { <>4__this = this, url = url }; } [IteratorStateMachine(typeof(<DownloadTimeoutCoroutine>d__34))] private IEnumerator DownloadTimeoutCoroutine(string requestId, string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DownloadTimeoutCoroutine>d__34(0) { <>4__this = this, requestId = requestId, url = url }; } [PunRPC] public async void StartDownloadAndSync(string url, int requesterId) { if (url == null) { return; } if (currentDownloadUrl != url) { currentDownloadUrl = url; if (!downloadsReady.ContainsKey(url)) { downloadsReady[url] = new HashSet<int>(); } if (!downloadErrors.ContainsKey(url)) { downloadErrors[url] = new HashSet<int>(); } } if (downloadedClips.ContainsKey(url)) { boomboxParent?.HandleDownloadedCurrentSong(); BaseListener.RPC(((MonoBehaviourPun)this).photonView, "ReportDownloadComplete", (RpcTarget)2, url, PhotonNetwork.LocalPlayer.ActorNumber); } else if (await StartAudioDownload(url) && (Object)(object)this != (Object)null) { boomboxParent?.HandleDownloadedCurrentSong(); BaseListener.RPC(((MonoBehaviourPun)this).photonView, "ReportDownloadComplete", (RpcTarget)2, url, PhotonNetwork.LocalPlayer.ActorNumber); } } [PunRPC] public void ReportDownloadComplete(string url, int actorNumber) { if (PhotonNetwork.IsMasterClient && url != null) { if (!downloadsReady.ContainsKey(url)) { downloadsReady[url] = new HashSet<int>(); } if (downloadErrors.ContainsKey(url) && downloadErrors[url].Contains(actorNumber)) { downloadErrors[url].Remove(actorNumber); } if (!downloadsReady[url].Contains(actorNumber)) { downloadsReady[url].Add(actorNumber); } } } [IteratorStateMachine(typeof(<WaitForPlayersReadyOrFailed>d__37))] private IEnumerator WaitForPlayersReadyOrFailed(string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForPlayersReadyOrFailed>d__37(0) { <>4__this = this, url = url }; } public static async Task<AudioClip> GetAudioClipAsync(string filePath) { await Task.Yield(); if (!File.Exists(filePath)) { throw new Exception("Audio file not found at path: " + filePath); } Uri fileUri = new Uri(filePath); string uri = fileUri.AbsoluteUri; UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(uri, (AudioType)13); try { www.timeout = 40; ((DownloadHandlerAudioClip)www.downloadHandler).streamAudio = true; TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); UnityWebRequestAsyncOperation operation = www.SendWebRequest(); ((AsyncOperation)operation).completed += delegate { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 if ((int)www.result != 1) { Logger.LogError((object)("Web request failed: " + www.error + ", URI: " + uri)); tcs.SetException(new Exception("Failed to load audio file: " + www.error)); } else { tcs.SetResult(result: true); } }; await tcs.Task; AudioClip clip = DownloadHandlerAudioClip.GetContent(www); if ((Object)(object)clip == (Object)null) { throw new Exception("Failed to get AudioClip content."); } return clip; } finally { if (www != null) { ((IDisposable)www).Dispose(); } } } public async Task<bool> StartAudioDownload(string url) { if (!downloadedClips.ContainsKey(url)) { try { string title = await YoutubeDL.DownloadAudioTitleAsync(url); songTitles[url] = title; BaseListener.RPC(((MonoBehaviourPun)this).photonView, "SetSongTitle", (RpcTarget)0, url, title); string filePath = await YoutubeDL.DownloadAudioAsync(url, title); if (boomboxParent?.data?.currentSong?.Url == url) { boomboxParent?.UpdateUIStatus("Processing audio: " + title); } AudioClip clip = await GetAudioClipAsync(filePath); downloadedClips[url] = clip; Logger.LogInfo((object)("Downloaded and cached clip for video: " + title)); } catch (Exception ex2) { Exception ex = ex2; if (boomboxParent?.data?.currentSong?.Url == url) { boomboxParent?.UpdateUIStatus("Error: " + ex.Message); } BaseListener.RPC(((MonoBehaviourPun)this).photonView, "ReportDownloadError", (RpcTarget)0, PhotonNetwork.LocalPlayer.ActorNumber, url, ex.Message); return false; } } if (boomboxParent?.data?.playbackQueue != null) { foreach (Boombox.AudioEntry song in boomboxParent.data.playbackQueue.FindAll((Boombox.AudioEntry entry) => entry.Url == url)) {