Decompiled source of YPlayBoombox v2.2.1

plugins\YPlay.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DamienG.Security.Cryptography;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using YPlay.NetcodePatcher;
using YPlayUtil;
using YPlayUtil.Helpers;
using YPlayUtil.Metadata;
using YPlayUtil.Options;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("YPlay")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("YPlay")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a9e02c48-30aa-4cf0-bbce-b71de7f55747")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DamienG.Security.Cryptography
{
	public sealed class Crc32 : HashAlgorithm
	{
		public const uint DefaultPolynomial = 3988292384u;

		public const uint DefaultSeed = uint.MaxValue;

		private static uint[] defaultTable;

		private readonly uint seed;

		private readonly uint[] table;

		private uint hash;

		public override int HashSize => 32;

		public Crc32()
			: this(3988292384u, uint.MaxValue)
		{
		}

		public Crc32(uint polynomial, uint seed)
		{
			if (!BitConverter.IsLittleEndian)
			{
				throw new PlatformNotSupportedException("Not supported on Big Endian processors");
			}
			table = InitializeTable(polynomial);
			this.seed = (hash = seed);
		}

		public override void Initialize()
		{
			hash = seed;
		}

		protected override void HashCore(byte[] array, int ibStart, int cbSize)
		{
			hash = CalculateHash(table, hash, array, ibStart, cbSize);
		}

		protected override byte[] HashFinal()
		{
			return HashValue = UInt32ToBigEndianBytes(~hash);
		}

		public static uint Compute(byte[] buffer)
		{
			return Compute(uint.MaxValue, buffer);
		}

		public static uint Compute(uint seed, byte[] buffer)
		{
			return Compute(3988292384u, seed, buffer);
		}

		public static uint Compute(uint polynomial, uint seed, byte[] buffer)
		{
			return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
		}

		private static uint[] InitializeTable(uint polynomial)
		{
			if (polynomial == 3988292384u && defaultTable != null)
			{
				return defaultTable;
			}
			uint[] array = new uint[256];
			for (int i = 0; i < 256; i++)
			{
				uint num = (uint)i;
				for (int j = 0; j < 8; j++)
				{
					num = (((num & 1) != 1) ? (num >> 1) : ((num >> 1) ^ polynomial));
				}
				array[i] = num;
			}
			if (polynomial == 3988292384u)
			{
				defaultTable = array;
			}
			return array;
		}

		private static uint CalculateHash(uint[] table, uint seed, IList<byte> buffer, int start, int size)
		{
			uint num = seed;
			for (int i = start; i < start + size; i++)
			{
				num = (num >> 8) ^ table[buffer[i] ^ (num & 0xFF)];
			}
			return num;
		}

		private static byte[] UInt32ToBigEndianBytes(uint uint32)
		{
			byte[] bytes = BitConverter.GetBytes(uint32);
			if (BitConverter.IsLittleEndian)
			{
				Array.Reverse((Array)bytes);
			}
			return bytes;
		}
	}
}
namespace YPlay
{
	internal class BoomboxAudioLoader : MonoBehaviour
	{
		internal static readonly Dictionary<string, AudioClip> filenameIdAudioClips = new Dictionary<string, AudioClip>();

		internal static readonly List<string> filenameIdsDownloaded = new List<string>();

		private static BoomboxAudioLoader Instance;

		internal void Start(IEnumerator routine)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = new GameObject(typeof(BoomboxAudioLoader).Name).AddComponent<BoomboxAudioLoader>();
				Object.DontDestroyOnLoad((Object)(object)Instance);
			}
			((MonoBehaviour)Instance).StartCoroutine(routine);
		}

		internal IEnumerator GetAudioClip(BoomboxItemController boomboxItemController, int requestId, string path, bool resync)
		{
			string filenameId = Path.GetFileNameWithoutExtension(path);
			bool flag = false;
			bool success = false;
			if (filenameIdAudioClips.ContainsKey(filenameId))
			{
				AudioClip audioClip = filenameIdAudioClips[filenameId];
				if (Object.op_Implicit((Object)(object)audioClip) && (int)audioClip.loadState == 2)
				{
					yield return null;
					SetAudio(filenameId, audioClip);
					flag = true;
					success = true;
				}
				else
				{
					filenameIdAudioClips.Remove(filenameId);
				}
			}
			bool flag2 = BoomboxAudioDownloader.IsFilenameIdDownloaded(filenameId);
			if (!flag && flag2)
			{
				if (filenameIdsDownloaded.Contains(filenameId))
				{
					filenameIdsDownloaded.Remove(filenameId);
				}
				filenameIdsDownloaded.Insert(0, filenameId);
				AudioType audioType = BoomboxAudioDownloader.audioType;
				UnityWebRequest unityWebRequest = UnityWebRequestMultimedia.GetAudioClip(path, audioType);
				try
				{
					((DownloadHandlerAudioClip)unityWebRequest.downloadHandler).streamAudio = (int)audioType == 13;
					yield return unityWebRequest.SendWebRequest();
					if ((int)unityWebRequest.result == 1)
					{
						AudioClip content = DownloadHandlerAudioClip.GetContent(unityWebRequest);
						if ((int)content.loadState == 2)
						{
							boomboxItemController.audioType = audioType;
							SetAudio(filenameId, content);
							success = true;
						}
					}
				}
				finally
				{
					((IDisposable)unityWebRequest)?.Dispose();
				}
			}
			if (!success)
			{
				string text = "Error " + (resync ? "resyncing" : "loading") + " request " + BoomboxAudioDownloader.GetFilenameIdString(filenameId);
				YPlay.LogWarning(text);
				YPlayCorePatch.AddChatMessageYP(text);
			}
			boomboxItemController.SendBoomboxLoadedServerDelegate(requestId, success, resync);
		}

		internal static void UnloadAudioClips()
		{
			foreach (KeyValuePair<string, AudioClip> item in new Dictionary<string, AudioClip>(filenameIdAudioClips))
			{
				AudioClip value = item.Value;
				string key = item.Key;
				value.UnloadAudioData();
				filenameIdAudioClips.Remove(key);
			}
		}

		private void SetAudio(string filenameId, AudioClip audioClip)
		{
			filenameIdAudioClips[filenameId] = audioClip;
			YPlayCorePatch.AddChatMessageYP("Loaded " + BoomboxAudioDownloader.GetFilenameIdString(filenameId));
		}
	}
	internal class BoomboxAudioDownloader
	{
		[CompilerGenerated]
		private BoomboxItemController <boomboxItemController>P;

		internal static readonly Dictionary<string, string> audioIdTitles = new Dictionary<string, string>();

		private static readonly Dictionary<string, int> audioIdDurations = new Dictionary<string, int>();

		internal int lastDownloadRequestId;

		internal string lastDownloadRequestFilenameId;

		private readonly BoomboxAudioLoader boomboxAudioLoader;

		private BoomboxAudioAction boomboxAudioAction;

		internal static HashSet<string> filenameIdsResyncing = new HashSet<string>();

		internal static string audioTypeExtension = "mp3";

		internal static AudioType audioType = (AudioType)13;

		private static readonly OptionSet optionSet = new OptionSet
		{
			NoPlaylist = true,
			ForceIPv4 = true
		};

		public BoomboxAudioDownloader(BoomboxItemController boomboxItemController)
		{
			<boomboxItemController>P = boomboxItemController;
			lastDownloadRequestId = -1;
			boomboxAudioLoader = new BoomboxAudioLoader();
			base..ctor();
		}

		internal async void DownloadTask(int requestId, string filenameId, string title, int duration, string url, float time, bool resync = false)
		{
			if (string.IsNullOrEmpty(filenameId?.Trim()) || string.IsNullOrEmpty(title?.Trim()) || string.IsNullOrEmpty(url?.Trim()))
			{
				YPlayCorePatch.AddChatMessageYP("Invalid " + (resync ? "resync" : "download") + " request");
				return;
			}
			if (resync)
			{
				filenameIdsResyncing.Add(filenameId);
			}
			lastDownloadRequestId = requestId;
			lastDownloadRequestFilenameId = filenameId;
			time = Mathf.Max(time, 0f);
			POST_TASK postTask = POST_TASK.NONE;
			audioIdTitles[filenameId] = title;
			audioIdDurations[filenameId] = duration;
			await Task.Run(delegate
			{
				string outputFileLocationForId = GetOutputFileLocationForId(filenameId);
				CancelCurrentProcess();
				if (IsFilenameLoaded(filenameId))
				{
					postTask = LoadFile(filenameId, outputFileLocationForId, requestId, resync);
				}
				else if (!YPlay.IsYPlayUtilValid())
				{
					postTask = POST_TASK.ERROR_MISSING_DEPENDENCY;
				}
				else if (YPlay.IsDownloadingTools())
				{
					postTask = POST_TASK.ERROR_DOWNLOADING_TOOLS;
				}
				else if (!YPlay.IsToolsExistAndNonEmpty())
				{
					postTask = POST_TASK.ERROR_INVALID_TOOLS;
				}
				else
				{
					boomboxAudioAction = new BoomboxAudioAction(this, requestId, filenameId, outputFileLocationForId, url);
					postTask = boomboxAudioAction.Start(resync);
				}
			});
			string text = null;
			RLE_REASON rLE_REASON = RLE_REASON.NONE;
			switch (postTask)
			{
			case POST_TASK.ERROR_MISSING_DEPENDENCY:
				rLE_REASON = RLE_REASON.MISSING_DEPENDENCY;
				text = "Missing dependency, please try reinstalling YPlayBoombox";
				break;
			case POST_TASK.ERROR_DOWNLOADING_TOOLS:
				rLE_REASON = RLE_REASON.DOWNLOADING_TOOLS;
				text = "Downloading tools...";
				break;
			case POST_TASK.ERROR_INVALID_TOOLS:
				rLE_REASON = RLE_REASON.INVALID_TOOLS;
				text = "Invalid tools, please try /yp reset-tools";
				break;
			case POST_TASK.ERROR_DOWNLOADING_AUDIO:
				rLE_REASON = RLE_REASON.FAILED_DOWNLOAD;
				text = "Error downloading request " + GetFilenameIdString(filenameId);
				break;
			case POST_TASK.ERROR_LOADING_AUDIO:
				rLE_REASON = RLE_REASON.FAILED_LOAD;
				text = "Error loading request " + GetFilenameIdString(filenameId);
				break;
			}
			if (rLE_REASON != 0)
			{
				<boomboxItemController>P.SendBoomboxLoadedServerDelegate(requestId, loaded: false, resync, rLE_REASON);
				YPlay.LogError(text);
				YPlayCorePatch.AddChatMessageYP(text);
			}
			filenameIdsResyncing.Remove(filenameId);
		}

		internal void CancelCurrentProcess()
		{
			if (boomboxAudioAction != null && boomboxAudioAction.actionState == ACTION_STATE.PROCESSING)
			{
				boomboxAudioAction.KillProcess();
				YPlayCorePatch.AddChatMessageYP("Previous process cancelled " + GetFilenameIdString(boomboxAudioAction.filenameId));
			}
		}

		internal void KillRequestId(int requestId)
		{
			if (boomboxAudioAction != null && boomboxAudioAction.requestId == requestId)
			{
				CancelCurrentProcess();
			}
		}

		internal async Task DownloadMetadata(BoomboxRequestMetadata boomboxRequestMetadata, string url, string filenameId, float time)
		{
			await Task.Run(delegate
			{
				RM_STATUS rM_STATUS = RM_STATUS.NONE;
				if (string.IsNullOrEmpty(url?.Trim()) || string.IsNullOrEmpty(filenameId?.Trim()))
				{
					rM_STATUS = RM_STATUS.INVALID_METADATA;
				}
				else if (!YPlay.IsYPlayUtilValid())
				{
					rM_STATUS = RM_STATUS.MISSING_DEPENDENCY;
				}
				else if (YPlay.IsDownloadingTools())
				{
					rM_STATUS = RM_STATUS.DOWNLOADING_TOOLS;
				}
				else if (!YPlay.IsToolsExistAndNonEmpty())
				{
					rM_STATUS = RM_STATUS.INVALID_TOOLS;
				}
				if (rM_STATUS != 0)
				{
					boomboxRequestMetadata.rmStatus = rM_STATUS;
				}
				else
				{
					string text = (audioIdTitles.ContainsKey(filenameId) ? audioIdTitles[filenameId] : null);
					int num = (audioIdDurations.ContainsKey(filenameId) ? audioIdDurations[filenameId] : 0);
					if (!IsMetadataLoadedForFilenameId(filenameId))
					{
						(text, num) = GetAudioTitleDuration(url);
						if (string.IsNullOrEmpty(text?.Trim()) || num == 0)
						{
							boomboxRequestMetadata.rmStatus = RM_STATUS.INVALID_METADATA;
							return;
						}
						audioIdTitles[filenameId] = text;
						audioIdDurations[filenameId] = num;
					}
					int num2 = num / 60;
					if (num2 > 12)
					{
						boomboxRequestMetadata.rmStatus = RM_STATUS.INVALID_MAX_DURATION;
					}
					else if (string.IsNullOrEmpty(text?.Trim()) || num == 0)
					{
						boomboxRequestMetadata.rmStatus = RM_STATUS.INVALID_METADATA;
					}
					else
					{
						boomboxRequestMetadata.filenameId = filenameId;
						boomboxRequestMetadata.url = url;
						boomboxRequestMetadata.time = time;
						boomboxRequestMetadata.title = text;
						boomboxRequestMetadata.duration = num;
						if (boomboxRequestMetadata.rmStatus != RM_STATUS.CANCELLED)
						{
							boomboxRequestMetadata.rmStatus = RM_STATUS.VALID;
						}
					}
				}
			});
		}

		private (string title, int duration) GetAudioTitleDuration(string url)
		{
			YoutubeDL val = YPlay.NewYoutubeDl();
			string text = "";
			int item = 0;
			try
			{
				OptionSet val2 = optionSet;
				RunResult<VideoData> result = val.RunVideoDataFetch(url, default(CancellationToken), true, false, val2).GetAwaiter().GetResult();
				VideoData data = result.Data;
				if (result != null)
				{
					text = data.Title;
					item = (int)data.Duration.GetValueOrDefault();
				}
			}
			catch (Exception)
			{
				return ("", 0);
			}
			if (string.IsNullOrEmpty(text?.Trim()))
			{
				text = GetFilenameIdFromUrl(url);
			}
			return (text, item);
		}

		internal POST_TASK LoadFile(string filenameId, string outputFileLocation, int requestId, bool resync)
		{
			if (IsFilenameLoaded(filenameId))
			{
				boomboxAudioLoader.Start(boomboxAudioLoader.GetAudioClip(<boomboxItemController>P, requestId, outputFileLocation, resync));
				return POST_TASK.NONE;
			}
			return POST_TASK.ERROR_LOADING_AUDIO;
		}

		private bool IsFilenameLoaded(string filenameId)
		{
			if (!string.IsNullOrEmpty(filenameId?.Trim()))
			{
				if (!IsFilenameIdDownloaded(filenameId))
				{
					return BoomboxAudioLoader.filenameIdAudioClips.ContainsKey(filenameId);
				}
				return true;
			}
			return false;
		}

		internal static bool IsFilenameIdDownloaded(string filenameId)
		{
			if (!string.IsNullOrEmpty(filenameId?.Trim()))
			{
				return IsFileValid(GetOutputFileLocationForId(filenameId));
			}
			return false;
		}

		internal static bool IsFileValid(string path)
		{
			if (File.Exists(path))
			{
				return new FileInfo(path).Length > 0;
			}
			return false;
		}

		internal static bool IsMetadataLoadedForFilenameId(string filenameId)
		{
			if (!string.IsNullOrEmpty(filenameId?.Trim()) && audioIdTitles.ContainsKey(filenameId))
			{
				return audioIdDurations.ContainsKey(filenameId);
			}
			return false;
		}

		internal static string GetFilenameIdFromUrl(string url)
		{
			if (string.IsNullOrEmpty(url?.Trim()))
			{
				return null;
			}
			url = url.Replace("https://", "").Replace("http://", "").Replace("www.", "");
			string text = null;
			int num = url.IndexOf("?v=", StringComparison.OrdinalIgnoreCase);
			int num2 = url.IndexOf("&v=", StringComparison.OrdinalIgnoreCase);
			int num3 = url.IndexOf("/shorts/", StringComparison.OrdinalIgnoreCase);
			int num4 = url.IndexOf("/", StringComparison.OrdinalIgnoreCase);
			if (num > -1)
			{
				text = url.Substring(num + "?v=".Length);
			}
			else if (num2 > -1)
			{
				text = url.Substring(num2 + "&v=".Length);
			}
			else if (num3 > -1)
			{
				text = url.Substring(num3 + "/shorts/".Length);
			}
			else if (num4 > -1)
			{
				text = url.Substring(num4 + "/".Length);
			}
			if (!string.IsNullOrEmpty(text?.Trim()))
			{
				int num5 = text.IndexOf("&", StringComparison.OrdinalIgnoreCase);
				if (num5 > -1)
				{
					text = text.Substring(0, num5);
				}
				int num6 = text.IndexOf("?", StringComparison.OrdinalIgnoreCase);
				if (num6 > -1)
				{
					text = text.Substring(0, num6);
				}
			}
			if (!string.IsNullOrEmpty(text?.Trim()))
			{
				return text;
			}
			return null;
		}

		internal static void KillAllBoomboxDownloaderProcesses()
		{
			foreach (KeyValuePair<ulong, BoomboxItemController> item in new Dictionary<ulong, BoomboxItemController>(BoomboxItemController.boomboxItemControllers))
			{
				BoomboxItemController value = item.Value;
				value.boomboxAudioDownloader.CancelCurrentProcess();
			}
		}

		internal static string GetOutputFileLocationWithoutExtensionForId(string id)
		{
			return YPlay.audioDirectory + "\\" + id;
		}

		internal static string GetOutputFileLocationTempForId(string id)
		{
			return GetOutputFileLocationWithoutExtensionForId(id) + ".part";
		}

		internal static string GetOutputFileLocationForId(string id)
		{
			return GetOutputFileLocationWithoutExtensionForId(id) + "." + audioTypeExtension;
		}

		internal static string GetFilenameIdString(string filenameId)
		{
			if (string.IsNullOrEmpty(filenameId?.Trim()))
			{
				return null;
			}
			return "[" + filenameId + "]";
		}
	}
	internal class BoomboxAudioAction
	{
		internal ACTION_STATE actionState;

		private readonly BoomboxAudioDownloader boomboxAudioDownloader;

		internal int requestId;

		internal string filenameId;

		private readonly string outputFileLocation;

		private readonly string url;

		private readonly string tmpFile;

		private readonly string tmpFileWithExt;

		private readonly YoutubeDL youtubeDL;

		private readonly CancellationTokenSource cancellationTokenSource;

		private static readonly OptionSet optionSet;

		internal BoomboxAudioAction(BoomboxAudioDownloader boomboxAudioDownloader, int requestId, string filenameId, string outputFileLocation, string url)
		{
			this.boomboxAudioDownloader = boomboxAudioDownloader;
			this.requestId = requestId;
			this.filenameId = filenameId;
			this.outputFileLocation = outputFileLocation;
			this.url = url;
			tmpFile = YPlay.GetRandomTempFileLocation();
			tmpFileWithExt = tmpFile + "." + BoomboxAudioDownloader.audioTypeExtension;
			youtubeDL = YPlay.NewYoutubeDl();
			youtubeDL.OutputFileTemplate = tmpFile;
			cancellationTokenSource = new CancellationTokenSource();
		}

		internal POST_TASK Start(bool resync)
		{
			YPlayCorePatch.AddChatMessageYP("Downloading " + BoomboxAudioDownloader.GetFilenameIdString(filenameId) + "...");
			try
			{
				RunResult<string> result = youtubeDL.RunAudioDownload(url, (AudioConversionFormat)(BoomboxAudioDownloader.audioTypeExtension.Equals("wav") ? 7 : 3), cancellationTokenSource.Token, (IProgress<DownloadProgress>)null, (IProgress<string>)null, optionSet).GetAwaiter().GetResult();
			}
			catch (Exception)
			{
			}
			try
			{
				if (actionState == ACTION_STATE.PROCESSING && boomboxAudioDownloader.lastDownloadRequestId == requestId)
				{
					if (!File.Exists(outputFileLocation))
					{
						if (!BoomboxAudioDownloader.IsFileValid(tmpFileWithExt))
						{
							throw new Exception("Temp file not valid");
						}
						YPlay.CreateParentDirectory(outputFileLocation);
						File.Move(tmpFileWithExt, outputFileLocation);
					}
					actionState = ACTION_STATE.FINISHED;
					return boomboxAudioDownloader.LoadFile(filenameId, outputFileLocation, requestId, resync);
				}
			}
			catch (Exception)
			{
				KillProcess();
				return POST_TASK.ERROR_DOWNLOADING_AUDIO;
			}
			finally
			{
				DeleteRequestFiles();
			}
			return POST_TASK.NONE;
		}

		internal void KillProcess()
		{
			if (actionState == ACTION_STATE.PROCESSING)
			{
				actionState = ACTION_STATE.KILLED;
				try
				{
					cancellationTokenSource?.Cancel();
				}
				catch (Exception)
				{
				}
			}
			DeleteRequestFiles();
		}

		private void DeleteRequestFiles()
		{
			Task.Delay(2000).ContinueWith(delegate
			{
				YPlay.DeleteFile(tmpFile);
				YPlay.DeleteFile(tmpFileWithExt);
			});
		}

		static BoomboxAudioAction()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			OptionSet val = new OptionSet();
			val.NoPlaylist = true;
			val.ForceIPv4 = true;
			val.Format = "140";
			val.PostprocessorArgs = MultiValue<string>.op_Implicit(new string[1] { "ffmpeg:-filter:a dynaudnorm" });
			optionSet = val;
		}
	}
	internal class BoomboxItemController : NetworkBehaviour
	{
		internal static readonly Dictionary<ulong, BoomboxItemController> boomboxItemControllers = new Dictionary<ulong, BoomboxItemController>();

		private static readonly Dictionary<AudioClip, BoomboxItemController> audioClipBoomboxItemController = new Dictionary<AudioClip, BoomboxItemController>();

		private static readonly Dictionary<ulong, double> clientIdsLastRequestSentMs = new Dictionary<ulong, double>();

		private double lastRequestSentMs;

		internal BoomboxAudioDownloader boomboxAudioDownloader;

		internal BoomboxItem boomboxItem;

		internal string serverFilenameId;

		internal string serverUrl;

		internal string serverTitle;

		internal int serverDuration;

		internal float serverTime;

		internal string filenameId;

		private string url;

		private string title;

		private int duration;

		private float timeSaved;

		private float timeRequested;

		internal AudioType audioType = (AudioType)13;

		private bool showSyncRandomBoomboxColorMsg;

		private COLOR_PATTERN colorPattern;

		private IEnumerator colorPatternCoroutine;

		internal BoomboxRequestMetadata boomboxRequestMetadata;

		private CancellationTokenSource metadataCompletionCancellationTokenSource;

		private CancellationTokenSource requestCompletionCancellationTokenSource;

		private static readonly DateTime epochDateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

		private readonly Dictionary<string, string> colorPatternRainbowDict = new Dictionary<string, string>
		{
			{ "R", "red" },
			{ "A", "orange" },
			{ "I", "yellow" },
			{ "N", "green" },
			{ "B", "lightblue" },
			{ "O", "mediumpurple" },
			{ "W", "violet" }
		};

		internal void Awake()
		{
			boomboxAudioDownloader = new BoomboxAudioDownloader(this);
			boomboxItem = ((Component)this).GetComponent<BoomboxItem>();
			((GrabbableObject)boomboxItem).itemProperties.requiresBattery = false;
		}

		internal void Start()
		{
			ulong networkObjectId = ((NetworkBehaviour)boomboxItem).NetworkObjectId;
			boomboxItemControllers[networkObjectId] = this;
			if (Config.configEntryRandomColor.Value && IsHostOrIsOffline())
			{
				SyncRandomBoomboxColor(((NetworkBehaviour)this).NetworkManager.LocalClientId);
			}
		}

		public override void OnNetworkSpawn()
		{
			((NetworkBehaviour)this).OnNetworkSpawn();
		}

		internal void SendRequestServerDelegate(string url, float time)
		{
			//IL_0015: 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 (YPlayCorePatch.IsOfflineMode())
			{
				SendRequestServerLocal(url, time);
			}
			else
			{
				SendRequestServerRpc(url, time);
			}
		}

		internal void SendBoomboxLoadedServerDelegate(int requestId, bool loaded, bool resync, RLE_REASON rleReason = RLE_REASON.NONE)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (YPlayCorePatch.IsOfflineMode())
			{
				SendBoomboxLoadedServerLocal(requestId, loaded, resync, rleReason);
			}
			else
			{
				SendBoomboxLoadedServerRpc(requestId, loaded, resync, rleReason);
			}
		}

		internal void SyncBoomboxVolumeRequestServerDelegate(float volume, bool msg = false)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (YPlayCorePatch.IsOfflineMode())
			{
				SyncBoomboxVolumeRequestClientShared(volume, YPlayCorePatch.LocalPlayerController.actualClientId, msg);
			}
			else
			{
				SyncBoomboxVolumeRequestServerRpc(volume, msg);
			}
		}

		internal void SyncBoomboxColorRequestServerDelegate(float r, float g, float b, COLOR_PATTERN colorPattern = COLOR_PATTERN.NONE)
		{
			//IL_003b: 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)
			if (YPlayCorePatch.IsOfflineMode())
			{
				if (!ApplyColorPattern(colorPattern, ((NetworkBehaviour)this).NetworkManager.LocalClientId))
				{
					SyncBoomboxColorRequestClientShared(r, g, b, colorPattern, YPlayCorePatch.LocalPlayerController.actualClientId, msg: true);
				}
			}
			else
			{
				SyncBoomboxColorRequestServerRpc(r, g, b, colorPattern);
			}
		}

		internal void ResetBoomboxRequestServerDelegate()
		{
			if (YPlayCorePatch.IsOfflineMode())
			{
				ResetBoombox();
			}
			else
			{
				ResetBoomboxRequestServerRpc();
			}
		}

		internal void SyncBoomboxTimeRequestServerDelegate(float time, REQUEST_TYPE requestType = REQUEST_TYPE.NONE)
		{
			//IL_0015: 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 (YPlayCorePatch.IsOfflineMode())
			{
				SyncBoomboxTimeRequestServerLocal(time, requestType);
			}
			else
			{
				SyncBoomboxTimeRequestServerRpc(time, requestType);
			}
		}

		internal void SyncBoomboxRequestLookingAtServerDelegate(ulong boomboxLookingAtId)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (YPlayCorePatch.IsOfflineMode())
			{
				SyncBoomboxRequestLookingAtServerLocal(boomboxLookingAtId);
			}
			else
			{
				SyncBoomboxRequestLookingAtServerRpc(boomboxLookingAtId);
			}
		}

		private void SyncRandomBoomboxColor(ulong clientId, bool msg = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Color randomBoomboxColor = GetRandomBoomboxColor();
			if (((NetworkBehaviour)this).IsHost)
			{
				SyncBoomboxColorRequestClientRpc(randomBoomboxColor.r, randomBoomboxColor.g, randomBoomboxColor.b, colorPattern, clientId, msg);
			}
			else
			{
				SyncBoomboxColorRequestClientShared(randomBoomboxColor.r, randomBoomboxColor.g, randomBoomboxColor.b, colorPattern, clientId, msg);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SendRequestServerRpc(string url, float time, ServerRpcParams serverRpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(3425911769u, serverRpcParams, (RpcDelivery)0);
				bool flag = url != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(url, false);
				}
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref time, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 3425911769u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost) || IsInvalidServerCall())
			{
				return;
			}
			ulong senderClientId = serverRpcParams.Receive.SenderClientId;
			if (ClientRequestWait(senderClientId))
			{
				return;
			}
			ClientRpcParams clientRpcParams = default(ClientRpcParams);
			clientRpcParams.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(senderClientId);
			RM_STATUS rM_STATUS = RM_STATUS.NONE;
			string filenameIdFromUrl = BoomboxAudioDownloader.GetFilenameIdFromUrl(url);
			if (string.IsNullOrEmpty(url?.Trim()) || string.IsNullOrEmpty(filenameIdFromUrl?.Trim()))
			{
				rM_STATUS = RM_STATUS.INVALID_URL;
			}
			else if (!IsBoomboxValid(boomboxItem))
			{
				rM_STATUS = RM_STATUS.INVALID_BOOMBOX;
			}
			else if (!YPlay.IsYPlayUtilValid())
			{
				rM_STATUS = RM_STATUS.MISSING_DEPENDENCY;
			}
			else if (YPlay.IsDownloadingTools())
			{
				rM_STATUS = RM_STATUS.DOWNLOADING_TOOLS;
			}
			else if (!YPlay.IsToolsExistAndNonEmpty())
			{
				rM_STATUS = RM_STATUS.INVALID_TOOLS;
			}
			if (rM_STATUS != 0)
			{
				if (senderClientId != YPlayCorePatch.LocalPlayerController.actualClientId)
				{
					string text = rM_STATUS switch
					{
						RM_STATUS.MISSING_DEPENDENCY => "you are missing a dependency, please try reinstalling YPlayBoombox", 
						RM_STATUS.DOWNLOADING_TOOLS => "you are still downloading tools", 
						RM_STATUS.INVALID_TOOLS => "you have invalid tools, please try /yp reset-tools", 
						_ => null, 
					};
					if (text != null)
					{
						string text2 = "You cannot process this client request because " + text;
						YPlay.LogError(text2);
						YPlayCorePatch.AddChatMessageYP(text2);
					}
				}
				SendRequestFailedClientRpc(filenameIdFromUrl, rM_STATUS, clientRpcParams);
			}
			else
			{
				if (boomboxRequestMetadata != null && boomboxRequestMetadata.rmStatus == RM_STATUS.INITIALIZING)
				{
					CancelBoomboxRequestServer(boomboxRequestMetadata.requestId, boomboxRequestMetadata.filenameId, senderClientId, RC_REASON.NEW_REQUEST);
				}
				DownloadMetadataServer(url, filenameIdFromUrl, time, senderClientId);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SendBoomboxLoadedServerRpc(int requestId, bool loaded, bool resync, RLE_REASON rleReason = RLE_REASON.NONE, ServerRpcParams serverRpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(1074417815u, serverRpcParams, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val, requestId);
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref loaded, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref resync, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<RLE_REASON>(ref rleReason, default(ForEnums));
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 1074417815u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost) || IsInvalidServerCall())
			{
				return;
			}
			ulong senderClientId = serverRpcParams.Receive.SenderClientId;
			if (resync && loaded)
			{
				SyncBoomboxRequestVerifyMultipleServer(resync, senderClientId);
			}
			else if (IsBoomboxRequestMetadataActive(boomboxRequestMetadata))
			{
				RC_REASON rC_REASON = RcReasonErrorCheck();
				if (rC_REASON != 0)
				{
					CancelBoomboxRequestServer(requestId, boomboxRequestMetadata.filenameId, senderClientId, rC_REASON);
				}
				else
				{
					SendBoomboxLoadedCallServer(boomboxRequestMetadata, senderClientId, loaded, rleReason);
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void ResetBoomboxRequestServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(2681523663u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 2681523663u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && !IsInvalidServerCall() && IsBoomboxValid(boomboxItem))
				{
					ResetBoomboxRequestClientRpc();
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncBoomboxRequestLookingAtServerRpc(ulong boomboxLookingAtId, ServerRpcParams serverRpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(3702246251u, serverRpcParams, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val, boomboxLookingAtId);
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 3702246251u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && !IsInvalidServerCall() && boomboxItemControllers.ContainsKey(boomboxLookingAtId))
			{
				BoomboxItemController boomboxItemController = boomboxItemControllers[boomboxLookingAtId];
				BoomboxItem val2 = boomboxItemController.boomboxItem;
				if (IsBoomboxValid(val2) && ShouldResync(boomboxItemController))
				{
					ulong senderClientId = serverRpcParams.Receive.SenderClientId;
					SyncBoomboxRequestLookingAtClientRpc(boomboxLookingAtId, senderClientId);
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncBoomboxTimeRequestServerRpc(float time, REQUEST_TYPE requestType = REQUEST_TYPE.NONE, ServerRpcParams serverRpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(2185615963u, serverRpcParams, (RpcDelivery)0);
					((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref time, default(ForPrimitives));
					((FastBufferWriter)(ref val)).WriteValueSafe<REQUEST_TYPE>(ref requestType, default(ForEnums));
					((NetworkBehaviour)this).__endSendServerRpc(ref val, 2185615963u, serverRpcParams, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && !IsInvalidServerCall() && IsBoomboxValid(boomboxItem) && IsBoomboxTimeValid(time) && ShouldResyncTime(time))
				{
					ulong senderClientId = serverRpcParams.Receive.SenderClientId;
					SyncBoomboxTimeRequestClientRpc(time, senderClientId, filenameId, requestType);
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncBoomboxVolumeRequestServerRpc(float volume, bool msg, ServerRpcParams serverRpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(160244116u, serverRpcParams, (RpcDelivery)0);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref volume, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref msg, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 160244116u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && !IsInvalidServerCall() && IsBoomboxValid(boomboxItem))
			{
				volume = Mathf.Clamp((float)Math.Round(volume, 1), 0f, 1f);
				if (ShouldResyncVolume(volume))
				{
					ulong senderClientId = serverRpcParams.Receive.SenderClientId;
					SyncBoomboxVolumeRequestClientRpc(volume, senderClientId, msg);
				}
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void SyncBoomboxColorRequestServerRpc(float r, float g, float b, COLOR_PATTERN colorPattern, ServerRpcParams serverRpcParams = default(ServerRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(3044477801u, serverRpcParams, (RpcDelivery)0);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref r, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref g, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref b, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<COLOR_PATTERN>(ref colorPattern, default(ForEnums));
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 3044477801u, serverRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && !IsInvalidServerCall())
			{
				ulong senderClientId = serverRpcParams.Receive.SenderClientId;
				if (!ApplyColorPattern(colorPattern, senderClientId))
				{
					SyncBoomboxColorRequestClientRpc(r, g, b, colorPattern, senderClientId, msg: true);
				}
			}
		}

		private bool ApplyColorPattern(COLOR_PATTERN colorPattern, ulong clientId)
		{
			this.colorPattern = colorPattern;
			if (colorPatternCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(colorPatternCoroutine);
			}
			if (this.colorPattern == COLOR_PATTERN.RAINBOW)
			{
				((MonoBehaviour)this).StartCoroutine(colorPatternCoroutine = ColorPatternRainbow(clientId));
				return true;
			}
			return false;
		}

		private IEnumerator ColorPatternRainbow(ulong clientId)
		{
			showSyncRandomBoomboxColorMsg = true;
			while (colorPattern == COLOR_PATTERN.RAINBOW)
			{
				SyncRandomBoomboxColor(clientId, showSyncRandomBoomboxColorMsg);
				showSyncRandomBoomboxColorMsg = false;
				yield return (object)new WaitForSeconds(1f);
			}
		}

		[ServerRpc(RequireOwnership = false)]
		internal void SyncAllBoomboxRequestServerRpc(ulong clientId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val = default(ServerRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1929840421u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, clientId);
				((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1929840421u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost) && !IsInvalidServerCall() && IsBoomboxValid(boomboxItem))
			{
				ulong networkObjectId = ((NetworkBehaviour)boomboxItem).NetworkObjectId;
				BoomboxRequest boomboxRequest = GetBoomboxRequest(networkObjectId, request: true);
				if (boomboxRequest != null)
				{
					ClientRpcParams clientRpcParams = default(ClientRpcParams);
					clientRpcParams.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(clientId);
					SyncBoomboxVolumeRequestClientRpc(boomboxRequest.volume, 0uL, msg: false, clientRpcParams);
					Color boomboxBodyColor = GetBoomboxBodyColor();
					SyncBoomboxColorRequestClientRpc(boomboxBodyColor.r, boomboxBodyColor.g, boomboxBodyColor.b, colorPattern, 0uL, msg: false, clientRpcParams);
					SyncBoomboxPlayingRequestClientRpc(boomboxRequest.filenameId, boomboxRequest.url, boomboxRequest.title, boomboxRequest.duration, boomboxRequest.time, boomboxRequest.isPlayingMusic, clientRpcParams);
				}
			}
		}

		private bool ClientRequestWait(ulong clientId)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			double timeMs = GetTimeMs();
			double val = 0.0;
			if (clientIdsLastRequestSentMs.ContainsKey(clientId))
			{
				val = clientIdsLastRequestSentMs[clientId];
			}
			else
			{
				clientIdsLastRequestSentMs[clientId] = timeMs;
			}
			double val2 = lastRequestSentMs;
			double num = Math.Max(val, val2);
			double num2 = timeMs - num;
			if (num2 <= 5000.0)
			{
				ClientRpcParams clientRpcParams = default(ClientRpcParams);
				clientRpcParams.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(clientId);
				double waitMs = Math.Max(0.0, 5000.0 - num2);
				SendRequestFailedWaitClientRpc(waitMs, clientRpcParams);
				return true;
			}
			clientIdsLastRequestSentMs[clientId] = (lastRequestSentMs = timeMs);
			return false;
		}

		private void SyncBoomboxRequestVerifyMultipleServer(bool resync = false, ulong clientId = 0uL)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			if (IsInvalidServerCall())
			{
				return;
			}
			Dictionary<ulong, BoomboxItemController> dictionary = new Dictionary<ulong, BoomboxItemController>(boomboxItemControllers);
			List<BoomboxItemController> list = new List<BoomboxItemController>();
			foreach (KeyValuePair<ulong, BoomboxItemController> item in dictionary)
			{
				BoomboxItemController value = item.Value;
				if (!((Object)(object)value == (Object)null) && (resync || !((Object)(object)value == (Object)(object)this)) && !(value.filenameId != filenameId))
				{
					list.Add(value);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			ClientRpcParams clientRpcParams = default(ClientRpcParams);
			if (resync)
			{
				clientRpcParams.Send.TargetClientIds = new <>z__ReadOnlySingleElementList<ulong>(clientId);
			}
			foreach (BoomboxItemController item2 in list)
			{
				ulong networkObjectId = ((NetworkBehaviour)item2).NetworkObjectId;
				BoomboxRequest boomboxRequest = item2.GetBoomboxRequest(networkObjectId);
				if (boomboxRequest != null)
				{
					item2.SyncBoomboxRequestVerifyMultipleClientRpc(boomboxRequest.filenameId, boomboxRequest.url, boomboxRequest.title, boomboxRequest.duration, boomboxRequest.time, boomboxRequest.isPlayingMusic, clientRpcParams);
				}
			}
			if (resync)
			{
				SendResyncedMessageClientRpc(clientRpcParams);
			}
		}

		internal void SendBoomboxLoadedCallServer(BoomboxRequestMetadata boomboxRequestMetadata, ulong clientId, bool loaded, RLE_REASON rleReason = RLE_REASON.NONE)
		{
			if (IsInvalidServerCall() || !IsBoomboxRequestMetadataActive(boomboxRequestMetadata) || !boomboxRequestMetadata.pendingClientIdRequests.Contains(clientId))
			{
				return;
			}
			boomboxRequestMetadata.pendingClientIdRequests.Remove(clientId);
			int count = boomboxRequestMetadata.originalClientIdRequests.Count;
			int count2 = boomboxRequestMetadata.pendingClientIdRequests.Count;
			int loadedClientCount = Mathf.Clamp(count - count2, 0, count);
			SendBoomboxLoadedClientRpc(boomboxRequestMetadata.requestId, boomboxRequestMetadata.filenameId, clientId, loaded, loadedClientCount, count, rleReason);
			if (!loaded && clientId == YPlayCorePatch.LocalPlayerController.actualClientId)
			{
				CancelBoomboxRequestServer(boomboxRequestMetadata.requestId, boomboxRequestMetadata.filenameId, clientId, RC_REASON.HOST_FAILED);
			}
			else if (count2 == 0)
			{
				boomboxRequestMetadata.pendingClientIdRequests.Clear();
				ulong networkObjectId = ((NetworkBehaviour)boomboxItem).NetworkObjectId;
				BoomboxRequest boomboxRequest = GetBoomboxRequest(networkObjectId, request: true);
				if (boomboxRequest != null)
				{
					boomboxRequest.filenameId = boomboxRequestMetadata.filenameId;
					boomboxRequest.url = boomboxRequestMetadata.url;
					boomboxRequest.title = boomboxRequestMetadata.title;
					boomboxRequest.duration = boomboxRequestMetadata.duration;
					boomboxRequest.time = boomboxRequestMetadata.time;
					SyncBoomboxRequestClientRpc(request: true, boomboxRequest.filenameId, boomboxRequest.url, boomboxRequest.title, boomboxRequest.duration, boomboxRequest.time, boomboxRequest.isPlayingMusic);
					SyncBoomboxRequestVerifyMultipleServer(resync: false, 0uL);
				}
			}
		}

		private async void DownloadMetadataServer(string url, string filenameId, float time, ulong clientId)
		{
			if (IsInvalidServerCall())
			{
				return;
			}
			SendRequestInitialisingMessageClientRpc(clientId, filenameId);
			if (boomboxRequestMetadata != null)
			{
				KillRequestIdClientRpc(boomboxRequestMetadata.requestId);
			}
			CancelMetadataAndRequestTimersShared();
			HashSet<ulong> collection = new HashSet<ulong>(YPlayCorePatch.modEnabledForClientIds);
			BoomboxRequestMetadata boomboxRequestMetadataLocal = (boomboxRequestMetadata = new BoomboxRequestMetadata
			{
				originalClientIdRequests = new HashSet<ulong>(collection),
				pendingClientIdRequests = new HashSet<ulong>(collection)
			});
			CancellationTokenSource metadataCompletionCancellationTokenSourceLocal = (metadataCompletionCancellationTokenSource = new CancellationTokenSource());
			Task metadataTask = boomboxAudioDownloader.DownloadMetadata(boomboxRequestMetadataLocal, url, filenameId, time);
			if (await Task.WhenAny(new Task[2]
			{
				metadataTask,
				Task.Delay(15000, metadataCompletionCancellationTokenSourceLocal.Token)
			}) != metadataTask)
			{
				if (metadataCompletionCancellationTokenSourceLocal.IsCancellationRequested || !IsBoomboxRequestMetadataActive(boomboxRequestMetadataLocal))
				{
					return;
				}
				SendRequestFailedClientRpc(filenameId, boomboxRequestMetadataLocal.rmStatus = RM_STATUS.TIMEOUT);
			}
			if (boomboxRequestMetadataLocal.rmStatus != RM_STATUS.VALID)
			{
				SendRequestFailedClientRpc(filenameId, boomboxRequestMetadataLocal.rmStatus);
				return;
			}
			DownloadTaskClientRpc(boomboxRequestMetadataLocal.requestId, boomboxRequestMetadataLocal.filenameId, boomboxRequestMetadataLocal.title, boomboxRequestMetadataLocal.duration, boomboxRequestMetadataLocal.url, time);
			CancellationTokenSource requestCompletionCancellationTokenSourceLocal = (requestCompletionCancellationTokenSource = new CancellationTokenSource());
			Task requestCompletionTimeoutTask = RequestCompletionTimeoutTask(45000);
			if (await Task.WhenAny(new Task[2]
			{
				requestCompletionTimeoutTask,
				Task.Delay(45000, requestCompletionCancellationTokenSourceLocal.Token)
			}) == requestCompletionTimeoutTask || requestCompletionCancellationTokenSourceLocal.IsCancellationRequested || !IsBoomboxRequestMetadataActive(boomboxRequestMetadataLocal))
			{
				return;
			}
			ulong actualClientId = YPlayCorePatch.LocalPlayerController.actualClientId;
			HashSet<ulong> hashSet = new HashSet<ulong>();
			foreach (ulong pendingClientIdRequest in boomboxRequestMetadataLocal.pendingClientIdRequests)
			{
				hashSet.Add(pendingClientIdRequest);
			}
			HashSet<ulong> hashSet2 = hashSet;
			if (hashSet2.Contains(YPlayCorePatch.LocalPlayerController.actualClientId))
			{
				hashSet2 = new HashSet<ulong> { actualClientId };
			}
			foreach (ulong item in hashSet2)
			{
				SendBoomboxLoadedCallServer(boomboxRequestMetadataLocal, item, loaded: false, RLE_REASON.TIMEOUT);
			}
		}

		private async Task RequestCompletionTimeoutTask(int timeout)
		{
			await Task.Run(delegate
			{
				Thread.Sleep(timeout);
			});
		}

		private void CancelBoomboxRequestServer(int requestId, string filenameId, ulong clientId, RC_REASON rcReason)
		{
			if (!IsInvalidServerCall())
			{
				CancelBoomboxServer(requestId);
				SendBoomboxRequestCancelledMessageClientRpc(filenameId, clientId, rcReason);
			}
		}

		private void CancelBoomboxServer(int requestId)
		{
			if (!IsInvalidServerCall())
			{
				if (boomboxRequestMetadata != null && boomboxRequestMetadata.requestId == requestId)
				{
					boomboxRequestMetadata.rmStatus = RM_STATUS.CANCELLED;
					boomboxRequestMetadata.pendingClientIdRequests.Clear();
					CancelRequestTimerShared();
				}
				ClearPreviousAudioClipsClientRpc();
			}
		}

		public override void OnDestroy()
		{
			if (!IsInvalidServerCall())
			{
				if (boomboxRequestMetadata != null)
				{
					CancelBoomboxServer(boomboxRequestMetadata.requestId);
				}
				((NetworkBehaviour)this).OnDestroy();
			}
		}

		[ClientRpc]
		private void KillRequestIdClientRpc(int requestId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3126721376u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, requestId);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3126721376u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					boomboxAudioDownloader.KillRequestId(requestId);
				}
			}
		}

		[ClientRpc]
		private void ClearPreviousAudioClipsClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3187082761u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3187082761u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					ClearUnusedAudioClips();
				}
			}
		}

		[ClientRpc]
		private void SyncBoomboxRequestLookingAtClientRpc(ulong boomboxLookingAtId, ulong clientId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3898947593u, val, (RpcDelivery)0);
					BytePacker.WriteValueBitPacked(val2, boomboxLookingAtId);
					BytePacker.WriteValueBitPacked(val2, clientId);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3898947593u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					SyncBoomboxRequestLookingAtClientShared(boomboxLookingAtId, clientId);
				}
			}
		}

		[ClientRpc]
		private void SendRequestInitialisingMessageClientRpc(ulong clientId, string filenameId)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2497770173u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, clientId);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(filenameId, false);
				}
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2497770173u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				string playerUsernameFromClientId = YPlayCorePatch.GetPlayerUsernameFromClientId(clientId);
				YPlayCorePatch.AddChatMessageYP(playerUsernameFromClientId + " requested [" + filenameId + "]...");
			}
		}

		[ClientRpc]
		private void SendResyncedMessageClientRpc(ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(3136043952u, clientRpcParams, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val, 3136043952u, clientRpcParams, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					YPlayCorePatch.AddChatMessageYP("Resync successful");
				}
			}
		}

		[ClientRpc]
		private void DownloadTaskClientRpc(int requestId, string filenameId, string title, int duration, string url, float time)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(923605557u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, requestId);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(filenameId, false);
				}
				bool flag2 = title != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(title, false);
				}
				BytePacker.WriteValueBitPacked(val2, duration);
				bool flag3 = url != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag3, default(ForPrimitives));
				if (flag3)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(url, false);
				}
				((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref time, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 923605557u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				DownloadTaskClientShared(requestId, filenameId, title, duration, url, time);
			}
		}

		[ClientRpc]
		private void SendRequestFailedClientRpc(string filenameId, RM_STATUS rmStatus, ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(2668383935u, clientRpcParams, (RpcDelivery)0);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(filenameId, false);
				}
				((FastBufferWriter)(ref val)).WriteValueSafe<RM_STATUS>(ref rmStatus, default(ForEnums));
				((NetworkBehaviour)this).__endSendClientRpc(ref val, 2668383935u, clientRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				SendRequestFailedClientShared(filenameId, rmStatus);
			}
		}

		[ClientRpc]
		private void SendRequestFailedWaitClientRpc(double waitMs, ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(115722075u, clientRpcParams, (RpcDelivery)0);
					((FastBufferWriter)(ref val)).WriteValueSafe<double>(ref waitMs, default(ForPrimitives));
					((NetworkBehaviour)this).__endSendClientRpc(ref val, 115722075u, clientRpcParams, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					int num = Math.Max(1, (int)Math.Ceiling(TimeSpan.FromMilliseconds(waitMs).TotalSeconds));
					YPlayCorePatch.AddChatMessageYP(string.Format("Please wait {0} second{1} before calling this command", num, (num == 1) ? null : "s"));
				}
			}
		}

		[ClientRpc]
		private void SendBoomboxRequestCancelledMessageClientRpc(string filenameId, ulong clientId, RC_REASON rcReason)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(4201653590u, val, (RpcDelivery)0);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(filenameId, false);
				}
				BytePacker.WriteValueBitPacked(val2, clientId);
				((FastBufferWriter)(ref val2)).WriteValueSafe<RC_REASON>(ref rcReason, default(ForEnums));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 4201653590u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				SendBoomboxRequestCancelledMessageClientShared(filenameId, rcReason);
			}
		}

		[ClientRpc]
		private void SendBoomboxLoadedClientRpc(int requestId, string filenameId, ulong clientId, bool loaded, int loadedClientCount, int originalRequestCount, RLE_REASON rleReason)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00d5: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3390314703u, val, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val2, requestId);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(filenameId, false);
				}
				BytePacker.WriteValueBitPacked(val2, clientId);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref loaded, default(ForPrimitives));
				BytePacker.WriteValueBitPacked(val2, loadedClientCount);
				BytePacker.WriteValueBitPacked(val2, originalRequestCount);
				((FastBufferWriter)(ref val2)).WriteValueSafe<RLE_REASON>(ref rleReason, default(ForEnums));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3390314703u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				SendBoomboxLoadedClientShared(requestId, filenameId, clientId, loaded, loadedClientCount, originalRequestCount, rleReason);
			}
		}

		[ClientRpc]
		private void ResetBoomboxRequestClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					ClientRpcParams val = default(ClientRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3381308416u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3381308416u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					ResetBoombox();
				}
			}
		}

		[ClientRpc]
		private void SyncBoomboxRequestClientRpc(bool request, string filenameId, string url, string title, int duration, float time, bool isPlayingMusic)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3399703514u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref request, default(ForPrimitives));
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(filenameId, false);
				}
				bool flag2 = url != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(url, false);
				}
				bool flag3 = title != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag3, default(ForPrimitives));
				if (flag3)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(title, false);
				}
				BytePacker.WriteValueBitPacked(val2, duration);
				((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref time, default(ForPrimitives));
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref isPlayingMusic, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3399703514u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				SyncBoomboxRequestClientShared(request, filenameId, url, title, duration, time, isPlayingMusic);
			}
		}

		[ClientRpc]
		private void SyncBoomboxRequestVerifyMultipleClientRpc(string filenameId, string url, string title, int duration, float time, bool isPlayingMusic, ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(1261714853u, clientRpcParams, (RpcDelivery)0);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(filenameId, false);
				}
				bool flag2 = url != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(url, false);
				}
				bool flag3 = title != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag3, default(ForPrimitives));
				if (flag3)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(title, false);
				}
				BytePacker.WriteValueBitPacked(val, duration);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref time, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref isPlayingMusic, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val, 1261714853u, clientRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall() && !(filenameId == this.filenameId))
			{
				AudioClip audioClipFromFilenameId = GetAudioClipFromFilenameId(filenameId);
				SyncBoombox(request: false, filenameId, url, title, duration, time, audioClipFromFilenameId, isPlayingMusic, autoRequestPlayState: false);
				ClearUnusedAudioClips();
			}
		}

		[ClientRpc]
		private void SyncBoomboxTimeRequestClientRpc(float time, ulong clientId, string filenameId, REQUEST_TYPE requestType)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1175447752u, val, (RpcDelivery)0);
				((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref time, default(ForPrimitives));
				BytePacker.WriteValueBitPacked(val2, clientId);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val2)).WriteValueSafe(filenameId, false);
				}
				((FastBufferWriter)(ref val2)).WriteValueSafe<REQUEST_TYPE>(ref requestType, default(ForEnums));
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1175447752u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
			{
				SyncBoomboxTimeRequestClientShared(time, clientId, filenameId, requestType);
			}
		}

		[ClientRpc]
		internal void SyncBoomboxVolumeRequestClientRpc(float volume, ulong clientId, bool msg = false, ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(1318585972u, clientRpcParams, (RpcDelivery)0);
					((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref volume, default(ForPrimitives));
					BytePacker.WriteValueBitPacked(val, clientId);
					((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref msg, default(ForPrimitives));
					((NetworkBehaviour)this).__endSendClientRpc(ref val, 1318585972u, clientRpcParams, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					SyncBoomboxVolumeRequestClientShared(volume, clientId, msg);
				}
			}
		}

		[ClientRpc]
		internal void SyncBoomboxColorRequestClientRpc(float r, float g, float b, COLOR_PATTERN colorPattern, ulong clientId, bool msg = false, ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
				{
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(3867183133u, clientRpcParams, (RpcDelivery)0);
					((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref r, default(ForPrimitives));
					((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref g, default(ForPrimitives));
					((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref b, default(ForPrimitives));
					((FastBufferWriter)(ref val)).WriteValueSafe<COLOR_PATTERN>(ref colorPattern, default(ForEnums));
					BytePacker.WriteValueBitPacked(val, clientId);
					((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref msg, default(ForPrimitives));
					((NetworkBehaviour)this).__endSendClientRpc(ref val, 3867183133u, clientRpcParams, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall())
				{
					SyncBoomboxColorRequestClientShared(r, g, b, colorPattern, clientId, msg);
				}
			}
		}

		[ClientRpc]
		internal void SyncBoomboxPlayingRequestClientRpc(string filenameId, string url, string title, int duration, float time, bool isPlayingMusic, ClientRpcParams clientRpcParams = default(ClientRpcParams))
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(1911341357u, clientRpcParams, (RpcDelivery)0);
				bool flag = filenameId != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(filenameId, false);
				}
				bool flag2 = url != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(url, false);
				}
				bool flag3 = title != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag3, default(ForPrimitives));
				if (flag3)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(title, false);
				}
				BytePacker.WriteValueBitPacked(val, duration);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref time, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref isPlayingMusic, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val, 1911341357u, clientRpcParams, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !IsInvalidClientCall() && IsBoomboxValid(boomboxItem))
			{
				AudioClip audioClipFromFilenameId = GetAudioClipFromFilenameId(filenameId);
				if (!Object.op_Implicit((Object)(object)audioClipFromFilenameId))
				{
					ResetAudioClip();
				}
				SyncBoombox(request: false, filenameId, url, title, duration, time, audioClipFromFilenameId, isPlayingMusic && !boomboxItem.isPlayingMusic);
			}
		}

		internal void PlayBoombox(float forceTime = 0f)
		{
			if (!IsBoomboxValid(boomboxItem))
			{
				return;
			}
			AudioClip clip = boomboxItem.boomboxAudio.clip;
			if (!Config.configEntrySync.Value && (Object)(object)clip != (Object)null)
			{
				if (audioClipBoomboxItemController.ContainsKey(clip))
				{
					BoomboxItemController boomboxItemController = audioClipBoomboxItemController[clip];
					if ((Object)(object)boomboxItemController != (Object)(object)this && IsBoomboxValid(boomboxItemController.boomboxItem) && !string.IsNullOrEmpty(filenameId?.Trim()) && boomboxItemController.filenameId == filenameId && boomboxItemController.boomboxItem.isPlayingMusic)
					{
						boomboxItemController.StopBoombox();
					}
				}
				audioClipBoomboxItemController[clip] = this;
			}
			if (!IsAudioLoadedInMemory())
			{
				boomboxItem.boomboxAudio.time = 0f;
			}
			else if (forceTime > 0f)
			{
				boomboxItem.boomboxAudio.time = forceTime;
			}
			else if (timeSaved > 0f)
			{
				boomboxItem.boomboxAudio.time = timeSaved;
			}
			boomboxItem.boomboxAudio.pitch = 1f;
			boomboxItem.boomboxAudio.Play();
			boomboxItem.isPlayingMusic = (((GrabbableObject)boomboxItem).isBeingUsed = true);
		}

		internal void StopBoombox(float forceTime = 0f)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (IsBoomboxValid(boomboxItem))
			{
				if (!IsAudioLoadedInMemory())
				{
					boomboxItem.boomboxAudio.time = (timeSaved = 0f);
				}
				else if (forceTime > 0f)
				{
					boomboxItem.boomboxAudio.time = (timeSaved = forceTime);
				}
				else
				{
					timeSaved = boomboxItem.boomboxAudio.time;
				}
				if (((NetworkBehaviour)this).IsHost)
				{
					SyncBoomboxTimeRequestServerRpc(boomboxItem.boomboxAudio.time, REQUEST_TYPE.STOP);
				}
				bool isPlayingMusic = boomboxItem.is

plugins\dep\YPlayUtil.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using YPlayUtil.Converters;
using YPlayUtil.Helpers;
using YPlayUtil.Metadata;
using YPlayUtil.Options;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Bluegrams,kerotein")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("© 2020-2024 Bluegrams")]
[assembly: AssemblyDescription("A simple .NET wrapper library for youtube-dl and yt-dlp.\r\n\r\nNote: Package versions >= 1.0 are optimized to work with yt-dlp.\r\nPackage versions 0.x retain support for the original youtube-dl.\r\n\r\nModified by kerotein for YPlayBoombox.")]
[assembly: AssemblyFileVersion("1.1.1.24278")]
[assembly: AssemblyInformationalVersion("1.1.1+8863d5327ce0a6cf747b294977161b224c066434")]
[assembly: AssemblyProduct("YPlayUtil")]
[assembly: AssemblyTitle("YPlayUtil")]
[assembly: AssemblyVersion("1.1.1.24278")]
namespace YPlayUtil
{
	public enum DownloadState
	{
		None,
		PreProcessing,
		Downloading,
		PostProcessing,
		Error,
		Success
	}
	public class DownloadProgress
	{
		public DownloadState State { get; }

		public float Progress { get; }

		public string TotalDownloadSize { get; }

		public string DownloadSpeed { get; }

		public string ETA { get; }

		public int VideoIndex { get; }

		public string Data { get; }

		public DownloadProgress(DownloadState status, float progress = 0f, string totalDownloadSize = null, string downloadSpeed = null, string eta = null, int index = 1, string data = null)
		{
			State = status;
			Progress = progress;
			TotalDownloadSize = totalDownloadSize;
			DownloadSpeed = downloadSpeed;
			ETA = eta;
			VideoIndex = index;
			Data = data;
		}
	}
	public class RunResult<T>
	{
		public bool Success { get; }

		public string[] ErrorOutput { get; }

		public T Data { get; }

		public RunResult(bool success, string[] error, T result)
		{
			Success = success;
			ErrorOutput = error;
			Data = result;
		}
	}
	public static class Utils
	{
		internal static class FFmpegApi
		{
			public class Root
			{
				[JsonProperty("version")]
				public string Version { get; set; }

				[JsonProperty("permalink")]
				public string Permalink { get; set; }

				[JsonProperty("bin")]
				public Bin Bin { get; set; }
			}

			public class Bin
			{
				[JsonProperty("windows-64")]
				public OsBinVersion Windows64 { get; set; }

				[JsonProperty("linux-64")]
				public OsBinVersion Linux64 { get; set; }

				[JsonProperty("osx-64")]
				public OsBinVersion Osx64 { get; set; }
			}

			public class OsBinVersion
			{
				[JsonProperty("ffmpeg")]
				public string Ffmpeg { get; set; }

				[JsonProperty("ffprobe")]
				public string Ffprobe { get; set; }
			}

			public enum BinaryType
			{
				[EnumMember(Value = "ffmpeg")]
				FFmpeg,
				[EnumMember(Value = "ffprobe")]
				FFprobe
			}
		}

		private static readonly HttpClient _client = new HttpClient();

		private static readonly Regex rgxTimestamp = new Regex("[0-9]+(?::[0-9]+)+", RegexOptions.Compiled);

		private static readonly Dictionary<char, string> accentChars = "ÂÃÄÀÁÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖŐØŒÙÚÛÜŰÝÞßàáâãäåæçèéêëìíîïðñòóôõöőøœùúûüűýþÿ".Zip(new string[68]
		{
			"A", "A", "A", "A", "A", "A", "AE", "C", "E", "E",
			"E", "E", "I", "I", "I", "I", "D", "N", "O", "O",
			"O", "O", "O", "O", "O", "OE", "U", "U", "U", "U",
			"U", "Y", "P", "ss", "a", "a", "a", "a", "a", "a",
			"ae", "c", "e", "e", "e", "e", "i", "i", "i", "i",
			"o", "n", "o", "o", "o", "o", "o", "o", "o", "oe",
			"u", "u", "u", "u", "u", "y", "p", "y"
		}, (char c, string s) => new
		{
			Key = c,
			Val = s
		}).ToDictionary(o => o.Key, o => o.Val);

		public static string YtDlpBinaryName => GetYtDlpBinaryName();

		public static string FfmpegBinaryName => GetFfmpegBinaryName();

		public static string FfprobeBinaryName => GetFfprobeBinaryName();

		public static string Sanitize(string s, bool restricted = false)
		{
			rgxTimestamp.Replace(s, (Match m) => m.Groups[0].Value.Replace(':', '_'));
			string text = string.Join("", s.Select((char c) => sanitizeChar(c, restricted)));
			text = text.Replace("__", "_").Trim(new char[1] { '_' });
			if (restricted && text.StartsWith("-_"))
			{
				text = text.Substring(2);
			}
			if (text.StartsWith("-"))
			{
				text = "_" + text.Substring(1);
			}
			text = text.TrimStart(new char[1] { '.' });
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "_";
			}
			return text;
		}

		private static string sanitizeChar(char c, bool restricted)
		{
			if (restricted && accentChars.ContainsKey(c))
			{
				return accentChars[c];
			}
			if (c != '?' && c >= ' ')
			{
				switch (c)
				{
				case '\u007f':
					break;
				case '"':
					if (!restricted)
					{
						return "'";
					}
					return "";
				case ':':
					if (!restricted)
					{
						return " -";
					}
					return "_-";
				default:
					if (Enumerable.Contains("\\/|*<>", c))
					{
						return "_";
					}
					if (restricted && Enumerable.Contains("!&'()[]{}$;`^,# ", c))
					{
						return "_";
					}
					if (restricted && c > '\u007f')
					{
						return "_";
					}
					return c.ToString();
				}
			}
			return "";
		}

		public static string GetFullPath(string fileName)
		{
			if (File.Exists(fileName))
			{
				return Path.GetFullPath(fileName);
			}
			string[] array = Environment.GetEnvironmentVariable("PATH").Split(new char[1] { Path.PathSeparator });
			for (int i = 0; i < array.Length; i++)
			{
				string text = Path.Combine(array[i], fileName);
				if (File.Exists(text))
				{
					return text;
				}
			}
			return null;
		}

		public static async Task DownloadBinaries(string ytDlpReleaseDate, bool skipExisting = true, string directoryPath = "")
		{
			if (skipExisting)
			{
				if (!File.Exists(Path.Combine(directoryPath, GetYtDlpBinaryName())))
				{
					await DownloadYtDlp(directoryPath);
				}
				if (!File.Exists(Path.Combine(directoryPath, GetFfmpegBinaryName())))
				{
					await DownloadFFmpeg(directoryPath);
				}
				if (!File.Exists(Path.Combine(directoryPath, GetFfprobeBinaryName())))
				{
					await DownloadFFprobe(directoryPath);
				}
			}
			else
			{
				await DownloadYtDlp(directoryPath);
				await DownloadFFmpeg(directoryPath);
				await DownloadFFprobe(directoryPath);
			}
		}

		private static string GetYtDlpDownloadUrl(string releaseDate)
		{
			string text = "https://github.com/yt-dlp/yt-dlp/releases/download/" + releaseDate + "/yt-dlp";
			return OSHelper.GetOSVersion() switch
			{
				OSVersion.Windows => text + "_x86.exe", 
				OSVersion.OSX => text + "_macos", 
				OSVersion.Linux => text, 
				_ => throw new Exception("Your OS isn't supported"), 
			};
		}

		private static string GetSevenZipDownloadUrl()
		{
			return "https://www.7-zip.org/a/7zr.exe";
		}

		private static string GetFFmpegEssentialsDownloadUrl(string version, bool sevenZip)
		{
			return "https://github.com/GyanD/codexffmpeg/releases/download/" + version + "/ffmpeg-" + version + "-essentials_build." + (sevenZip ? "7z" : "zip");
		}

		private static string GetYtDlpBinaryName()
		{
			string ytDlpDownloadUrl = GetYtDlpDownloadUrl(null);
			switch (OSHelper.GetOSVersion())
			{
			case OSVersion.Windows:
				return "yt-dlp.exe";
			case OSVersion.OSX:
			case OSVersion.Linux:
				return Path.GetFileName(ytDlpDownloadUrl);
			default:
				throw new Exception("Your OS isn't supported");
			}
		}

		private static string GetFfmpegBinaryName()
		{
			switch (OSHelper.GetOSVersion())
			{
			case OSVersion.Windows:
				return "ffmpeg.exe";
			case OSVersion.OSX:
			case OSVersion.Linux:
				return "ffmpeg";
			default:
				throw new Exception("Your OS isn't supported");
			}
		}

		private static string GetFfprobeBinaryName()
		{
			switch (OSHelper.GetOSVersion())
			{
			case OSVersion.Windows:
				return "ffprobe.exe";
			case OSVersion.OSX:
			case OSVersion.Linux:
				return "ffprobe";
			default:
				throw new Exception("Your OS isn't supported");
			}
		}

		public static async Task DownloadYtDlp(string releaseDate, string directoryPath = "")
		{
			string ytDlpDownloadUrl = GetYtDlpDownloadUrl(releaseDate);
			if (string.IsNullOrEmpty(directoryPath))
			{
				directoryPath = Directory.GetCurrentDirectory();
			}
			string downloadLocation = Path.Combine(directoryPath, GetYtDlpBinaryName());
			File.WriteAllBytes(downloadLocation, await DownloadFileBytesAsync(ytDlpDownloadUrl));
		}

		public static async Task DownloadFFmpeg(string version, string directoryPath = "")
		{
			await FFDownloader(version, directoryPath);
		}

		public static async Task DownloadFFprobe(string version, string directoryPath = "")
		{
			await FFDownloader(version, directoryPath, FFmpegApi.BinaryType.FFprobe);
		}

		public static async Task DownloadSevenZip(string path = "")
		{
			File.WriteAllBytes(path, await DownloadFileBytesAsync(GetSevenZipDownloadUrl()));
		}

		public static async Task DownloadFFmpegEssentials7zArchive(string version, string path = "")
		{
			File.WriteAllBytes(path, await DownloadFileBytesAsync(GetFFmpegEssentialsDownloadUrl(version, sevenZip: true)));
		}

		public static async Task DownloadFFmpegEssentials(string version, string directoryPath = "")
		{
			using MemoryStream stream = new MemoryStream(await DownloadFileBytesAsync(GetFFmpegEssentialsDownloadUrl(version, sevenZip: false)));
			using ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Read);
			if (zipArchive.Entries.Count <= 0)
			{
				return;
			}
			string ffmpegBinaryName = GetFfmpegBinaryName();
			foreach (ZipArchiveEntry entry in zipArchive.Entries)
			{
				if (entry.Name.Equals(ffmpegBinaryName, StringComparison.OrdinalIgnoreCase))
				{
					entry.ExtractToFile(Path.Combine(directoryPath, entry.Name), overwrite: true);
					break;
				}
			}
		}

		public static async Task Extract7z(string sevenZipExePath, string path, string workingDirectory = "")
		{
			await Task.Run(delegate
			{
				string ffmpegBinaryName = GetFfmpegBinaryName();
				try
				{
					using Process process = new Process();
					process.StartInfo.FileName = sevenZipExePath;
					process.StartInfo.UseShellExecute = false;
					process.StartInfo.Arguments = "e \"" + path + "\" *" + ffmpegBinaryName + " -r -aoa";
					process.StartInfo.WorkingDirectory = workingDirectory;
					process.StartInfo.CreateNoWindow = true;
					process.StartInfo.RedirectStandardOutput = true;
					process.Start();
					process.WaitForExit();
				}
				catch (Exception)
				{
				}
			});
		}

		public static async Task ExtractZip(string path, string workingDirectory = "")
		{
			await Task.Run(delegate
			{
				string ffmpegBinaryName = GetFfmpegBinaryName();
				using ZipArchive zipArchive = ZipFile.OpenRead(path);
				foreach (ZipArchiveEntry entry in zipArchive.Entries)
				{
					if (entry.Name.Equals(ffmpegBinaryName, StringComparison.OrdinalIgnoreCase))
					{
						entry.ExtractToFile(Path.Combine(workingDirectory, ffmpegBinaryName));
						break;
					}
				}
			});
		}

		private static async Task FFDownloader(string version, string directoryPath = "", FFmpegApi.BinaryType binary = FFmpegApi.BinaryType.FFmpeg)
		{
			if (string.IsNullOrEmpty(directoryPath))
			{
				directoryPath = Directory.GetCurrentDirectory();
			}
			string requestUri = "https://ffbinaries.com/api/v1/version/" + version;
			FFmpegApi.Root root = JsonConvert.DeserializeObject<FFmpegApi.Root>(await (await _client.GetAsync(requestUri)).Content.ReadAsStringAsync());
			FFmpegApi.OsBinVersion osBinVersion = OSHelper.GetOSVersion() switch
			{
				OSVersion.Windows => root?.Bin.Windows64, 
				OSVersion.OSX => root?.Bin.Osx64, 
				OSVersion.Linux => root?.Bin.Linux64, 
				_ => throw new NotImplementedException("Your OS isn't supported"), 
			};
			using MemoryStream stream = new MemoryStream(await DownloadFileBytesAsync((binary == FFmpegApi.BinaryType.FFmpeg) ? osBinVersion.Ffmpeg : osBinVersion.Ffprobe));
			using ZipArchive zipArchive = new ZipArchive(stream, ZipArchiveMode.Read);
			if (zipArchive.Entries.Count > 0)
			{
				zipArchive.Entries[0].ExtractToFile(Path.Combine(directoryPath, zipArchive.Entries[0].FullName), overwrite: true);
			}
		}

		public static async Task<byte[]> DownloadFileBytesAsync(string uri)
		{
			if (!Uri.TryCreate(uri, UriKind.Absolute, out Uri _))
			{
				throw new InvalidOperationException("URI is invalid.");
			}
			return await _client.GetByteArrayAsync(uri);
		}

		public static void EnsureSuccess<T>(this RunResult<T> runResult)
		{
			if (!runResult.Success)
			{
				throw new Exception("Download failed:\n" + string.Join("\n", runResult.ErrorOutput));
			}
		}
	}
	public class YoutubeDL
	{
		private static readonly Regex rgxFile = new Regex("^outfile:\\s\\\"?(.*)\\\"?", RegexOptions.Compiled);

		private static Regex rgxFilePostProc = new Regex("\\[download\\] Destination: [a-zA-Z]:\\\\\\S+\\.\\S{3,}", RegexOptions.Compiled);

		protected ProcessRunner runner;

		public string YoutubeDLPath { get; set; } = Utils.YtDlpBinaryName;


		public string FFmpegPath { get; set; } = Utils.FfmpegBinaryName;


		public string OutputFolder { get; set; } = Environment.CurrentDirectory;


		public string OutputFileTemplate { get; set; } = "%(title)s [%(id)s].%(ext)s";


		public bool RestrictFilenames { get; set; }

		public bool OverwriteFiles { get; set; } = true;


		public bool IgnoreDownloadErrors { get; set; } = true;


		public string PythonInterpreterPath { get; set; }

		public string Version => FileVersionInfo.GetVersionInfo(Utils.GetFullPath(YoutubeDLPath)).FileVersion;

		public YoutubeDL(byte maxNumberOfProcesses = 4)
		{
			runner = new ProcessRunner(maxNumberOfProcesses);
		}

		public async Task SetMaxNumberOfProcesses(byte count)
		{
			await runner.SetTotalCount(count);
		}

		public async Task<RunResult<string[]>> RunWithOptions(string[] urls, OptionSet options, CancellationToken ct)
		{
			List<string> output = new List<string>();
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				output.Add(e.Data);
			};
			var (num, error) = await runner.RunThrottled(youtubeDLProcess, urls, options, ct);
			return new RunResult<string[]>(num == 0, error, output.ToArray());
		}

		public async Task<RunResult<string>> RunWithOptions(string url, OptionSet options, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, bool showArgs = true)
		{
			string outFile = string.Empty;
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			if (showArgs)
			{
				output?.Report("Arguments: " + youtubeDLProcess.ConvertToArgs(new string[1] { url }, options) + "\n");
			}
			else
			{
				output?.Report("Starting Download: " + url);
			}
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFilePostProc.Match(e.Data);
				if (match.Success)
				{
					outFile = match.Groups[0].ToString().Replace("[download] Destination:", "").Replace(" ", "");
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, outFile));
				}
				output?.Report(e.Data);
			};
			var (num, error) = await runner.RunThrottled(youtubeDLProcess, new string[1] { url }, options, ct, progress);
			return new RunResult<string>(num == 0, error, outFile);
		}

		public async Task<string> RunUpdate()
		{
			string output = string.Empty;
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				output = e.Data;
			};
			await youtubeDLProcess.RunAsync(null, new OptionSet
			{
				Update = true
			});
			return output;
		}

		public async Task<RunResult<VideoData>> RunVideoDataFetch(string url, CancellationToken ct = default(CancellationToken), bool flat = true, bool fetchComments = false, OptionSet overrideOptions = null)
		{
			OptionSet optionSet = GetDownloadOptions();
			optionSet.DumpSingleJson = true;
			optionSet.FlatPlaylist = flat;
			optionSet.WriteComments = fetchComments;
			if (overrideOptions != null)
			{
				optionSet = optionSet.OverrideOptions(overrideOptions);
			}
			VideoData videoData = null;
			YoutubeDLProcess process = CreateYoutubeDLProcess();
			process.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				try
				{
					videoData = JsonConvert.DeserializeObject<VideoData>(e.Data);
				}
				catch (JsonSerializationException)
				{
					process.RedirectToError(e);
				}
			};
			var (num, error) = await runner.RunThrottled(process, new string[1] { url }, optionSet, ct);
			return new RunResult<VideoData>(num == 0, error, videoData);
		}

		public async Task<RunResult<string>> RunVideoDownload(string url, string format = "bestvideo+bestaudio/best", DownloadMergeFormat mergeFormat = DownloadMergeFormat.Unspecified, VideoRecodeFormat recodeFormat = VideoRecodeFormat.None, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			OptionSet optionSet = GetDownloadOptions();
			optionSet.Format = format;
			optionSet.MergeOutputFormat = mergeFormat;
			optionSet.RecodeVideo = recodeFormat;
			if (overrideOptions != null)
			{
				optionSet = optionSet.OverrideOptions(overrideOptions);
			}
			string outputFile = string.Empty;
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + youtubeDLProcess.ConvertToArgs(new string[1] { url }, optionSet) + "\n");
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					outputFile = match.Groups[1].ToString().Trim(new char[1] { '"' });
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, outputFile));
				}
				output?.Report(e.Data);
			};
			var (num, error) = await runner.RunThrottled(youtubeDLProcess, new string[1] { url }, optionSet, ct, progress);
			return new RunResult<string>(num == 0, error, outputFile);
		}

		public async Task<RunResult<string[]>> RunVideoPlaylistDownload(string url, int? start = 1, int? end = null, int[] items = null, string format = "bestvideo+bestaudio/best", VideoRecodeFormat recodeFormat = VideoRecodeFormat.None, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			OptionSet optionSet = GetDownloadOptions();
			optionSet.NoPlaylist = false;
			optionSet.PlaylistStart = start;
			optionSet.PlaylistEnd = end;
			if (items != null)
			{
				optionSet.PlaylistItems = string.Join(",", items);
			}
			optionSet.Format = format;
			optionSet.RecodeVideo = recodeFormat;
			if (overrideOptions != null)
			{
				optionSet = optionSet.OverrideOptions(overrideOptions);
			}
			List<string> outputFiles = new List<string>();
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + youtubeDLProcess.ConvertToArgs(new string[1] { url }, optionSet) + "\n");
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					string text = match.Groups[1].ToString().Trim(new char[1] { '"' });
					outputFiles.Add(text);
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, text));
				}
				output?.Report(e.Data);
			};
			var (num, error) = await runner.RunThrottled(youtubeDLProcess, new string[1] { url }, optionSet, ct, progress);
			return new RunResult<string[]>(num == 0, error, outputFiles.ToArray());
		}

		public async Task<RunResult<string>> RunAudioDownload(string url, AudioConversionFormat format = AudioConversionFormat.Best, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			OptionSet optionSet = GetDownloadOptions();
			optionSet.Format = "bestaudio/best";
			optionSet.ExtractAudio = true;
			optionSet.AudioFormat = format;
			if (overrideOptions != null)
			{
				optionSet = optionSet.OverrideOptions(overrideOptions);
			}
			string outputFile = string.Empty;
			new List<string>();
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + youtubeDLProcess.ConvertToArgs(new string[1] { url }, optionSet) + "\n");
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					outputFile = match.Groups[1].ToString().Trim(new char[1] { '"' });
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, outputFile));
				}
				output?.Report(e.Data);
			};
			var (num, error) = await runner.RunThrottled(youtubeDLProcess, new string[1] { url }, optionSet, ct, progress);
			return new RunResult<string>(num == 0, error, outputFile);
		}

		public async Task<RunResult<string[]>> RunAudioPlaylistDownload(string url, int? start = 1, int? end = null, int[] items = null, AudioConversionFormat format = AudioConversionFormat.Best, CancellationToken ct = default(CancellationToken), IProgress<DownloadProgress> progress = null, IProgress<string> output = null, OptionSet overrideOptions = null)
		{
			List<string> outputFiles = new List<string>();
			OptionSet optionSet = GetDownloadOptions();
			optionSet.NoPlaylist = false;
			optionSet.PlaylistStart = start;
			optionSet.PlaylistEnd = end;
			if (items != null)
			{
				optionSet.PlaylistItems = string.Join(",", items);
			}
			optionSet.Format = "bestaudio/best";
			optionSet.ExtractAudio = true;
			optionSet.AudioFormat = format;
			if (overrideOptions != null)
			{
				optionSet = optionSet.OverrideOptions(overrideOptions);
			}
			YoutubeDLProcess youtubeDLProcess = CreateYoutubeDLProcess();
			output?.Report("Arguments: " + youtubeDLProcess.ConvertToArgs(new string[1] { url }, optionSet) + "\n");
			youtubeDLProcess.OutputReceived += delegate(object o, DataReceivedEventArgs e)
			{
				Match match = rgxFile.Match(e.Data);
				if (match.Success)
				{
					string text = match.Groups[1].ToString().Trim(new char[1] { '"' });
					outputFiles.Add(text);
					progress?.Report(new DownloadProgress(DownloadState.Success, 0f, null, null, null, 1, text));
				}
				output?.Report(e.Data);
			};
			var (num, error) = await runner.RunThrottled(youtubeDLProcess, new string[1] { url }, optionSet, ct, progress);
			return new RunResult<string[]>(num == 0, error, outputFiles.ToArray());
		}

		protected virtual OptionSet GetDownloadOptions()
		{
			return new OptionSet
			{
				IgnoreErrors = IgnoreDownloadErrors,
				IgnoreConfig = true,
				NoPlaylist = true,
				Downloader = "m3u8:native",
				DownloaderArgs = "ffmpeg:-nostats -loglevel 0",
				Output = Path.Combine(OutputFolder, OutputFileTemplate),
				RestrictFilenames = RestrictFilenames,
				ForceOverwrites = OverwriteFiles,
				NoOverwrites = !OverwriteFiles,
				NoPart = true,
				FfmpegLocation = Utils.GetFullPath(FFmpegPath),
				Exec = "echo outfile: {}"
			};
		}

		private YoutubeDLProcess CreateYoutubeDLProcess()
		{
			return new YoutubeDLProcess(YoutubeDLPath)
			{
				PythonPath = PythonInterpreterPath
			};
		}
	}
	public class YoutubeDLProcess
	{
		private static readonly Regex rgxPlaylist = new Regex("Downloading video (\\d+) of (\\d+)", RegexOptions.Compiled);

		private static readonly Regex rgxProgress = new Regex("\\[download\\]\\s+(?:(?<percent>[\\d\\.]+)%(?:\\s+of\\s+\\~?\\s*(?<total>[\\d\\.\\w]+))?\\s+at\\s+(?:(?<speed>[\\d\\.\\w]+\\/s)|[\\w\\s]+)\\s+ETA\\s(?<eta>[\\d\\:]+))?", RegexOptions.Compiled);

		private static readonly Regex rgxPost = new Regex("\\[(\\w+)\\]\\s+", RegexOptions.Compiled);

		public string PythonPath { get; set; }

		public string ExecutablePath { get; set; }

		public bool UseWindowsEncodingWorkaround { get; set; } = true;


		public event EventHandler<DataReceivedEventArgs> OutputReceived;

		public event EventHandler<DataReceivedEventArgs> ErrorReceived;

		public YoutubeDLProcess(string executablePath = "yt-dlp.exe")
		{
			ExecutablePath = executablePath;
		}

		internal string ConvertToArgs(string[] urls, OptionSet options)
		{
			return options.ToString() + " -- " + ((urls != null) ? string.Join(" ", urls.Select((string s) => "\"" + s + "\"")) : string.Empty);
		}

		internal void RedirectToError(DataReceivedEventArgs e)
		{
			this.ErrorReceived?.Invoke(this, e);
		}

		public async Task<int> RunAsync(string[] urls, OptionSet options)
		{
			return await RunAsync(urls, options, CancellationToken.None);
		}

		public async Task<int> RunAsync(string[] urls, OptionSet options, CancellationToken ct, IProgress<DownloadProgress> progress = null)
		{
			TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
			Process process = new Process();
			ProcessStartInfo processStartInfo = new ProcessStartInfo
			{
				CreateNoWindow = true,
				UseShellExecute = false,
				RedirectStandardOutput = true,
				RedirectStandardError = true,
				StandardOutputEncoding = Encoding.UTF8,
				StandardErrorEncoding = Encoding.UTF8
			};
			if (OSHelper.IsWindows && UseWindowsEncodingWorkaround)
			{
				processStartInfo.FileName = "cmd.exe";
				string text = (string.IsNullOrEmpty(PythonPath) ? ("\"" + ExecutablePath + "\" " + ConvertToArgs(urls, options)) : ("\"" + PythonPath + "\" \"" + ExecutablePath + "\" " + ConvertToArgs(urls, options)));
				processStartInfo.Arguments = "/C chcp 65001 >nul 2>&1 && " + text;
			}
			else if (!string.IsNullOrEmpty(PythonPath))
			{
				processStartInfo.FileName = PythonPath;
				processStartInfo.Arguments = "\"" + ExecutablePath + "\" " + ConvertToArgs(urls, options);
			}
			else
			{
				processStartInfo.FileName = ExecutablePath;
				processStartInfo.Arguments = ConvertToArgs(urls, options);
			}
			process.EnableRaisingEvents = true;
			process.StartInfo = processStartInfo;
			TaskCompletionSource<bool> tcsOut = new TaskCompletionSource<bool>();
			bool isDownloading = false;
			process.OutputDataReceived += delegate(object o, DataReceivedEventArgs e)
			{
				if (e.Data == null)
				{
					tcsOut.SetResult(result: true);
				}
				else
				{
					Match match;
					if ((match = rgxProgress.Match(e.Data)).Success)
					{
						if (match.Groups.Count > 1 && match.Groups[1].Length > 0)
						{
							float progress2 = float.Parse(match.Groups[1].ToString(), CultureInfo.InvariantCulture) / 100f;
							Group group = match.Groups["total"];
							string totalDownloadSize = (group.Success ? group.Value : null);
							Group group2 = match.Groups["speed"];
							string downloadSpeed = (group2.Success ? group2.Value : null);
							Group group3 = match.Groups["eta"];
							string eta = (group3.Success ? group3.Value : null);
							progress?.Report(new DownloadProgress(DownloadState.Downloading, progress2, totalDownloadSize, downloadSpeed, eta));
						}
						else
						{
							progress?.Report(new DownloadProgress(DownloadState.Downloading));
						}
						isDownloading = true;
					}
					else if ((match = rgxPlaylist.Match(e.Data)).Success)
					{
						int index = int.Parse(match.Groups[1].Value);
						progress?.Report(new DownloadProgress(DownloadState.PreProcessing, 0f, null, null, null, index));
						isDownloading = false;
					}
					else if (isDownloading && (match = rgxPost.Match(e.Data)).Success)
					{
						progress?.Report(new DownloadProgress(DownloadState.PostProcessing, 1f));
						isDownloading = false;
					}
					this.OutputReceived?.Invoke(this, e);
				}
			};
			TaskCompletionSource<bool> tcsError = new TaskCompletionSource<bool>();
			process.ErrorDataReceived += delegate(object o, DataReceivedEventArgs e)
			{
				if (e.Data == null)
				{
					tcsError.SetResult(result: true);
				}
				else
				{
					progress?.Report(new DownloadProgress(DownloadState.Error, 0f, null, null, null, 1, e.Data));
					this.ErrorReceived?.Invoke(this, e);
				}
			};
			process.Exited += async delegate
			{
				await tcsOut.Task;
				await tcsError.Task;
				tcs.TrySetResult(process.ExitCode);
				process.Dispose();
			};
			ct.Register(delegate
			{
				if (!tcs.Task.IsCompleted)
				{
					tcs.TrySetCanceled();
				}
				try
				{
					if (!process.HasExited)
					{
						process.KillTree();
					}
				}
				catch
				{
				}
			});
			if (!(await Task.Run(() => process.Start())))
			{
				tcs.TrySetException(new InvalidOperationException("Failed to start yt-dlp process."));
			}
			process.BeginOutputReadLine();
			process.BeginErrorReadLine();
			progress?.Report(new DownloadProgress(DownloadState.PreProcessing));
			return await tcs.Task;
		}
	}
}
namespace YPlayUtil.Options
{
	public enum DownloadMergeFormat
	{
		Unspecified,
		Mp4,
		Mkv,
		Ogg,
		Webm,
		Flv
	}
	public enum AudioConversionFormat
	{
		Best,
		Aac,
		Flac,
		Mp3,
		M4a,
		Opus,
		Vorbis,
		Wav
	}
	public enum VideoRecodeFormat
	{
		None,
		Mp4,
		Mkv,
		Ogg,
		Webm,
		Flv,
		Avi
	}
	public interface IOption
	{
		string DefaultOptionString { get; }

		string[] OptionStrings { get; }

		bool IsSet { get; }

		bool IsCustom { get; }

		void SetFromString(string s);

		IEnumerable<string> ToStringCollection();
	}
	public class MultiOption<T> : IOption
	{
		private MultiValue<T> value;

		public string DefaultOptionString => OptionStrings.Last();

		public string[] OptionStrings { get; }

		public bool IsSet { get; private set; }

		public bool IsCustom { get; }

		public MultiValue<T> Value
		{
			get
			{
				return value;
			}
			set
			{
				IsSet = !object.Equals(value, default(T));
				this.value = value;
			}
		}

		public MultiOption(params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
		}

		public MultiOption(bool isCustom, params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
			IsCustom = isCustom;
		}

		public void SetFromString(string s)
		{
			string[] array = s.Split(new char[1] { ' ' });
			string stringValue = s.Substring(array[0].Length).Trim().Trim(new char[1] { '"' });
			if (!OptionStrings.Contains(array[0]))
			{
				throw new ArgumentException("Given string does not match required format.");
			}
			T val = Utils.OptionValueFromString<T>(stringValue);
			if (!IsSet)
			{
				Value = val;
			}
			else
			{
				Value.Values.Add(val);
			}
		}

		public override string ToString()
		{
			return string.Join(" ", ToStringCollection());
		}

		public IEnumerable<string> ToStringCollection()
		{
			if (!IsSet)
			{
				return new string[1] { "" };
			}
			List<string> list = new List<string>();
			foreach (T value in Value.Values)
			{
				list.Add(DefaultOptionString + Utils.OptionValueToString(value));
			}
			return list;
		}
	}
	public class MultiValue<T>
	{
		private readonly List<T> values;

		public List<T> Values => values;

		public MultiValue(params T[] values)
		{
			this.values = values.ToList();
		}

		public static implicit operator MultiValue<T>(T value)
		{
			return new MultiValue<T>(value);
		}

		public static implicit operator MultiValue<T>(T[] values)
		{
			return new MultiValue<T>(values);
		}

		public static explicit operator T(MultiValue<T> value)
		{
			if (value.Values.Count == 1)
			{
				return value.Values[0];
			}
			throw new InvalidCastException($"Cannot cast sequence of values to {typeof(T)}.");
		}

		public static explicit operator T[](MultiValue<T> value)
		{
			return value.Values.ToArray();
		}
	}
	public class Option<T> : IOption
	{
		private T value;

		public string DefaultOptionString => OptionStrings.First();

		public string[] OptionStrings { get; }

		public bool IsSet { get; private set; }

		public T Value
		{
			get
			{
				return value;
			}
			set
			{
				IsSet = !object.Equals(value, default(T));
				this.value = value;
			}
		}

		public bool IsCustom { get; }

		public Option(params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
		}

		public Option(bool isCustom, params string[] optionStrings)
		{
			OptionStrings = optionStrings;
			IsSet = false;
			IsCustom = isCustom;
		}

		public void SetFromString(string s)
		{
			string[] array = s.Split(new char[1] { ' ' });
			string stringValue = s.Substring(array[0].Length).Trim().Trim(new char[1] { '"' });
			if (!OptionStrings.Contains(array[0]))
			{
				throw new ArgumentException("Given string does not match required format.");
			}
			Value = Utils.OptionValueFromString<T>(stringValue);
		}

		public override string ToString()
		{
			if (!IsSet)
			{
				return string.Empty;
			}
			string text = Utils.OptionValueToString(Value);
			return DefaultOptionString + text;
		}

		public IEnumerable<string> ToStringCollection()
		{
			return new string[1] { ToString() };
		}
	}
	internal class OptionComparer : IEqualityComparer<IOption>
	{
		public bool Equals(IOption x, IOption y)
		{
			if (x != null)
			{
				if (y != null)
				{
					return x.ToString().Equals(y.ToString());
				}
				return false;
			}
			return y == null;
		}

		public int GetHashCode(IOption obj)
		{
			return obj.ToString().GetHashCode();
		}
	}
	public class OptionSet : ICloneable
	{
		private Option<string> username = new Option<string>("-u", "--username");

		private Option<string> password = new Option<string>("-p", "--password");

		private Option<string> twoFactor = new Option<string>("-2", "--twofactor");

		private Option<bool> netrc = new Option<bool>("-n", "--netrc");

		private Option<string> netrcLocation = new Option<string>("--netrc-location");

		private Option<string> netrcCmd = new Option<string>("--netrc-cmd");

		private Option<string> videoPassword = new Option<string>("--video-password");

		private Option<string> apMso = new Option<string>("--ap-mso");

		private Option<string> apUsername = new Option<string>("--ap-username");

		private Option<string> apPassword = new Option<string>("--ap-password");

		private Option<bool> apListMso = new Option<bool>("--ap-list-mso");

		private Option<string> clientCertificate = new Option<string>("--client-certificate");

		private Option<string> clientCertificateKey = new Option<string>("--client-certificate-key");

		private Option<string> clientCertificatePassword = new Option<string>("--client-certificate-password");

		private static readonly OptionComparer Comparer = new OptionComparer();

		public static readonly OptionSet Default = new OptionSet();

		private Option<bool> getDescription = new Option<bool>("--get-description");

		private Option<bool> getDuration = new Option<bool>("--get-duration");

		private Option<bool> getFilename = new Option<bool>("--get-filename");

		private Option<bool> getFormat = new Option<bool>("--get-format");

		private Option<bool> getId = new Option<bool>("--get-id");

		private Option<bool> getThumbnail = new Option<bool>("--get-thumbnail");

		private Option<bool> getTitle = new Option<bool>("-e", "--get-title");

		private Option<bool> getUrl = new Option<bool>("-g", "--get-url");

		private Option<string> matchTitle = new Option<string>("--match-title");

		private Option<string> rejectTitle = new Option<string>("--reject-title");

		private Option<long?> minViews = new Option<long?>("--min-views");

		private Option<long?> maxViews = new Option<long?>("--max-views");

		private Option<bool> breakOnReject = new Option<bool>("--break-on-reject");

		private Option<string> userAgent = new Option<string>("--user-agent");

		private Option<string> referer = new Option<string>("--referer");

		private Option<int?> playlistStart = new Option<int?>("--playlist-start");

		private Option<int?> playlistEnd = new Option<int?>("--playlist-end");

		private Option<bool> playlistReverse = new Option<bool>("--playlist-reverse");

		private Option<bool> noColors = new Option<bool>("--no-colors");

		private Option<bool> forceGenericExtractor = new Option<bool>("--force-generic-extractor");

		private Option<string> execBeforeDownload = new Option<string>("--exec-before-download");

		private Option<bool> noExecBeforeDownload = new Option<bool>("--no-exec-before-download");

		private Option<bool> allFormats = new Option<bool>("--all-formats");

		private Option<bool> allSubs = new Option<bool>("--all-subs");

		private Option<bool> printJson = new Option<bool>("--print-json");

		private Option<string> autonumberSize = new Option<string>("--autonumber-size");

		private Option<int?> autonumberStart = new Option<int?>("--autonumber-start");

		private Option<bool> id = new Option<bool>("--id");

		private Option<string> metadataFromTitle = new Option<string>("--metadata-from-title");

		private Option<bool> hlsPreferNative = new Option<bool>("--hls-prefer-native");

		private Option<bool> hlsPreferFfmpeg = new Option<bool>("--hls-prefer-ffmpeg");

		private Option<bool> listFormatsOld = new Option<bool>("--list-formats-old", "--no-list-formats-as-table");

		private Option<bool> listFormatsAsTable = new Option<bool>("--list-formats-as-table", "--no-list-formats-old");

		private Option<bool> youtubeSkipDashManifest = new Option<bool>("--youtube-skip-dash-manifest", "--no-youtube-include-dash-manifest");

		private Option<bool> youtubeSkipHlsManifest = new Option<bool>("--youtube-skip-hls-manifest", "--no-youtube-include-hls-manifest");

		private Option<bool> geoBypass = new Option<bool>("--geo-bypass");

		private Option<bool> noGeoBypass = new Option<bool>("--no-geo-bypass");

		private Option<string> geoBypassCountry = new Option<string>("--geo-bypass-country");

		private Option<string> geoBypassIpBlock = new Option<string>("--geo-bypass-ip-block");

		private Option<int?> concurrentFragments = new Option<int?>("-N", "--concurrent-fragments");

		private Option<long?> limitRate = new Option<long?>("-r", "--limit-rate");

		private Option<long?> throttledRate = new Option<long?>("--throttled-rate");

		private Option<int?> retries = new Option<int?>("-R", "--retries");

		private Option<int?> fileAccessRetries = new Option<int?>("--file-access-retries");

		private Option<int?> fragmentRetries = new Option<int?>("--fragment-retries");

		private MultiOption<string> retrySleep = new MultiOption<string>("--retry-sleep");

		private Option<bool> skipUnavailableFragments = new Option<bool>("--skip-unavailable-fragments", "--no-abort-on-unavailable-fragments");

		private Option<bool> abortOnUnavailableFragments = new Option<bool>("--abort-on-unavailable-fragments", "--no-skip-unavailable-fragments");

		private Option<bool> keepFragments = new Option<bool>("--keep-fragments");

		private Option<bool> noKeepFragments = new Option<bool>("--no-keep-fragments");

		private Option<long?> bufferSize = new Option<long?>("--buffer-size");

		private Option<bool> resizeBuffer = new Option<bool>("--resize-buffer");

		private Option<bool> noResizeBuffer = new Option<bool>("--no-resize-buffer");

		private Option<long?> httpChunkSize = new Option<long?>("--http-chunk-size");

		private Option<bool> playlistRandom = new Option<bool>("--playlist-random");

		private Option<bool> lazyPlaylist = new Option<bool>("--lazy-playlist");

		private Option<bool> noLazyPlaylist = new Option<bool>("--no-lazy-playlist");

		private Option<bool> xattrSetFilesize = new Option<bool>("--xattr-set-filesize");

		private Option<bool> hlsUseMpegts = new Option<bool>("--hls-use-mpegts");

		private Option<bool> noHlsUseMpegts = new Option<bool>("--no-hls-use-mpegts");

		private MultiOption<string> downloadSections = new MultiOption<string>("--download-sections");

		private MultiOption<string> downloader = new MultiOption<string>("--downloader", "--external-downloader");

		private MultiOption<string> downloaderArgs = new MultiOption<string>("--downloader-args", "--external-downloader-args");

		private Option<int?> extractorRetries = new Option<int?>("--extractor-retries");

		private Option<bool> allowDynamicMpd = new Option<bool>("--allow-dynamic-mpd", "--no-ignore-dynamic-mpd");

		private Option<bool> ignoreDynamicMpd = new Option<bool>("--ignore-dynamic-mpd", "--no-allow-dynamic-mpd");

		private Option<bool> hlsSplitDiscontinuity = new Option<bool>("--hls-split-discontinuity");

		private Option<bool> noHlsSplitDiscontinuity = new Option<bool>("--no-hls-split-discontinuity");

		private MultiOption<string> extractorArgs = new MultiOption<string>("--extractor-args");

		private Option<string> batchFile = new Option<string>("-a", "--batch-file");

		private Option<bool> noBatchFile = new Option<bool>("--no-batch-file");

		private MultiOption<string> paths = new MultiOption<string>("-P", "--paths");

		private Option<string> output = new Option<string>("-o", "--output");

		private Option<string> outputNaPlaceholder = new Option<string>("--output-na-placeholder");

		private Option<bool> restrictFilenames = new Option<bool>("--restrict-filenames");

		private Option<bool> noRestrictFilenames = new Option<bool>("--no-restrict-filenames");

		private Option<bool> windowsFilenames = new Option<bool>("--windows-filenames");

		private Option<bool> noWindowsFilenames = new Option<bool>("--no-windows-filenames");

		private Option<int?> trimFilenames = new Option<int?>("--trim-filenames");

		private Option<bool> noOverwrites = new Option<bool>("-w", "--no-overwrites");

		private Option<bool> forceOverwrites = new Option<bool>("--force-overwrites");

		private Option<bool> noForceOverwrites = new Option<bool>("--no-force-overwrites");

		private Option<bool> doContinue = new Option<bool>("-c", "--continue");

		private Option<bool> noContinue = new Option<bool>("--no-continue");

		private Option<bool> part = new Option<bool>("--part");

		private Option<bool> noPart = new Option<bool>("--no-part");

		private Option<bool> mtime = new Option<bool>("--mtime");

		private Option<bool> noMtime = new Option<bool>("--no-mtime");

		private Option<bool> writeDescription = new Option<bool>("--write-description");

		private Option<bool> noWriteDescription = new Option<bool>("--no-write-description");

		private Option<bool> writeInfoJson = new Option<bool>("--write-info-json");

		private Option<bool> noWriteInfoJson = new Option<bool>("--no-write-info-json");

		private Option<bool> writePlaylistMetafiles = new Option<bool>("--write-playlist-metafiles");

		private Option<bool> noWritePlaylistMetafiles = new Option<bool>("--no-write-playlist-metafiles");

		private Option<bool> cleanInfoJson = new Option<bool>("--clean-info-json");

		private Option<bool> noCleanInfoJson = new Option<bool>("--no-clean-info-json");

		private Option<bool> writeComments = new Option<bool>("--write-comments", "--get-comments");

		private Option<bool> noWriteComments = new Option<bool>("--no-write-comments", "--no-get-comments");

		private Option<string> loadInfoJson = new Option<string>("--load-info-json");

		private Option<string> cookies = new Option<string>("--cookies");

		private Option<bool> noCookies = new Option<bool>("--no-cookies");

		private Option<string> cookiesFromBrowser = new Option<string>("--cookies-from-browser");

		private Option<bool> noCookiesFromBrowser = new Option<bool>("--no-cookies-from-browser");

		private Option<string> cacheDir = new Option<string>("--cache-dir");

		private Option<bool> noCacheDir = new Option<bool>("--no-cache-dir");

		private Option<bool> removeCacheDir = new Option<bool>("--rm-cache-dir");

		private Option<bool> help = new Option<bool>("-h", "--help");

		private Option<bool> version = new Option<bool>("--version");

		private Option<bool> update = new Option<bool>("-U", "--update");

		private Option<bool> noUpdate = new Option<bool>("--no-update");

		private Option<string> updateTo = new Option<string>("--update-to");

		private Option<bool> ignoreErrors = new Option<bool>("-i", "--ignore-errors");

		private Option<bool> noAbortOnError = new Option<bool>("--no-abort-on-error");

		private Option<bool> abortOnError = new Option<bool>("--abort-on-error", "--no-ignore-errors");

		private Option<bool> dumpUserAgent = new Option<bool>("--dump-user-agent");

		private Option<bool> listExtractors = new Option<bool>("--list-extractors");

		private Option<bool> extractorDescriptions = new Option<bool>("--extractor-descriptions");

		private Option<string> useExtractors = new Option<string>("--use-extractors", "--ies");

		private Option<string> defaultSearch = new Option<string>("--default-search");

		private Option<bool> ignoreConfig = new Option<bool>("--ignore-config", "--no-config");

		private Option<bool> noConfigLocations = new Option<bool>("--no-config-locations");

		private MultiOption<string> configLocations = new MultiOption<string>("--config-locations");

		private Option<bool> flatPlaylist = new Option<bool>("--flat-playlist");

		private Option<bool> noFlatPlaylist = new Option<bool>("--no-flat-playlist");

		private Option<bool> liveFromStart = new Option<bool>("--live-from-start");

		private Option<bool> noLiveFromStart = new Option<bool>("--no-live-from-start");

		private Option<string> waitForVideo = new Option<string>("--wait-for-video");

		private Option<bool> noWaitForVideo = new Option<bool>("--no-wait-for-video");

		private Option<bool> markWatched = new Option<bool>("--mark-watched");

		private Option<bool> noMarkWatched = new Option<bool>("--no-mark-watched");

		private MultiOption<string> color = new MultiOption<string>("--color");

		private Option<string> compatOptions = new Option<string>("--compat-options");

		private MultiOption<string> alias = new MultiOption<string>("--alias");

		private Option<string> geoVerificationProxy = new Option<string>("--geo-verification-proxy");

		private Option<string> xff = new Option<string>("--xff");

		private Option<bool> writeLink = new Option<bool>("--write-link");

		private Option<bool> writeUrlLink = new Option<bool>("--write-url-link");

		private Option<bool> writeWeblocLink = new Option<bool>("--write-webloc-link");

		private Option<bool> writeDesktopLink = new Option<bool>("--write-desktop-link");

		private Option<string> proxy = new Option<string>("--proxy");

		private Option<int?> socketTimeout = new Option<int?>("--socket-timeout");

		private Option<string> sourceAddress = new Option<string>("--source-address");

		private Option<string> impersonate = new Option<string>("--impersonate");

		private Option<bool> listImpersonateTargets = new Option<bool>("--list-impersonate-targets");

		private Option<bool> forceIPv4 = new Option<bool>("-4", "--force-ipv4");

		private Option<bool> forceIPv6 = new Option<bool>("-6", "--force-ipv6");

		private Option<bool> enableFileUrls = new Option<bool>("--enable-file-urls");

		private Option<bool> extractAudio = new Option<bool>("-x", "--extract-audio");

		private Option<AudioConversionFormat> audioFormat = new Option<AudioConversionFormat>("--audio-format");

		private Option<byte?> audioQuality = new Option<byte?>("--audio-quality");

		private Option<string> remuxVideo = new Option<string>("--remux-video");

		private Option<VideoRecodeFormat> recodeVideo = new Option<VideoRecodeFormat>("--recode-video");

		private MultiOption<string> postprocessorArgs = new MultiOption<string>("--postprocessor-args", "--ppa");

		private Option<bool> keepVideo = new Option<bool>("-k", "--keep-video");

		private Option<bool> noKeepVideo = new Option<bool>("--no-keep-video");

		private Option<bool> postOverwrites = new Option<bool>("--post-overwrites");

		private Option<bool> noPostOverwrites = new Option<bool>("--no-post-overwrites");

		private Option<bool> embedSubs = new Option<bool>("--embed-subs");

		private Option<bool> noEmbedSubs = new Option<bool>("--no-embed-subs");

		private Option<bool> embedThumbnail = new Option<bool>("--embed-thumbnail");

		private Option<bool> noEmbedThumbnail = new Option<bool>("--no-embed-thumbnail");

		private Option<bool> embedMetadata = new Option<bool>("--embed-metadata", "--add-metadata");

		private Option<bool> noEmbedMetadata = new Option<bool>("--no-embed-metadata", "--no-add-metadata");

		private Option<bool> embedChapters = new Option<bool>("--embed-chapters", "--add-chapters");

		private Option<bool> noEmbedChapters = new Option<bool>("--no-embed-chapters", "--no-add-chapters");

		private Option<bool> embedInfoJson = new Option<bool>("--embed-info-json");

		private Option<bool> noEmbedInfoJson = new Option<bool>("--no-embed-info-json");

		private Option<string> parseMetadata = new Option<string>("--parse-metadata");

		private MultiOption<string> replaceInMetadata = new MultiOption<string>("--replace-in-metadata");

		private Option<bool> xattrs = new Option<bool>("--xattrs");

		private Option<string> concatPlaylist = new Option<string>("--concat-playlist");

		private Option<string> fixup = new Option<string>("--fixup");

		private Option<string> ffmpegLocation = new Option<string>("--ffmpeg-location");

		private MultiOption<string> exec = new MultiOption<string>("--exec");

		private Option<bool> noExec = new Option<bool>("--no-exec");

		private Option<string> convertSubs = new Option<string>("--convert-subs", "--convert-subtitles");

		private Option<string> convertThumbnails = new Option<string>("--convert-thumbnails");

		private Option<bool> splitChapters = new Option<bool>("--split-chapters");

		private Option<bool> noSplitChapters = new Option<bool>("--no-split-chapters");

		private MultiOption<string> removeChapters = new MultiOption<string>("--remove-chapters");

		private Option<bool> noRemoveChapters = new Option<bool>("--no-remove-chapters");

		private Option<bool> forceKeyframesAtCuts = new Option<bool>("--force-keyframes-at-cuts");

		private Option<bool> noForceKeyframesAtCuts = new Option<bool>("--no-force-keyframes-at-cuts");

		private MultiOption<string> usePostprocessor = new MultiOption<string>("--use-postprocessor");

		private Option<string> sponsorblockMark = new Option<string>("--sponsorblock-mark");

		private Option<string> sponsorblockRemove = new Option<string>("--sponsorblock-remove");

		private Option<string> sponsorblockChapterTitle = new Option<string>("--sponsorblock-chapter-title");

		private Option<bool> noSponsorblock = new Option<bool>("--no-sponsorblock");

		private Option<string> sponsorblockApi = new Option<string>("--sponsorblock-api");

		private Option<bool> writeSubs = new Option<bool>("--write-subs");

		private Option<bool> noWriteSubs = new Option<bool>("--no-write-subs");

		private Option<bool> writeAutoSubs = new Option<bool>("--write-auto-subs", "--write-automatic-subs");

		private Option<bool> noWriteAutoSubs = new Option<bool>("--no-write-auto-subs", "--no-write-automatic-subs");

		private Option<bool> listSubs = new Option<bool>("--list-subs");

		private Option<string> subFormat = new Option<string>("--sub-format");

		private Option<string> subLangs = new Option<string>("--sub-langs");

		private Option<bool> writeThumbnail = new Option<bool>("--write-thumbnail");

		private Option<bool> noWriteThumbnail = new Option<bool>("--no-write-thumbnail");

		private Option<bool> writeAllThumbnails = new Option<bool>("--write-all-thumbnails");

		private Option<bool> listThumbnails = new Option<bool>("--list-thumbnails");

		private Option<bool> quiet = new Option<bool>("-q", "--quiet");

		private Option<bool> noQuiet = new Option<bool>("--no-quiet");

		private Option<bool> noWarnings = new Option<bool>("--no-warnings");

		private Option<bool> simulate = new Option<bool>("-s", "--simulate");

		private Option<bool> noSimulate = new Option<bool>("--no-simulate");

		private Option<bool> ignoreNoFormatsError = new Option<bool>("--ignore-no-formats-error");

		private Option<bool> noIgnoreNoFormatsError = new Option<bool>("--no-ignore-no-formats-error");

		private Option<bool> skipDownload = new Option<bool>("--skip-download", "--no-download");

		private MultiOption<string> print = new MultiOption<string>("-O", "--print");

		private MultiOption<string> printToFile = new MultiOption<string>("--print-to-file");

		private Option<bool> dumpJson = new Option<bool>("-j", "--dump-json");

		private Option<bool> dumpSingleJson = new Option<bool>("-J", "--dump-single-json");

		private Option<bool> forceWriteArchive = new Option<bool>("--force-write-archive", "--force-download-archive");

		private Option<bool> newline = new Option<bool>("--newline");

		private Option<bool> noProgress = new Option<bool>("--no-progress");

		private Option<bool> progress = new Option<bool>("--progress");

		private Option<bool> consoleTitle = new Option<bool>("--console-title");

		private Option<string> progressTemplate = new Option<string>("--progress-template");

		private Option<string> progressDelta = new Option<string>("--progress-delta");

		private Option<bool> verbose = new Option<bool>("-v", "--verbose");

		private Option<bool> dumpPages = new Option<bool>("--dump-pages");

		private Option<bool> writePages = new Option<bool>("--write-pages");

		private Option<bool> printTraffic = new Option<bool>("--print-traffic");

		private Option<string> format = new Option<string>("-f", "--format");

		private Option<string> formatSort = new Option<string>("-S", "--format-sort");

		private Option<bool> formatSortForce = new Option<bool>("--format-sort-force", "--S-force");

		private Option<bool> noFormatSortForce = new Option<bool>("--no-format-sort-force");

		private Option<bool> videoMultistreams = new Option<bool>("--video-multistreams");

		private Option<bool> noVideoMultistreams = new Option<bool>("--no-video-multistreams");

		private Option<bool> audioMultistreams = new Option<bool>("--audio-multistreams");

		private Option<bool> noAudioMultistreams = new Option<bool>("--no-audio-multistreams");

		private Option<bool> preferFreeFormats = new Option<bool>("--prefer-free-formats");

		private Option<bool> noPreferFreeFormats = new Option<bool>("--no-prefer-free-formats");

		private Option<bool> checkFormats = new Option<bool>("--check-formats");

		private Option<bool> checkAllFormats = new Option<bool>("--check-all-formats");

		private Option<bool> noCheckFormats = new Option<bool>("--no-check-formats");

		private Option<bool> listFormats = new Option<bool>("-F", "--list-formats");

		private Option<DownloadMergeFormat> mergeOutputFormat = new Option<DownloadMergeFormat>("--merge-output-format");

		private Option<string> playlistItems = new Option<string>("-I", "--playlist-items");

		private Option<string> minFilesize = new Option<string>("--min-filesize");

		private Option<string> maxFilesize = new Option<string>("--max-filesize");

		private Option<DateTime> date = new Option<DateTime>("--date");

		private Option<DateTime> dateBefore = new Option<DateTime>("--datebefore");

		private Option<DateTime> dateAfter = new Option<DateTime>("--dateafter");

		private MultiOption<string> matchFilters = new MultiOption<string>("--match-filters");

		private Option<bool> noMatchFilters = new Option<bool>("--no-match-filters");

		private Option<string> breakMatchFilters = new Option<string>("--break-match-filters");

		private Option<bool> noBreakMatchFilters = new Option<bool>("--no-break-match-filters");

		private Option<bool> noPlaylist = new Option<bool>("--no-playlist");

		private Option<bool> yesPlaylist = new Option<bool>("--yes-playlist");

		private Option<byte?> ageLimit = new Option<byte?>("--age-limit");

		private Option<string> downloadArchive = new Option<string>("--download-archive");

		private Option<bool> noDownloadArchive = new Option<bool>("--no-download-archive");

		private Option<int?> maxDownloads = new Option<int?>("--max-downloads");

		private Option<bool> breakOnExisting = new Option<bool>("--break-on-existing");

		private Option<bool> noBreakOnExisting = new Option<bool>("--no-break-on-existing");

		private Option<bool> breakPerInput = new Option<bool>("--break-per-input");

		private Option<bool> noBreakPerInput = new Option<bool>("--no-break-per-input");

		private Option<int?> skipPlaylistAfterErrors = new Option<int?>("--skip-playlist-after-errors");

		private Option<string> encoding = new Option<string>("--encoding");

		private Option<bool> legacyServerConnect = new Option<bool>("--legacy-server-connect");

		private Option<bool> noCheckCertificates = new Option<bool>("--no-check-certificates");

		private Option<bool> preferInsecure = new Option<bool>("--prefer-insecure");

		private MultiOption<string> addHeaders = new MultiOption<string>("--add-headers");

		private Option<bool> bidiWorkaround = new Option<bool>("--bidi-workaround");

		private Option<int?> sleepRequests = new Option<int?>("--sleep-requests");

		private Option<int?> sleepInterval = new Option<int?>("--sleep-interval", "--min-sleep-interval");

		private Option<int?> maxSleepInterval = new Option<int?>("--max-sleep-interval");

		private Option<int?> sleepSubtitles = new Option<int?>("--sleep-subtitles");

		public string Username
		{
			get
			{
				return username.Value;
			}
			set
			{
				username.Value = value;
			}
		}

		public string Password
		{
			get
			{
				return password.Value;
			}
			set
			{
				password.Value = value;
			}
		}

		public string TwoFactor
		{
			get
			{
				return twoFactor.Value;
			}
			set
			{
				twoFactor.Value = value;
			}
		}

		public bool Netrc
		{
			get
			{
				return netrc.Value;
			}
			set
			{
				netrc.Value = value;
			}
		}

		public string NetrcLocation
		{
			get
			{
				return netrcLocation.Value;
			}
			set
			{
				netrcLocation.Value = value;
			}
		}

		public string NetrcCmd
		{
			get
			{
				return netrcCmd.Value;
			}
			set
			{
				netrcCmd.Value = value;
			}
		}

		public string VideoPassword
		{
			get
			{
				return videoPassword.Value;
			}
			set
			{
				videoPassword.Value = value;
			}
		}

		public string ApMso
		{
			get
			{
				return apMso.Value;
			}
			set
			{
				apMso.Value = value;
			}
		}

		public string ApUsername
		{
			get
			{
				return apUsername.Value;
			}
			set
			{
				apUsername.Value = value;
			}
		}

		public string ApPassword
		{
			get
			{
				return apPassword.Value;
			}
			set
			{
				apPassword.Value = value;
			}
		}

		public bool ApListMso
		{
			get
			{
				return apListMso.Value;
			}
			set
			{
				apListMso.Value = value;
			}
		}

		public string ClientCertificate
		{
			get
			{
				return clientCertificate.Value;
			}
			set
			{
				clientCertificate.Value = value;
			}
		}

		public string ClientCertificateKey
		{
			get
			{
				return clientCertificateKey.Value;
			}
			set
			{
				clientCertificateKey.Value = value;
			}
		}

		public string ClientCertificatePassword
		{
			get
			{
				return clientCertificatePassword.Value;
			}
			set
			{
				clientCertificatePassword.Value = value;
			}
		}

		public IOption[] CustomOptions { get; set; } = new IOption[0];


		[Obsolete("Deprecated in favor of: --print description.")]
		public bool GetDescription
		{
			get
			{
				return getDescription.Value;
			}
			set
			{
				getDescription.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print duration_string.")]
		public bool GetDuration
		{
			get
			{
				return getDuration.Value;
			}
			set
			{
				getDuration.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print filename.")]
		public bool GetFilename
		{
			get
			{
				return getFilename.Value;
			}
			set
			{
				getFilename.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print format.")]
		public bool GetFormat
		{
			get
			{
				return getFormat.Value;
			}
			set
			{
				getFormat.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print id.")]
		public bool GetId
		{
			get
			{
				return getId.Value;
			}
			set
			{
				getId.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print thumbnail.")]
		public bool GetThumbnail
		{
			get
			{
				return getThumbnail.Value;
			}
			set
			{
				getThumbnail.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print title.")]
		public bool GetTitle
		{
			get
			{
				return getTitle.Value;
			}
			set
			{
				getTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --print urls.")]
		public bool GetUrl
		{
			get
			{
				return getUrl.Value;
			}
			set
			{
				getUrl.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"title ~= (?i)REGEX\".")]
		public string MatchTitle
		{
			get
			{
				return matchTitle.Value;
			}
			set
			{
				matchTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"title !~= (?i)REGEX\".")]
		public string RejectTitle
		{
			get
			{
				return rejectTitle.Value;
			}
			set
			{
				rejectTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"view_count >=? COUNT\".")]
		public long? MinViews
		{
			get
			{
				return minViews.Value;
			}
			set
			{
				minViews.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --match-filter \"view_count <=? COUNT\".")]
		public long? MaxViews
		{
			get
			{
				return maxViews.Value;
			}
			set
			{
				maxViews.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: Use --break-match-filter.")]
		public bool BreakOnReject
		{
			get
			{
				return breakOnReject.Value;
			}
			set
			{
				breakOnReject.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --add-header \"User-Agent:UA\".")]
		public string UserAgent
		{
			get
			{
				return userAgent.Value;
			}
			set
			{
				userAgent.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --add-header \"Referer:URL\".")]
		public string Referer
		{
			get
			{
				return referer.Value;
			}
			set
			{
				referer.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -I NUMBER:.")]
		public int? PlaylistStart
		{
			get
			{
				return playlistStart.Value;
			}
			set
			{
				playlistStart.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -I :NUMBER.")]
		public int? PlaylistEnd
		{
			get
			{
				return playlistEnd.Value;
			}
			set
			{
				playlistEnd.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -I ::-1.")]
		public bool PlaylistReverse
		{
			get
			{
				return playlistReverse.Value;
			}
			set
			{
				playlistReverse.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --color no_color.")]
		public bool NoColors
		{
			get
			{
				return noColors.Value;
			}
			set
			{
				noColors.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --ies generic,default.")]
		public bool ForceGenericExtractor
		{
			get
			{
				return forceGenericExtractor.Value;
			}
			set
			{
				forceGenericExtractor.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --exec \"before_dl:CMD\".")]
		public string ExecBeforeDownload
		{
			get
			{
				return execBeforeDownload.Value;
			}
			set
			{
				execBeforeDownload.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --no-exec.")]
		public bool NoExecBeforeDownload
		{
			get
			{
				return noExecBeforeDownload.Value;
			}
			set
			{
				noExecBeforeDownload.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -f all.")]
		public bool AllFormats
		{
			get
			{
				return allFormats.Value;
			}
			set
			{
				allFormats.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --sub-langs all --write-subs.")]
		public bool AllSubs
		{
			get
			{
				return allSubs.Value;
			}
			set
			{
				allSubs.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -j --no-simulate.")]
		public bool PrintJson
		{
			get
			{
				return printJson.Value;
			}
			set
			{
				printJson.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: Use string formatting, e.g. %(autonumber)03d.")]
		public string AutonumberSize
		{
			get
			{
				return autonumberSize.Value;
			}
			set
			{
				autonumberSize.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: Use internal field formatting like %(autonumber+NUMBER)s.")]
		public int? AutonumberStart
		{
			get
			{
				return autonumberStart.Value;
			}
			set
			{
				autonumberStart.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: -o \"%(id)s.%(ext)s\".")]
		public bool Id
		{
			get
			{
				return id.Value;
			}
			set
			{
				id.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --parse-metadata \"%(title)s:FORMAT\".")]
		public string MetadataFromTitle
		{
			get
			{
				return metadataFromTitle.Value;
			}
			set
			{
				metadataFromTitle.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --downloader \"m3u8:native\".")]
		public bool HlsPreferNative
		{
			get
			{
				return hlsPreferNative.Value;
			}
			set
			{
				hlsPreferNative.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --downloader \"m3u8:ffmpeg\".")]
		public bool HlsPreferFfmpeg
		{
			get
			{
				return hlsPreferFfmpeg.Value;
			}
			set
			{
				hlsPreferFfmpeg.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --compat-options list-formats (Alias: --no-list-formats-as-table).")]
		public bool ListFormatsOld
		{
			get
			{
				return listFormatsOld.Value;
			}
			set
			{
				listFormatsOld.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --compat-options -list-formats [Default] (Alias: --no-list-formats-old).")]
		public bool ListFormatsAsTable
		{
			get
			{
				return listFormatsAsTable.Value;
			}
			set
			{
				listFormatsAsTable.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --extractor-args \"youtube:skip=dash\" (Alias: --no-youtube-include-dash-manifest).")]
		public bool YoutubeSkipDashManifest
		{
			get
			{
				return youtubeSkipDashManifest.Value;
			}
			set
			{
				youtubeSkipDashManifest.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --extractor-args \"youtube:skip=hls\" (Alias: --no-youtube-include-hls-manifest).")]
		public bool YoutubeSkipHlsManifest
		{
			get
			{
				return youtubeSkipHlsManifest.Value;
			}
			set
			{
				youtubeSkipHlsManifest.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff \"default\".")]
		public bool GeoBypass
		{
			get
			{
				return geoBypass.Value;
			}
			set
			{
				geoBypass.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff \"never\".")]
		public bool NoGeoBypass
		{
			get
			{
				return noGeoBypass.Value;
			}
			set
			{
				noGeoBypass.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff CODE.")]
		public string GeoBypassCountry
		{
			get
			{
				return geoBypassCountry.Value;
			}
			set
			{
				geoBypassCountry.Value = value;
			}
		}

		[Obsolete("Deprecated in favor of: --xff IP_BLOCK.")]
		public string GeoBypassIpBlock
		{
			get
			{
				return geoBypassIpBlock.Value;
			}
			set
			{
				geoBypassIpBlock.Value = value;
			}
		}

		public int? ConcurrentFragments
		{
			get
			{
				return concurrentFragments.Value;
			}
			set
			{
				concurrentFragments.Value = value;
			}
		}

		public long? LimitRate
		{
			get
			{
				return limitRate.Value;
			}
			set
			{
				limitRate.Value = value;
			}
		}

		public long? ThrottledRate
		{
			get
			{
				return throttledRate.Value;
			}
			set
			{
				throttledRate.Value = value;
			}
		}

		public int? Retries
		{
			get
			{
				return retries.Value;
			}
			set
			{
				retries.Value = value;
			}
		}

		public int? FileAccessRetries
		{
			get
			{
				return fileAccessRetries.Value;
			}
			set
			{
				fileAccessRetries.Value = value;
			}
		}

		public int? FragmentRetries
		{
			get
			{
				return fragmentRetries.Value;
			}
			set
			{
				fragmentRetries.Value = value;
			}
		}

		public MultiValue<string> RetrySleep
		{
			get
			{
				return retrySleep.Value;
			}
			set
			{
				retrySleep.Value = value;
			}
		}

		public bool SkipUnavailableFragments
		{
			get
			{
				return skipUnavailableFragments.Value;
			}
			set
			{
				skipUnavailableFragments.Value = value;
			}
		}

		public bool AbortOnUnavailableFragments
		{
			get
			{
				return abortOnUnavailableFragments.Value;
			}
			set
			{
				abortOnUnavailableFragments.Value = value;
			}
		}

		public bool KeepFragments
		{
			get
			{
				return keepFragments.Value;
			}
			set
			{
				keepFragments.Value = value;
			}
		}

		public bool NoKeepFragments
		{
			get
			{
				return noKeepFragments.Value;
			}
			set
			{
				noKeepFragments.Value = value;
			}
		}

		public long? BufferSize
		{
			get
			{
				return bufferSize.Value;
			}
			set
			{
				bufferSize.Value = value;
			}
		}

		public bool ResizeBuffer
		{
			get
			{
				return resizeBuffer.Value;
			}
			set
			{
				resizeBuffer.Value = value;
			}
		}

		public bool NoResizeBuffer
		{
			get
			{
				return noResizeBuffer.Value;
			}
			set
			{
				noResizeBuffer.Value = value;
			}
		}

		public long? HttpChunkSize
		{
			get
			{
				return httpChunkSize.Value;
			}
			set
			{
				httpChunkSize.Value = value;
			}
		}

		public bool PlaylistRandom
		{
			get
			{
				return playlistRandom.Value;
			}
			set
			{
				playlistRandom.Value = value;
			}
		}

		public bool LazyPlaylist
		{
			get
			{
				return lazyPlaylist.Value;
			}
			set
			{
				lazyPlaylist.Value = value;
			}
		}

		public bool NoLazyPlaylist
		{
			get
			{
				return noLazyPlaylist.Value;
			}
			set
			{
				noLazyPlaylist.Value = value;
			}
		}

		public bool XattrSetFilesize
		{
			get
			{
				return xattrSetFilesize.Value;
			}
			set
			{
				xattrSetFilesize.Value = value;
			}
		}

		public bool HlsUseMpegts
		{
			get
			{
				return hlsUseMpegts.Value;
			}
			set
			{
				hlsUseMpegts.Value = value;
			}
		}

		public bool NoHlsUseMpegts
		{
			get
			{
				return noHlsUseMpegts.Value;
			}
			set
			{
				noHlsUseMpegts.Value = value;
			}
		}

		public MultiValue<string> DownloadSections
		{
			get
			{
				return downloadSections.Value;
			}
			set
			{
				downloadSections.Value = value;
			}
		}

		public MultiValue<string> Downloader
		{
			get
			{
				return downloader.Value;
			}
			set
			{
				downloader.Value = value;
			}
		}

		public MultiValue<string> DownloaderArgs
		{
			get
			{
				return downloaderArgs.Value;
			}
			set
			{
				downloaderArgs.Value = value;
			}
		}

		public int? ExtractorRetries
		{
			get
			{
				return extractorRetries.Value;
			}
			set
			{
				extractorRetries.Value = value;
			}
		}

		public bool AllowDynamicMpd
		{
			get
			{
				return allowDynamicMpd.Value;
			}
			set
			{
				allowDynamicMpd.Value = value;
			}
		}

		public bool IgnoreDynamicMpd
		{
			get
			{
				return ignoreDynamicMpd.Value;
			}
			set
			{
				ignoreDynamicMpd.Value = value;
			}
		}

		public bool HlsSplitDiscontinuity
		{
			get
			{
				return hlsSplitDiscontinuity.Value;
			}
			set
			{
				hlsSplitDiscontinuity.Value = value;
			}
		}

		public bool NoHlsSplitDiscontinuity
		{
			get
			{
				return noHlsSplitDiscontinuity.Value;
			}
			set
			{
				noHlsSplitDiscontinuity.Value = value;
			}
		}

		public MultiValue<string> ExtractorArgs
		{
			get
			{
				return extractorArgs.Value;
			}
			set
			{
				extractorArgs.Value = value;
			}
		}

		public string BatchFile
		{
			get
			{
				return batchFile.Value;
			}
			set
			{
				batchFile.Value = value;
			}
		}

		public bool NoBatchFile
		{
			get
			{
				return noBatchFile.Value;
			}
			set
			{
				noBatchFile.Value = value;
			}
		}

		public MultiValue<string> Paths
		{
			get
			{
				return paths.Value;
			}
			set
			{
				paths.Value = value;
			}
		}

		public string Output
		{
			get
			{
				return output.Value;
			}
			set
			{
				output.Value = value;
			}
		}

		public string OutputNaPlaceholder
		{
			get
			{
				return outputNaPlaceholder.Value;
			}
			set
			{
				outputNaPlaceholder.Value = value;
			}
		}

		public bool RestrictFilenames
		{
			get
			{
				return restrictFilenames.Value;
			}
			set
			{
				restrictFilenames.Value = value;
			}
		}

		public bool NoRestrictFilenames
		{
			get
			{
				return noRestrictFilenames.Value;
			}
			set
			{
				noRestrictFilenames.Value = value;
			}
		}

		public bool WindowsFilenames
		{
			get
			{
				return windowsFilenames.Value;
			}
			set
			{
				windowsFilenames.Value = value;
			}
		}

		public bool NoWindowsFilenames
		{
			get
			{
				return noWindowsFilenames.Value;
			}
			set
			{
				noWindowsFilenames.Value = value;
			}
		}

		public int? TrimFilenames
		{
			get
			{
				return trimFilenames.Value;
			}
			set
			{
				trimFilenames.Value = value;
			}
		}

		public bool NoOverwrites
		{
			get
			{
				return noOverwrites.Value;
			}
			set
			{
				noOverwrites.Value = value;
			}
		}

		public bool ForceOverwrites
		{
			get
			{
				return forceOverwrites.Value;
			}
			set
			{
				forceOverwrites.Value = value;
			}
		}

		public bool NoForceOverwrites
		{
			get
			{
				return noForceOverwrites.Value;
			}
			set
			{
				noForceOverwrites.Value = value;
			}
		}

		public bool Continue
		{
			get
			{
				return doContinue.Value;
			}
			set
			{
				doContinue.Value = value;
			}
		}

		public bool NoContinue
		{
			get
			{
				return noContinue.Value;
			}
			set
			{
				noContinue.Value = value;
			}
		}

		public bool Part
		{
			get
			{
				return part.Value;
			}
			set
			{
				part.Value = value;
			}
		}

		public bool NoPart
		{
			get
			{
				return noPart.Value;
			}
			set
			{
				noPart.Value = value;
			}
		}

		public bool Mtime
		{
			get
			{
				return mtime.Value;
			}
			set
			{
				mtime.Value = value;
			}
		}

		public bool NoMtime
		{
			get
			{
				return noMtime.Value;
			}
			set
			{
				noMtime.Value = value;
			}
		}

		public bool WriteDescription
		{
			get
			{
				return writeDescription.Value;
			}
			set
			{
				writeDescription.Value = value;
			}
		}

		public bool NoWriteDescription
		{
			get
			{
				return noWriteDescription.Value;
			}
			set
			{
				noWriteDescription.Value = value;
			}
		}

		public bool WriteInfoJson
		{
			get
			{
				return writeInfoJson.Value;
			}
			set
			{
				writeInfoJson.Value = value;
			}
		}

		public bool NoWriteInfoJson
		{
			get
			{
				return noWriteInfoJson.Value;
			}
			set
			{
				noWriteInfoJson.Value = value;
			}
		}

		public bool WritePlaylistMetafiles
		{
			get
			{
				return writePlaylistMetafiles.Value;
			}
			set
			{
				writePlaylistMetafiles.Value = value;
			}
		}

		public bool NoWritePlaylistMetafiles
		{
			get
			{
				return noWritePlaylistMetafiles.Value;
			}
			set
			{
				noWritePlaylistMetafiles.Value = value;
			}
		}

		public bool CleanInfoJson
		{
			get
			{
				return cleanInfoJson.Value;
			}
			set
			{
				cleanInfoJson.Value = value;
			}
		}

		public bool NoCleanInfoJson
		{
			get
			{
				return noCleanInfoJson.Value;
			}
			set
			{
				noCleanInfoJson.Value = value;
			}
		}

		public bool WriteComments
		{
			get
			{
				return writeComments.Value;
			}
			set
			{
				writeComments.Value = value;
			}
		}

		public bool NoWriteComments
		{
			get
			{
				return noWriteComments.Value;
			}
			set
			{
				noWriteComments.Value = value;
			}
		}

		public string LoadInfoJson
		{
			get
			{
				return loadInfoJson.Value;
			}
			set
			{
				loadInfoJson.Value = value;
			}
		}

		public string Cookies
		{
			get
			{
				return cookies.Value;
			}
			set
			{
				cookies.Value = value;
			}
		}

		public bool NoCookies
		{
			get
			{
				return noCookies.Value;
			}
			set
			{
				noCookies.Value = value;
			}
		}

		public string CookiesFromBrowser
		{
			get
			{
				return cookiesFromBrowser.Value;
			}
			set
			{
				cookiesFromBrowser.Value = value;
			}
		}

		public bool NoCookiesFromBrowser
		{
			get
			{
				return noCookiesFromBrowser.Value;
			}
			set
			{
				noCookiesFromBrowser.Value = value;
			}
		}

		public string CacheDir
		{
			get
			{
				return cacheDir.Value;
			}
			set
			{
				cacheDir.Value = value;
			}
		}

		public bool NoCacheDir
		{
			get
			{
				return noCacheDir.Value;
			}
			set
			{
				noCacheDir.Value = value;
			}
		}

		public bool RemoveCacheDir
		{
			get
			{
				return removeCacheDir.Value;
			}
			set
			{
				removeCacheDir.Value = value;
			}
		}

		public bool Help
		{
			get
			{
				return help.Value;
			}
			set
			{
				help.Value = value;
			}
		}

		public bool Version
		{
			get
			{
				return version.Value;
			}
			set
			{
				version.Value = value;
			}
		}

		public bool Update
		{
			get
			{
				return update.Value;
			}
			set
			{
				update.Value = value;
			}
		}

		public bool NoUpdate
		{
			get
			{
				return noUpdate.Value;
			}
			set
			{
				noUpdate.Value = value;
			}
		}

		public string UpdateTo
		{
			get
			{
				return updateTo.Value;
			}
			set
			{
				updateTo.Value = value;
			}
		}

		public bool IgnoreErrors
		{
			get
			{
				return ignoreErrors.Value;
			}
			set
			{
				ignoreErrors.Value = value;
			}
		}

		public bool NoAbortOnError
		{
			get
			{
				return noAbortOnError.Value;
			}
			set
			{
				noAbortOnError.Value = value;
			}
		}

		public bool AbortOnError
		{
			get
			{
				return abortOnError.Value;
			}
			set
			{
				abortOnError.Value = value;
			}
		}

		public bool DumpUserAgent
		{
			get
			{
				return dumpUserAgent.Value;
			}
			set
			{
				dumpUserAgent.Value = value;
			}
		}

		public bool ListExtractors
		{
			get
			{
				return listExtractors.Value;
			}
			set
			{
				listExtractors.Value = value;
			}
		}

		public bool ExtractorDescriptions
		{
			get
			{
				return extractorDescriptions.Value;
			}
			set
			{
				extractorDescriptions.Value = value;
			}
		}

		public string UseExtractors
		{
			get
			{
				return useExtractors.Value;
			}
			set
			{
				useExtractors.Value = value;
			}
		}

		public string DefaultSearch
		{
			get
			{
				return defaultSearch.Value;
			}
			set
			{
				defaultSearch.Value = value;
			}
		}

		public bool IgnoreConfig
		{
			get
			{
				return ignoreConfig.Value;
			}
			set
			{
				ignoreConfig.Value = value;
			}
		}

		public bool NoConfigLocations
		{
			get
			{
				return noConfigLocations.Value;
			}
			set
			{
				noConfigLocations.Value = value;
			}
		}

		public MultiValue<string> ConfigLocations
		{
			get
			{
				return configLocations.Value;
			}
			set
			{
				configLocations.Value = value;
			}
		}

		public bool FlatPlaylist
		{
			get
			{
				return flatPlaylist.Value;
			}
			set
			{
				flatPlaylist.Value = value;
			}
		}

		public bool NoFlatPlaylist
		{
			get
			{
				return noFlatPlaylist.Value;
			}
			set
			{
				noFlatPlaylist.Value = value;
			}
		}

		public bool LiveFromStart
		{
			get
			{
				return liveFromStart.Value;
			}
			set
			{
				liveFromStart.Value = value;
			}
		}

		public bool NoLiveFromStart
		{
			get
			{
				return noLiveFromStart.Value;
			}
			set
			{
				noLiveFromStart.Value = value;
			}
		}

		public string WaitForVideo
		{
			get
			{
				return waitForVideo.Value;
			}
			set
			{
				waitForVideo.Value = value;
			}
		}

		public bool NoWaitForVideo
		{
			get
			{
				return noWaitForVideo.Value;
			}
			set
			{
				noWaitForVideo.Value = value;
			}
		}

		public bool MarkWatched
		{
			get
			{
				return markWatched.Value;
			}
			set
			{
				markWatched.Value = value;
			}
		}

		public bool NoMarkWatched
		{
			get
			{
				return noMarkWatched.Value;
			}
			set
			{
				noMarkWatched.Value = value;
			}
		}

		public MultiValue<string> Color
		{
			get
			{
				return color.Value;
			}
			set
			{
				color.Value = value;
			}
		}

		public string CompatOptions
		{
			get
			{
				return compatOptions.Value;
			}
			set
			{
				compatOptions.Value = value;
			}
		}

		public MultiValue<string> Alias
		{
			get
			{
				return alias.Value;
			}
			set
			{
				alias.Value = value;
			}
		}

		public string GeoVerificationProxy
		{
			get
			{
				return geoVerificationProxy.Value;
			}
			set
			{
				geoVerificationProxy.Value = value;
			}
		}

		public string Xff
		{
			get
			{
				return xff.Value;
			}
			set
			{
				xff.Value = value;
			}
		}

		public bool WriteLink
		{
			get
			{
				return writeLink.Value;
			}
			set
			{
				writeLink.Value = value;
			}
		}

		public bool WriteUrlLink
		{
			get
			{
				return writeUrlLink.Value;
			}
			set
			{
				writeUrlLink.Value = value;
			}
		}

		public bool WriteWeblocLink
		{
			get
			{
				return writeWeblocLink.Value;
			}
			set
			{
				writeWeblocLink.Value = value;
			}
		}

		public bool WriteDesktopLink
		{
			get
			{
				return writeDesktopLink.Value;
			}
			set
			{
				writeDesktopLink.Value = value;
			}
		}

		public string Proxy
		{
			get
			{
				return proxy.Value;
			}
			set
			{
				proxy.Value = value;
			}
		}

		public int? SocketTimeout
		{
			get
			{
				return socketTimeout.Value;
			}
			set
			{
				socketTimeout.Value = value;
			}
		}

		public string SourceAddress
		{
			get
			{
				return sourceAddress.Value;
			}
			set
			{
				sourceAddress.Value = value;
			}
		}

		public string Impersonate
		{
			get
			{
				return impersonate.Value;
			}
			set
			{
				impersonate.Value = value;
			}
		}

		public bool ListImpersonateTargets
		{
			get
			{
				return listImpersonateTargets.Value;
			}
			set
			{
				listImpersonateTargets.Value = value;
			}
		}

		public bool ForceIPv4
		{
			get
			{
				return forceIPv4.Value;
			}
			set
			{
				forceIPv4.Value = value;
			}
		}

		public bool ForceIPv6
		{
			get
			{
				return forceIPv6.Value;
			}
			set
			{
				forceIPv6.Value = value;
			}
		}

		public bool EnableFileUrls
		{
			get
			{
				return enableFileUrls.Value;
			}
			set
			{
				enableFileUrls.Value = value;
			}
		}

		public bool ExtractAudio
		{
			get
			{
				return extractAudio.Value;
			}
			set
			{
				extractAudio.Value = value;
			}
		}

		public AudioConversionFormat AudioFormat
		{
			get
			{
				return audioFormat.Value;
			}
			set
			{
				audioFormat.Value = value;
			}
		}

		public byte? AudioQuality
		{
			get
			{
				return audioQuality.Value;
			}
			set
			{
				audioQuality.Value = value;
			}
		}

		public string RemuxVideo
		{
			get
			{
				return remuxVideo.Value;
			}
			set
			{
				remuxVideo.Value = value;
			}
		}

		public VideoRecodeFormat RecodeVideo
		{
			get
			{
				return recodeVideo.Value;
			}
			set
			{
				recodeVideo.Value = value;
			}
		}

		public MultiValue<string> PostprocessorArgs
		{
			get
			{
				return postprocessorArgs.Value;
			}
			set
			{
				postprocessorArgs.Value = value;
			}
		}

		public bool KeepVideo
		{
			get
			{
				return keepVideo.Value;
			}
			set
			{
				keepVideo.Value = value;
			}
		}

		public bool NoKeepVideo
		{
			get
			{
				return noKeepVideo.Value;
			}
			set
			{
				noKeepVideo.Value = value;
			}
		}

		public bool PostOverwrites
		{
			get
			{
				return postOverwrites.Value;
			}
			set
			{
				postOverwrites.Value = value;
			}
		}

		public bool NoPostOverwrites
		{
			get
			{
				return noPostOverwrites.Value;
			}
			set
			{
				noPostOverwrites.Value = value;
			}
		}

		public bool EmbedSubs
		{
			get
			{
				return embedSubs.Value;
			}
			set
			{
				embedSubs.Value = value;
			}
		}

		public bool NoEmbedSubs
		{
			get
			{
				return noEmbedSubs.Value;
			}
			set
			{
				noEmbedSubs.Value = value;
			}
		}

		public bool EmbedThumbnail
		{
			get
			{
				return embedThumbnail.Value;
			}
			set
			{
				embedThumbnail.Value = value;
			}
		}

		public bool NoEmbedThumbnail
		{
			get
			{
				return noEmbedThumbnail.Value;
			}
			set
			{
				noEmbedThumbnail.Value = value;
			}
		}

		public bool EmbedMetadata
		{
			get
			{
				return embedMetadata.Value;
			}
			set
			{
				embedMetadata.Value = value;
			}
		}

		public bool NoEmbedMetadata
		{
			get
			{
				return noEmbedMetadata.Value;
			}
			set
			{
				noEmbedMetadata.Value = value;
			}
		}

		public bool EmbedChapters
		{
			get
			{
				return embedChapters.Value;
			}
			set
			{
				embedChapters.Value = value;
			}
		}

		public bool NoEmbedChapters
		{
			get
			{
				return noEmbedChapters.Value;
			}
			set
			{
				noEmbedChapters.Value = value;
			}
		}

		public bool EmbedInfoJson
		{
			get
			{
				return embedInfoJson.Value;
			}
			set
			{
				embedInfoJson.Value = value;
			}
		}

		public bool NoEmbedInfoJson
		{
			get
			{
				return noEmbedInfoJson.Value;
			}
			set
			{
				noEmbedInfoJson.Value = value;
			}
		}

		public string ParseMetadata
		{
			get
			{
				return parseMetadata.Value;
			}
			set
			{
				parseMetadata.Value = value;
			}
		}

		public MultiValue<string> ReplaceInMetadata
		{
			get
			{
				return replaceInMetadata.Value;
			}
			set
			{
				replaceInMetadata.Value = value;
			}
		}

		public bool Xattrs
		{
			get
			{
				return xattrs.Value;
			}
			set
			{
				xattrs.Value = value;
			}
		}

		public string ConcatPlaylist
		{
			get
			{
				return concatPlaylist.Value;
			}
			set
			{
				concatPlaylist.Value = value;
			}
		}

		public string Fixup
		{
			get
			{
				return fixup.Value;
			}
			set
			{
				fixup.Value = value;
			}
		}

		public string FfmpegLocation
		{
			get
			{
				return ffmpegLocation.Value;
			}
			set
			{
				ffmpegLocation.Value = value;
			}
		}

		public MultiValue<string> Exec
		{
			get
			{
				return exec.Value;
			}
			set
			{
				exec.Value = value;
			}
		}

		public bool NoExec
		{
			get
			{
				return noExec.Value;
			}
			set
			{
				noExec.Value = value;
			}
		}

		public string ConvertSubs
		{
			get
			{
				return convertSubs.Value;
			}
			set
			{
				convertSubs.Value = value;
			}
		}

		public string ConvertThumbnails
		{
			get
			{
				return convertThumbnails.Value;
			}
			set
			{
				convertThumbnails.Value = value;
			}
		}

		public bool SplitChapters
		{
			get
			{
				return splitChapters.Value;
			}
			set
			{
				splitChapters.Value = value;
			}
		}

		public bool NoSplitChapters
		{
			get
			{
				return noSplitChapters.Value;
			}
			set
			{
				noSplitChapters.Value = value;
			}
		}

		public MultiValue<string> RemoveChapters
		{
			get
			{
				return removeChapters.Value;
			}
			set
			{
				removeChapters.Value = value;
			}
		}

		public bool NoRemoveChapters
		{
			get
			{
				return noRemoveChapters.Value;
			}
			set
			{
				noRemoveChapters.Value = value;
			}
		}

		public bool ForceKeyframesAtCuts
		{
			get
			{
				return forceKeyframesAtCuts.Value;
			}
			set
			{
				forceKeyframesAtCuts.Value = value;
			}
		}

		public bool NoForceKeyframesAtCuts
		{
			get
			{
				return noForceKeyframesAtCuts.Value;
			}
			set
			{
				noForceKeyframesAtCuts.Value = value;
			}
		}

		public MultiValue<string> UsePostprocessor
		{
			get
			{
				return usePostprocessor.Value;
			}
			set
			{
				usePostprocessor.Value = value;
			}
		}

		public string SponsorblockMark
		{
			get
			{
				return sponsorblockMark.Value;
			}
			set
			{
				sponsorblockMark.Value = value;
			}
		}

		public string SponsorblockRemove
		{
			get
			{
				return sponsorblockRemove.Value;
			}
			set
			{
				sponsorblockRemove.Value = value;
			}
		}

		public string SponsorblockChapterTitle
		{
			get
			{
				return sponsorblockChapterTitle.Value;
			}
			set
			{
				sponsorblockChapterTitle.Value = value;
			}
		}

		public bool NoSponsorblock
		{
			get
			{
				return noSponsorblock.Value;
			}
			set
			{
				noSponsorblock.Value = value;
			}
		}

		public string SponsorblockApi
		{
			get
			{
				return sponsorblockApi.Value;
			}
			set
			{
				sponsorblockApi.Value = value;
			}
		}

		public bool WriteSubs
		{
			get
			{
				return writeSubs.Value;
			}
			set
			{
				writeSubs.Value = value;
			}
		}

		public bool NoWriteSubs
		{
			get
			{
				return noWriteSubs.Value;
			}
			set
			{
				noWriteSubs.Value = value;
			}
		}

		public bool WriteAutoSubs
		{
			get
			{
				return writeAutoSubs.Value;
			}
			set
			{
				writeAutoSubs.Value = value;
			}
		}

		public bool NoWriteAutoSubs
		{
			get
			{
				return noWriteAutoSubs.Value;
			}
			set
			{
				noWriteAutoSubs.Value = value;
			}
		}

		public bool ListSubs
		{
			get
			{
				return listSubs.Value;
			}
			set
			{
				listSubs.Value = value;
			}
		}

		public string SubFormat
		{
			get
			{
				return subFormat.Value;
			}
			set
			{
				subFormat.Value = value;
			}
		}

		public string SubLangs
		{
			get
			{
				return subLangs.Value;
			}
			set
			{
				subLangs.Value = value;
			}
		}

		public bool WriteThumbnail
		{
			get
			{
				return writeThumbnail.Value;
			}
			set
			{
				writeThumbnail.Value = value;
			}
		}

		public bool NoWriteThumbnail
		{
			get
			{
				return noWriteThumbnail.Value;
			}
			set
			{
				noWriteThumbnail.Value = value;
			}
		}

		public bool WriteAllThumbnails
		{
			get
			{
				return writeAllThumbnails.Value;
			}
			set
			{
				writeAllThumbnails.Value = value;
			}
		}

		public bool ListThumbnails
		{
			get
			{
				return listThumbnails.Value;
			}
			set
			{
				listThumbnails.Value = value;
			}
		}

		public bool Quiet
		{
			get
			{
				return quiet.Value;
			}
			set
			{
				quiet.Value = value;
			}
		}

		public bool NoQuiet
		{
			get
			{
				return noQuiet.Value;
			}
			set
			{
				noQuiet.Value = value;
			}
		}

		public bool NoWarnings
		{
			get
			{
				return noWarnings.Value;
			}
			set
			{
				noWarnings.Value = value;
			}
		}

		public bool Simulate
		{
			get
			{
				return simulate.Value;
			}
			set
			{
				simulate.Value = value;
			}
		}

		public bool NoSimulate
		{
			get
			{
				return noSimulate.Value;
			}
			set
			{
				noSimulate.Value = value;
			}
		}

		public bool IgnoreNoFormatsError
		{
			get
			{
				return ignoreNoFormatsError.Value;
			}
			set
			{
				ignoreNoFormatsError.Value = value;
			}
		}

		public bool NoIgnoreNoFormatsError
		{
			get
			{
				return noIgnoreNoFormatsError.Value;
			}
			set
			{
				noIgnoreNoFormatsError.Value = value;
			}
		}

		public bool SkipDownload
		{
			get
			{
				return skipDownload.Value;
			}
			set
			{
				skipDownload.Value = value;
			}
		}

		public MultiValue<string> Print
		{
			get
			{
				return print.Value;
			}
			set
			{
				print.Value = value;
			}
		}

		public MultiValue<string> PrintToFile
		{
			get
			{
				return printToFile.Value;
			}
			set
			{
				printToFile.Value = value;
			}
		}

		public bool DumpJson
		{
			get
			{
				return dumpJson.Value;
			}
			set
			{
				dumpJson.Value = value;
			}
		}

		public bool DumpSingleJson
		{
			get
			{
				return dumpSingleJson.Value;
			}
			set
			{
				dumpSingleJson.Value = value;
			}
		}

		public bool ForceWriteArchive
		{
			get
			{
				return forceWriteArchive.Value;
			}
			set
			{
				forceWriteArchive.Value = value;
			}
		}

		public bool Newline
		{
			get
			{
				return newline.Value;
			}
			set
			{
				newline.Value = value;
			}
		}

		public bool NoProgress
		{
			get
			{
				return noProgress.Value;
			}
			set
			{
				noProgress.Value = value;
			}
		}

		public bool Progress
		{
			get
			{
				return progress.Value;
			}
			set
			{
				progress.Value = value;
			}
		}

		public bool ConsoleTitle
		{
			get
			{
				return consoleTitle.Value;
			}
			set
			{
				consoleTitle.Value = value;
			}
		}

		public string ProgressTemplate
		{
			get
			{
				return progressTemplate.Value;
			}
			set
			{
				progressTemplate.Value = value;
			}
		}

		public string ProgressDelta
		{
			get
			{
				return progressDelta.Value;
			}
			set
			{
				progressDelta.Value = value;
			}
		}

		public bool Verbose
		{
			get
			{
				return verbose.Value;
			}
			set
			{
				verbose.Value = value;
			}
		}

		public bool DumpPages
		{
			get
			{
				return dumpPages.Value;
			}
			set
			{
				dumpPages.Value = value;
			}
		}

		public bool WritePages
		{
			get
			{
				return writePages.Value;
			}
			set
			{
				writePages.Value = value;
			}
		}

		public bool PrintTraffic
		{
			get
			{
				return printTraffic.Value;
			}
			set
			{
				printTraffic.Value = value;
			}
		}

		public string Format
		{
			get
			{
				return format.Value;
			}
			set
			{
				format.Value = value;
			}
		}

		public string FormatSort
		{
			get
			{
				return formatSort.Value;
			}
			set
			{
				formatSort.Value = value;
			}
		}

		public bool FormatSortForce
		{
			get
			{
				return formatSortForce.Value;
			}
			set
			{
				formatSortForce.Value = value;
			}
		}

		public bool NoFormatSortForce
		{
			get
			{
				return noFormatSortForce.Value;
			}
			set
			{
				noFormatSortForce.Value = value;
			}
		}

		public bool VideoMultistreams
		{
			get
			{
				return videoMultistreams.Value;
			}
			set
			{
				videoMultistreams.Value = value;
			}
		}

		public bool NoVideoMultistreams
		{
			get
			{
				return noVideoMultistreams.Value;
			}
			set
			{
				noVideoMultistreams.Value = value;
			}
		}

		public bool AudioMultistreams
		{
			get
			{
				return audioMultistreams.Value;
			}
			set
			{
				audioMultistreams.Value = value;
			}
		}

		public bool NoAudioMultistreams
		{
			get
			{
				return noAudioMultistreams.Value;
			}
			set
			{
				noAudioMultistreams.Value = value;
			}
		}

		public bool PreferFreeFormats
		{
			get
			{
				return preferFreeFormats.Value;
			}
			set
			{
				preferFreeFormats.Value = value;
			}
		}

		public bool NoPreferFreeFormats
		{
			get
			{
				return noPreferFreeFormats.Value;
			}
			set
			{
				noPreferFreeFormats.Value = value;
			}
		}

		public bool CheckFormats
		{
			get
			{
				return checkFormats.Value;
			}
			set
			{
				checkFormats.Value = value;
			}
		}

		public bool CheckAllFormats
		{
			get
			{
				return checkAllFormats.Value;
			}
			set
			{
				checkAllFormats.Value = value;
			}
		}

		public bool NoCheckFormats
		{
			get
			{
				return noCheckFormats.Value;
			}
			set
			{
				noCheckFormats.Value = value;
			}
		}

		public bool ListFormats
		{
			get
			{
				return listFormats.Value;
			}
			set
			{
				listFormats.Value = value;
			}
		}

		public DownloadMergeFormat MergeOutputFormat
		{
			get
			{
				return mergeOutputFormat.Value;
			}
			set
			{
				mergeOutputFormat.Value = value;
			}
		}

		public string PlaylistItems
		{
			get
			{
				return playlistItems.Value;
			}
			set
			{
				playlistItems.Value = value;
			}
		}

		public string MinFilesize
		{
			get
			{
				return minFilesize.Value;
			}
			set
			{
				minFilesize.Value = value;
			}
		}

		public string MaxFilesize
		{
			get
			{
				return maxFilesize.Value;
			}
			set
			{
				maxFilesize.Value = value;
			}
		}

		public DateTime Date
		{
			get
			{
				return date.Value;
			}
			set
			{
				date.Value = value;
			}
		}

		public DateTime DateBefore
		{
			get
			{
				return dateBefore.Value;
			}
			set
			{
				dateBefore.Value = value;
			}
		}

		public DateTime DateAfter
		{
			get
			{
				return dateAfter.Value;
			}
			set
			{
				dateAfter.Value = value;
			}
		}

		public MultiValue<string> MatchFilters
		{
			get
			{
				return matchFilters.Value;
			}
			set
			{
				matchFilters.Value = value;
			}
		}

		public bool NoMatchFilters
		{
			get
			{
				return noMatchFilters.Value;
			}
			set
			{
				noMatchFilters.Value = value;
			}
		}

		public string BreakMatchFilters
		{
			get
			{
				return breakMatchFilters.Value;
			}
			set
			{
				breakMatchFilters.Value = value;
			}
		}

		public bool NoBreakMatchFilters
		{
			get
			{
				return noBreakMatchFilters.Value;
			}
			set
			{
				noBreakMatchFilters.Value = value;
			}
		}

		public bool NoPlaylist
		{
			get
			{
				return noPlaylist.Value;
			}
			set
			{
				noPlaylist.Value = value;
			}
		}

		public bool YesPlaylist
		{
			get
			{
				return yesPlaylist.Value;
			}
			set
			{
				yesPlaylist.Value = value;
			}
		}

		public byte? AgeLimit
		{
			get
			{
				return ageLimit.Value;
			}
			set
			{
				ageLimit.Value = value;
			}
		}

		public string DownloadArchive
		{
			get
			{
				return downloadArchive.Value;
			}
			set
			{
				downloadArchive.Value = value;
			}
		}

		public bool NoDownloadArchive
		{
			get
			{
				return noDownloadArchive.Value;
			}
			set
			{
				noDownloadArchive.Value = value;
			}
		}

		public int? MaxDownloads
		{
			get
			{
				return maxDownloads.Value;
			}
			set
			{
				maxDownloads.Value = value;
			}
		}

		public bool BreakOnExisting
		{
			get
			{
				return breakOnExisting.Value;
			}
			set
			{
				breakOnExisting.Value = value;
			}
		}

		public bool NoBreakOnExisting
		{
			get
			{
				return noBreakOnExisting.Value;
			}
			set
			{
				noBreakOnExisting.Value = value;
			}
		}

		public bool BreakPerInput
		{
			get
			{
				return breakPerInput.Value;
			}
			set
			{
				breakPerInput.Value = value;
			}
		}

		public bool NoBreakPerInput
		{
			get
			{
				return noBreakPerInput.Value;
			}
			set
			{
				noBreakPerInput.Value = value;
			}
		}

		public int? SkipPlaylistAfterErrors
		{
			get
			{
				return skipPlaylistAfterErrors.Value;
			}
			set
			{
				skipPlaylistAfterErrors.Value = value;
			}
		}

		public string Encoding
		{
			get
			{
				return encoding.Value;
			}
			set
			{
				encoding.Value = value;
			}
		}

		public bool LegacyServerConnect
		{
			get
			{
				return legacyServerConnect.Value;
			}
			set
			{
				legacyServerConnect.Value = value;
			}
		}

		public bool NoCheckCertificates
		{
			get
			{
				return noCheckCertificates.Value;
			}
			set
			{
				noCheckCertificates.Value = value;
			}
		}

		public bool PreferInsecure
		{
			get
			{
				return preferInsecure.Value;
			}
			set
			{
				preferInsecure.Value = value;
			}
		}

		public MultiValue<string> AddHeaders
		{
			get
			{
				return addHeaders.Value;
			}
			set
			{
				addHeaders.Value = value;
			}
		}

		public bool BidiWorkaround
		{
			get
			{
				return bidiWorkaround.Value;
			}
			set
			{
				bidiWorkaround.Value = value;
			}
		}

		public int? SleepRequests
		{
			get
			{
				return sleepRequests.Value;
			}
			set
			{
				sleepRequests.Value = value;
			}
		}

		public int? SleepInterval
		{
			get
			{
				return sleepInterval.Value;
			}
			set
			{
				sleepInterval.Value = value;
			}
		}

		public int? MaxSleepInterval
		{
			get
			{
				return maxSleepInterval.Value;
			}
			set
			{
				maxSleepInterval.Value = value;
			}
		}

		public int? SleepSubtitles
		{
			get
			{
				return sleepSubtitles.Value;
			}
			set
			{
				sleepSubtitles.Value = value;
			}
		}

		public void WriteConfigFile(string path)
		{
			File.WriteAllLines(path, GetOptionFlags());
		}

		public override string ToString()
		{
			return " " + string.Join(" ", GetOptionFlags());
		}

		public IEnumerable<string> GetOptionFlags()
		{
			return from value in GetKnownOptions().Concat(CustomOptions).SelectMany((IOption opt) => opt.ToStringCollection())
				where !string.IsNullOrWhiteSpace(value)
				select value;
		}

		internal IEnumerable<IOption> GetKnownOptions()
		{
			return (from p in GetType().GetRuntimeFields()
				where p.FieldType.IsGenericType && p.FieldType.GetInterfaces().Contains(typeof(IOption))
				select p.GetValue(this)).Cast<IOption>();
		}

		public OptionSet OverrideOptions(OptionSet overrideOptions, bool forceOverride = false)
		{
			OptionSet optionSet = (OptionSet)Clone();
			optionSet.CustomOptions = optionSet.CustomOptions.Concat(overrideOptions.CustomOptions).Distinct(Comparer).ToArray();
			foreach (FieldInfo item in from p in overrideOptions.GetType().GetRuntimeFields()
				where p.FieldType.IsGenericType && p.FieldType.GetInterfaces().Contains(typeof(IOption))
				select p)
			{
				IOption option = (IOption)item.GetValue(overrideOptions);
				if (forceOverride || option.IsSet)
				{
					optionSet.GetType().GetField(item.Name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(optionSet, option);
				}
			}
			return optionSet;
		}

		public static OptionSet FromString(IEnumerable<string> lines)
		{
			OptionSet optionSet = new OptionSet();
			IOption[] customOptions = (from option in GetOptions(lines, optionSet.GetKnownOptions())
				where option.IsCustom
				select option).ToArray();
			optionSet.CustomOptions = customOptions;
			return optionSet;
		}

		private static IEnumerable<IOption> GetOptions(IEnumerable<string> lines, IEnumerable<IOption> options)
		{
			IEnumerable<IOption> knownOptions = options.ToList();
			foreach (string line in lines)
			{
				string text = line.Trim();
				if (!text.StartsWith("#") && !string.IsNullOrWhiteSpace(text))
				{
					string[] array = text.Split(new char[1] { ' ' });
					string flag = array[0];
					IOption option = knownOptions.FirstOrDefault((IOption o) => o.OptionStrings.Contains(flag));
					IOption option3;
					if (array.Length <= 1)
					{
						IOption option2 = new Option<bool>(true, flag);
						option3 = option2;
					}
					else
					{
						IOption option2 = new Option<string>(true, flag);
						option3 = option2;
					}
					IOption option4 = option3;
					IOption option5 = option ?? option4;
					option5.SetFromString(text);
					yield return option5;
				}
			}
		}

		public static OptionSet LoadConfigFile(string path)
		{
			return FromString(File.ReadAllLines(path));
		}

		public object Clone()
		{
			return FromString(GetOptionFlags());
		}

		public void AddCustomOption<T>(string optionString, T value)
		{
			Option<T> option = new Option<T>(true, optionString);
			option.Value = value;
			CustomOptio