Decompiled source of Speakerboxes v1.1.0

Speakerbox.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Speakerbox")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Go Go Gadget Speakerbox")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0")]
[assembly: AssemblyProduct("Speakerbox")]
[assembly: AssemblyTitle("Speakerbox")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 BigWalkSpeaker
{
	[BepInPlugin("com.bigwalkmods.bigwalkspeaker", "Big Walk Speaker", "0.9.0")]
	public class BigWalkSpeakerPlugin : BasePlugin
	{
		internal static ManualLogSource Logger;

		public override void Load()
		{
			Logger = ((BasePlugin)this).Log;
			Logger.LogInfo((object)"Big Walk Speaker 0.9.0 loading...");
			ClassInjector.RegisterTypeInIl2Cpp<BoomboxItem>();
			((BasePlugin)this).AddComponent<SpeakerController>();
			Logger.LogInfo((object)"Big Walk Speaker loaded.");
		}
	}
	public class BoomboxItem : MonoBehaviour
	{
		public AudioSource CreatedAudioSource;

		public GameObject CreatedParticleObject;

		public bool AudioSourcePreExisted;

		public BoomboxItem(IntPtr ptr)
			: base(ptr)
		{
		}
	}
	public class SpeakerController : MonoBehaviour
	{
		private enum LoopMode
		{
			LoopAll,
			LoopOne,
			NoLoop
		}

		private GameObject speakerObject;

		private AudioSource sphereAudioSource;

		private bool speakerActive;

		private const float InteractRange = 4f;

		private UnityWebRequest audioRequest;

		private bool loadingAudio;

		private string loadingFileName;

		private AudioSource loadTargetAudioSource;

		private readonly List<string> musicFiles = new List<string>();

		private int currentTrackIndex = -1;

		private bool menuOpen;

		private Rect menuRect = new Rect(60f, 60f, 350f, 650f);

		private GameObject menuTargetObject;

		private LoopMode loopMode = LoopMode.LoopAll;

		private bool syncSpeakers = false;

		private Vector2 scrollPos;

		private bool wasPlayingLastFrame = false;

		private bool isPaused = false;

		private GrabKernal grabKernal;

		private bool grabKernalDumped;

		private PlayerCharacter playerCharacter;

		private bool playerCharacterDumped;

		private HashSet<string> dumpedSubComponents = new HashSet<string>();

		private float nextGrabKernalSearchTime;

		private string youtubeUrl = "";

		private string downloadStatus = "";

		private bool isDownloading = false;

		private string downloadResult = "";

		private bool downloadFinished = false;

		public void Update()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)290))
			{
				ToggleSpeaker();
			}
			UpdateAudioRequest();
			HandleAllInteractionInput();
			GameObject currentlyHeldObject = GetCurrentlyHeldObject();
			if (menuOpen && (Object)(object)menuTargetObject != (Object)null)
			{
				if ((Object)(object)menuTargetObject == (Object)(object)speakerObject)
				{
					if ((Object)(object)Camera.main != (Object)null)
					{
						float num = Vector3.Distance(((Component)Camera.main).transform.position, speakerObject.transform.position);
						if (num > 4f)
						{
							menuOpen = false;
							menuTargetObject = null;
							loadTargetAudioSource = null;
						}
					}
				}
				else if ((Object)(object)currentlyHeldObject != (Object)(object)menuTargetObject)
				{
					menuOpen = false;
					menuTargetObject = null;
					loadTargetAudioSource = null;
				}
			}
			if ((Object)(object)loadTargetAudioSource != (Object)null && (Object)(object)loadTargetAudioSource.clip != (Object)null)
			{
				bool isPlaying = loadTargetAudioSource.isPlaying;
				if (wasPlayingLastFrame && !isPlaying && !isPaused && loadTargetAudioSource.time >= loadTargetAudioSource.clip.length - 0.1f && loopMode == LoopMode.LoopAll)
				{
					ChangeTrack(1);
				}
				wasPlayingLastFrame = isPlaying;
				bool flag = loopMode == LoopMode.LoopOne;
				if (loadTargetAudioSource.loop != flag)
				{
					loadTargetAudioSource.loop = flag;
				}
			}
			else
			{
				wasPlayingLastFrame = false;
			}
			if (downloadFinished)
			{
				downloadFinished = false;
				isDownloading = false;
				downloadStatus = downloadResult;
				if (downloadResult.Contains("complete"))
				{
					ScanMusicFiles();
				}
			}
		}

		private void HandleAllInteractionInput()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			GameObject currentlyHeldObject = GetCurrentlyHeldObject();
			if (Input.GetKeyDown((KeyCode)114))
			{
				if ((Object)(object)currentlyHeldObject != (Object)null)
				{
					BoomboxItem component = currentlyHeldObject.GetComponent<BoomboxItem>();
					if ((Object)(object)component == (Object)null)
					{
						ConvertToBoombox(currentlyHeldObject);
						component = currentlyHeldObject.GetComponent<BoomboxItem>();
					}
					if ((Object)(object)component != (Object)null && (Object)(object)component.CreatedAudioSource != (Object)null)
					{
						menuTargetObject = currentlyHeldObject;
						loadTargetAudioSource = component.CreatedAudioSource;
						menuOpen = true;
					}
				}
				else if (speakerActive && (Object)(object)speakerObject != (Object)null && (Object)(object)Camera.main != (Object)null)
				{
					float num = Vector3.Distance(((Component)Camera.main).transform.position, speakerObject.transform.position);
					if (num <= 4f)
					{
						menuTargetObject = speakerObject;
						loadTargetAudioSource = sphereAudioSource;
						menuOpen = true;
					}
				}
			}
			if (Input.GetKeyDown((KeyCode)110) && (Object)(object)currentlyHeldObject != (Object)null && (Object)(object)currentlyHeldObject.GetComponent<BoomboxItem>() != (Object)null)
			{
				RevertBoombox(currentlyHeldObject);
			}
		}

		private List<AudioSource> GetAllActiveSpeakers()
		{
			List<AudioSource> list = new List<AudioSource>();
			if (syncSpeakers)
			{
				if ((Object)(object)sphereAudioSource != (Object)null && (Object)(object)((Component)sphereAudioSource).gameObject != (Object)null)
				{
					list.Add(sphereAudioSource);
				}
				BoomboxItem[] array = Il2CppArrayBase<BoomboxItem>.op_Implicit(Object.FindObjectsOfType<BoomboxItem>());
				BoomboxItem[] array2 = array;
				foreach (BoomboxItem boomboxItem in array2)
				{
					if ((Object)(object)boomboxItem != (Object)null && (Object)(object)boomboxItem.CreatedAudioSource != (Object)null && !list.Contains(boomboxItem.CreatedAudioSource))
					{
						list.Add(boomboxItem.CreatedAudioSource);
					}
				}
			}
			else if ((Object)(object)loadTargetAudioSource != (Object)null)
			{
				list.Add(loadTargetAudioSource);
			}
			return list;
		}

		private void SyncAllSpeakers()
		{
			if ((Object)(object)loadTargetAudioSource == (Object)null || (Object)(object)loadTargetAudioSource.clip == (Object)null)
			{
				return;
			}
			foreach (AudioSource allActiveSpeaker in GetAllActiveSpeakers())
			{
				if ((Object)(object)allActiveSpeaker != (Object)(object)loadTargetAudioSource)
				{
					allActiveSpeaker.clip = loadTargetAudioSource.clip;
					allActiveSpeaker.time = loadTargetAudioSource.time;
					allActiveSpeaker.volume = loadTargetAudioSource.volume;
					allActiveSpeaker.loop = loopMode == LoopMode.LoopOne;
					if (loadTargetAudioSource.isPlaying)
					{
						allActiveSpeaker.Play();
					}
					else
					{
						allActiveSpeaker.Pause();
					}
				}
			}
		}

		private GameObject GetCurrentlyHeldObject()
		{
			if ((Object)(object)grabKernal == (Object)null)
			{
				if (Time.time < nextGrabKernalSearchTime)
				{
					return null;
				}
				nextGrabKernalSearchTime = Time.time + 2f;
				grabKernal = Object.FindObjectOfType<GrabKernal>();
				if ((Object)(object)grabKernal == (Object)null)
				{
					return null;
				}
			}
			if (!grabKernalDumped)
			{
				DumpMembers(grabKernal, "GrabKernal");
				grabKernalDumped = true;
			}
			if ((Object)(object)playerCharacter == (Object)null)
			{
				playerCharacter = grabKernal.playerCharacter;
				if ((Object)(object)playerCharacter == (Object)null)
				{
					return null;
				}
			}
			if (!playerCharacterDumped)
			{
				DumpMembers(playerCharacter, "PlayerCharacter");
				playerCharacterDumped = true;
			}
			GameObject val = SearchInsideSubComponent(playerCharacter, "beak", "PlayerBeak");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = SearchInsideSubComponent(playerCharacter, "hands", "PlayerHands");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = SearchInsideSubComponent(playerCharacter, "arms", "PlayerArms");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			val = SearchForHeldGameObject(playerCharacter);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return SearchForHeldGameObject(grabKernal);
		}

		private GameObject SearchInsideSubComponent(object instance, string propertyName, string label)
		{
			Type type = instance.GetType();
			PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
			if (property == null)
			{
				return null;
			}
			object value;
			try
			{
				value = property.GetValue(instance);
			}
			catch
			{
				return null;
			}
			if (value == null)
			{
				return null;
			}
			if (!dumpedSubComponents.Contains(label))
			{
				DumpMembers(value, label);
				dumpedSubComponents.Add(label);
			}
			return SearchForHeldGameObject(value);
		}

		private static GameObject SearchForHeldGameObject(object instance)
		{
			Type type = instance.GetType();
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (LooksHeldRelated(propertyInfo.Name))
				{
					object value;
					try
					{
						value = propertyInfo.GetValue(instance);
					}
					catch
					{
						continue;
					}
					GameObject val = ExtractGameObject(value);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (LooksHeldRelated(fieldInfo.Name))
				{
					object value2;
					try
					{
						value2 = fieldInfo.GetValue(instance);
					}
					catch
					{
						continue;
					}
					GameObject val2 = ExtractGameObject(value2);
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
			}
			return null;
		}

		private void DumpMembers(object instance, string label)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			Type type = instance.GetType();
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			bool flag = default(bool);
			foreach (PropertyInfo propertyInfo in properties)
			{
				ManualLogSource logger = BigWalkSpeakerPlugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(19, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Boombox]   prop: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(propertyInfo.PropertyType.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(propertyInfo.Name);
				}
				logger.LogInfo(val);
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				ManualLogSource logger2 = BigWalkSpeakerPlugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Boombox]   field: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(fieldInfo.FieldType.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(fieldInfo.Name);
				}
				logger2.LogInfo(val);
			}
		}

		private static bool LooksHeldRelated(string name)
		{
			if (IsKnownPlayerGuideName(name))
			{
				return false;
			}
			string text = name.ToLowerInvariant();
			return text.Contains("held") || text.Contains("grab") || text.Contains("hold") || text.Contains("item") || text.Contains("current") || text.Contains("target");
		}

		private static bool IsKnownPlayerGuideName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string text = name.ToLowerInvariant();
			return text == "holdhighguide" || (text.Contains("guide") && text.Contains("hold"));
		}

		private static GameObject ExtractGameObject(object value)
		{
			if (value == null)
			{
				return null;
			}
			GameObject val = null;
			GameObject val2 = (GameObject)((value is GameObject) ? value : null);
			if (val2 != null)
			{
				val = val2;
			}
			else
			{
				Component val3 = (Component)((value is Component) ? value : null);
				if (val3 != null)
				{
					val = val3.gameObject;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if (IsKnownPlayerGuideName(((Object)val).name))
			{
				return null;
			}
			Component[] array = Il2CppArrayBase<Component>.op_Implicit(val.GetComponents<Component>());
			Component[] array2 = array;
			foreach (Component val4 in array2)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					string name = ((object)val4).GetType().Name;
					if (!(name == "BoomboxItem") && !(name == "SpeakerController") && name.StartsWith("Player"))
					{
						return null;
					}
				}
			}
			return val;
		}

		private void ConvertToBoombox(GameObject item)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)item == (Object)null) && !IsKnownPlayerGuideName(((Object)item).name) && !((Object)(object)item.GetComponent<BoomboxItem>() != (Object)null))
			{
				BoomboxItem boomboxItem = item.AddComponent<BoomboxItem>();
				AudioSource component = item.GetComponent<AudioSource>();
				if ((Object)(object)component != (Object)null)
				{
					boomboxItem.AudioSourcePreExisted = true;
					boomboxItem.CreatedAudioSource = component;
				}
				else
				{
					boomboxItem.CreatedAudioSource = item.AddComponent<AudioSource>();
				}
				AudioSource createdAudioSource = boomboxItem.CreatedAudioSource;
				createdAudioSource.volume = 1f;
				createdAudioSource.playOnAwake = false;
				createdAudioSource.loop = loopMode == LoopMode.LoopOne;
				createdAudioSource.spatialBlend = 1f;
				createdAudioSource.minDistance = 2f;
				createdAudioSource.maxDistance = 35f;
				createdAudioSource.rolloffMode = (AudioRolloffMode)0;
				createdAudioSource.dopplerLevel = 0f;
				ParticleSystem val = Object.FindObjectOfType<ParticleSystem>();
				if ((Object)(object)val != (Object)null)
				{
					GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject);
					((Object)val2).name = "BoomboxParticles";
					val2.transform.SetParent(item.transform, false);
					val2.transform.localPosition = Vector3.zero;
					boomboxItem.CreatedParticleObject = val2;
				}
				ScanMusicFiles();
				if (musicFiles.Count > 0)
				{
					LoadTrackInto(createdAudioSource, 0);
				}
			}
		}

		private void RevertBoombox(GameObject item)
		{
			if ((Object)(object)menuTargetObject == (Object)(object)item)
			{
				menuOpen = false;
				menuTargetObject = null;
				loadTargetAudioSource = null;
			}
			BoomboxItem component = item.GetComponent<BoomboxItem>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			if ((Object)(object)component.CreatedParticleObject != (Object)null)
			{
				Object.Destroy((Object)(object)component.CreatedParticleObject);
			}
			if ((Object)(object)component.CreatedAudioSource != (Object)null)
			{
				component.CreatedAudioSource.Stop();
				if (!component.AudioSourcePreExisted)
				{
					Object.Destroy((Object)(object)component.CreatedAudioSource);
				}
			}
			Object.Destroy((Object)(object)component);
		}

		private void ToggleSpeaker()
		{
			if (speakerActive)
			{
				DestroySpeaker();
			}
			else
			{
				CreateSpeaker();
			}
		}

		private void CreateSpeaker()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)main).transform.position;
			position.y -= 1f;
			speakerObject = GameObject.CreatePrimitive((PrimitiveType)0);
			if (!((Object)(object)speakerObject == (Object)null))
			{
				((Object)speakerObject).name = "BigWalkSpeaker";
				speakerObject.transform.position = position;
				speakerObject.transform.localScale = Vector3.one * 0.5f;
				ApplyWorkingRenderSetup(speakerObject);
				SphereCollider component = speakerObject.GetComponent<SphereCollider>();
				if ((Object)(object)component != (Object)null)
				{
					((Collider)component).enabled = true;
				}
				sphereAudioSource = speakerObject.AddComponent<AudioSource>();
				sphereAudioSource.volume = 1f;
				sphereAudioSource.playOnAwake = false;
				sphereAudioSource.loop = loopMode == LoopMode.LoopOne;
				sphereAudioSource.spatialBlend = 1f;
				sphereAudioSource.minDistance = 2f;
				sphereAudioSource.maxDistance = 35f;
				sphereAudioSource.rolloffMode = (AudioRolloffMode)0;
				sphereAudioSource.dopplerLevel = 0f;
				speakerActive = true;
				ScanMusicFiles();
				if (musicFiles.Count > 0)
				{
					LoadTrackInto(sphereAudioSource, 0);
				}
			}
		}

		private void ApplyWorkingRenderSetup(GameObject target)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer component = target.GetComponent<MeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			GameObject val = GameObject.Find("radio_body");
			if ((Object)(object)val != (Object)null)
			{
				MeshRenderer component2 = val.GetComponent<MeshRenderer>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)((Renderer)component2).sharedMaterial != (Object)null)
				{
					target.layer = val.layer;
					((Renderer)component).sharedMaterial = ((Renderer)component2).sharedMaterial;
					return;
				}
			}
			int num = LayerMask.NameToLayer("Prop");
			target.layer = ((num >= 0) ? num : 0);
			Shader val2 = Shader.Find("Unlit/Color");
			if ((Object)(object)val2 != (Object)null)
			{
				Material val3 = new Material(val2)
				{
					name = "BigWalkSpeakerUnlit"
				};
				val3.SetColor("_Color", Color.red);
				((Renderer)component).sharedMaterial = val3;
			}
		}

		private void DestroySpeaker()
		{
			if ((Object)(object)menuTargetObject == (Object)(object)speakerObject)
			{
				menuOpen = false;
				menuTargetObject = null;
				loadTargetAudioSource = null;
			}
			if (audioRequest != null && (Object)(object)loadTargetAudioSource == (Object)(object)sphereAudioSource)
			{
				audioRequest.Dispose();
				audioRequest = null;
				loadingAudio = false;
			}
			if ((Object)(object)speakerObject != (Object)null)
			{
				Object.Destroy((Object)(object)speakerObject);
			}
			speakerObject = null;
			sphereAudioSource = null;
			speakerActive = false;
		}

		private void ScanMusicFiles()
		{
			musicFiles.Clear();
			string directoryName = Path.GetDirectoryName(typeof(BigWalkSpeakerPlugin).Assembly.Location);
			if (string.IsNullOrEmpty(directoryName))
			{
				return;
			}
			string[] files = Directory.GetFiles(directoryName);
			string[] array = files;
			foreach (string text in array)
			{
				string text2 = Path.GetExtension(text).ToLowerInvariant();
				if (text2 == ".mp3" || text2 == ".ogg" || text2 == ".wav")
				{
					musicFiles.Add(text);
				}
			}
			musicFiles.Sort();
		}

		private void LoadTrackInto(AudioSource target, int index)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null) && index >= 0 && index < musicFiles.Count)
			{
				currentTrackIndex = index;
				loadTargetAudioSource = target;
				wasPlayingLastFrame = false;
				isPaused = false;
				string text = musicFiles[index];
				AudioType audioType = GetAudioType(text);
				loadingFileName = Path.GetFileName(text);
				string absoluteUri = new Uri(text).AbsoluteUri;
				if (audioRequest != null)
				{
					audioRequest.Dispose();
					audioRequest = null;
				}
				audioRequest = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, audioType);
				loadingAudio = true;
				audioRequest.SendWebRequest();
			}
		}

		private void UpdateAudioRequest()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			if (!loadingAudio)
			{
				return;
			}
			if (audioRequest == null)
			{
				loadingAudio = false;
			}
			else
			{
				if (!audioRequest.isDone)
				{
					return;
				}
				loadingAudio = false;
				try
				{
					if ((int)audioRequest.result != 1)
					{
						return;
					}
					AudioClip content = DownloadHandlerAudioClip.GetContent(audioRequest);
					if ((Object)(object)content == (Object)null)
					{
						return;
					}
					foreach (AudioSource allActiveSpeaker in GetAllActiveSpeakers())
					{
						allActiveSpeaker.clip = content;
						allActiveSpeaker.Play();
					}
				}
				catch (Exception ex)
				{
					ManualLogSource logger = BigWalkSpeakerPlugin.Logger;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(17, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Audio exception: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
				finally
				{
					audioRequest.Dispose();
					audioRequest = null;
				}
			}
		}

		private static AudioType GetAudioType(string filePath)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			return (AudioType)(Path.GetExtension(filePath).ToLowerInvariant() switch
			{
				".mp3" => 13, 
				".ogg" => 14, 
				".wav" => 20, 
				_ => 0, 
			});
		}

		private void StartDownload(string url)
		{
			isDownloading = true;
			downloadStatus = "Starting download...";
			Task.Run(delegate
			{
				try
				{
					string directoryName = Path.GetDirectoryName(typeof(BigWalkSpeakerPlugin).Assembly.Location);
					string text = Path.Combine(directoryName, "yt-dlp.exe");
					if (!File.Exists(text))
					{
						downloadResult = "yt-dlp.exe not found in plugin folder!";
						downloadFinished = true;
						return;
					}
					string value = directoryName;
					ProcessStartInfo startInfo = new ProcessStartInfo
					{
						FileName = text,
						WorkingDirectory = directoryName,
						Arguments = $"--no-playlist -q -x --audio-format mp3 --audio-quality 0 --restrict-filenames --ffmpeg-location \"{value}\" -o \"%(title)s.%(ext)s\" \"{url}\"",
						RedirectStandardOutput = true,
						RedirectStandardError = true,
						UseShellExecute = false,
						CreateNoWindow = true
					};
					using Process process = Process.Start(startInfo);
					string text2 = process.StandardError.ReadToEnd();
					process.WaitForExit();
					if (process.ExitCode == 0)
					{
						downloadResult = "Download complete! Added to track list.";
					}
					else
					{
						downloadResult = "Error: " + text2.Substring(0, Math.Min(100, text2.Length));
					}
				}
				catch (Exception ex)
				{
					downloadResult = "Exception: " + ex.Message;
				}
				finally
				{
					downloadFinished = true;
				}
			});
		}

		private void OnGUI()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			if (menuOpen)
			{
				float num = (float)Screen.height / 1080f;
				if (num < 0.5f)
				{
					num = 0.5f;
				}
				Matrix4x4 matrix = GUI.matrix;
				GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f));
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((Rect)(ref menuRect)).x / num, ((Rect)(ref menuRect)).y / num, ((Rect)(ref menuRect)).width / num, ((Rect)(ref menuRect)).height / num);
				if (musicFiles.Count == 0 && !isDownloading)
				{
					menuRect = GUILayout.Window(918273, val, WindowFunction.op_Implicit((Action<int>)DrawEmptyMenu), "Speaker", (Il2CppReferenceArray<GUILayoutOption>)null);
				}
				else
				{
					menuRect = GUILayout.Window(918273, val, WindowFunction.op_Implicit((Action<int>)DrawMusicMenu), "Boombox Controls", (Il2CppReferenceArray<GUILayoutOption>)null);
				}
				menuRect = new Rect(((Rect)(ref menuRect)).x * num, ((Rect)(ref menuRect)).y * num, ((Rect)(ref menuRect)).width * num, ((Rect)(ref menuRect)).height * num);
				GUI.matrix = matrix;
			}
		}

		private void DrawEmptyMenu(int windowId)
		{
			GUILayout.Label("No music files found beside the DLL.", (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Space(10f);
			GUILayout.Label("YouTube Downloader", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			youtubeUrl = GUILayout.TextField(youtubeUrl, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.EndHorizontal();
			string text = (isDownloading ? "Downloading..." : "Download Track");
			bool enabled = !isDownloading && !string.IsNullOrWhiteSpace(youtubeUrl);
			GUI.enabled = enabled;
			if (GUILayout.Button(text, (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				StartDownload(youtubeUrl);
			}
			GUI.enabled = true;
			if (!string.IsNullOrEmpty(downloadStatus))
			{
				GUILayout.Label(downloadStatus, (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			if (GUILayout.Button("Close", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				menuOpen = false;
			}
			GUI.DragWindow();
		}

		private void DrawMusicMenu(int windowId)
		{
			//IL_075c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0774: Unknown result type (might be due to invalid IL or missing references)
			//IL_0779: Unknown result type (might be due to invalid IL or missing references)
			string text = ((currentTrackIndex >= 0 && currentTrackIndex < musicFiles.Count) ? Path.GetFileNameWithoutExtension(musicFiles[currentTrackIndex]) : "No track");
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Track: " + text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (GUILayout.Button(syncSpeakers ? "Sync: ON" : "Sync: OFF", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
			{
				syncSpeakers = !syncSpeakers;
				if (syncSpeakers)
				{
					SyncAllSpeakers();
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Loop:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			string text2 = ((loopMode == LoopMode.LoopAll) ? "All" : ((loopMode == LoopMode.LoopOne) ? "One" : "Off"));
			if (GUILayout.Button(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
			{
				if (loopMode == LoopMode.LoopAll)
				{
					loopMode = LoopMode.LoopOne;
				}
				else if (loopMode == LoopMode.LoopOne)
				{
					loopMode = LoopMode.NoLoop;
				}
				else
				{
					loopMode = LoopMode.LoopAll;
				}
				bool loop = loopMode == LoopMode.LoopOne;
				foreach (AudioSource allActiveSpeaker in GetAllActiveSpeakers())
				{
					allActiveSpeaker.loop = loop;
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			if (GUILayout.Button("<< Prev", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				ChangeTrack(-1);
			}
			string text3 = (isPaused ? "Play" : "Pause");
			if (GUILayout.Button(text3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				bool flag = isPaused;
				foreach (AudioSource allActiveSpeaker2 in GetAllActiveSpeakers())
				{
					if ((Object)(object)allActiveSpeaker2.clip != (Object)null)
					{
						if (flag)
						{
							allActiveSpeaker2.Play();
						}
						else
						{
							allActiveSpeaker2.Pause();
						}
					}
				}
				isPaused = !isPaused;
			}
			if (GUILayout.Button("Next >>", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				ChangeTrack(1);
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			if (GUILayout.Button("-5s", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }) && (Object)(object)loadTargetAudioSource != (Object)null && (Object)(object)loadTargetAudioSource.clip != (Object)null)
			{
				foreach (AudioSource allActiveSpeaker3 in GetAllActiveSpeakers())
				{
					allActiveSpeaker3.time = Mathf.Max(0f, loadTargetAudioSource.time - 5f);
				}
			}
			if (GUILayout.Button("+5s", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }) && (Object)(object)loadTargetAudioSource != (Object)null && (Object)(object)loadTargetAudioSource.clip != (Object)null)
			{
				foreach (AudioSource allActiveSpeaker4 in GetAllActiveSpeakers())
				{
					allActiveSpeaker4.time = Mathf.Min(loadTargetAudioSource.clip.length, loadTargetAudioSource.time + 5f);
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label("Volume:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			if (GUILayout.Button("-", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }))
			{
				foreach (AudioSource allActiveSpeaker5 in GetAllActiveSpeakers())
				{
					allActiveSpeaker5.volume = Mathf.Clamp01(allActiveSpeaker5.volume - 0.1f);
				}
			}
			float num = (((Object)(object)loadTargetAudioSource != (Object)null) ? loadTargetAudioSource.volume : 0f);
			GUILayout.Label($"{num * 100f:0}%", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) }))
			{
				foreach (AudioSource allActiveSpeaker6 in GetAllActiveSpeakers())
				{
					allActiveSpeaker6.volume = Mathf.Clamp01(allActiveSpeaker6.volume + 0.1f);
				}
			}
			GUILayout.EndHorizontal();
			if ((Object)(object)loadTargetAudioSource != (Object)null && (Object)(object)loadTargetAudioSource.clip != (Object)null && loadTargetAudioSource.clip.length > 0f)
			{
				GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
				GUILayout.Label(FormatTime(loadTargetAudioSource.time), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
				bool changed = GUI.changed;
				GUI.changed = false;
				float time = GUILayout.HorizontalSlider(loadTargetAudioSource.time, 0f, loadTargetAudioSource.clip.length, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				bool changed2 = GUI.changed;
				GUI.changed = changed || changed2;
				GUILayout.Label(FormatTime(loadTargetAudioSource.clip.length), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
				GUILayout.EndHorizontal();
				if (changed2)
				{
					foreach (AudioSource allActiveSpeaker7 in GetAllActiveSpeakers())
					{
						allActiveSpeaker7.time = time;
					}
				}
			}
			else
			{
				GUILayout.Label("Loading / No audio...", (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			GUILayout.Space(5f);
			GUILayout.Label($"Track List ({musicFiles.Count} songs):", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			scrollPos = GUILayout.BeginScrollView(scrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
			for (int i = 0; i < musicFiles.Count; i++)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(musicFiles[i]);
				if (i == currentTrackIndex)
				{
					GUILayout.Label("> " + fileNameWithoutExtension, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				}
				else if (GUILayout.Button(fileNameWithoutExtension, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }) && (Object)(object)loadTargetAudioSource != (Object)null)
				{
					LoadTrackInto(loadTargetAudioSource, i);
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(10f);
			GUILayout.Label("YouTube Downloader", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			youtubeUrl = GUILayout.TextField(youtubeUrl, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.EndHorizontal();
			string text4 = (isDownloading ? "Downloading..." : "Download Track");
			bool enabled = !isDownloading && !string.IsNullOrWhiteSpace(youtubeUrl);
			GUI.enabled = enabled;
			if (GUILayout.Button(text4, (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				StartDownload(youtubeUrl);
			}
			GUI.enabled = true;
			if (!string.IsNullOrEmpty(downloadStatus))
			{
				GUILayout.Label(downloadStatus, (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			if (GUILayout.Button("Close", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				menuOpen = false;
			}
			GUI.DragWindow();
		}

		private string FormatTime(float seconds)
		{
			if (float.IsNaN(seconds) || float.IsInfinity(seconds) || seconds < 0f)
			{
				return "00:00";
			}
			return TimeSpan.FromSeconds(seconds).ToString("mm\\:ss");
		}

		private void ChangeTrack(int direction)
		{
			if (musicFiles.Count != 0 && !((Object)(object)loadTargetAudioSource == (Object)null))
			{
				int num = currentTrackIndex + direction;
				if (num < 0)
				{
					num = musicFiles.Count - 1;
				}
				if (num >= musicFiles.Count)
				{
					num = 0;
				}
				LoadTrackInto(loadTargetAudioSource, num);
			}
		}
	}
}