The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of BingBong BoomBox v1.2.0
BingBongBoomBox.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Web; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; using UnityEngine.Networking; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BingBongBoomBox")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6492a568987d6ea8c0bdfd4a1ed7f8f6158487b0")] [assembly: AssemblyProduct("BingBong BoomBox")] [assembly: AssemblyTitle("BingBongBoomBox")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BingBongPlayer { [BepInPlugin("com.damianmqr.bingbongplayer", "BingBongBoomBox", "1.2.0")] public class BingBongPlayerPlugin : BaseUnityPlugin { private enum SongLoadingState { Loaded, Loading, Error } [Serializable] private class SongMetadata { public string? title; } [Serializable] private class SongRequest { public string url = ""; public string hash = ""; public string requestedBy = ""; public int requestedByActor = -1; public string title = ""; } [Serializable] private class SongQueueWrapper { public List<SongRequest> items = new List<SongRequest>(); } [Serializable] private class HostConfigPayload { public bool publicEnqueue; public bool globalAudio; public bool bypassEnv; public bool allowDuplicates; public bool autoAdvance; public float maxHearingDistance; public int maxQueueSize; public int perUserQueueLimit; public string v; } [HarmonyPatch(typeof(Item))] private static class ItemPatches { private static bool IsBingBong(Item it) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) int result; if ((it.itemTags & 0x10) == 0) { ItemUIData uIData = it.UIData; if (uIData == null || !(uIData.itemName?.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) >= 0)) { string name = ((Object)it).name; result = ((name != null && name.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0); goto IL_0077; } } result = 1; goto IL_0077; IL_0077: return (byte)result != 0; } [HarmonyPostfix] [HarmonyPatch("Awake")] private static void Awake_Post(Item __instance) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Invalid comparison between Unknown and I4 if (!IsBingBong(__instance)) { return; } bingBong = ((Component)__instance).transform; Transform transform = ((Component)__instance).transform; bingBongMouth = null; Animator[] componentsInChildren = ((Component)transform).GetComponentsInChildren<Animator>(true); Animator[] array = componentsInChildren; foreach (Animator val in array) { try { AnimatorControllerParameter[] parameters = val.parameters; AnimatorControllerParameter val2 = null; AnimatorControllerParameter[] array2 = parameters; foreach (AnimatorControllerParameter val3 in array2) { if ((int)val3.type == 1 && val3.name.IndexOf("mouth", StringComparison.OrdinalIgnoreCase) >= 0) { val2 = val3; break; } } if (val2 != null) { mouthOpenParam = val2.name; mouthOpenHash = val2.nameHash; bingBongMouth = val; break; } } catch { } } } [HarmonyPrefix] [HarmonyPatch("OnDestroy")] private static void OnDestroy_Pre(Item __instance) { if ((Object)(object)bingBong == (Object)(object)((Component)__instance).transform) { mouthOpenParam = null; mouthOpenHash = 0; bingBongMouth = null; bingBong = null; } } } [CompilerGenerated] private sealed class <>c__DisplayClass136_0 { public int requestorActor; public List<string> lines; public Func<SongRequest, bool> <>9__3; internal bool <EnqueueYouTubePlaylist>b__0(SongRequest it) { return it.requestedByActor == requestorActor; } internal void <EnqueueYouTubePlaylist>b__1(object s, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data)) { lines.Add(e.Data); } } internal bool <EnqueueYouTubePlaylist>b__3(SongRequest it) { return it.requestedByActor == requestorActor; } } [CompilerGenerated] private sealed class <>c__DisplayClass136_1 { public string url; internal bool <EnqueueYouTubePlaylist>b__4(SongRequest it) { return it.url.Equals(url, StringComparison.OrdinalIgnoreCase); } } [CompilerGenerated] private sealed class <>c__DisplayClass144_0 { public string titleFromPrint; internal void <DownloadAudio>b__0(object s, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data) && e.Data.StartsWith("title-current:")) { titleFromPrint = e.Data.Substring("title-current:".Length).Trim(); } } } [CompilerGenerated] private sealed class <>c__DisplayClass155_0 { public string fetched; internal void <FetchTitleCoroutine>b__0(object s, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data) && e.Data.StartsWith("title-current:")) { fetched = e.Data.Substring("title-current:".Length).Trim(); } } } [CompilerGenerated] private sealed class <DebouncePlayCoroutine>d__141 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public string url; public string userId; public BingBongPlayerPlugin <>4__this; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DebouncePlayCoroutine>d__141(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(delay); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.PlayAudio(url, userId); 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 <DebounceRequestCoroutine>d__127 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public string url; public BingBongPlayerPlugin <>4__this; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DebounceRequestCoroutine>d__127(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(delay); <>1__state = 1; return true; case 1: { <>1__state = -1; PhotonView? photonView = BingBongPlayerPlugin.photonView; if (photonView != null) { photonView.RPC("RPC_RequestEnqueue", (RpcTarget)0, new object[2] { url, <>4__this.userId }); } 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 <DownloadAudio>d__144 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string url; public string outputPath; public string metadataPath; public BingBongPlayerPlugin <>4__this; private <>c__DisplayClass144_0 <>8__1; private ProcessStartInfo <psi>5__2; private Process <proc>5__3; private float <startTime>5__4; private SongMetadata <metadata>5__5; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DownloadAudio>d__144(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <psi>5__2 = null; <proc>5__3 = null; <metadata>5__5 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass144_0(); <>4__this.CleanupOldTempFiles(); <>4__this.songLoadingState = SongLoadingState.Loading; <>8__1.titleFromPrint = ""; if (string.IsNullOrEmpty(<>4__this.ytDlpPath) || !File.Exists(<>4__this.ytDlpPath) || string.IsNullOrEmpty(<>4__this.ffmpegPath) || !File.Exists(<>4__this.ffmpegPath)) { <>4__this.songLoadingState = SongLoadingState.Error; return false; } <psi>5__2 = new ProcessStartInfo { FileName = <>4__this.ytDlpPath, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; <psi>5__2.ArgumentList.Add("--no-playlist"); <psi>5__2.ArgumentList.Add("--max-filesize"); <psi>5__2.ArgumentList.Add($"{<>4__this.MaxAudioSizeMb}M"); <psi>5__2.ArgumentList.Add("--extractor-args"); <psi>5__2.ArgumentList.Add("youtube:player_client=tv_simply,default,-tv"); <psi>5__2.ArgumentList.Add("-x"); <psi>5__2.ArgumentList.Add("-f"); <psi>5__2.ArgumentList.Add("bestaudio[abr<=128]/bestaudio[abr<=160]/bestaudio"); <psi>5__2.ArgumentList.Add("--ffmpeg-location"); <psi>5__2.ArgumentList.Add(<>4__this.ffmpegPath); <psi>5__2.ArgumentList.Add("--audio-format"); <psi>5__2.ArgumentList.Add("wav"); <psi>5__2.ArgumentList.Add("--print"); <psi>5__2.ArgumentList.Add("title-current:%(title)s"); <psi>5__2.ArgumentList.Add("--no-simulate"); <psi>5__2.ArgumentList.Add("-o"); <psi>5__2.ArgumentList.Add(outputPath); <psi>5__2.ArgumentList.Add(url); <proc>5__3 = new Process { StartInfo = <psi>5__2 }; <proc>5__3.OutputDataReceived += delegate(object s, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data) && e.Data.StartsWith("title-current:")) { <>8__1.titleFromPrint = e.Data.Substring("title-current:".Length).Trim(); } }; <proc>5__3.ErrorDataReceived += delegate { }; try { <proc>5__3.Start(); } catch (Exception) { <>4__this.songLoadingState = SongLoadingState.Error; <>4__this.downloadCoroutine = null; return false; } <proc>5__3.BeginOutputReadLine(); <proc>5__3.BeginErrorReadLine(); <startTime>5__4 = Time.realtimeSinceStartup; break; case 1: <>1__state = -1; break; } if (!<proc>5__3.HasExited) { if (!(Time.realtimeSinceStartup - <startTime>5__4 > (float)(<>4__this.TitleProbeTimeoutSec + 60))) { <>2__current = null; <>1__state = 1; return true; } try { <proc>5__3.Kill(); } catch { } } if (File.Exists(outputPath)) { if (!string.IsNullOrWhiteSpace(<>8__1.titleFromPrint)) { <>4__this.currentSongTitle = <>8__1.titleFromPrint; } try { <metadata>5__5 = new SongMetadata { title = <>4__this.currentSongTitle }; File.WriteAllText(metadataPath, JsonUtility.ToJson((object)<metadata>5__5)); <metadata>5__5 = null; } catch { } <>4__this.currentPlaybackCoroutine = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.LoadAndPlay(outputPath)); } else { <>4__this.songLoadingState = SongLoadingState.Error; if (<>4__this.ActAsHost()) { <>4__this.PlayNextImpl(); } } <>4__this.downloadCoroutine = null; 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 <EnqueueYouTubePlaylist>d__136 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string playlistUrl; public string requestorId; public int requestorActor; public BingBongPlayerPlugin <>4__this; private <>c__DisplayClass136_0 <>8__1; private int <remainingQueueSlots>5__2; private int <userCount>5__3; private int <remainingUserSlots>5__4; private int <maxToAdd>5__5; private ProcessStartInfo <psi>5__6; private Process <proc>5__7; private bool <started>5__8; private float <startTime>5__9; private int <added>5__10; private List<string>.Enumerator <>s__11; private string <raw>5__12; private <>c__DisplayClass136_1 <>8__13; private int <tab>5__14; private string <title>5__15; private int <uCount>5__16; private bool <ok>5__17; private SongRequest <addedItem>5__18; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EnqueueYouTubePlaylist>d__136(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <psi>5__6 = null; <proc>5__7 = null; <>s__11 = default(List<string>.Enumerator); <raw>5__12 = null; <>8__13 = null; <title>5__15 = null; <addedItem>5__18 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass136_0(); <>8__1.requestorActor = requestorActor; if (string.IsNullOrEmpty(<>4__this.ytDlpPath) || !File.Exists(<>4__this.ytDlpPath)) { return false; } <remainingQueueSlots>5__2 = Math.Max(0, <>4__this.MaxQueueSize - <>4__this.queue.Count); <userCount>5__3 = <>4__this.queue.Count((SongRequest it) => it.requestedByActor == <>8__1.requestorActor); <remainingUserSlots>5__4 = Math.Max(0, <>4__this.PerUserQueueLimit - <userCount>5__3); <maxToAdd>5__5 = Math.Min(<remainingQueueSlots>5__2, <remainingUserSlots>5__4); if (<maxToAdd>5__5 <= 0) { return false; } <psi>5__6 = new ProcessStartInfo { FileName = <>4__this.ytDlpPath, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; <psi>5__6.ArgumentList.Add("--yes-playlist"); <psi>5__6.ArgumentList.Add("--flat-playlist"); <psi>5__6.ArgumentList.Add("--ignore-errors"); <psi>5__6.ArgumentList.Add("--playlist-items"); <psi>5__6.ArgumentList.Add($"1-{<maxToAdd>5__5}"); <psi>5__6.ArgumentList.Add("--print"); <psi>5__6.ArgumentList.Add("%(title)s\t%(webpage_url)s"); <psi>5__6.ArgumentList.Add(playlistUrl); <proc>5__7 = new Process { StartInfo = <psi>5__6 }; <>8__1.lines = new List<string>(); <proc>5__7.OutputDataReceived += delegate(object s, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data)) { <>8__1.lines.Add(e.Data); } }; <proc>5__7.ErrorDataReceived += delegate { }; <started>5__8 = false; try { <started>5__8 = <proc>5__7.Start(); } catch (Exception) { } if (!<started>5__8) { return false; } <proc>5__7.BeginOutputReadLine(); <proc>5__7.BeginErrorReadLine(); <startTime>5__9 = Time.realtimeSinceStartup; break; case 1: <>1__state = -1; break; } if (!<proc>5__7.HasExited) { if (!(Time.realtimeSinceStartup - <startTime>5__9 > (float)<>4__this.PlaylistProbeTimeoutSec)) { <>2__current = null; <>1__state = 1; return true; } try { <proc>5__7.Kill(); } catch { } } <added>5__10 = 0; <>s__11 = <>8__1.lines.GetEnumerator(); try { while (<>s__11.MoveNext()) { <raw>5__12 = <>s__11.Current; <>8__13 = new <>c__DisplayClass136_1(); if (string.IsNullOrWhiteSpace(<raw>5__12)) { continue; } <tab>5__14 = <raw>5__12.IndexOf('\t'); if (<tab>5__14 <= 0 || <tab>5__14 >= <raw>5__12.Length - 1) { continue; } <title>5__15 = <raw>5__12.Substring(0, <tab>5__14).Trim(); <>8__13.url = <raw>5__12.Substring(<tab>5__14 + 1).Trim(); if (<>4__this.queue.Count >= <>4__this.MaxQueueSize) { break; } <uCount>5__16 = <>4__this.queue.Count((SongRequest it) => it.requestedByActor == <>8__1.requestorActor); if (<uCount>5__16 >= <>4__this.PerUserQueueLimit) { break; } if (<>4__this.AllowDuplicates || !<>4__this.queue.Any((SongRequest it) => it.url.Equals(<>8__13.url, StringComparison.OrdinalIgnoreCase))) { <ok>5__17 = <>4__this.TryEnqueueInternal(<>8__13.url, requestorId, <>8__1.requestorActor, out <addedItem>5__18, <title>5__15); if (<ok>5__17 && <addedItem>5__18 != null) { <added>5__10++; } <>8__13 = null; <title>5__15 = null; <addedItem>5__18 = null; <raw>5__12 = null; } } } finally { ((IDisposable)<>s__11).Dispose(); } <>s__11 = default(List<string>.Enumerator); if (<added>5__10 > 0) { <>4__this.BroadcastQueue(); } if (<added>5__10 > 0 && !audioSource.isPlaying && <>4__this.songLoadingState != SongLoadingState.Loading) { <>4__this.PlayNextImpl(); } 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 <FetchTitleCoroutine>d__155 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string hash; public string url; public BingBongPlayerPlugin <>4__this; private <>c__DisplayClass155_0 <>8__1; private ProcessStartInfo <psi>5__2; private Process <proc>5__3; private bool <started>5__4; private float <startTime>5__5; private string <metadataPath>5__6; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FetchTitleCoroutine>d__155(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <psi>5__2 = null; <proc>5__3 = null; <metadataPath>5__6 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass155_0(); <>4__this.titleFetchInProgress.Add(hash); if (string.IsNullOrEmpty(<>4__this.ytDlpPath) || !File.Exists(<>4__this.ytDlpPath)) { <>4__this.titleFetchInProgress.Remove(hash); return false; } <>8__1.fetched = ""; <psi>5__2 = new ProcessStartInfo { FileName = <>4__this.ytDlpPath, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; <psi>5__2.ArgumentList.Add("--no-playlist"); <psi>5__2.ArgumentList.Add("--skip-download"); <psi>5__2.ArgumentList.Add("--print"); <psi>5__2.ArgumentList.Add("title-current:%(title)s"); <psi>5__2.ArgumentList.Add(url); <proc>5__3 = new Process { StartInfo = <psi>5__2 }; <proc>5__3.OutputDataReceived += delegate(object s, DataReceivedEventArgs e) { if (!string.IsNullOrEmpty(e.Data) && e.Data.StartsWith("title-current:")) { <>8__1.fetched = e.Data.Substring("title-current:".Length).Trim(); } }; <proc>5__3.ErrorDataReceived += delegate { }; <started>5__4 = false; try { <started>5__4 = <proc>5__3.Start(); } catch (Exception) { } if (!<started>5__4) { <>4__this.titleFetchInProgress.Remove(hash); return false; } <proc>5__3.BeginOutputReadLine(); <proc>5__3.BeginErrorReadLine(); <startTime>5__5 = Time.realtimeSinceStartup; break; case 1: <>1__state = -1; break; } if (!<proc>5__3.HasExited) { if (!(Time.realtimeSinceStartup - <startTime>5__5 > (float)<>4__this.TitleProbeTimeoutSec)) { <>2__current = null; <>1__state = 1; return true; } try { <proc>5__3.Kill(); } catch { } } if (!string.IsNullOrWhiteSpace(<>8__1.fetched)) { <>4__this.UpdateQueueTitle(hash, <>8__1.fetched); try { <metadataPath>5__6 = Path.Combine(<>4__this.tempAudioDir, "bingbong_" + hash + ".json"); File.WriteAllText(<metadataPath>5__6, JsonUtility.ToJson((object)new SongMetadata { title = <>8__1.fetched })); <metadataPath>5__6 = null; } catch { } } <>4__this.titleFetchInProgress.Remove(hash); 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 <LoadAndPlay>d__146 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string path; public BingBongPlayerPlugin <>4__this; private UnityWebRequest <www>5__1; private AudioClip <clip>5__2; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAndPlay>d__146(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <www>5__1 = null; <clip>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Invalid comparison between Unknown and I4 bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; if ((Object)(object)audioSource == (Object)null) { <>4__this.songLoadingState = SongLoadingState.Error; result = false; break; } <>4__this.songLoadingState = SongLoadingState.Loaded; <www>5__1 = UnityWebRequestMultimedia.GetAudioClip("file://" + path, (AudioType)20); <>1__state = -3; <>2__current = <www>5__1.SendWebRequest(); <>1__state = 1; result = true; break; case 1: <>1__state = -3; if ((int)<www>5__1.result != 1) { <>4__this.songLoadingState = SongLoadingState.Error; result = false; } else { <clip>5__2 = DownloadHandlerAudioClip.GetContent(<www>5__1); audioSource.clip = <clip>5__2; if (<>4__this.ActAsHost()) { audioSource.Play(); } result = false; } <>m__Finally1(); break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<www>5__1 != null) { ((IDisposable)<www>5__1).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static ManualLogSource? logger; private static AudioSource? audioSource; private static PhotonView? photonView; private string? ytDlpPath; private string? ffmpegPath; private string urlInput = ""; private Coroutine? currentPlaybackCoroutine; private Coroutine? debouncePlayCoroutine = null; private Coroutine? downloadCoroutine = null; private const ushort BingBongItemID = 13; private static string? mouthOpenParam = null; private static int mouthOpenHash = 0; public static Transform? bingBong = null; public static Animator? bingBongMouth = null; private ConfigEntry<float>? volumeSetting; private ConfigEntry<int>? maxAudioSizeMbCfg; private ConfigEntry<int>? maxTempFilesCfg; private ConfigEntry<int>? maxQueueSizeCfg; private ConfigEntry<int>? perUserQueueLimitCfg; private ConfigEntry<bool>? allowDuplicatesCfg; private ConfigEntry<bool>? autoAdvanceCfg; private ConfigEntry<int>? titleProbeTimeoutSecCfg; private ConfigEntry<int>? playlistProbeTimeoutSecCfg; private ConfigEntry<bool>? globalAudioCfg; private ConfigEntry<bool>? bypassEnvCfg; private ConfigEntry<bool>? publicEnqueueCfg; private ConfigEntry<float>? maxHearingDistanceCfg; private ConfigEntry<float>? uiScaleCfg; private ConfigEntry<bool>? showAdvancedCfg; private bool hostPublicEnqueue = false; private bool hostGlobalAudio = false; private bool hostBypassEnv = false; private bool hostAllowDuplicates = false; private bool hostAutoAdvance = true; private float hostMaxHearingDistance = 35f; private int hostMaxQueueSize = 20; private int hostPerUserQueueLimit = 5; private float syncInterval = 5f; private float lastSyncTime = 0f; private float lastConfigBroadcast = -999f; private bool sentInitialConfig = false; public float vocalLow = 300f; public float vocalHigh = 3400f; public int sampleSize = 256; public float currentVolume = 0.45f; public FFTWindow fftWindow = (FFTWindow)5; private bool lastConnectedState = false; private float[]? spectrumData; private string? tempAudioDir; private string currentSongTitle = ""; private string currentSongHash = ""; private string lastUsedPlayer = ""; private string userId = Guid.NewGuid().ToString(); private bool manualStop = false; private SongLoadingState songLoadingState = SongLoadingState.Loaded; public static readonly string[] LoadingProgress = new string[4] { "Loading.", "Loading..", "Loading...", "Loading" }; private bool hostHasMod = PhotonNetwork.IsMasterClient; private readonly List<SongRequest> queue = new List<SongRequest>(); private Vector2 queueScroll = Vector2.zero; private Vector2 panelScroll = Vector2.zero; private readonly HashSet<string> titleFetchInProgress = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private float spectrumTimer = 0f; private float spectrumInterval = 0.012f; private GUIStyle? boxStyle; private GUIStyle? labelStyle; private GUIStyle? buttonStyle; private GUIStyle? sliderStyle; private GUIStyle? sliderThumbStyle; private GUIStyle? headerStyle; private GUIStyle? smallLabelStyle; private GUIStyle? toggleStyle; private GUIStyle? foldoutStyle; private Texture2D? boxBgTex; private Texture2D? sliderBgTex; private Texture2D? sliderThumbTex; private Texture2D? buttonNormalBgTex; private Texture2D? buttonHoverBgTex; private bool initializedStyles; private float appliedUiScale = -1f; private static readonly string[] AllowedHosts = new string[20] { "youtube.com", "www.youtube.com", "m.youtube.com", "music.youtube.com", "www.music.youtube.com", "youtu.be", "www.youtu.be", "soundcloud.com", "www.soundcloud.com", "vimeo.com", "www.vimeo.com", "bandcamp.com", "www.bandcamp.com", "twitch.tv", "www.twitch.tv", "clips.twitch.tv", "tiktok.com", "www.tiktok.com", "mixcloud.com", "www.mixcloud.com" }; private int MaxAudioSizeMb => Mathf.Max(1, maxAudioSizeMbCfg?.Value ?? 100); private int MaxTempFiles => Mathf.Max(1, maxTempFilesCfg?.Value ?? 5); private int MaxQueueSize => Mathf.Max(1, (!ActAsHost()) ? ((hostMaxQueueSize > 0) ? hostMaxQueueSize : 20) : (maxQueueSizeCfg?.Value ?? 20)); private int PerUserQueueLimit => Mathf.Max(1, (!ActAsHost()) ? ((hostPerUserQueueLimit > 0) ? hostPerUserQueueLimit : 5) : (perUserQueueLimitCfg?.Value ?? 5)); private bool AllowDuplicates => (!ActAsHost()) ? hostAllowDuplicates : (allowDuplicatesCfg?.Value ?? false); private bool AutoAdvance => (!ActAsHost()) ? hostAutoAdvance : (autoAdvanceCfg?.Value ?? true); private int TitleProbeTimeoutSec => Mathf.Max(5, titleProbeTimeoutSecCfg?.Value ?? 20); private int PlaylistProbeTimeoutSec => Mathf.Max(5, playlistProbeTimeoutSecCfg?.Value ?? 30); private bool GlobalAudio => (!ActAsHost()) ? hostGlobalAudio : (globalAudioCfg?.Value ?? false); private bool BypassEnv => (!ActAsHost()) ? hostBypassEnv : (bypassEnvCfg?.Value ?? false); private bool PublicEnqueue => (!ActAsHost()) ? hostPublicEnqueue : (publicEnqueueCfg?.Value ?? false); private float MaxHearingDistance => Mathf.Clamp((!ActAsHost()) ? ((hostMaxHearingDistance <= 0f) ? 35f : hostMaxHearingDistance) : (maxHearingDistanceCfg?.Value ?? 35f), 5f, 10000f); private float UiScale => Mathf.Clamp(uiScaleCfg?.Value ?? 1f, 0.75f, 2f); private bool ShowAdvanced => showAdvancedCfg?.Value ?? false; private bool ActAsHost() { return PhotonNetwork.IsMasterClient || (!hostHasMod && lastUsedPlayer == userId); } private int LocalActor() { return (PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : (-1); } private int GetCurrentHolderActorNumber() { try { foreach (Player allPlayer in PlayerHandler.GetAllPlayers()) { if ((Object)(object)allPlayer == (Object)null || (Object)(object)allPlayer.character == (Object)null || !allPlayer.HasInAnySlot((ushort)13)) { continue; } int num = -1; try { Character character = allPlayer.character; int? obj; if (character == null) { obj = null; } else { PhotonView obj2 = ((MonoBehaviourPun)character).photonView; obj = ((obj2 != null) ? new int?(obj2.OwnerActorNr) : null); } int? num2 = obj; num = num2.GetValueOrDefault(-1); } catch { } if (num <= 0) { try { PhotonView obj4 = ((MonoBehaviourPun)allPlayer).photonView; num = ((obj4 != null) ? obj4.OwnerActorNr : (-1)); } catch { } } if (num <= 0) { continue; } return num; } } catch (Exception ex) { ManualLogSource? obj6 = logger; if (obj6 != null) { obj6.LogWarning((object)("GetCurrentHolderActorNumber failed: " + ex.Message)); } } return -1; } private bool IsRequestorHolder(int requestorActorNumber) { int currentHolderActorNumber = GetCurrentHolderActorNumber(); return currentHolderActorNumber > 0 && requestorActorNumber == currentHolderActorNumber; } private void Awake() { //IL_03a8: Unknown result type (might be due to invalid IL or missing references) logger = ((BaseUnityPlugin)this).Logger; photonView = ((Component)this).gameObject.AddComponent<PhotonView>(); photonView.ViewID = 215151321; spectrumData = new float[sampleSize]; string path = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath; ytDlpPath = Path.Combine(path, "yt-dlp.exe"); ffmpegPath = Path.Combine(path, "ffmpeg.exe"); tempAudioDir = Path.Combine(Path.GetTempPath(), "BingBongAudio"); Directory.CreateDirectory(tempAudioDir); CleanupOldTempFiles(); if (!File.Exists(ytDlpPath)) { ManualLogSource? obj = logger; if (obj != null) { obj.LogError((object)"yt-dlp.exe not found!"); } } if (!File.Exists(ffmpegPath)) { ManualLogSource? obj2 = logger; if (obj2 != null) { obj2.LogError((object)"ffmpeg.exe not found!"); } } volumeSetting = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 0.45f, "Default playback volume (0.0 to 1.0)"); currentVolume = Mathf.Clamp01(volumeSetting.Value); maxAudioSizeMbCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "MaxAudioSizeMB", 100, "Max file size yt-dlp may download."); maxTempFilesCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "MaxTempFiles", 5, "How many cached WAVs to keep."); maxQueueSizeCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "MaxQueueSize", 20, "Max items allowed in queue. (Host only)"); perUserQueueLimitCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Limits", "PerUserQueueLimit", 5, "Max items one user can have pending in the queue. (Host only)"); allowDuplicatesCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Queue", "AllowDuplicates", false, "Allow the same URL to be enqueued multiple times. (Host only)"); autoAdvanceCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Queue", "AutoAdvance", true, "Automatically advance to next track when one finishes. (Host only)"); titleProbeTimeoutSecCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Advanced", "TitleProbeTimeoutSec", 20, "Timeout for title probes (seconds)."); playlistProbeTimeoutSecCfg = ((BaseUnityPlugin)this).Config.Bind<int>("Advanced", "PlaylistProbeTimeoutSec", 30, "Timeout for playlist expansion (seconds)."); globalAudioCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "GlobalAudio", false, "2D audio heard anywhere. (Host only)"); bypassEnvCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "BypassEnvironmentEffects", false, "Bypass reverb/occlusion. (Host only)"); maxHearingDistanceCfg = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "MaxHearingDistance", 35f, "3D audio max distance. (Host only)"); publicEnqueueCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Queue", "PublicEnqueue", false, "Non-holders may add and control playback. (Host only)"); uiScaleCfg = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "UiScale", 1f, "Scale UI text/vertical only (client)"); showAdvancedCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowAdvanced", false, "Show Advanced section (client)"); audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource.spatialBlend = 1f; audioSource.volume = currentVolume; audioSource.loop = false; audioSource.rolloffMode = (AudioRolloffMode)1; audioSource.minDistance = 1f; audioSource.maxDistance = MaxHearingDistance; audioSource.bypassEffects = BypassEnv; audioSource.bypassListenerEffects = BypassEnv; audioSource.bypassReverbZones = BypassEnv; new Harmony("com.damianmqr.bingbongplayer").PatchAll(); } private void OnDestroy() { if (currentPlaybackCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(currentPlaybackCoroutine); } if (debouncePlayCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(debouncePlayCoroutine); } if (downloadCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(downloadCoroutine); } } private void LateUpdate() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) bool flag = (int)PhotonNetwork.Server == 1; if (lastConnectedState && !flag) { StopAndResetSong(); queue.Clear(); sentInitialConfig = false; } lastConnectedState = flag; if ((Object)(object)audioSource == (Object)null || !PhotonNetwork.IsConnectedAndReady || (Object)(object)photonView == (Object)null) { return; } if (ActAsHost()) { if (!sentInitialConfig) { BroadcastHostConfig(); sentInitialConfig = true; } if (Time.time - lastConfigBroadcast > 15f) { BroadcastHostConfig(); } } if (ActAsHost() && Time.time - lastSyncTime > syncInterval) { photonView.RPC("RPC_SyncPlaying", (RpcTarget)1, new object[4] { currentSongHash, audioSource.isPlaying, PhotonNetwork.IsMasterClient, currentSongTitle }); if (audioSource.isPlaying) { photonView.RPC("RPC_SyncTime", (RpcTarget)1, new object[2] { currentSongHash, audioSource.time }); } lastSyncTime = Time.time; } bool flag2 = Singleton<PeakHandler>.Instance?.isPlayingCinematic ?? false; Vector3? val = null; if ((Object)(object)bingBong != (Object)null) { val = bingBong.position; } else { Player? obj = FindPlayerWithBingBong(); Vector3? obj2; if (obj == null) { obj2 = null; } else { Character character = obj.character; obj2 = ((character != null) ? new Vector3?(character.Center) : null); } val = obj2; } if (GlobalAudio) { audioSource.spatialBlend = 0f; audioSource.volume = currentVolume; } else { audioSource.spatialBlend = (flag2 ? 0f : 1f); audioSource.maxDistance = MaxHearingDistance; audioSource.volume = (val.HasValue ? currentVolume : 0f); if (val.HasValue) { ((Component)audioSource).transform.position = val.Value; } } audioSource.bypassEffects = BypassEnv; audioSource.bypassListenerEffects = BypassEnv; audioSource.bypassReverbZones = BypassEnv; if (ActAsHost() && AutoAdvance && !manualStop && (Object)(object)audioSource.clip != (Object)null && !audioSource.isPlaying && !string.IsNullOrEmpty(currentSongHash) && songLoadingState == SongLoadingState.Loaded) { PlayNextImpl(); } if (!((Object)(object)audioSource != (Object)null) || !((Object)(object)bingBongMouth != (Object)null) || mouthOpenParam == null) { return; } spectrumTimer += Time.deltaTime; if (!(spectrumTimer >= spectrumInterval)) { return; } spectrumTimer = 0f; float num = 0f; if (audioSource.isPlaying && spectrumData != null && (Object)(object)audioSource.clip != (Object)null) { audioSource.GetSpectrumData(spectrumData, 0, fftWindow); float num2 = (float)AudioSettings.outputSampleRate / 2f / (float)sampleSize; int num3 = Mathf.FloorToInt(vocalLow / num2); int num4 = Mathf.CeilToInt(vocalHigh / num2); num3 = Mathf.Clamp(num3, 0, sampleSize - 1); num4 = Mathf.Clamp(num4, 0, sampleSize - 1); float num5 = 0f; int num6 = 0; for (int i = num3; i <= num4; i++) { num5 += spectrumData[i]; num6++; } float num7 = ((num6 > 0) ? (num5 / (float)num6) : 0f); num = Mathf.Clamp01(num7 * 50f); } try { bingBongMouth.SetFloat(mouthOpenHash, num); } catch { } } private void BroadcastHostConfig() { lastConfigBroadcast = Time.time; HostConfigPayload hostConfigPayload = new HostConfigPayload { publicEnqueue = PublicEnqueue, globalAudio = GlobalAudio, bypassEnv = BypassEnv, allowDuplicates = AllowDuplicates, autoAdvance = AutoAdvance, maxHearingDistance = MaxHearingDistance, maxQueueSize = MaxQueueSize, perUserQueueLimit = PerUserQueueLimit, v = "1.2.0" }; PhotonView? obj = photonView; if (obj != null) { obj.RPC("RPC_ConfigSync", (RpcTarget)1, new object[1] { JsonUtility.ToJson((object)hostConfigPayload) }); } } [PunRPC] private void RPC_ConfigSync(string json) { try { HostConfigPayload hostConfigPayload = JsonUtility.FromJson<HostConfigPayload>(json); if (hostConfigPayload != null) { hostPublicEnqueue = hostConfigPayload.publicEnqueue; hostGlobalAudio = hostConfigPayload.globalAudio; hostBypassEnv = hostConfigPayload.bypassEnv; hostAllowDuplicates = hostConfigPayload.allowDuplicates; hostAutoAdvance = hostConfigPayload.autoAdvance; hostMaxHearingDistance = hostConfigPayload.maxHearingDistance; hostMaxQueueSize = hostConfigPayload.maxQueueSize; hostPerUserQueueLimit = hostConfigPayload.perUserQueueLimit; } } catch { } } private Player? FindPlayerWithBingBong() { foreach (Player allPlayer in PlayerHandler.GetAllPlayers()) { if ((Object)(object)allPlayer.character != (Object)null && allPlayer.HasInAnySlot((ushort)13)) { return allPlayer; } } return null; } private Texture2D MakeSolidColorTex(Color col) { //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, col); val.Apply(); return val; } private void InitStyles() { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Expected O, but got Unknown //IL_0281: Expected O, but got Unknown //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Expected O, but got Unknown //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Expected O, but got Unknown //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Expected O, but got Unknown //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Expected O, but got Unknown //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Expected O, but got Unknown if (initializedStyles && Mathf.Abs(appliedUiScale - UiScale) < 0.001f) { return; } appliedUiScale = UiScale; Font val = null; Font[] array = Resources.FindObjectsOfTypeAll<Font>(); foreach (Font val2 in array) { if (((Object)val2).name == "DarumaDropOne-Regular") { val = val2; break; } } if (!((Object)(object)val == (Object)null) || PhotonNetwork.IsConnectedAndReady) { boxBgTex = MakeSolidColorTex(new Color(0f, 0f, 0f, 0.8f)); int num = Mathf.RoundToInt(12f * UiScale); GUIStyle val3 = new GUIStyle(GUI.skin.box) { padding = new RectOffset(12, 12, num, num), margin = new RectOffset(10, 10, 10, 10) }; val3.normal.background = boxBgTex; boxStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.label) { fontSize = Mathf.RoundToInt(14f * UiScale) }; val4.normal.textColor = Color.white; val4.richText = true; labelStyle = val4; GUIStyle val5 = new GUIStyle(GUI.skin.label) { fontSize = Mathf.RoundToInt(12f * UiScale) }; val5.normal.textColor = Color.white; val5.richText = true; smallLabelStyle = val5; GUIStyle val6 = new GUIStyle(GUI.skin.label) { fontSize = Mathf.RoundToInt(22f * UiScale) }; val6.normal.textColor = Color.white; val6.richText = true; headerStyle = val6; toggleStyle = new GUIStyle(GUI.skin.toggle) { fontSize = Mathf.RoundToInt(13f * UiScale) }; foldoutStyle = new GUIStyle(GUI.skin.button) { fontSize = Mathf.RoundToInt(13f * UiScale), alignment = (TextAnchor)3, padding = new RectOffset(8, 8, Mathf.RoundToInt(6f * UiScale), Mathf.RoundToInt(6f * UiScale)) }; buttonNormalBgTex = MakeSolidColorTex(new Color(0.2f, 0.2f, 0.2f, 0.95f)); buttonHoverBgTex = MakeSolidColorTex(new Color(0.3f, 0.3f, 0.3f, 0.95f)); GUIStyle val7 = new GUIStyle(GUI.skin.button) { fontSize = Mathf.RoundToInt(13f * UiScale), margin = new RectOffset(5, 5, 5, 5), padding = new RectOffset(8, 8, Mathf.RoundToInt(6f * UiScale), Mathf.RoundToInt(6f * UiScale)) }; val7.normal.background = buttonNormalBgTex; val7.hover.background = buttonHoverBgTex; buttonStyle = val7; sliderBgTex = MakeSolidColorTex(new Color(0.15f, 0.15f, 0.15f, 1f)); sliderThumbTex = MakeSolidColorTex(new Color(1f, 0.6f, 0f, 1f)); GUIStyle val8 = new GUIStyle(GUI.skin.horizontalSlider); val8.normal.background = sliderBgTex; val8.fixedHeight = Mathf.RoundToInt(12f * UiScale); sliderStyle = val8; GUIStyle val9 = new GUIStyle(GUI.skin.horizontalSliderThumb); val9.normal.background = sliderThumbTex; val9.fixedWidth = Mathf.RoundToInt(16f * UiScale); val9.fixedHeight = Mathf.RoundToInt(16f * UiScale); sliderThumbStyle = val9; if ((Object)(object)val != (Object)null) { labelStyle.font = val; smallLabelStyle.font = val; headerStyle.font = val; buttonStyle.font = val; toggleStyle.font = val; foldoutStyle.font = val; } initializedStyles = true; } } private void OnGUI() { //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0e0e: Unknown result type (might be due to invalid IL or missing references) //IL_0e32: Unknown result type (might be due to invalid IL or missing references) //IL_0e37: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.localPlayer == (Object)null || (Object)(object)photonView == (Object)null) { return; } InitStyles(); if (!initializedStyles) { return; } GUIManager instance = GUIManager.instance; if (instance != null) { GameObject pauseMenu = instance.pauseMenu; if (((pauseMenu != null) ? new bool?(pauseMenu.activeSelf) : null).GetValueOrDefault()) { float num = 10f; float num2 = Mathf.Min(720f, (float)Screen.width - 2f * num); float num3 = (float)Screen.height - 2f * num; Rect val = default(Rect); ((Rect)(ref val))..ctor(num, num, num2, num3); GUILayout.BeginArea(val, boxStyle); panelScroll = GUILayout.BeginScrollView(panelScroll, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(num2 - 8f), GUILayout.Height(num3 - 8f) }); GUILayout.Label("【BingBong Player】", headerStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label(ActAsHost() ? "※ You are the acting host." : "※ Waiting for host…", smallLabelStyle, Array.Empty<GUILayoutOption>()); bool flag = Player.localPlayer.HasInAnySlot((ushort)13); if (flag || PublicEnqueue) { GUILayout.Space(4f * UiScale); GUILayout.Label("URL:", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); urlInput = GUILayout.TextField(urlInput, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(num2 - 180f), GUILayout.Height(26f * UiScale) }); if (GUILayout.Button("Clear", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(70f), GUILayout.Height(26f * UiScale) })) { urlInput = ""; } if (GUILayout.Button("Add »", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(70f), GUILayout.Height(26f * UiScale) })) { RequestEnqueue(urlInput); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool enabled = flag || PublicEnqueue; GUI.enabled = enabled; if (GUILayout.Button("Stop", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f * UiScale) })) { photonView.RPC("RPC_RequestStop", (RpcTarget)0, Array.Empty<object>()); } if (GUILayout.Button("〈〈 10s", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f * UiScale) })) { photonView.RPC("RPC_RequestSeek", (RpcTarget)0, new object[1] { -10f }); } if (GUILayout.Button("10s 〉〉", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f * UiScale) })) { photonView.RPC("RPC_RequestSeek", (RpcTarget)0, new object[1] { 10f }); } if (GUILayout.Button("Next »", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f * UiScale) })) { photonView.RPC("RPC_RequestNext", (RpcTarget)0, Array.Empty<object>()); } GUI.enabled = true; if (!flag && PublicEnqueue) { GUILayout.Label("※ Public enqueue is enabled.", smallLabelStyle, Array.Empty<GUILayoutOption>()); } GUILayout.EndHorizontal(); } GUILayout.Space(8f * UiScale); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f * UiScale); GUILayout.Label($"Local Volume: {Mathf.RoundToInt(currentVolume * 100f)}%", labelStyle, Array.Empty<GUILayoutOption>()); float num4 = GUILayout.HorizontalSlider(currentVolume, 0f, 1f, sliderStyle, sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num2 - 40f) }); if (Mathf.Abs(num4 - currentVolume) > 0.001f) { currentVolume = num4; if (volumeSetting != null) { volumeSetting.Value = num4; } if ((Object)(object)audioSource != (Object)null) { audioSource.volume = currentVolume; } } GUILayout.Space(8f * UiScale); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f * UiScale); bool flag2 = ShowAdvanced; string text = (flag2 ? "▼ Advanced" : "► Advanced"); if (GUILayout.Button(text, foldoutStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f * UiScale) })) { flag2 = !flag2; if (showAdvancedCfg != null) { showAdvancedCfg.Value = flag2; } } if (flag2) { bool enabled2 = ActAsHost(); GUI.enabled = enabled2; bool flag3 = GUILayout.Toggle(GlobalAudio, " Global Audio (2D / Hear Anywhere)", toggleStyle, Array.Empty<GUILayoutOption>()); bool flag4 = GUILayout.Toggle(BypassEnv, " Bypass Environment Effects", toggleStyle, Array.Empty<GUILayoutOption>()); bool flag5 = GUILayout.Toggle(PublicEnqueue, " Allow Public Enqueue (add/controls)", toggleStyle, Array.Empty<GUILayoutOption>()); if (flag3 != GlobalAudio) { globalAudioCfg.Value = flag3; BroadcastHostConfig(); } if (flag4 != BypassEnv) { bypassEnvCfg.Value = flag4; BroadcastHostConfig(); } if (flag5 != PublicEnqueue) { publicEnqueueCfg.Value = flag5; BroadcastHostConfig(); } if (!GlobalAudio) { GUILayout.Label($"Max Hearing Distance: {Mathf.RoundToInt(MaxHearingDistance)}m", labelStyle, Array.Empty<GUILayoutOption>()); float num5 = GUILayout.HorizontalSlider(MaxHearingDistance, 5f, 300f, sliderStyle, sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num2 - 40f) }); if (Mathf.Abs(num5 - MaxHearingDistance) > 0.001f) { maxHearingDistanceCfg.Value = num5; BroadcastHostConfig(); } } GUILayout.Label($"Max Queue Size: {MaxQueueSize}", smallLabelStyle, Array.Empty<GUILayoutOption>()); int num6 = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)MaxQueueSize, 5f, 50f, sliderStyle, sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num2 - 40f) })); if (num6 != MaxQueueSize) { maxQueueSizeCfg.Value = num6; BroadcastHostConfig(); } GUILayout.Label($"Per-User Queue Limit: {PerUserQueueLimit}", smallLabelStyle, Array.Empty<GUILayoutOption>()); int num7 = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)PerUserQueueLimit, 1f, 15f, sliderStyle, sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num2 - 40f) })); if (num7 != PerUserQueueLimit) { perUserQueueLimitCfg.Value = num7; BroadcastHostConfig(); } bool flag6 = GUILayout.Toggle(AllowDuplicates, " Allow Duplicate URLs", toggleStyle, Array.Empty<GUILayoutOption>()); if (flag6 != AllowDuplicates) { allowDuplicatesCfg.Value = flag6; BroadcastHostConfig(); } bool flag7 = GUILayout.Toggle(AutoAdvance, " Auto-Advance", toggleStyle, Array.Empty<GUILayoutOption>()); if (flag7 != AutoAdvance) { autoAdvanceCfg.Value = flag7; BroadcastHostConfig(); } GUI.enabled = true; GUILayout.Label($"UI Scale: {UiScale:0.00}x", smallLabelStyle, Array.Empty<GUILayoutOption>()); float num8 = GUILayout.HorizontalSlider(UiScale, 0.75f, 2f, sliderStyle, sliderThumbStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num2 - 40f) }); if (Mathf.Abs(num8 - UiScale) > 0.001f) { uiScaleCfg.Value = num8; } } if (songLoadingState == SongLoadingState.Loading) { GUILayout.Space(8f * UiScale); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f * UiScale); int num9 = Mathf.FloorToInt(Time.time) % LoadingProgress.Length; GUILayout.Label(LoadingProgress[num9], labelStyle, Array.Empty<GUILayoutOption>()); } else if (songLoadingState == SongLoadingState.Error) { GUILayout.Space(8f * UiScale); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f * UiScale); GUILayout.Label("ERROR! Couldn't load audio.", labelStyle, Array.Empty<GUILayoutOption>()); } else if (!string.IsNullOrEmpty(currentSongTitle)) { AudioSource? obj = audioSource; if ((Object)(object)((obj != null) ? obj.clip : null) != (Object)null && (audioSource.isPlaying || audioSource.time > 0f)) { GUILayout.Space(8f * UiScale); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f * UiScale); GUILayout.Label("Now Playing: 「" + currentSongTitle + "」", labelStyle, Array.Empty<GUILayoutOption>()); int num10 = Mathf.FloorToInt(audioSource.time / 60f); int num11 = Mathf.FloorToInt(audioSource.time % 60f); int num12 = Mathf.FloorToInt(audioSource.clip.length / 60f); int num13 = Mathf.FloorToInt(audioSource.clip.length % 60f); GUILayout.Label($"{num10:D2}:{num11:D2} / {num12:D2}:{num13:D2}", labelStyle, Array.Empty<GUILayoutOption>()); } } GUILayout.Space(8f * UiScale); GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.Height(1f) }); GUILayout.Space(8f * UiScale); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label($"【Queue】 ({queue.Count}/{MaxQueueSize})", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (flag || PublicEnqueue) { if (GUILayout.Button("〜 Shuffle", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f * UiScale) })) { photonView.RPC("RPC_RequestShuffle", (RpcTarget)0, Array.Empty<object>()); } if (GUILayout.Button("[ ] Clear", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f * UiScale) })) { photonView.RPC("RPC_RequestClearQueue", (RpcTarget)0, Array.Empty<object>()); } } GUILayout.EndHorizontal(); float num14 = 140f * UiScale; float num15 = Mathf.Clamp((float)Screen.height * 0.65f, 160f, (float)Screen.height - 260f); float num16 = 22f * UiScale; float num17 = Mathf.Clamp((float)queue.Count * num16 + 8f, num14, num15); queueScroll = GUILayout.BeginScrollView(queueScroll, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(num17), GUILayout.Width(num2 - 20f) }); for (int i = 0; i < queue.Count; i++) { SongRequest songRequest = queue[i]; string arg = (string.IsNullOrEmpty(songRequest.title) ? "Fetching title…" : songRequest.title); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label($"{i + 1}. • {arg} ({ShortId(songRequest.requestedBy)})", smallLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num2 - 180f) }); bool enabled3 = flag || PublicEnqueue || songRequest.requestedByActor == LocalActor(); GUI.enabled = enabled3; if (GUILayout.Button("Remove", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { photonView.RPC("RPC_RequestRemoveAt", (RpcTarget)0, new object[1] { i }); } GUI.enabled = true; GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); GUILayout.EndScrollView(); GUILayout.EndArea(); return; } } if (Player.localPlayer.HasInAnySlot((ushort)13)) { GUILayout.BeginArea(new Rect(10f, 10f, 480f, (float)Mathf.RoundToInt(100f * UiScale))); GUILayout.Label("<b>Press [ESC] to access Music Player</b>", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.EndArea(); } } private string ShortId(string id) { return string.IsNullOrEmpty(id) ? "??" : ((id.Length <= 6) ? id : id.Substring(0, 6)); } private void RequestEnqueue(string url) { if (!string.IsNullOrWhiteSpace(url) && IsSupportedMediaUrl(url)) { if (debouncePlayCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(debouncePlayCoroutine); debouncePlayCoroutine = null; } debouncePlayCoroutine = ((MonoBehaviour)this).StartCoroutine(DebounceRequestCoroutine(0.4f, url)); } } [IteratorStateMachine(typeof(<DebounceRequestCoroutine>d__127))] private IEnumerator DebounceRequestCoroutine(float delay, string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DebounceRequestCoroutine>d__127(0) { <>4__this = this, delay = delay, url = url }; } [PunRPC] private void RPC_RequestEnqueue(string url, string requestorId, PhotonMessageInfo info) { //IL_0028: 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) if (!IsSupportedMediaUrl(url) || !ActAsHost()) { return; } int requestorActor = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); if (IsYouTubePlaylistUrl(url)) { ((MonoBehaviour)this).StartCoroutine(EnqueueYouTubePlaylist(url, requestorId, requestorActor)); return; } SongRequest addedItem; bool flag = TryEnqueueInternal(url, requestorId, requestorActor, out addedItem, null); BroadcastQueue(); if (flag && addedItem != null && string.IsNullOrEmpty(addedItem.title)) { StartTitleFetchIfNeeded(addedItem.hash, addedItem.url); } if (!audioSource.isPlaying && songLoadingState != SongLoadingState.Loading) { PlayNextImpl(); } } [PunRPC] private void RPC_RequestRemoveAt(int index, PhotonMessageInfo info) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (ActAsHost() && index >= 0 && index < queue.Count) { int num = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); SongRequest songRequest = queue[index]; if (songRequest.requestedByActor == num || IsRequestorHolder(num) || PublicEnqueue) { queue.RemoveAt(index); BroadcastQueue(); } } } [PunRPC] private void RPC_RequestClearQueue(PhotonMessageInfo info) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (ActAsHost()) { int requestorActorNumber = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); if (PublicEnqueue || IsRequestorHolder(requestorActorNumber)) { queue.Clear(); BroadcastQueue(); } } } [PunRPC] private void RPC_RequestNext(PhotonMessageInfo info) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (ActAsHost()) { int requestorActorNumber = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); if (PublicEnqueue || IsRequestorHolder(requestorActorNumber)) { PlayNextImpl(); } } } [PunRPC] private void RPC_RequestShuffle(PhotonMessageInfo info) { //IL_0013: 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) if (!ActAsHost()) { return; } int requestorActorNumber = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); if (PublicEnqueue || IsRequestorHolder(requestorActorNumber)) { Random random = new Random(); for (int num = queue.Count - 1; num > 0; num--) { int num2 = random.Next(num + 1); List<SongRequest> list = queue; int index = num; List<SongRequest> list2 = queue; int index2 = num2; SongRequest value = queue[num2]; SongRequest value2 = queue[num]; list[index] = value; list2[index2] = value2; } BroadcastQueue(); } } [PunRPC] private void RPC_RequestStop(PhotonMessageInfo info) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (ActAsHost()) { int requestorActorNumber = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); if (PublicEnqueue || IsRequestorHolder(requestorActorNumber)) { photonView.RPC("RPC_StopAudio", (RpcTarget)0, Array.Empty<object>()); } } } [PunRPC] private void RPC_RequestSeek(float seconds, PhotonMessageInfo info) { //IL_0013: 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) if (ActAsHost()) { int requestorActorNumber = ((info.Sender != null) ? info.Sender.ActorNumber : (-1)); if ((PublicEnqueue || IsRequestorHolder(requestorActorNumber)) && !((Object)(object)audioSource == (Object)null) && !((Object)(object)audioSource.clip == (Object)null)) { float num = Mathf.Clamp(audioSource.time + seconds, 0f, audioSource.clip.length); audioSource.time = num; photonView.RPC("RPC_SyncTime", (RpcTarget)1, new object[2] { currentSongHash, num }); } } } private bool IsYouTubePlaylistUrl(string url) { if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result)) { return false; } string text = result.Host.ToLowerInvariant(); if (!text.Contains("youtube.com") && !text.Contains("youtu.be") && !text.Contains("music.youtube.com")) { return false; } NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(result.Query); bool flag = !string.IsNullOrEmpty(nameValueCollection["list"]); bool flag2 = false; if (text.Contains("youtu.be")) { string value = result.AbsolutePath.Trim('/'); flag2 = !string.IsNullOrEmpty(value); } else { string value2 = nameValueCollection["v"]; if (!string.IsNullOrEmpty(value2)) { flag2 = true; } string text2 = result.AbsolutePath.ToLowerInvariant(); if (text2.StartsWith("/shorts/")) { flag2 = true; } } return flag && !flag2; } [IteratorStateMachine(typeof(<EnqueueYouTubePlaylist>d__136))] private IEnumerator EnqueueYouTubePlaylist(string playlistUrl, string requestorId, int requestorActor) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EnqueueYouTubePlaylist>d__136(0) { <>4__this = this, playlistUrl = playlistUrl, requestorId = requestorId, requestorActor = requestorActor }; } private bool TryEnqueueInternal(string url, string requestorId, int requestorActor, out SongRequest? addedItem, string? knownTitle) { string url2 = url; addedItem = null; if (queue.Count >= MaxQueueSize) { return false; } int num = queue.Count((SongRequest it) => it.requestedByActor == requestorActor); if (num >= PerUserQueueLimit) { return false; } if (!AllowDuplicates && queue.Any((SongRequest it) => it.url.Equals(url2, StringComparison.OrdinalIgnoreCase))) { return false; } string safeSongId = GetSafeSongId(url2); string path = Path.Combine(tempAudioDir, "bingbong_" + safeSongId + ".json"); string text = knownTitle ?? ""; if (string.IsNullOrEmpty(text) && File.Exists(path)) { try { text = JsonUtility.FromJson<SongMetadata>(File.ReadAllText(path))?.title ?? ""; } catch { text = ""; } } SongRequest songRequest = new SongRequest { url = url2, hash = safeSongId, requestedBy = requestorId, requestedByActor = requestorActor, title = text }; queue.Add(songRequest); addedItem = songRequest; if (!string.IsNullOrEmpty(text)) { try { File.WriteAllText(path, JsonUtility.ToJson((object)new SongMetadata { title = text })); } catch { } } if (string.IsNullOrEmpty(text)) { StartTitleFetchIfNeeded(safeSongId, url2); } return true; } private void PlayNextImpl() { manualStop = false; if (queue.Count == 0) { StopAndResetSong(); BroadcastQueue(); return; } SongRequest songRequest = queue[0]; queue.RemoveAt(0); BroadcastQueue(); lastUsedPlayer = songRequest.requestedBy; PhotonView? obj = photonView; if (obj != null) { obj.RPC("RPC_StopAudio", (RpcTarget)0, Array.Empty<object>()); } PlayAudio(songRequest.url, lastUsedPlayer); if (string.IsNullOrEmpty(songRequest.title)) { StartTitleFetchIfNeeded(songRequest.hash, songRequest.url); } } private void BroadcastQueue() { SongQueueWrapper songQueueWrapper = new SongQueueWrapper { items = queue }; string text = JsonUtility.ToJson((object)songQueueWrapper); photonView.RPC("RPC_SyncQueue", (RpcTarget)1, new object[1] { text }); } [PunRPC] private void RPC_SyncQueue(string json) { try { SongQueueWrapper songQueueWrapper = JsonUtility.FromJson<SongQueueWrapper>(json); if (songQueueWrapper != null && songQueueWrapper.items != null) { queue.Clear(); queue.AddRange(songQueueWrapper.items.Take(MaxQueueSize)); } } catch { } } [IteratorStateMachine(typeof(<DebouncePlayCoroutine>d__141))] private IEnumerator DebouncePlayCoroutine(float delay, string url, string userId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DebouncePlayCoroutine>d__141(0) { <>4__this = this, delay = delay, url = url, userId = userId }; } [PunRPC] private void RPC_PlayAudio(string url, string userId, PhotonMessageInfo info) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((info.Sender == null || info.Sender.IsMasterClient || !hostHasMod) && !string.IsNullOrWhiteSpace(url) && IsSupportedMediaUrl(url)) { if (debouncePlayCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(debouncePlayCoroutine); debouncePlayCoroutine = null; } debouncePlayCoroutine = ((MonoBehaviour)this).StartCoroutine(DebouncePlayCoroutine(1f, url, userId)); } } private void PlayAudio(string url, string userId) { debouncePlayCoroutine = null; if (string.IsNullOrWhiteSpace(url) || !IsSupportedMediaUrl(url)) { return; } lastUsedPlayer = userId; manualStop = false; if (ActAsHost()) { AudioSource? obj = audioSource; if (obj != null) { obj.Stop(); } PhotonView? obj2 = photonView; if (obj2 != null) { obj2.RPC("RPC_StopAudio", (RpcTarget)1, Array.Empty<object>()); } PhotonView? obj3 = photonView; if (obj3 != null) { obj3.RPC("RPC_PlayAudio", (RpcTarget)1, new object[2] { url, userId }); } } currentSongTitle = "Unknown"; currentSongHash = GetSafeSongId(url); string text = Path.Combine(tempAudioDir, "bingbong_" + currentSongHash + ".wav"); string text2 = Path.Combine(tempAudioDir, "bingbong_" + currentSongHash + ".json"); if (File.Exists(text2)) { try { string text3 = File.ReadAllText(text2); SongMetadata songMetadata = JsonUtility.FromJson<SongMetadata>(text3); if (!string.IsNullOrEmpty(songMetadata?.title)) { currentSongTitle = songMetadata.title; } } catch { currentSongTitle = "Unknown"; } } if (currentPlaybackCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(currentPlaybackCoroutine); } if (File.Exists(text)) { currentPlaybackCoroutine = ((MonoBehaviour)this).StartCoroutine(LoadAndPlay(text)); return; } if (downloadCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(downloadCoroutine); downloadCoroutine = null; } downloadCoroutine = ((MonoBehaviour)this).StartCoroutine(DownloadAudio(url, text, text2)); } [IteratorStateMachine(typeof(<DownloadAudio>d__144))] private IEnumerator DownloadAudio(string url, string outputPath, string metadataPath) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DownloadAudio>d__144(0) { <>4__this = this, url = url, outputPath = outputPath, metadataPath = metadataPath }; } private string GetSafeSongId(string url) { try { Uri uri = new Uri(url); string text = uri.Host.ToLowerInvariant(); if (text.Contains("youtu.be")) { string text2 = uri.AbsolutePath.Trim('/'); if (!string.IsNullOrEmpty(text2)) { return text2; } } if (text.Contains("youtube.com") || text.Contains("music.youtube.com")) { NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(uri.Query); string text3 = nameValueCollection["v"]; if (!string.IsNullOrEmpty(text3)) { return text3; } string text4 = uri.AbsolutePath.Trim('/'); if (text4.StartsWith("shorts/", StringComparison.OrdinalIgnoreCase)) { string[] array = text4.Split('/'); if (array.Length >= 2 && array[1].Length > 0) { return array[1]; } } } } catch { } using SHA1 sHA = SHA1.Create(); byte[] array2 = sHA.ComputeHash(Encoding.UTF8.GetBytes(url)); return BitConverter.ToString(array2, 0, 6).Replace("-", ""); } [IteratorStateMachine(typeof(<LoadAndPlay>d__146))] private IEnumerator LoadAndPlay(string path) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAndPlay>d__146(0) { <>4__this = this, path = path }; } [PunRPC] private void RPC_StopAudio() { manualStop = true; if ((Object)(object)audioSource != (Object)null) { audioSource.Stop(); audioSource.clip = null; } } [PunRPC] private void RPC_SyncTime(string songHash, float hostTime) { if (!ActAsHost() && (Object)(object)audioSource != (Object)null && (Object)(object)audioSource.clip != (Object)null && songHash == currentSongHash && Mathf.Abs(audioSource.time - hostTime) > 0.5f && hostTime >= 0f && hostTime <= audioSource.clip.length) { audioSource.time = hostTime; } } [PunRPC] private void RPC_SyncPlaying(string songHash, bool hostIsPlaying, bool isOwner, string hostTitle) { if (isOwner) { hostHasMod = true; } if (!string.IsNullOrEmpty(hostTitle)) { currentSongTitle = hostTitle; } if (!ActAsHost() && (Object)(object)audioSource != (Object)null) { if (!audioSource.isPlaying && hostIsPlaying && (Object)(object)audioSource.clip != (Object)null && songHash == currentSongHash) { audioSource.Play(); } if (audioSource.isPlaying && (!hostIsPlaying || songHash != currentSongHash)) { audioSource.Stop(); } } } private void StopAndResetSong() { if (currentPlaybackCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(currentPlaybackCoroutine); } AudioSource? obj = audioSource; if (obj != null) { obj.Stop(); } if ((Object)(object)audioSource != (Object)null) { audioSource.clip = null; } songLoadingState = SongLoadingState.Loaded; currentSongTitle = ""; currentSongHash = ""; lastUsedPlayer = ""; manualStop = false; hostHasMod = PhotonNetwork.IsMasterClient; } private void CleanupOldTempFiles() { if (string.IsNullOrEmpty(tempAudioDir) || !Directory.Exists(tempAudioDir)) { return; } List<FileInfo> list = (from f in new DirectoryInfo(tempAudioDir).GetFiles("bingbong_*.wav") orderby f.LastAccessTimeUtc descending select f).ToList(); for (int i = MaxTempFiles; i < list.Count; i++) { FileInfo fileInfo = list[i]; try { fileInfo.Delete(); } catch { } string path = Path.ChangeExtension(fileInfo.FullName, ".json"); if (File.Exists(path)) { try { File.Delete(path); } catch { } } } } private bool IsSupportedMediaUrl(string url) { if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result)) { return false; } string value = result.Host.ToLowerInvariant(); if (AllowedHosts.Contains(value)) { return true; } return result.Scheme == Uri.UriSchemeHttp || result.Scheme == Uri.UriSchemeHttps; } private void StartTitleFetchIfNeeded(string hash, string url) { if (!ActAsHost() || titleFetchInProgress.Contains(hash)) { return; } string path = Path.Combine(tempAudioDir, "bingbong_" + hash + ".json"); if (File.Exists(path)) { try { SongMetadata songMetadata = JsonUtility.FromJson<SongMetadata>(File.ReadAllText(path)); if (!string.IsNullOrEmpty(songMetadata?.title)) { UpdateQueueTitle(hash, songMetadata.title); return; } } catch { } } ((MonoBehaviour)this).StartCoroutine(FetchTitleCoroutine(hash, url)); } [IteratorStateMachine(typeof(<FetchTitleCoroutine>d__155))] private IEnumerator FetchTitleCoroutine(string hash, string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FetchTitleCoroutine>d__155(0) { <>4__this = this, hash = hash, url = url }; } private void UpdateQueueTitle(string hash, string title) { bool flag = false; for (int i = 0; i < queue.Count; i++) { if (queue[i].hash == hash && string.IsNullOrEmpty(queue[i].title)) { queue[i].title = title; flag = true; } } if (flag) { BroadcastQueue(); } if (currentSongHash == hash && (string.IsNullOrEmpty(currentSongTitle) || currentSongTitle == "Unknown")) { currentSongTitle = title; } } } }