using 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;
}
}
}
}