Decompiled source of MuzikaGromche v1337.9001.67

Ratijas.MuzikaGromche.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using Ratijas.MuzikaGromche.NetcodePatcher;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("Ratijas.MuzikaGromche")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Add some content to your inverse teleporter experience on Titan!")]
[assembly: AssemblyFileVersion("1337.9001.67.0")]
[assembly: AssemblyInformationalVersion("1337.9001.67+835d69d2d02300bdae84abf854dffdaaf90cfc0d")]
[assembly: AssemblyProduct("Muzika Gromche")]
[assembly: AssemblyTitle("Ratijas.MuzikaGromche")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://git.vilunov.me/ratijas/muzika-gromche")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1337.9001.67.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MuzikaGromche
{
	internal static class AudioClipsCacheManager
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass5_0
		{
			public IAudioTrack track;

			public List<UnityWebRequest> requests;

			internal void <LoadAudioTrackCoroutine>b__0(AudioClip clip)
			{
				track.LoadedIntro = clip;
			}

			internal void <LoadAudioTrackCoroutine>b__1(AudioClip clip)
			{
				track.LoadedLoop = clip;
			}

			internal bool <LoadAudioTrackCoroutine>b__2()
			{
				return requests.All((UnityWebRequest request) => request.isDone);
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass5_1
		{
			public UnityWebRequest request;

			internal bool <LoadAudioTrackCoroutine>b__7(KeyValuePair<string, (UnityWebRequest Request, List<Action<AudioClip>> Setters)> kv)
			{
				return kv.Value.Request == request;
			}
		}

		[CompilerGenerated]
		private sealed class <LoadAudioTrackCoroutine>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IAudioTrack track;

			private <>c__DisplayClass5_0 <>8__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadAudioTrackCoroutine>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass5_0();
					<>8__1.track = track;
					<>8__1.requests = new List<UnityWebRequest>();
					<>8__1.requests.Capacity = 2;
					LoadAudioClip(<>8__1.requests, <>8__1.track.AudioType, <>8__1.track.FileNameIntro, delegate(AudioClip clip)
					{
						<>8__1.track.LoadedIntro = clip;
					});
					LoadAudioClip(<>8__1.requests, <>8__1.track.AudioType, <>8__1.track.FileNameLoop, delegate(AudioClip clip)
					{
						<>8__1.track.LoadedLoop = clip;
					});
					<>2__current = (object)new WaitUntil((Func<bool>)(() => <>8__1.requests.All((UnityWebRequest request) => request.isDone)));
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					if (<>8__1.requests.All((UnityWebRequest request) => (int)request.result == 1))
					{
						foreach (UnityWebRequest request in <>8__1.requests)
						{
							foreach (KeyValuePair<string, (UnityWebRequest, List<Action<AudioClip>>)> request2 in Requests)
							{
								request2.Deconstruct(out var key, out var value);
								(UnityWebRequest, List<Action<AudioClip>>) tuple2 = value;
								string text = key;
								var (val, list) = tuple2;
								if (request != val)
								{
									continue;
								}
								Plugin.Log.LogDebug((object)("Audio clip loaded successfully: " + text));
								AudioClip content = DownloadHandlerAudioClip.GetContent(request);
								Cache[text] = content;
								foreach (Action<AudioClip> item in list)
								{
									item(content);
								}
							}
						}
					}
					else
					{
						IEnumerable<string> values = from tuple in Requests.Values
							where (int)tuple.Request.result != 1
							select tuple.Request.GetUrl();
						Plugin.Log.LogError((object)("Could not load audio file " + string.Join(", ", values)));
					}
					using (List<UnityWebRequest>.Enumerator enumerator4 = <>8__1.requests.GetEnumerator())
					{
						while (enumerator4.MoveNext())
						{
							<>c__DisplayClass5_1 CS$<>8__locals0 = new <>c__DisplayClass5_1
							{
								request = enumerator4.Current
							};
							string[] array = (from kv in Requests
								where kv.Value.Request == CS$<>8__locals0.request
								select kv.Key).ToArray();
							string[] array2 = array;
							foreach (string key2 in array2)
							{
								if (Requests.TryGetValue(key2, out (UnityWebRequest, List<Action<AudioClip>>) value2) && value2.Item1 != null)
								{
									value2.Item1.Dispose();
								}
								Requests.Remove(key2);
							}
						}
					}
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly Dictionary<string, AudioClip> Cache = new Dictionary<string, AudioClip>();

		private static readonly Dictionary<string, (UnityWebRequest Request, List<Action<AudioClip>> Setters)> Requests = new Dictionary<string, (UnityWebRequest, List<Action<AudioClip>>)>();

		private static readonly string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		public static bool AllDone => Requests.Count == 0;

		public static void LoadAudioTrack(IAudioTrack track)
		{
			GlobalBehaviour.Instance.StartCoroutine(LoadAudioTrackCoroutine(track));
		}

		[IteratorStateMachine(typeof(<LoadAudioTrackCoroutine>d__5))]
		private static IEnumerator LoadAudioTrackCoroutine(IAudioTrack track)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadAudioTrackCoroutine>d__5(0)
			{
				track = track
			};
		}

		private static void LoadAudioClip(List<UnityWebRequest> requests, AudioType audioType, string fileName, Action<AudioClip> setter)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (Cache.TryGetValue(fileName, out AudioClip value))
			{
				Plugin.Log.LogDebug((object)("Found cached audio clip: " + fileName));
				setter(value);
				return;
			}
			if (Requests.TryGetValue(fileName, out (UnityWebRequest, List<Action<AudioClip>>) value2))
			{
				Plugin.Log.LogDebug((object)("Found existing in-flight request for audio clip: " + fileName));
				value2.Item2.Add(setter);
				return;
			}
			Plugin.Log.LogDebug((object)("Sending request to load audio clip: " + fileName));
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file://" + dir + "/" + fileName, audioType);
			audioClip.SendWebRequest();
			Requests[fileName] = (audioClip, new List<Action<AudioClip>>(1) { setter });
			requests.Add(audioClip);
		}

		public static void Clear()
		{
			Plugin.Log.LogDebug((object)$"Clearing {Cache.Count} cached audio clips and {Requests.Count} pending requests");
			string key;
			if (Cache.Count > 0)
			{
				IAudioTrack[] array = Plugin.Tracks.SelectMany((ISelectableTrack t) => t.GetTracks()).ToArray();
				foreach (KeyValuePair<string, AudioClip> item in Cache)
				{
					item.Deconstruct(out key, out var value);
					string text = key;
					AudioClip val = value;
					IAudioTrack[] array2 = array;
					foreach (IAudioTrack audioTrack in array2)
					{
						if (audioTrack.FileNameIntro == text)
						{
							audioTrack.LoadedIntro = null;
						}
						if (audioTrack.FileNameLoop == text)
						{
							audioTrack.LoadedLoop = null;
						}
					}
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
				Cache.Clear();
			}
			foreach (KeyValuePair<string, (UnityWebRequest, List<Action<AudioClip>>)> request in Requests)
			{
				request.Deconstruct(out key, out var value2);
				(UnityWebRequest, List<Action<AudioClip>>) tuple = value2;
				string text2 = key;
				var (val2, list) = tuple;
				if (val2 != null)
				{
					val2.Abort();
					val2.Dispose();
				}
			}
			Requests.Clear();
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal static class ClearAudioClipCachePatch
	{
		[HarmonyPatch("DespawnPropsAtEndOfRound")]
		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroy(RoundManager __instance)
		{
			AudioClipsCacheManager.Clear();
		}
	}
	internal static class Compatibility
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Register(BaseUnityPlugin plugin)
		{
			if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"))
			{
				RegisterLobbyCompatibility(plugin.Info.Metadata);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void RegisterLobbyCompatibility(BepInPlugin plugin)
		{
			PluginHelper.RegisterPlugin(plugin.GUID, plugin.Version, (CompatibilityLevel)2, (VersionStrictness)3);
		}
	}
	internal static class DeathScreenGameOverTextManager
	{
		[CompilerGenerated]
		private sealed class <SetTextAndClear>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string text;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SetTextAndClear>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					SetText(text);
					<>2__current = (object)new WaitForSeconds(5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					Clear();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const string GameOverTextVanilla = "[LIFE SUPPORT: OFFLINE]";

		public const string GameOverTextModdedDefault = "[ MUZIKA: GROMCHE ]";

		public static void Clear()
		{
			SetTextImpl("[LIFE SUPPORT: OFFLINE]");
		}

		public static void SetText(string? text)
		{
			SetTextImpl(text ?? "[ MUZIKA: GROMCHE ]");
		}

		[IteratorStateMachine(typeof(<SetTextAndClear>d__4))]
		public static IEnumerator SetTextAndClear(string? text)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SetTextAndClear>d__4(0)
			{
				text = text
			};
		}

		private static void SetTextImpl(string text)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("Systems/UI/Canvas/DeathScreen/GameOverText");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			RectTransform component2 = val.GetComponent<RectTransform>();
			if (!((Object)(object)component2 == (Object)null))
			{
				Vector2 sizeDelta = component2.sizeDelta;
				if (Mathf.Approximately(sizeDelta.x, 645.8f))
				{
					sizeDelta.x += 100f;
					component2.sizeDelta = sizeDelta;
				}
				((TMP_Text)component).text = text;
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal static class DeathScreenGameOverTextResetPatch
	{
		[HarmonyPatch("DespawnPropsAtEndOfRound")]
		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroy(RoundManager __instance)
		{
			DeathScreenGameOverTextManager.Clear();
		}
	}
	public static class DiscoBallManager
	{
		private readonly record struct TilePatch(string TileName, GameObject DiscoBallContainer)
		{
			public readonly string TileCloneName = TileName + "(Clone)";
		}

		[CompilerGenerated]
		private sealed class <FindDiscoBallAnimators>d__9 : IEnumerable<Animator>, IEnumerable, IEnumerator<Animator>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private Animator <>2__current;

			private int <>l__initialThreadId;

			private GameObject discoBall;

			public GameObject <>3__discoBall;

			private string[] <>7__wrap1;

			private int <>7__wrap2;

			Animator IEnumerator<Animator>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FindDiscoBallAnimators>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>7__wrap1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					goto IL_0087;
				}
				<>1__state = -1;
				<>7__wrap1 = AnimatorContainersNames;
				<>7__wrap2 = 0;
				goto IL_0095;
				IL_0087:
				<>7__wrap2++;
				goto IL_0095;
				IL_0095:
				if (<>7__wrap2 < <>7__wrap1.Length)
				{
					string text = <>7__wrap1[<>7__wrap2];
					Transform val = discoBall.transform.Find(text);
					if (!((Object)(object)val == (Object)null))
					{
						GameObject gameObject = ((Component)val).gameObject;
						Animator val2 = ((gameObject != null) ? gameObject.GetComponent<Animator>() : null);
						if (!((Object)(object)val2 == (Object)null))
						{
							<>2__current = val2;
							<>1__state = 1;
							return true;
						}
					}
					goto IL_0087;
				}
				<>7__wrap1 = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<Animator> IEnumerable<Animator>.GetEnumerator()
			{
				<FindDiscoBallAnimators>d__9 <FindDiscoBallAnimators>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<FindDiscoBallAnimators>d__ = this;
				}
				else
				{
					<FindDiscoBallAnimators>d__ = new <FindDiscoBallAnimators>d__9(0);
				}
				<FindDiscoBallAnimators>d__.discoBall = <>3__discoBall;
				return <FindDiscoBallAnimators>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<Animator>)this).GetEnumerator();
			}
		}

		private static TilePatch[] Patches = Array.Empty<TilePatch>();

		private static readonly List<GameObject> CachedDiscoBalls = new List<GameObject>();

		private static readonly List<Animator> CachedDiscoBallAnimators = new List<Animator>();

		private static readonly string[] AnimatorContainersNames = new string[6] { "DiscoBallProp/AnimContainer", "DiscoBallProp1/AnimContainer", "DiscoBallProp2/AnimContainer", "DiscoBallProp3/AnimContainer", "DiscoBallProp4/AnimContainer", "DiscoBallProp5/AnimContainer" };

		public static void Load()
		{
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "muzikagromche_discoball");
			AssetBundle assetBundle = AssetBundle.LoadFromFile(text) ?? throw new NullReferenceException("Failed to load bundle");
			(string, string)[] source = new(string, string)[6]
			{
				("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManor.prefab", "ManorStartRoomSmall"),
				("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManorOLD.prefab", "ManorStartRoom"),
				("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerFactory.prefab", "StartRoom"),
				("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerMineShaft.prefab", "MineshaftStartTile"),
				("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerLargeForkTileB.prefab", "LargeForkTileB"),
				("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerBirthdayRoomTile.prefab", "BirthdayRoomTile")
			};
			Patches = source.Select(((string PrefabPath, string TileName) d) => new TilePatch(d.TileName, HotFixPrefab(d.PrefabPath, assetBundle.LoadAsset<GameObject>(d.PrefabPath)))).ToArray();
		}

		private static GameObject HotFixPrefab(string PrefabPath, GameObject gameObject)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject2 = gameObject;
			if (PrefabPath == "Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerFactory.prefab")
			{
				RemoveGameObject("DiscoBallProp1");
				RemoveGameObject("DiscoBallProp2");
				Transform val = gameObject2.transform.Find("DiscoBallProp3");
				if ((Object)(object)val != (Object)null)
				{
					Vector3 position = val.position;
					position.y -= 5f;
					val.position = position;
				}
			}
			return gameObject2;
			void RemoveGameObject(string gameObjectPath)
			{
				Transform val2 = gameObject2.transform.Find(gameObjectPath);
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
			}
		}

		internal static void Patch(Tile tile)
		{
			Tile tile2 = tile;
			IEnumerable<TilePatch> enumerable = Patches.Where((TilePatch patch) => ((Object)((Component)tile2).gameObject).name == patch.TileCloneName);
			foreach (TilePatch item in enumerable)
			{
				Patch(tile2, item);
			}
		}

		private static void Patch(Tile tile, TilePatch patch)
		{
			GameObject val = Object.Instantiate<GameObject>(patch.DiscoBallContainer, ((Component)tile).transform);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			foreach (Animator item in FindDiscoBallAnimators(val))
			{
				CachedDiscoBallAnimators.Add(item);
			}
			CachedDiscoBalls.Add(val);
			val.SetActive(false);
			Plugin.Log.LogDebug((object)("DiscoBallManager Patched tile '" + ((Object)((Component)tile).gameObject).name + "'"));
		}

		[IteratorStateMachine(typeof(<FindDiscoBallAnimators>d__9))]
		private static IEnumerable<Animator> FindDiscoBallAnimators(GameObject discoBall)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FindDiscoBallAnimators>d__9(-2)
			{
				<>3__discoBall = discoBall
			};
		}

		public static void Toggle(bool on)
		{
			Plugin.Log.LogDebug((object)string.Format("{0} Toggle {1} {2} animators", "DiscoBallManager", on ? "ON" : "OFF", CachedDiscoBallAnimators.Count));
			foreach (GameObject cachedDiscoBall in CachedDiscoBalls)
			{
				cachedDiscoBall.SetActive(on);
			}
			foreach (Animator cachedDiscoBallAnimator in CachedDiscoBallAnimators)
			{
				if (cachedDiscoBallAnimator != null)
				{
					cachedDiscoBallAnimator.SetBool("on", on);
				}
			}
		}

		public static void Enable()
		{
			Toggle(on: true);
		}

		public static void Disable()
		{
			Toggle(on: false);
		}

		internal static void Clear()
		{
			Plugin.Log.LogDebug((object)string.Format("{0} Clearing {1} disco balls & {2} animators", "DiscoBallManager", CachedDiscoBalls.Count, CachedDiscoBallAnimators.Count));
			CachedDiscoBallAnimators.Clear();
			CachedDiscoBalls.Clear();
		}
	}
	[HarmonyPatch(typeof(Tile))]
	internal static class DiscoBallTilePatch
	{
		[HarmonyPatch("AddTriggerVolume")]
		[HarmonyPostfix]
		private static void OnAddTriggerVolume(Tile __instance)
		{
			DiscoBallManager.Patch(__instance);
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal static class DiscoBallDespawnPatch
	{
		[HarmonyPatch("DespawnPropsAtEndOfRound")]
		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroy(RoundManager __instance)
		{
			DiscoBallManager.Clear();
		}
	}
	internal static class GlobalBehaviour
	{
		private sealed class AdhocBehaviour : MonoBehaviour
		{
		}

		private static AdhocBehaviour? instance;

		public static MonoBehaviour Instance
		{
			get
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Expected O, but got Unknown
				if ((Object)(object)instance == (Object)null)
				{
					GameObject val = new GameObject("MuzikaGromche_GlobalBehaviour", new Type[1] { typeof(AdhocBehaviour) })
					{
						hideFlags = (HideFlags)61
					};
					Object.DontDestroyOnLoad((Object)(object)val);
					instance = val.GetComponent<AdhocBehaviour>();
				}
				return (MonoBehaviour)(object)instance;
			}
		}
	}
	[BepInPlugin("Ratijas.MuzikaGromche", "Muzika Gromche", "1337.9001.67")]
	[BepInDependency("ainavt.lc.lethalconfig", "1.4.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private static Harmony Harmony = null;

		internal static ManualLogSource Log = null;

		internal static Dictionary<Light, Color> InitialLightsColors = new Dictionary<Light, Color>();

		private static readonly string[] PwnLyricsVariants;

		private static readonly TimeSeries<float> DrunknessLoopOffsetTimeSeriesBeefLiver;

		private static readonly Palette PalettePickUpSticks;

		public static readonly ISelectableTrack[] Tracks;

		internal const float CompatModeAllowLongerTrack = 3f;

		internal const float CompatModeAllowShorterTrack = 3f;

		public const float AudioMaxDistance = 150f;

		internal static Config Config { get; private set; } = null;


		private static int GetCurrentSeed()
		{
			int result = 0;
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.dungeonGenerator != (Object)null)
			{
				result = instance.dungeonGenerator.Generator.ChosenSeed;
			}
			return result;
		}

		private static (ISelectableTrack[], Season?) GetTracksAndSeason()
		{
			DateTime today = DateTime.Today;
			Season? season = SeasonalContentManager.CurrentSeason(today);
			IEnumerable<ISelectableTrack> source = Tracks.Filter(season);
			if (MuzikaGromche.Config.SkipExplicitTracks.Value)
			{
				source = source.Where((ISelectableTrack track) => !track.IsExplicit);
			}
			ISelectableTrack[] item = source.ToArray();
			return (item, season);
		}

		public static ISelectableTrack ChooseTrack()
		{
			int currentSeed = GetCurrentSeed();
			(ISelectableTrack[], Season?) tracksAndSeason = GetTracksAndSeason();
			ISelectableTrack[] item = tracksAndSeason.Item1;
			Season? item2 = tracksAndSeason.Item2;
			int[] weights = item.Select((ISelectableTrack track) => track.Weight.Value).ToArray();
			RandomWeightedIndex randomWeightedIndex = new RandomWeightedIndex(weights);
			int randomWeightedIndex2 = randomWeightedIndex.GetRandomWeightedIndex(currentSeed);
			ISelectableTrack selectableTrack = item[randomWeightedIndex2];
			Log.LogInfo((object)string.Format("Seed is {0}, season is {1}, chosen track is \"{2}\", #{3} of {4}", currentSeed, item2?.Name ?? "<none>", selectableTrack.Name, randomWeightedIndex2, randomWeightedIndex));
			return item[randomWeightedIndex2];
		}

		public static IAudioTrack? ChooseTrackCompat(float vanillaPopUpTimer)
		{
			int currentSeed = GetCurrentSeed();
			(ISelectableTrack[], Season?) tracksAndSeason = GetTracksAndSeason();
			ISelectableTrack[] item = tracksAndSeason.Item1;
			Season? item2 = tracksAndSeason.Item2;
			float minTimer = vanillaPopUpTimer - 3f;
			float maxTimer = vanillaPopUpTimer + 3f;
			bool allWeightsAreZero = item.All((ISelectableTrack t) => t.Weight.Value == 0);
			ISelectableTrack[] array = item.Where((ISelectableTrack track) => WeightIsCompatible(track) && track.GetTracks().Any(TimerIsCompatible)).ToArray();
			if (array.Length == 0)
			{
				Log.LogWarning((object)string.Format("Seed is {0}, season is {1}, no compat tracks found for timer {2}", currentSeed, item2?.Name ?? "<none>", vanillaPopUpTimer));
				return null;
			}
			int[] weights = array.Select((ISelectableTrack track) => track.Weight.Value).ToArray();
			int randomWeightedIndex = new RandomWeightedIndex(weights).GetRandomWeightedIndex(currentSeed);
			ISelectableTrack selectableTrack = array[randomWeightedIndex];
			IAudioTrack[] array2 = selectableTrack.GetTracks().Where(TimerIsCompatible).ToArray();
			Random random = new Random(currentSeed + (int)(vanillaPopUpTimer * 1000f));
			int index = random.Next();
			IAudioTrack audioTrack = Mod.Index(array2, index);
			Log.LogInfo((object)string.Format("Seed is {0}, season is {1}, chosen compat track is \"{2}\" with timer: {3}, vanilla timer: {4}", currentSeed, item2?.Name ?? "<none>", audioTrack.Name, audioTrack.WindUpTimer, vanillaPopUpTimer));
			return audioTrack;
			bool TimerIsCompatible(IAudioTrack t)
			{
				if (minTimer <= t.WindUpTimer)
				{
					return t.WindUpTimer <= maxTimer;
				}
				return false;
			}
			bool WeightIsCompatible(ISelectableTrack t)
			{
				if (!allWeightsAreZero)
				{
					return t.Weight.Value > 0;
				}
				return true;
			}
		}

		public static IAudioTrack? FindTrackNamed(string name)
		{
			string name2 = name;
			return Tracks.SelectMany((ISelectableTrack track) => track.GetTracks()).FirstOrDefault((IAudioTrack track) => track.Name == name2);
		}

		public static bool LocalPlayerCanHearMusic(EnemyAI jester)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			AudioListener audioListener = StartOfRound.Instance.audioListener;
			if ((Object)(object)localPlayerController == (Object)null || (Object)(object)audioListener == (Object)null || !localPlayerController.isInsideFactory)
			{
				return false;
			}
			float num = Vector3.Distance(((Component)audioListener).transform.position, ((Component)jester).transform.position);
			return num <= 150f;
		}

		public static void DisplayLyrics(string text)
		{
			HUDManager.Instance.DisplayTip("[Lyrics]", text, false, false, "LC_Tip1");
			HUDManager.Instance.UIAudio.Stop();
		}

		private void Awake()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Array.Sort(Tracks.Select((ISelectableTrack track) => track.Name).ToArray(), Tracks);
			Config = new Config(((BaseUnityPlugin)this).Config);
			DiscoBallManager.Load();
			PoweredLightsAnimators.Load();
			Harmony = new Harmony("Muzika Gromche");
			Harmony.PatchAll(typeof(GameNetworkManagerPatch));
			Harmony.PatchAll(typeof(JesterPatch));
			Harmony.PatchAll(typeof(EnemyAIPatch));
			Harmony.PatchAll(typeof(PoweredLightsAnimatorsPatch));
			Harmony.PatchAll(typeof(AllPoweredLightsPatch));
			Harmony.PatchAll(typeof(DiscoBallTilePatch));
			Harmony.PatchAll(typeof(DiscoBallDespawnPatch));
			Harmony.PatchAll(typeof(SpawnRatePatch));
			Harmony.PatchAll(typeof(DeathScreenGameOverTextResetPatch));
			Harmony.PatchAll(typeof(ScreenFiltersManager.HUDManagerScreenFiltersPatch));
			Harmony.PatchAll(typeof(ClearAudioClipCachePatch));
			NetcodePatcher();
			Compatibility.Register((BaseUnityPlugin)(object)this);
		}

		private static void NetcodePatcher()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}

		static Plugin()
		{
			List<string> list = new List<string>();
			list.Add("");
			list.Add("");
			list.Add("");
			list.AddRange(from a in (from n in NetworkInterface.GetAllNetworkInterfaces()
					where n.OperationalStatus == OperationalStatus.Up
					select n).SelectMany((NetworkInterface n) => n.GetIPProperties().UnicastAddresses)
				where a.Address.AddressFamily == AddressFamily.InterNetwork
				select a.Address.ToString() into a
				select " Trying... " + a);
			PwnLyricsVariants = list.ToArray();
			DrunknessLoopOffsetTimeSeriesBeefLiver = new TimeSeries<float>(new float[13]
			{
				-0.5f, 0.5f, 8f, 15f, 16f, 24f, 29f, 30f, 36f, 37f,
				38f, 44f, 47.5f
			}, new float[13]
			{
				0f, 0.6f, 0f, 0f, 0.4f, 0f, 0f, 0.3f, 0f, 0f,
				0.3f, 0f, 0f
			});
			PalettePickUpSticks = Palette.Parse(new string[5] { "#FC933C", "#FC3C9D", "#EEA0A5", "#CA71FC", "#d01760" }).Use(delegate(Palette p)
			{
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				Palette palette6 = p * 6 + new Palette(p.Colors[0..2]);
				Palette palette7 = (p * 3 + new Palette((Color[])(object)new Color[1] { p.Colors[2] })).Stretch(2);
				return palette6 + palette7;
			});
			Tracks = new ISelectableTrack[28]
			{
				new SelectableAudioTrack
				{
					Name = "MuzikaGromche",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 46.3f,
					Bars = 16,
					BeatsOffset = 0f,
					FadeOutBeat = -3f,
					FadeOutDuration = 3f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.25f,
					ColorTransitionEasing = Easing.OutExpo,
					FlickerLightsTimeSeries = new float[3] { -5f, 29f, 61f },
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[9] { -2f, 0f, 1f, 3f, 30f, 32f, 33f, 35f, 62f }, new float[9] { 0f, 0.4f, 0.6f, 0f, 0f, 0.5f, 0.7f, 0f, 0f }),
					Palette = Palette.Parse(new string[6] { "#B300FF", "#FFF100", "#00FF51", "#474747", "#FF00B3", "#0070FF" }),
					Lyrics = new(float, string)[22]
					{
						(-68f, "Devchata pljashut pod spidami"),
						(-60f, "A ty stoish', kak vkopannyj"),
						(-52f, "Krossovkami lomajut pol"),
						(-44f, "A ty stoish', kak vkopannyj"),
						(-36f, "Ja-ja-ja znaju, chto ty hochesh',"),
						(-32f, "Ja-ja-ja znaju, chto ty hochesh',\nTy hochesh' tancevat'"),
						(-28f, "Nu-nu zhe, nu davaj zhe,"),
						(-24f, "Nu-nu zhe, nu davaj zhe,\nNu-nu zhe, nu davaj zhe"),
						(-20f, "Ja znaju, chto ty znaesh'\nJetot trek, gotov'sja podpevat'"),
						(-12f, "1) RAZ"),
						(-10f, "raz, DVA"),
						(-8f, "raz, 2wo,\nTRI"),
						(-6f, "ras, dva,\n7ri, 4ETYRE"),
						(-1f, "Muzyka Gromche\nGlaza zakryty >_<"),
						(6f, "This is NON-STOP,\nNoch'ju otkrytij"),
						(12f, "Delaj chto hochesh', ja zabyvajus'"),
						(22f, "This is NON-STOP,\nne prekrashhajas'"),
						(31f, "Muzyka Gromche\nGlaza zakryty -.-"),
						(38f, "This is NON-STOP,\nNoch'ju otkrytij"),
						(46f, "Budu s toboju,\nsamoj primernoju"),
						(54f, "Utro v okne\nyi my budem pervye"),
						(63f, "Muzyka Gromche\nGlaza zakryty >_<")
					}
				},
				new SelectableAudioTrack
				{
					Name = "VseVZale",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 38.28f,
					Bars = 16,
					LoopOffset = 0,
					BeatsOffset = 0.25f,
					FadeOutBeat = -3f,
					FadeOutDuration = 2.5f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.25f,
					ColorTransitionEasing = Easing.OutExpo,
					FlickerLightsTimeSeries = new float[3] { -5f, 29f, 59f },
					Palette = Palette.Parse(new string[6] { "#FF7F00", "#FFB600", "#FFED00", "#00D1FF", "#6696FB", "#704DF8" }).Use((Palette palette) => palette * 5 + new Palette(palette.Colors[0..2]) + (new Palette(palette.Colors[2..]) + palette * 2).Stretch(2)),
					Lyrics = new(float, string)[12]
					{
						(-30f, "VSE V ZALE\nDvigajtes' s nami"),
						(-24f, "Chtob sotrjasalis'\nSami my, steny i pol!"),
						(-14f, "Vse znaem - jeto examen na dom nam zadan"),
						(-4f, "HIP-HOP, HOUSE & ROCK-N-ROLL"),
						(2f, "VSE V ZALE\nDvigajtes' s nami"),
						(8f, "Chtob sotrjasalis'\nSami my, steny i pol!"),
						(18f, "Vse znaem - jeto examen na dom nam zadan"),
						(28f, "HIP-HOP, HOUSE & ROCK-N-ROLL"),
						(32f, "O-o-o-o! Zdes' startuet hip-hop party"),
						(44f, "Tolstyj paren', nam igraj!"),
						(48f, "O-o-o-o! Pesen i devchonok hvatit!"),
						(60f, "Everybody shake your body")
					}
				},
				new SelectableAudioTrack
				{
					Name = "DeployDestroy",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 40.68f,
					Bars = 8,
					LoopOffset = 32,
					BeatsOffset = 0.2f,
					FadeOutBeat = -38f,
					FadeOutDuration = 4f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.25f,
					ColorTransitionEasing = Easing.OutExpo,
					FlickerLightsTimeSeries = new float[7] { -101f, -93f, -77f, -61f, -37f, -5f, 27f },
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[6] { -48f, -46f, -42f, 16f, 19f, 23f }, new float[6] { 0f, 0.7f, 0f, 0f, 0.3f, 0f }),
					Palette = Palette.Parse(new string[5] { "#217F87", "#BAFF00", "#73BE25", "#78AB4E", "#FFFF00" }),
					Lyrics = new(float, string)[24]
					{
						(-111f, "Deploy Destroy, porjadok eto otstoj"),
						(-103f, "Krushi, lomaj, trjasi bashkoju pustoj"),
						(-95f, "Dopej, razbej i novuju otkryvaj"),
						(-87f, "Davaj-davaj!"),
						(-79f, "Chestnoe slovo ja nevinoven"),
						(-75f, "Ja ne pomnju, otkuda stol'ko krovi"),
						(-71f, "Na moih ladonjah\nyi moej odezhde"),
						(-67f, "Ja nikogda nikogo\nne bil prezhde"),
						(-63f, "Ja nikogda nichego\nne pil prezhde"),
						(-59f, "Byl tih, spokoen,\nso vsemi vezhliv"),
						(-55f, "Vsegda tol'ko v urnu\nbrosal musor"),
						(-51f, "Obhodil storonoj shumnye tusy"),
						(-47f, "Zapreshhjonnyh veshhestv nikakih ne juzal"),
						(-43f, "Byl polozhitel'nej samogo pljusa"),
						(-39f, "A potom kak-to raz\njetu pesnju uslyshal"),
						(-35f, "I vsjo proshhaj, moja krysha"),
						(-31f, "Deploy Destroy, porjadok eto otstoj"),
						(-23f, "Krushi, lomaj, trjasi bashkoju pustoj"),
						(-15f, "Dopej, razbej i novuju otkryvaj"),
						(-7f, "Davaj-davaj!"),
						(1f, "Deploy Destroy, porjadok eto otstoj"),
						(9f, "Krushi, lomaj, trjasi bashkoju pustoj"),
						(17f, "Dopej, razbej i novuju otkryvaj"),
						(25f, "Davaj-davaj!")
					}
				},
				new SelectableAudioTrack
				{
					Name = "MoyaZhittya",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 34.53f,
					Bars = 8,
					LoopOffset = 32,
					BeatsOffset = 0f,
					FadeOutBeat = -35f,
					FadeOutDuration = 3.3f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.5f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[6] { "#A8C480", "#3ABBBE", "#6E9855", "#4c6846", "#748084", "#058099" }),
					FlickerLightsTimeSeries = new float[14]
					{
						-100.5f, -99.5f, -92.5f, -91.5f, -76.5f, -75.5f, -60.5f, -59.5f, -37f, -36f,
						-4.5f, -3.5f, 27.5f, 28.5f
					},
					Lyrics = new(float, string)[28]
					{
						(-84f, "This ain't a song for the broken-hearted"),
						(-68f, "No silent prayer for the faith-departed"),
						(-52f, "I ain't gonna be"),
						(-48f, "I ain't gonna be\njust a face in the crowd"),
						(-45f, "YOU'RE"),
						(-44f, "you're GONNA"),
						(-43.5f, "you're gonna HEAR"),
						(-43f, "you're gonna hear\nMY"),
						(-42f, "you're gonna hear\nmy VOICE"),
						(-41f, "WHEN I"),
						(-40f, "When I SHOUT IT"),
						(-39f, "When I shout it\nOUT LOUD"),
						(-34f, "IT'S MY"),
						(-32f, "IT'S MY\nLIIIIIFE"),
						(-28f, "And it's now or never"),
						(-22f, "I ain't gonna"),
						(-20f, "I ain't gonna\nlive forever"),
						(-14f, "I just want to live"),
						(-10f, "I just want to live\nwhile I'm alive"),
						(-2f, "IT'S MY"),
						(0f, "IT'S MY\nLIIIIIFE"),
						(2f, "My heart is like"),
						(4f, "My heart is like\nan open highway"),
						(10f, "Like Frankie said,"),
						(12f, "Like Frankie said,\n\"I did it my way\""),
						(18f, "I just want to live"),
						(22f, "I just want to live\nwhile I'm alive"),
						(30f, "IT'S MY")
					},
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[7] { -33f, -31f, 24f, -1f, 1f, 8f, 31f }, new float[7] { 0f, 0.7f, 0f, 0f, 0.7f, 0f, 0f }),
					GameOverText = "[LIFE IS: NOW OR NEVER]"
				},
				new SelectableAudioTrack
				{
					Name = "Gorgorod",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 43.2f,
					Bars = 6,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.25f,
					ColorTransitionEasing = Easing.InExpo,
					Palette = Palette.Parse(new string[8] { "#42367E", "#FF9400", "#932A04", "#FF9400", "#932A04", "#42367E", "#FF9400", "#932A04" }),
					LoopOffset = 0,
					FadeOutBeat = -2f,
					FadeOutDuration = 2f,
					FlickerLightsTimeSeries = new float[1] { 20f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableAudioTrack
				{
					Name = "Durochka",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 37f,
					Bars = 10,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.3f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[8] { "#5986FE", "#FEFEDC", "#FF4FDF", "#FEFEDC", "#FFAA23", "#FEFEDC", "#F95A5A", "#FEFEDC" }),
					LoopOffset = 0,
					FadeOutBeat = -7f,
					FadeOutDuration = 7f,
					FlickerLightsTimeSeries = new float[1] { -9f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableAudioTrack
				{
					Name = "ZmeiGorynich",
					AudioType = (AudioType)14,
					Language = Language.KOREAN,
					WindUpTimer = 46.13f,
					Bars = 8,
					BeatsOffset = 0.1f,
					ColorTransitionIn = 0.4f,
					ColorTransitionOut = 0.4f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[6] { "#4C8AC5", "#AF326A", "#0B1666", "#AFD2FC", "#C55297", "#540070" }),
					LoopOffset = 0,
					FadeOutBeat = -4f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[2] { -5f, 31f },
					Lyrics = Array.Empty<(float, string)>(),
					GameOverText = "[MUZIKA: K-POP GROMCHE]"
				},
				new SelectableAudioTrack
				{
					Name = "GodMode",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 40.38f,
					Bars = 16,
					BeatsOffset = 0.1f,
					ColorTransitionIn = 0.5f,
					ColorTransitionOut = 0.5f,
					ColorTransitionEasing = Easing.OutCubic,
					Palette = Palette.Parse(new string[8] { "#FBDBDB", "#4B81FF", "#564242", "#C90AE2", "#FBDBDB", "#61CBE3", "#564242", "#ED3131" }),
					LoopOffset = 0,
					FadeOutBeat = -4f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[1] { -5f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[4] { -0.5f, 0f, 8f, 63.5f }, new float[4] { 0f, 0.7f, 0f, 0f }),
					GameOverText = "[COULD'VE BEEN: IMMORTAL]"
				},
				new SelectableAudioTrack
				{
					Name = "RiseAndShine",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 59.87f,
					Bars = 16,
					BeatsOffset = 0.1f,
					ColorTransitionIn = 0.5f,
					ColorTransitionOut = 0.5f,
					ColorTransitionEasing = Easing.OutCubic,
					Palette = Palette.Parse(new string[8] { "#FC6F3C", "#3CB0FC", "#FCD489", "#564242", "#FC6F3C", "#3CB0FC", "#63E98C", "#866868" }),
					LoopOffset = 0,
					FadeOutBeat = -4.5f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[3] { -5.5f, 31f, 63.9f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[4] { -0.5f, 0f, 8f, 63.5f }, new float[4] { 0f, 0.7f, 0f, 0f }),
					GameOverText = "[ HEY, YOUNG BLOOD ]"
				},
				new SelectableAudioTrack
				{
					Name = "Song2",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 38.63f,
					Beats = 34,
					BeatsOffset = 0.1f,
					ColorTransitionIn = 0.3f,
					ColorTransitionOut = 0.3f,
					ColorTransitionEasing = Easing.InCubic,
					Palette = Palette.Parse(new string[8] { "#FFD3E3", "#78A0FF", "#FFD3E3", "#74A392", "#FFD3E3", "#E4B082", "#FFD3E3", "#E277AA" }),
					LoopOffset = 0,
					FadeOutBeat = -2f,
					FadeOutDuration = 2f,
					FlickerLightsTimeSeries = new float[1] { 2.5f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableAudioTrack
				{
					Name = "Peretasovka",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 39.68f,
					Bars = 8,
					BeatsOffset = 0.3f,
					ColorTransitionIn = 0.4f,
					ColorTransitionOut = 0.4f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[8] { "#65C7FA", "#FCEB3C", "#89FC8F", "#FEE9E9", "#FC3C9D", "#FCEB3C", "#89FC8F", "#FC3C9D" }),
					LoopOffset = 0,
					FadeOutBeat = -6f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[2] { -8f, 31f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableAudioTrack
				{
					Name = "Yalgaar",
					AudioType = (AudioType)14,
					Language = Language.HINDI,
					WindUpTimer = 52.17f,
					Bars = 8,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.1f,
					ColorTransitionOut = 0.35f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[8] { "#C0402D", "#906F0B", "#DC8044", "#70190A", "#929FAF", "#4248A2", "#AE2727", "#2D2D42" }),
					LoopOffset = 0,
					FadeOutBeat = -4f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[1] { -5f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableAudioTrack
				{
					Name = "Chereshnya",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 45.48f,
					Bars = 16,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.3f,
					ColorTransitionOut = 0.35f,
					ColorTransitionEasing = Easing.InOutCubic,
					Palette = Palette.Parse(new string[16]
					{
						"#A01471", "#CB2243", "#4CAF50", "#F01D7A", "#AF005A", "#EF355F", "#FFD85D", "#FF66B2", "#A01471", "#4CAF50",
						"#CB2243", "#F01D7A", "#AF005A", "#FFD85D", "#EF355F", "#FF66B2"
					}),
					LoopOffset = 0,
					FadeOutBeat = -4f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[5] { -5f, 27f, 29f, 59f, 61f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableAudioTrack
				{
					Name = "PWNED",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					IsExplicit = true,
					WindUpTimer = 39.73f,
					Bars = 32,
					BeatsOffset = -0.2f,
					ColorTransitionIn = 0.5f,
					ColorTransitionOut = 0.3f,
					ColorTransitionEasing = Easing.InExpo,
					Palette = Palette.Parse(new string[8] { "#9E9E9E", "#383838", "#5E5E5E", "#2E2E2E", "#666666", "#4B4B4B", "#8E8E8E", "#1D1D1D" }).Use(delegate(Palette gray8)
					{
						Palette palette2 = Palette.Parse(new string[4] { "#FFFFFF", "#0032A0", "#DA291C", "#000000" });
						Palette palette3 = new Palette(gray8.Colors[0..6]);
						Palette palette4 = palette2 + (gray8 + palette3).Stretch(2);
						Palette palette5 = gray8.Stretch(4);
						return palette4 * 2 + palette5 * 2;
					}),
					LoopOffset = 0,
					FadeOutBeat = -8f,
					FadeOutDuration = 6f,
					FlickerLightsTimeSeries = new float[4] { -136f, -72f, -12f, 88f },
					Lyrics = new(float, string)[44]
					{
						(-190f, "These Russian hackers have been"),
						(-184f, "in these US governments\nsince March"),
						(-172f, "and it is an extraordinary invasion of our cyberspace"),
						(-152f, "Russian hackers got access to sensitive"),
						(-142f, "parts of the White House email system..."),
						(-134f, "[They began to recognize...]"),
						(-126f, "<Russian hackers/>"),
						(-118f, "<Russian hackers/>\n X__X"),
						(-110f, "Gonna crack your"),
						(-102f, "Gonna crack your\nStrongest pa$$words%123"),
						(-94f, "You popped online"),
						(-86f, "You popped online\nTo look for sneakers"),
						(-78f, "My hand just popped"),
						(-70f, "My hand just popped\nRight in your knickers >_< "),
						(-62f, "Keystrokes like Uzi"),
						(-54f, "Keystrokes like Uzi\nWill make you go all goosey"),
						(-46f, "Kicking down your backdoor"),
						(-38f, "Kicking down your backdoor\nCount down before you lose it"),
						(-30f, "Keystrokes like Uzi"),
						(-22f, "Keystrokes like Uzi\nWill make you go all goosey"),
						(-14f, "Kicking down your backdoor"),
						(-6f, "Kicking down your backdoor\nCount down before you lose it"),
						(0f, "C:\\> $Ru55ian hack3rs"),
						(4f, "C:\\> $Ru55ian hack3rs\n O__o"),
						(8f, "Infamous White House attackers"),
						(16f, "Stealing your cookies\nto this beat"),
						(24f, "Counting crypto to\nembarrass Wall Street"),
						(32f, "Russi?n ^hackers\tЯushan h@ckers###"),
						(34f, "\tЯushan h@ckers###\n   X_X"),
						(36f, "Russi?n ^hackers\n--.--\tЯushan h@ckers###\n  X___X"),
						(38f, "\tЯushan h@ckers###\n X_____X"),
						(40f, "Infamous White House attackers"),
						(48f, "Stealing your cookies\nto this beat"),
						(56f, "Counting crypto to\nembarrass Wall Street"),
						(80f, "Instling min3r.exe\t\t\tresolving ur private IP\n/"),
						(82f, "Instling min3r.exe\n00% [8=D            ]\tHenllo ${username = \"" + Environment.UserName + "\"}\t\tresolving ur private IP\n-" + PwnLyricsVariants[^3]),
						(84f, "Instling min3r.exe\n34% [8====D         ]\t\t\tresolving ur private IP\n\\" + PwnLyricsVariants[^3]),
						(86f, "Instling min3r.exe\n69% [8=========D    ]\t\t\tresolving ur private IP\n|" + PwnLyricsVariants[^2]),
						(88f, "Instling min3r.exe\n95% [8============D ]\t\tWhere did you download\nthis < mod / dll > from?\tresolving ur private IP\n" + PwnLyricsVariants[^2] + "/"),
						(90f, "Instling min3r.exe\n99% [8=============D]\t\t\tresolving ur private IP\n-" + PwnLyricsVariants[^2]),
						(92f, "Encrpt1ng f!les.. \n99% [8=============D]\t\t\tresolving ur private IP\n\\" + PwnLyricsVariants[^1]),
						(94f, "Encrpt1ng f!les...\n100% enj0y \\o/\t\t\tresolving ur private IP\n|" + PwnLyricsVariants[^1]),
						(96f, "\t\t\tresolving ur private IP\n/" + PwnLyricsVariants[^1]),
						(98f, "\t\t\tresolving ur private IP\nP_WNED")
					},
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[7] { -128f, -127f, -116f, 68f, 72f, 88f, 98f }, new float[7] { 0f, 0.7f, 0f, 0f, 0.3f, 0.5f, 0f }),
					GameOverText = "[HACK3D BY: RUSSI4NS]"
				},
				new SelectableAudioTrack
				{
					Name = "Kach",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 47.3f,
					Bars = 12,
					BeatsOffset = 0.4f,
					ColorTransitionIn = 0.8f,
					ColorTransitionOut = 0.4f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[12]
					{
						"#7774DE", "#1EA59A", "#3BC457", "#3BC457", "#CA6935", "#A82615", "#A7AA43", "#A7AA43", "#4C2B81", "#2E802B",
						"#C952E7", "#C952E7"
					}),
					LoopOffset = 0,
					FadeOutBeat = -6f,
					FadeOutDuration = 6f,
					FlickerLightsTimeSeries = new float[6] { -120.5f, -105f, -89f, -8f, 44f, 45f },
					Lyrics = Array.Empty<(float, string)>(),
					GameOverText = "[DIDN'T PUMP IT: LOUDER]"
				},
				new SelectableTracksGroup
				{
					Name = "BeefLiver",
					Language = Language.ENGLISH,
					Tracks = new IAudioTrack[3]
					{
						new CoreAudioTrack
						{
							Name = "BeefLiver1",
							FileNameLoop = "BeefLiverLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 39.35f,
							Bars = 12,
							BeatsOffset = 0.2f,
							ColorTransitionIn = 0.4f,
							ColorTransitionOut = 0.4f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[8] { "#FFEBEB", "#FFEBEB", "#445782", "#EBA602", "#5EEBB9", "#8EE3DC", "#A23045", "#262222" }),
							LoopOffset = 0,
							FadeOutBeat = -3f,
							FadeOutDuration = 3f,
							FlickerLightsTimeSeries = new float[4] { -48f, -40f, -4.5f, 44f },
							DrunknessLoopOffsetTimeSeries = DrunknessLoopOffsetTimeSeriesBeefLiver,
							Lyrics = new(float, string)[13]
							{
								(-66f, "First things first"),
								(-62f, "First things first,\nI'ma say all the words\ninside my head"),
								(-57f, "I'm fired up and tired of"),
								(-52f, "the way that things have been,\noh-ooh"),
								(-44f, "(x2)\nThe way that things have been,\noh-ooooh"),
								(-34f, "I was broken from a young age, taking my sulkin' to the masses"),
								(-27f, "Writing my poems for the few"),
								(-23f, "that look at me, took to me,\nshook at me, feelin' me"),
								(-19f, "Singing from heartache from the pain"),
								(-15f, "Singing from heartache from the pain,\ntaking my message from the veins"),
								(-11f, "Speaking my lesson from the brain"),
								(-8f, "Speaking my lesson from the brain,\nseeing the beauty through the"),
								(-0.1f, "PAIN!")
							}
						},
						new CoreAudioTrack
						{
							Name = "BeefLiver3",
							FileNameLoop = "BeefLiverLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 39.35f,
							Bars = 12,
							BeatsOffset = 0.2f,
							ColorTransitionIn = 0.4f,
							ColorTransitionOut = 0.4f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[8] { "#FFEBEB", "#FFEBEB", "#445782", "#EBA602", "#5EEBB9", "#8EE3DC", "#A23045", "#262222" }),
							LoopOffset = 0,
							FadeOutBeat = -3f,
							FadeOutDuration = 3f,
							FlickerLightsTimeSeries = new float[4] { -48f, -40f, -4.5f, 44f },
							DrunknessLoopOffsetTimeSeries = DrunknessLoopOffsetTimeSeriesBeefLiver,
							Lyrics = new(float, string)[13]
							{
								(-66f, "Third things third"),
								(-62f, "Third things third,\nsend a prayer to the ones up above"),
								(-57f, "All the hate that you've heard has turned"),
								(-52f, "your spirit to a dove,\noh-ooh"),
								(-44f, "(x2)\nYour spirit up above,\noh-ooooh"),
								(-34f, "I was chokin' in the crowd, building my rain up in the cloud"),
								(-27f, "Falling like ashes to the ground"),
								(-23f, "hoping my feelings, they would drown"),
								(-19f, "But they never did, ever lived, ebbin' and flowin'"),
								(-15f, "Inhibited, limited 'til it broke open"),
								(-11f, "Inhibited, limited 'til it broke open and rained down"),
								(-8f, "It rained down like"),
								(-0.1f, "PAIN!")
							}
						},
						new CoreAudioTrack
						{
							Name = "BeefLiver4",
							AudioType = (AudioType)14,
							WindUpTimer = 31.68f,
							Bars = 12,
							BeatsOffset = 0.2f,
							ColorTransitionIn = 0.4f,
							ColorTransitionOut = 0.4f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[8] { "#FFEBEB", "#FFEBEB", "#445782", "#EBA602", "#5EEBB9", "#8EE3DC", "#A23045", "#262222" }),
							LoopOffset = 0,
							FadeOutBeat = -3f,
							FadeOutDuration = 3f,
							FlickerLightsTimeSeries = new float[4] { -32f, -24f, -4.5f, 44f },
							DrunknessLoopOffsetTimeSeries = DrunknessLoopOffsetTimeSeriesBeefLiver,
							Lyrics = new(float, string)[10]
							{
								(-50f, "Last things last"),
								(-46f, "Last things last,\nby the grace\nof the fire and the flames"),
								(-41f, "You're the face of the future"),
								(-36f, "the blood in my veins, oh-ooh"),
								(-28f, "(x2)\nThe blood in my veins, oh-ooooh"),
								(-19f, "But they never did, ever lived, ebbin' and flowin'"),
								(-15f, "Inhibited, limited 'til it broke open"),
								(-11f, "Inhibited, limited 'til it broke open and rained down"),
								(-8f, "It rained down like"),
								(-0.1f, "PAIN!")
							}
						}
					}
				},
				new SelectableTracksGroup
				{
					Name = "Beha",
					Language = Language.RUSSIAN,
					IsExplicit = true,
					Tracks = new IAudioTrack[3]
					{
						new CoreAudioTrack
						{
							Name = "Beha1",
							FileNameLoop = "BehaLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 35.23f,
							Beats = 34,
							BeatsOffset = 0f,
							ColorTransitionIn = 0.1f,
							ColorTransitionOut = 0.6f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[6] { "#9554F9", "#3769FD", "#E43B65", "#59CFEA", "#7F3FEE", "#C831FE" }),
							LoopOffset = 0,
							FadeOutBeat = -4f,
							FadeOutDuration = 3.9f,
							FlickerLightsTimeSeries = new float[2] { -6f, 16.5f },
							Lyrics = Array.Empty<(float, string)>()
						},
						new CoreAudioTrack
						{
							Name = "Beha2",
							FileNameLoop = "BehaLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 38.16f,
							Beats = 34,
							BeatsOffset = 0f,
							ColorTransitionIn = 0.1f,
							ColorTransitionOut = 0.6f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[6] { "#9554F9", "#3769FD", "#E43B65", "#59CFEA", "#7F3FEE", "#C831FE" }),
							LoopOffset = 0,
							FadeOutBeat = -4f,
							FadeOutDuration = 3.9f,
							FlickerLightsTimeSeries = new float[2] { -6f, 16.5f },
							Lyrics = Array.Empty<(float, string)>()
						},
						new CoreAudioTrack
						{
							Name = "Beha3",
							FileNameLoop = "BehaLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 35.21f,
							Beats = 34,
							BeatsOffset = 0f,
							ColorTransitionIn = 0.1f,
							ColorTransitionOut = 0.6f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[6] { "#9554F9", "#3769FD", "#E43B65", "#59CFEA", "#7F3FEE", "#C831FE" }),
							LoopOffset = 0,
							FadeOutBeat = -4f,
							FadeOutDuration = 3.9f,
							FlickerLightsTimeSeries = new float[2] { -6f, 16.5f },
							Lyrics = Array.Empty<(float, string)>()
						}
					}
				},
				new SelectableAudioTrack
				{
					Name = "OnePartiyaUdar",
					AudioType = (AudioType)14,
					Language = Language.JAPANESE,
					WindUpTimer = 41.27f,
					Bars = 12,
					BeatsOffset = 0.3f,
					ColorTransitionIn = 0.6f,
					ColorTransitionOut = 0.15f,
					ColorTransitionEasing = Easing.InOutExpo,
					Palette = Palette.Parse(new string[6] { "#9C3C37", "#E9BF5C", "#B5E3EA", "#662422", "#EBC3A8", "#AA8238" }),
					LoopOffset = 0,
					FadeOutBeat = -8f,
					FadeOutDuration = 6f,
					FlickerLightsTimeSeries = new float[3] { -68.5f, -16.5f, 30.5f },
					Lyrics = Array.Empty<(float, string)>()
				},
				new SelectableTracksGroup
				{
					Name = "AttentionPls",
					Language = Language.RUSSIAN,
					IsExplicit = true,
					Tracks = new IAudioTrack[2]
					{
						new CoreAudioTrack
						{
							Name = "AttentionPls1",
							FileNameLoop = "AttentionPlsLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 39.19f,
							Bars = 8,
							BeatsOffset = 0.3f,
							ColorTransitionIn = 0.4f,
							ColorTransitionOut = 0.4f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[8] { "#FCEB3C", "#FC3C9D", "#65C7FA", "#89FC8F", "#FEE9E9", "#FCEB3C", "#89FC8F", "#FC3C9D" }),
							LoopOffset = 0,
							FadeOutBeat = -6f,
							FadeOutDuration = 5f,
							FlickerLightsTimeSeries = new float[2] { -8f, 31f },
							Lyrics = Array.Empty<(float, string)>(),
							DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 7f, 12f, 15f }, new float[3] { 0f, 0.9f, 0f }),
							CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 23f, 28f, 31f }, new float[3] { 0f, 0.4f, 0f })
						},
						new CoreAudioTrack
						{
							Name = "AttentionPls2",
							FileNameLoop = "AttentionPlsLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 39.19f,
							Bars = 8,
							BeatsOffset = 0.3f,
							ColorTransitionIn = 0.4f,
							ColorTransitionOut = 0.4f,
							ColorTransitionEasing = Easing.OutExpo,
							Palette = Palette.Parse(new string[8] { "#FCEB3C", "#FC3C9D", "#65C7FA", "#89FC8F", "#FEE9E9", "#FCEB3C", "#89FC8F", "#FC3C9D" }),
							LoopOffset = 0,
							FadeOutBeat = -6f,
							FadeOutDuration = 5f,
							FlickerLightsTimeSeries = new float[2] { -8f, 31f },
							Lyrics = Array.Empty<(float, string)>(),
							DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 7f, 12f, 15f }, new float[3] { 0f, 0.9f, 0f }),
							CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 23f, 28f, 31f }, new float[3] { 0f, 0.4f, 0f })
						}
					}
				},
				new SelectableAudioTrack
				{
					Name = "BbIXODaHET",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					WindUpTimer = 40.85f,
					Bars = 8,
					BeatsOffset = 0.3f,
					ColorTransitionIn = 0.7f,
					ColorTransitionOut = 0.3f,
					ColorTransitionEasing = Easing.InOutCubic,
					Palette = Palette.Parse(new string[6] { "#E6D58F", "#612F7E", "#D9783F", "#C3411C", "#D3B742", "#549BDE" }),
					LoopOffset = 0,
					FadeOutBeat = -6f,
					FadeOutDuration = 6f,
					FlickerLightsTimeSeries = new float[3] { -32.5f, -16.5f, 30.5f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[4] { -1f, 2f, 7f, 31f }, new float[4] { 0f, 0.4f, 0f, 0f })
				},
				new SelectableAudioTrack
				{
					Name = "Whistle",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 41.27f,
					Bars = 12,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.5f,
					ColorTransitionOut = 0.2f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[6] { "#8DDEDD", "#98DE28", "#E8DB4B", "#F060A8", "#EEC263", "#725DEB" }),
					LoopOffset = 16,
					FadeOutBeat = -22f,
					FadeOutDuration = 6f,
					FlickerLightsTimeSeries = new float[2] { -20f, 12f },
					Lyrics = new(float, string)[20]
					{
						(-40f, "Can you blow my whistle, baby, whistle, baby?"),
						(-36f, "Can you blow my whistle, baby, whistle, baby? Let me know"),
						(-33.5f, "Girl, I'm gonna show you how to\ndo it"),
						(-30.5f, "Girl, I'm gonna show you how to\ndo it and we start real slow"),
						(-27f, "You just put your lips together"),
						(-24f, "You just put your lips together and you come real close"),
						(-21f, "Can you blow my whistle, baby, whistle, baby?"),
						(-17f, "HERE WE GO"),
						(10f, "Yeah, baby, make that whistle"),
						(12f, "Yeah, baby, make that whistle\nblow oh oh oh"),
						(15f, "Can you blow my whistle, baby, whistle, baby?"),
						(20f, "Can you blow my whistle, baby, whistle, baby? Let me know"),
						(23f, "Girl, I'm gonna show you how to\ndo it"),
						(28f, "Girl, I'm gonna show you how to\ndo it and we start real slow"),
						(32f, "You just put your lips together"),
						(36f, "You just put your lips together and you come real close"),
						(39f, "Can you blow my whistle, baby, whistle, baby?"),
						(46f, "HERE"),
						(47f, "Here WE"),
						(48f, "Here we GO")
					},
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[8] { -16f, -15.25f, -12f, 9f, 15f, 16f, 18f, 21f }, new float[8] { 0f, 0.7f, 0f, 0f, 0.4f, 0.7f, 0.4f, 0f })
				},
				new SelectableAudioTrack
				{
					Name = "ReelGoon",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 45.15f,
					Bars = 16,
					BeatsOffset = -0.35f,
					ColorTransitionIn = 0.1f,
					ColorTransitionOut = 0.35f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[8] { "#DE1C31", "#F7E26B", "#3D3D3D", "#FBB040", "#ED4E4A", "#F0BD37", "#E41E2E", "#2E2D2B" }),
					LoopOffset = 0,
					FadeOutBeat = -2f,
					FadeOutDuration = 2f,
					FlickerLightsTimeSeries = new float[2] { -41f, 61f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[5] { -0.5f, -0.05f, 6f, 60f, 61f }, new float[5] { 0f, 0.5f, 0f, 0f, 0.5f }),
					GameOverText = "[LIFE SUPPORT: REAL GONE]"
				},
				new SelectableAudioTrack
				{
					Name = "HighLow",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 37.12f,
					Bars = 12,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.75f,
					ColorTransitionOut = 0.25f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[8] { "#2e2e28", "#dfa24d", "#2e2e28", "#dfa24d", "#2e2e28", "#dfa24d", "#2e2e28", "#dfa24d" }),
					LoopOffset = 0,
					FadeOutBeat = -1.5f,
					FadeOutDuration = 1.5f,
					FlickerLightsTimeSeries = new float[2] { -33f, 39f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { -2f, -1f, 6f }, new float[3] { 0f, 0.5f, 0f }),
					CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { -2f, -1f, 6f }, new float[3] { 0f, 0.5f, 0f }),
					GameOverText = "[LIFE SUPORT: NIRVANA]"
				},
				new SelectableAudioTrack
				{
					Name = "IkWilJe",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					Season = Season.NewYear,
					WindUpTimer = 43.03f,
					Beats = 54,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.01f,
					ColorTransitionOut = 0.99f,
					ColorTransitionEasing = Easing.OutExpo,
					Palette = Palette.Parse(new string[6] { "#0B6623", "#FF2D2D", "#FFD700", "#00BFFF", "#9400D3", "#00FF7F" }),
					LoopOffset = 0,
					FadeOutBeat = -14f,
					FadeOutDuration = 12f,
					FlickerLightsTimeSeries = new float[1] { 31.45f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 0f, 0.25f, 6f }, new float[3] { 0f, 0.5f, 0f }),
					GameOverText = "[NEXT YEAR -- DEFINITELY]"
				},
				new SelectableAudioTrack
				{
					Name = "Paarden",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					Season = Season.NewYear,
					WindUpTimer = 36.12f,
					Bars = 8,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.4f,
					ColorTransitionEasing = Easing.OutCubic,
					Palette = Palette.Parse(new string[6] { "#F0FBFF", "#9ED9FF", "#0B95FF", "#66C7FF", "#CAE8FF", "#3BB6FF" }),
					LoopOffset = 0,
					FadeOutBeat = -4f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[1] { 31.5f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 0f, 0.25f, 6f }, new float[3] { 0f, 0.5f, 0f }),
					GameOverText = "[NEXT YEAR -- DEFINITELY]"
				},
				new SelectableAudioTrack
				{
					Name = "DiscoKapot",
					AudioType = (AudioType)14,
					Language = Language.RUSSIAN,
					Season = Season.NewYear,
					WindUpTimer = 30.3f,
					Bars = 8,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.25f,
					ColorTransitionOut = 0.6f,
					ColorTransitionEasing = Easing.InOutExpo,
					Palette = Palette.Parse(new string[6] { "#0B6623", "#FF2D2D", "#FFD700", "#00BFFF", "#9400D3", "#00FF7F" }),
					LoopOffset = 0,
					FadeOutBeat = -4f,
					FadeOutDuration = 4f,
					FlickerLightsTimeSeries = new float[5] { -32f, -24f, -16f, 16f, 32f },
					Lyrics = Array.Empty<(float, string)>(),
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[3] { 0f, 0.25f, 6f }, new float[3] { 0f, 0.5f, 0f }),
					GameOverText = "[NEXT YEAR -- DEFINITELY]"
				},
				new SelectableTracksGroup
				{
					Name = "PickUpSticks",
					Language = Language.ENGLISH,
					Tracks = new IAudioTrack[2]
					{
						new CoreAudioTrack
						{
							Name = "PickUpSticks1",
							FileNameLoop = "PickUpSticksLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 38.5f,
							Bars = 16,
							BeatsOffset = 0.2f,
							ColorTransitionIn = 0.6f,
							ColorTransitionOut = 0.3f,
							ColorTransitionEasing = Easing.InOutCubic,
							Palette = PalettePickUpSticks,
							LoopOffset = 0,
							FadeOutBeat = -2f,
							FadeOutDuration = 2f,
							FlickerLightsTimeSeries = new float[3] { -36f, -4f, 32f },
							Lyrics = Array.Empty<(float, string)>(),
							DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[6] { 0f, 0.5f, 3f, 32f, 34f, 40f }, new float[6] { 0f, 0.5f, 0f, 0f, 0.3f, 0f }),
							CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[6] { 23f, 28f, 31f, 34f, 38f, 52f }, new float[6] { 0f, 0.6f, 0f, 0f, 0.7f, 0f }),
							GameOverText = "[LOVE SUPPORT: OFFLINE]"
						},
						new CoreAudioTrack
						{
							Name = "PickUpSticks2",
							FileNameLoop = "PickUpSticksLoop.ogg",
							AudioType = (AudioType)14,
							WindUpTimer = 38.47f,
							Bars = 16,
							BeatsOffset = 0.2f,
							ColorTransitionIn = 0.6f,
							ColorTransitionOut = 0.3f,
							ColorTransitionEasing = Easing.InOutCubic,
							Palette = PalettePickUpSticks,
							LoopOffset = 0,
							FadeOutBeat = -2f,
							FadeOutDuration = 2f,
							FlickerLightsTimeSeries = new float[3] { -36f, -4f, 32f },
							Lyrics = Array.Empty<(float, string)>(),
							DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[6] { 0f, 0.5f, 3f, 32f, 34f, 40f }, new float[6] { 0f, 0.5f, 0f, 0f, 0.3f, 0f }),
							CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[6] { 23f, 28f, 31f, 34f, 38f, 52f }, new float[6] { 0f, 0.5f, 0f, 0f, 0.5f, 0f }),
							GameOverText = "[LOVE SUPPORT: OFFLINE]"
						}
					}
				},
				new SelectableAudioTrack
				{
					Name = "TwoFastTuFurious",
					AudioType = (AudioType)14,
					Language = Language.ENGLISH,
					WindUpTimer = 36.08f,
					Bars = 24,
					BeatsOffset = 0f,
					ColorTransitionIn = 0.4f,
					ColorTransitionOut = 0.6f,
					ColorTransitionEasing = Easing.InOutCubic,
					Palette = Palette.Parse(new string[6] { "#F0FBFF", "#9ED9FF", "#0B95FF", "#66C7FF", "#CAE8FF", "#3BB6FF" }),
					LoopOffset = 48,
					FadeOutBeat = -54f,
					FadeOutDuration = 6f,
					FlickerLightsTimeSeries = new float[4] { -80f, -14f, 34f, 82f },
					Lyrics = new(float, string)[12]
					{
						(-126f, "Starting from here,\nlet's make a promise"),
						(-110f, "You and me, let's just be honest"),
						(-100f, "We're gonna run,\nnothing can stop us"),
						(-89f, "Even the night,\nthat falls all around us"),
						(-80f, "Soon there will be\nlaughter and voices"),
						(-70f, "Beyond the clouds,\nover the mountains"),
						(-62f, "We'll run away,\non roads that are empty"),
						(-55f, "Lights from the airfield,\nshining upon you"),
						(-48f, "Nothing can stop this"),
						(-44f, "Nothing can stop this,\nnot now, I love you"),
						(-40f, "They're not gonna get us"),
						(-36f, "They're not gonna get us\nTHEY'RE NOT GONNA GET US")
					},
					DrunknessLoopOffsetTimeSeries = new TimeSeries<float>(new float[9] { -48f, -47.75f, -42f, 0f, 0.25f, 6f, 48f, 48.25f, 54f }, new float[9] { 0f, 0.5f, 0f, 0f, 0.5f, 0f, 0f, 0.5f, 0f }),
					CondensationLoopOffsetTimeSeries = new TimeSeries<float>(new float[9] { -24f, -23.75f, -18f, 24f, 24.25f, 30f, 72f, 72.25f, 78f }, new float[9] { 0f, 0.5f, 0f, 0f, 0.5f, 0f, 0f, 0.5f, 0f }),
					GameOverText = "[ O NOES, THEY GOT US ]"
				}
			};
		}
	}
	public readonly record struct Language(string Short, string Full)
	{
		public static readonly Language ENGLISH = new Language("EN", "English");

		public static readonly Language RUSSIAN = new Language("RU", "Russian");

		public static readonly Language KOREAN = new Language("KO", "Korean");

		public static readonly Language JAPANESE = new Language("JP", "Japanese");

		public static readonly Language HINDI = new Language("HI", "Hindi");
	}
	public readonly record struct Easing(string Name, Func<float, float> Eval)
	{
		public static Easing Linear = new Easing("Linear", (float x) => x);

		public static Easing InCubic = new Easing("InCubic", (float x) => x * x * x);

		public static Easing OutCubic = new Easing("OutCubic", (float x) => 1f - Mathf.Pow(1f - x, 3f));

		public static Easing InOutCubic = new Easing("InOutCubic", (float x) => (!(x < 0.5f)) ? (1f - Mathf.Pow(-2f * x + 2f, 3f) / 2f) : (4f * x * x * x));

		public static Easing InExpo = new Easing("InExpo", (float x) => (x != 0f) ? Mathf.Pow(2f, 10f * x - 10f) : 0f);

		public static Easing OutExpo = new Easing("OutExpo", (float x) => (x != 1f) ? (1f - Mathf.Pow(2f, -10f * x)) : 1f);

		public static Easing InOutExpo = new Easing("InOutExpo", (float x) => (x != 0f) ? ((x != 1f) ? ((!(x < 0.5f)) ? ((2f - Mathf.Pow(2f, -20f * x + 10f)) / 2f) : (Mathf.Pow(2f, 20f * x - 10f) / 2f)) : 1f) : 0f);

		public static readonly Easing[] All = new Easing[7] { Linear, InCubic, OutCubic, InOutCubic, InExpo, OutExpo, InOutExpo };

		public static readonly string[] AllNames = All.Select((Easing easing) => easing.Name).ToArray();

		public static Easing FindByName(string Name)
		{
			string Name2 = Name;
			return All.Where((Easing easing) => easing.Name == Name2).DefaultIfEmpty(Linear).First();
		}

		public override string ToString()
		{
			return Name;
		}
	}
	public readonly record struct Palette(Color[] Colors)
	{
		public static readonly Palette DEFAULT = new Palette((Color[])(object)new Color[4]
		{
			Color.magenta,
			Color.cyan,
			Color.green,
			Color.yellow
		});

		public static Palette Parse(string[] hexColors)
		{
			Color[] array = (Color[])(object)new Color[hexColors.Length];
			for (int i = 0; i < hexColors.Length; i++)
			{
				if (!ColorUtility.TryParseHtmlString(hexColors[i], ref array[i]))
				{
					throw new ArgumentException($"Unable to parse color #{i}: {hexColors}");
				}
			}
			return new Palette(array);
		}

		public static Palette operator +(Palette before, Palette after)
		{
			Color[] colors = before.Colors;
			Color[] colors2 = after.Colors;
			int num = 0;
			Color[] array = (Color[])(object)new Color[colors.Length + colors2.Length];
			ReadOnlySpan<Color> readOnlySpan = new ReadOnlySpan<Color>(colors);
			readOnlySpan.CopyTo(new Span<Color>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			ReadOnlySpan<Color> readOnlySpan2 = new ReadOnlySpan<Color>(colors2);
			readOnlySpan2.CopyTo(new Span<Color>(array).Slice(num, readOnlySpan2.Length));
			num += readOnlySpan2.Length;
			return new Palette(array);
		}

		public static Palette operator *(Palette palette, int repeat)
		{
			Color[] colors = Enumerable.Repeat(palette.Colors, repeat).SelectMany((Color[] x) => x).ToArray();
			return new Palette(colors);
		}

		public Palette Stretch(int times)
		{
			Color[] colors = Colors.SelectMany((Color color) => Enumerable.Repeat<Color>(color, times)).ToArray();
			return new Palette(colors);
		}

		public Palette Use(Func<Palette, Palette> op)
		{
			return op(this);
		}
	}
	public readonly struct TimeSeries<T>
	{
		public int Length => Beats.Length;

		public float[] Beats { get; }

		public T[] Values { get; }

		public TimeSeries()
			: this(Array.Empty<float>(), Array.Empty<T>())
		{
		}

		public TimeSeries(float[] beats, T[] values)
		{
			Beats = Array.Empty<float>();
			Values = Array.Empty<T>();
			if (beats.Length != values.Length)
			{
				throw new ArgumentOutOfRangeException($"Time series length mismatch: {beats.Length} != {values.Length}");
			}
			SortedDictionary<float, T> sortedDictionary = new SortedDictionary<float, T>();
			for (int i = 0; i < values.Length; i++)
			{
				sortedDictionary.Add(beats[i], values[i]);
			}
			Beats = sortedDictionary.Keys.ToArray();
			Values = sortedDictionary.Values.ToArray();
		}

		public override string ToString()
		{
			return "TimeSeries([" + string.Join(", ", Beats) + "], [" + string.Join(", ", Values) + "])";
		}
	}
	public interface ISelectableTrack : ISeasonalContent
	{
		string Name { get; init; }

		Language Language { get; init; }

		bool IsExplicit { get; init; }

		internal ConfigEntry<int> Weight { get; set; }

		internal IAudioTrack[] GetTracks();

		internal IAudioTrack SelectTrack(int index);

		internal void Debug();
	}
	public interface IAudioTrack
	{
		string Name { get; }

		float WindUpTimer { get; }

		float Bpm
		{
			get
			{
				if ((Object)(object)LoadedLoop == (Object)null || LoadedLoop.length <= 0f)
				{
					return 0f;
				}
				return 60f / (LoadedLoop.length / (float)Beats);
			}
		}

		int Beats { get; }

		int LoopOffset { get; }

		float LoopOffsetInSeconds
		{
			get
			{
				if ((Object)(object)LoadedLoop == (Object)null || LoadedLoop.length <= 0f)
				{
					return 0f;
				}
				return (float)LoopOffset / (float)Beats * LoadedLoop.length;
			}
		}

		AudioType AudioType { get; }

		AudioClip? LoadedIntro { get; internal set; }

		AudioClip? LoadedLoop { get; internal set; }

		string FileNameIntro { get; }

		string FileNameLoop { get; }

		string Ext
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Invalid comparison between Unknown and I4
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Invalid comparison between Unknown and I4
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Invalid comparison between Unknown and I4
				AudioType audioType = AudioType;
				if ((int)audioType != 13)
				{
					if ((int)audioType != 14)
					{
						if ((int)audioType == 20)
						{
							return "wav";
						}
						return "";
					}
					return "ogg";
				}
				return "mp3";
			}
		}

		float BeatsOffset { get; }

		float BeatsOffsetInSeconds
		{
			get
			{
				if ((Object)(object)LoadedLoop == (Object)null || LoadedLoop.length <= 0f)
				{
					return 0f;
				}
				return BeatsOffset / (float)Beats * LoadedLoop.length;
			}
		}

		float FadeOutBeat { get; }

		float FadeOutDuration { get; }

		float ColorTransitionIn { get; }

		float ColorTransitionOut { get; }

		Easing ColorTransitionEasing { get; }

		float[] FlickerLightsTimeSeries { get; }

		float[] LyricsTimeSeries { get; }

		string[] LyricsLines { get; }

		TimeSeries<float> DrunknessLoopOffsetTimeSeries { get; }

		TimeSeries<float> CondensationLoopOffsetTimeSeries { get; }

		Palette Palette { get; }

		string? GameOverText => null;
	}
	public abstract class ProxyAudioTrack : IAudioTrack
	{
		internal IAudioTrack Track;

		string IAudioTrack.Name => Track.Name;

		float IAudioTrack.WindUpTimer => Track.WindUpTimer;

		int IAudioTrack.Beats => Track.Beats;

		int IAudioTrack.LoopOffset => Track.LoopOffset;

		AudioType IAudioTrack.AudioType => Track.AudioType;

		AudioClip? IAudioTrack.LoadedIntro
		{
			get
			{
				return Track.LoadedIntro;
			}
			set
			{
				Track.LoadedIntro = value;
			}
		}

		AudioClip? IAudioTrack.LoadedLoop
		{
			get
			{
				return Track.LoadedLoop;
			}
			set
			{
				Track.LoadedLoop = value;
			}
		}

		string IAudioTrack.FileNameIntro => Track.FileNameIntro;

		string IAudioTrack.FileNameLoop => Track.FileNameLoop;

		float IAudioTrack.BeatsOffset => Track.BeatsOffset;

		float IAudioTrack.FadeOutBeat => Track.FadeOutBeat;

		float IAudioTrack.FadeOutDuration => Track.FadeOutDuration;

		float IAudioTrack.ColorTransitionIn => Track.ColorTransitionIn;

		float IAudioTrack.ColorTransitionOut => Track.ColorTransitionOut;

		Easing IAudioTrack.ColorTransitionEasing => Track.ColorTransitionEasing;

		float[] IAudioTrack.FlickerLightsTimeSeries => Track.FlickerLightsTimeSeries;

		float[] IAudioTrack.LyricsTimeSeries => Track.LyricsTimeSeries;

		string[] IAudioTrack.LyricsLines => Track.LyricsLines;

		TimeSeries<float> IAudioTrack.DrunknessLoopOffsetTimeSeries => Track.DrunknessLoopOffsetTimeSeries;

		TimeSeries<float> IAudioTrack.CondensationLoopOffsetTimeSeries => Track.CondensationLoopOffsetTimeSeries;

		Palette IAudioTrack.Palette => Track.Palette;

		string? IAudioTrack.GameOverText => Track.GameOverText;

		protected ProxyAudioTrack(IAudioTrack track)
		{
			Track = track;
			base..ctor();
		}
	}
	public class CoreAudioTrack : IAudioTrack
	{
		private string? FileNameIntroOverride;

		private string? FileNameLoopOverride;

		public float[] _FlickerLightsTimeSeries = Array.Empty<float>();

		public string Name { get; init; } = "";


		public float WindUpTimer { get; init; }

		public int Beats { get; init; }

		public int Bars
		{
			init
			{
				Beats = value * 4;
			}
		}

		public int LoopOffset { get; init; }

		public AudioType AudioType { get; init; } = (AudioType)13;


		public AudioClip? LoadedIntro { get; set; }

		public AudioClip? LoadedLoop { get; set; }

		public string FileNameIntro
		{
			get
			{
				return FileNameIntroOverride ?? (Name + "Intro." + ((IAudioTrack)this).Ext);
			}
			init
			{
				FileNameIntroOverride = value;
			}
		}

		public string FileNameLoop
		{
			get
			{
				return FileNameLoopOverride ?? (Name + "Loop." + ((IAudioTrack)this).Ext);
			}
			init
			{
				FileNameLoopOverride = value;
			}
		}

		public float BeatsOffset { get; init; }

		public float FadeOutBeat { get; init; } = float.NaN;


		public float FadeOutDuration { get; init; } = 2f;


		public float ColorTransitionIn { get; init; } = 0.25f;


		public float ColorTransitionOut { get; init; } = 0.25f;


		public Easing ColorTransitionEasing { get; init; } = Easing.OutExpo;


		public float[] FlickerLightsTimeSeries
		{
			get
			{
				return _FlickerLightsTimeSeries;
			}
			init
			{
				Array.Sort(value);
				_FlickerLightsTimeSeries = value;
			}
		}

		public float[] LyricsTimeSeries { get; private set; } = Array.Empty<float>();


		public string[] LyricsLines { get; private set; } = Array.Empty<string>();


		public (float, string)[] Lyrics
		{
			set
			{
				SortedDictionary<float, string> sortedDictionary = new SortedDictionary<float, string>();
				for (int i = 0; i < value.Length; i++)
				{
					var (key, value2) = value[i];
					sortedDictionary.Add(key, value2);
				}
				LyricsTimeSeries = sortedDictionary.Keys.ToArray();
				LyricsLines = sortedDictionary.Values.ToArray();
			}
		}

		public TimeSeries<float> DrunknessLoopOffsetTimeSeries { get; init; } = new TimeSeries<float>();


		public TimeSeries<float> CondensationLoopOffsetTimeSeries { get; init; } = new TimeSeries<float>();


		public Palette Palette { get; set; } = Palette.DEFAULT;


		public string? GameOverText { get; init; }
	}
	public class SelectableAudioTrack : CoreAudioTrack, ISelectableTrack, ISeasonalContent
	{
		public Language Language { get; init; }

		public bool IsExplicit { get; init; }

		public Season? Season { get; init; }

		ConfigEntry<int> ISelectableTrack.Weight { get; set; }

		IAudioTrack[] ISelectableTrack.GetTracks()
		{
			return new IAudioTrack[1] { this };
		}

		IAudioTrack ISelectableTrack.SelectTrack(int index)
		{
			return this;
		}

		void ISelectableTrack.Debug()
		{
			ManualLogSource log = Plugin.Log;
			string name = base.Name;
			AudioClip? loadedIntro = base.LoadedIntro;
			object arg = ((loadedIntro != null) ? new float?(loadedIntro.length) : null);
			AudioClip? loadedLoop = base.LoadedLoop;
			log.LogDebug((object)$"Track \"{name}\", Intro={arg:N4}, Loop={((loadedLoop != null) ? new float?(loadedLoop.length) : null):N4}");
		}
	}
	public class SelectableTracksGroup : ISelectableTrack, ISeasonalContent
	{
		public IAudioTrack[] Tracks = Array.Empty<IAudioTrack>();

		public string Name { get; init; } = "";


		public Language Language { get; init; }

		public bool IsExplicit { get; init; }

		public Season? Season { get; init; }

		ConfigEntry<int> ISelectableTrack.Weight { get; set; }

		IAudioTrack[] ISelectableTrack.GetTracks()
		{
			return Tracks;
		}

		IAudioTrack ISelectableTrack.SelectTrack(int index)
		{
			if (Tracks.Length == 0)
			{
				throw new IndexOutOfRangeException("Tracks list is empty");
			}
			return Mod.Index(Tracks, index);
		}

		void ISelectableTrack.Debug()
		{
			Plugin.Log.LogDebug((object)$"Track Group \"{Name}\", Count={Tracks.Length}");
			foreach (var item3 in Tracks.Select((IAudioTrack x, int i) => (x, i)))
			{
				IAudioTrack item = item3.Item1;
				int item2 = item3.Item2;
				ManualLogSource log = Plugin.Log;
				object[] obj = new object[4] { item2, item.Name, null, null };
				AudioClip? loadedIntro = item.LoadedIntro;
				obj[2] = ((loadedIntro != null) ? new float?(loadedIntro.length) : null);
				AudioClip? loadedLoop = item.LoadedLoop;
				obj[3] = ((loadedLoop != null) ? new float?(loadedLoop.length) : null);
				log.LogDebug((object)string.Format("    Track {0} \"{1}\", Intro={2:N4}, Loop={3:N4}", obj));
			}
		}
	}
	internal readonly record struct BeatTimestamp
	{
		public float HalfLoopBeats => (float)LoopBeats / 2f;

		public readonly int LoopBeats;

		public readonly bool IsLooping;

		public readonly float Beat;

		public readonly bool IsExtrapolated;

		public BeatTimestamp(int loopBeats, bool isLooping, float beat, bool isExtrapolated)
		{
			IsLooping = false;
			Beat = 0f;
			IsExtrapolated = false;
			LoopBeats = loopBeats;
			IsLooping = isLooping || beat >= HalfLoopBeats;
			Beat = ((isLooping || beat >= (float)LoopBeats) ? Mod.Positive(beat, LoopBeats) : beat);
			IsExtrapolated = isExtrapolated;
		}

		public static BeatTimestamp operator +(BeatTimestamp self, float delta)
		{
			if (delta < 0f - self.HalfLoopBeats && self.Beat > self.HalfLoopBeats)
			{
				_ = self.IsLooping;
			}
			return new BeatTimestamp(self.LoopBeats, self.IsLooping, self.Beat + delta, self.IsExtrapolated);
		}

		public static BeatTimestamp operator -(BeatTimestamp self, float delta)
		{
			return self + (0f - delta);
		}

		public BeatTimestamp Floor()
		{
			float beat = Mathf.Floor(Beat);
			return new BeatTimestamp(LoopBeats, IsLooping, beat, IsExtrapolated);
		}

		public override string ToString()
		{
			return string.Format("{0}({1}{2} {3:N4}/{4})", "BeatTimestamp", IsLooping ? 'Y' : 'n', IsExtrapolated ? 'E' : '_', Beat, LoopBeats);
		}

		[CompilerGenerated]
		private bool PrintMembers(StringBuilder builder)
		{
			builder.Append("LoopBeats = ");
			builder.Append(LoopBeats.ToString());
			builder.Append(", HalfLoopBeats = ");
			builder.Append(HalfLoopBeats.ToString());
			builder.Append(", IsLooping = ");
			builder.Append(IsLooping.ToString());
			builder.Append(", Beat = ");
			builder.Append(Beat.ToString());
			builder.Append(", IsExtrapolated = ");
			builder.Append(IsExtrapolated.ToString());
			return true;
		}
	}
	internal readonly record struct BeatTimeSpan
	{
		public float HalfLoopBeats => (float)LoopBeats / 2f;

		public readonly int LoopBeats;

		public readonly bool IsLooping;

		public readonly float BeatFromExclusive;

		public readonly float BeatToInclusive;

		public readonly bool IsExtrapolated;

		public static BeatTimeSpan Empty;

		public BeatTimeSpan(int loopBeats, bool isLooping, float beatFromExclusive, float beatToInclusive, bool isExtrapolated)
		{
			IsLooping = false;
			BeatFromExclusive = 0f;
			BeatToInclusive = 0f;
			IsExtrapolated = false;
			LoopBeats = loopBeats;
			IsLooping = isLooping || beatToInclusive >= HalfLoopBeats;
			BeatFromExclusive = wrap(beatFromExclusive);
			BeatToInclusive = wrap(beatToInclusive);
			IsExtrapolated = isExtrapolated;
			float wrap(float beat)
			{
				if (!isLooping && !(beat >= (float)loopBeats))
				{
					return beat;
				}
				return Mod.Positive(beat, loopBeats);
			}
		}

		public static BeatTimeSpan Between(BeatTimestamp timestampFromExclusive, BeatTimestamp timestampToInclusive)
		{
			bool isExtrapolated = timestampFromExclusive.IsExtrapolated || timestampToInclusive.IsExtrapolated;
			return new BeatTimeSpan(timestampToInclusive.LoopBeats, timestampToInclusive.IsLooping, timestampFromExclusive.Beat, timestampToInclusive.Beat, isExtrapolated);
		}

		public static BeatTimeSpan Between(float beatFromExclusive, BeatTimestamp timestampToInclusive)
		{
			return new BeatTimeSpan(timestampToInclusive.LoopBeats, timestampToInclusive.IsLooping, beatFromExclusive, timestampToInclusive.Beat, timestampToInclusive.IsExtrapolated);
		}

		public BeatTimestamp ToTimestamp()
		{
			return new BeatTimestamp(LoopBeats, IsLooping, BeatToInclusive, IsExtrapolated);
		}

		public bool ContainsExact(float beat)
		{
			if (BeatFromExclusive < beat)
			{
				return beat <= BeatToInclusive;
			}
			return false;
		}

		public int? GetLastIndex(float[] timeSeries)
		{
			if (IsEmpty() || timeSeries == null || timeSeries.Length == 0)
			{
				return null;
			}
			if (IsWrapped())
			{
				int? lastIndex = new BeatTimeSpan(LoopBeats, isLooping: false, -0.001f, BeatToInclusive, IsExtrapolated).GetLastIndex(timeSeries);
				if (lastIndex.HasValue)
				{
					return lastIndex;
				}
				int num = timeSeries.Length - 1;
				if (timeSeries[num] > BeatFromExclusive)
				{
					return num;
				}
			}
			else
			{
				int num2 = Array.BinarySearch(timeSeries, BeatToInclusive);
				if (num2 > 0 && num2 < timeSeries.Length && timeSeries[num2] > BeatFromExclusive)
				{
					return num2;
				}
				num2 = ~num2;
				num2--;
				if (num2 >= 0 && timeSeries[num2] > BeatFromExclusive && timeSeries[num2] <= BeatToInclusive)
				{
					return num2;
				}
			}
			return null;
		}

		public float Duration(bool longest = false)
		{
			if (longest)
			{
				float num = BeatToInclusive;
				if (BeatFromExclusive >= 0f && BeatToInclusive >= 0f && num < BeatFromExclusive)
				{
					num += (float)LoopBeats;
				}
				return Mathf.Max(0f, num - BeatFromExclusive);
			}
			if (IsEmpty())
			{
				return 0f;
			}
			if (IsWrapped())
			{
				float num2 = (float)LoopBeats - BeatFromExclusive;
				float num3 = BeatToInclusive - 0f;
				return num2 + num3;
			}
			return BeatToInclusive - BeatFromExclusive;
		}

		public bool IsEmpty()
		{
			if (IsLooping)
			{
				float num = BeatToInclusive;
				if (BeatToInclusive < BeatFromExclusive)
				{
					num = BeatToInclusive + (float)LoopBeats;
				}
				return num - BeatFromExclusive > HalfLoopBeats;
			}
			return BeatFromExclusive > BeatToInclusive;
		}

		public bool IsWrapped()
		{
			if (IsLooping && !IsEmpty())
			{
				return BeatToInclusive < BeatFromExclusive;
			}
			return false;
		}

		public override string ToString()
		{
			return string.Format("{0}({1}{2}, {3:N4}..{4:N4}/{5}{6})", "BeatTimeSpan", IsLooping ? 'Y' : 'n', IsExtrapolated ? 'E' : '_', BeatFromExclusive, BeatToInclusive, LoopBeats, IsEmpty() ? " Empty!" : "");
		}

		[CompilerGenerated]
		private bool PrintMembers(StringBuilder builder)
		{
			builder.Append("LoopBeats = ");
			builder.Append(LoopBeats.ToString());
			builder.Append(", HalfLoopBeats = ");
			builder.Append(HalfLoopBeats.ToString());
			builder.Append(", IsLooping = ");
			builder.Append(IsLooping.ToString());
			builder.Append(", BeatFromExclusive = ");
			builder.Append(BeatFromExclusive.ToString());
			builder.Append(", BeatToInclusive = ");
			builder.Append(BeatToInclusive.ToString());
			builder.Append(", IsExtrapolated = ");
			builder.Append(IsExtrapolated.ToString());
			return true;
		}
	}
	internal class ExtrapolatedAudioSourceState
	{
		private float ExtrapolatedTime;

		private float LastKnownNonExtrapolatedTime;

		private float LastKnownRealtime;

		private const float MaxExtrapolationInterval = 0.5f;

		public bool IsPlaying { get; private set; }

		public float Time => ExtrapolatedTime;

		public bool HasStarted { get; private set; }

		public bool IsExtrapolated => LastKnownNonExtrapolatedTime != ExtrapolatedTime;

		public void Update(AudioSource audioSource, float realtime)
		{
			IsPlaying = audioSource.isPlaying;
			HasStarted |= audioSource.time != 0f;
			if (LastKnownNonExtrapolatedTime != audioSource.time)
			{
				LastKnownRealtime = realtime;
				LastKnownNonExtrapolatedTime = (ExtrapolatedTime = audioSource.time);
			}
			else if (IsPlaying && HasStarted && Config.ExtrapolateTime)
			{
				float num = realtime - LastKnownRealtime;
				if (0f < num && num < 0.5f)
				{
					ExtrapolatedTime = LastKnownNonExtrapolatedTime + num;
				}
			}
		}

		public override string ToString()
		{
			return string.Format("{0}({1}{2} ", "ExtrapolatedAudioSourceState", IsPlaying ? 'P' : '_', HasStarted ? 'S' : '0') + (IsExtrapolated ? $"{LastKnownRealtime:N4}, {LastKnownNonExtrapolatedTime:N4} => {ExtrapolatedTime:N4}" : $"{LastKnownRealtime:N4}, {LastKnownNonExtrapolatedTime:N4}") + ")";
		}
	}
	internal class JesterAudioSourcesState
	{
		private readonly float IntroClipLength;

		private readonly ExtrapolatedAudioSourceState Intro = new ExtrapolatedAudioSourceState();

		private readonly ExtrapolatedAudioSourceState Loop = new ExtrapolatedAudioSourceState();

		private bool ReferenceIsIntro = true;

		public bool HasStarted => Intro.HasStarted;

		public bool IsExtrapolated
		{
			get
			{
				if (!ReferenceIsIntro)
				{
					return Loop.IsExtrapolated;
				}
				return Intro.IsExtrapolated;
			}
		}

		public float Time
		{
			get
			{
				if (!ReferenceIsIntro)
				{
					return IntroClipLength + Loop.Time;
				}
				return Intro.Time;
			}
		}

		public JesterAudioSourcesState(float introClipLength)
		{
			IntroClipLength = introClipLength;
		}

		public void Update(AudioSource intro, AudioSource loop, float realtime)
		{
			Loop.Update(loop, realtime);
			if (!Loop.HasStarted)
			{
				Intro.Update(intro, realtime);
			}
			else
			{
				ReferenceIsIntro = false;
			}
		}
	}
	internal class AudioLoopingState
	{
		private readonly float StartOfLoop;

		private readonly float LoopLength;

		private readonly int Beats;

		public bool IsLooping { get; private set; }

		public AudioLoopingState(float startOfLoop, float loopLength, int beats)
		{
			StartOfLoop = startOfLoop;
			LoopLength = loopLength;
			Beats = beats;
		}

		public BeatTimestamp Update(float time, bool isExtrapolated, float additionalOffset)
		{
			float num = StartOfLoop + additionalOffset;
			float num2 = time - num;
			float num3 = ((LoopLength <= 0f) ? 0f : (num2 / LoopLength));
			float beat = num3 * (float)Beats;
			BeatTimestamp result = new BeatTimestamp(Beats, IsLooping, beat, isExtrapolated);
			IsLooping |= result.IsLooping;
			return result;
		}
	}
	internal class BeatTimeState
	{
		private readonly IAudioTrack track;

		private readonly JesterAudioSourcesState AudioState;

		private readonly AudioLoopingState WindUpLoopingState;

		private readonly AudioLoopingState LoopLoopingState;

		private float LastKnownLoopOffsetBeat = float.NegativeInfinity;

		private static Random LyricsRandom;

		private int LyricsRandomPerLoop;

		private bool WindUpZeroBeatEventTriggered;

		public BeatTimeState(IAudioTrack track)
		{
			if (LyricsRandom == null)
			{
				LyricsRandom = new Random(RoundManager.Instance.playersManager.randomMapSeed + 1337);
				LyricsRandomPerLoop = LyricsRandom.Next();
			}
			this.track = track;
			AudioClip? loadedIntro = track.LoadedIntro;
			AudioState = new JesterAudioSourcesState((loadedIntro != null) ? loadedIntro.length : 0f);
			AudioClip? loadedLoop = track.LoadedLoop;
			float loopLength = ((loadedLoop != null) ? loadedLoop.length : 0f);
			WindUpLoopingState = new AudioLoopingState(track.WindUpTimer, loopLength, track.Beats);
			LoopLoopingState = new AudioLoopingState(track.WindUpTimer + track.LoopOffsetInSeconds, loopLength, track.Beats);
		}

		public List<BaseEvent> Update(AudioSource intro, AudioSource loop)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			AudioState.Update(intro, loop, realtimeSinceStartup);
			if (AudioState.HasStarted)
			{
				BeatTimestamp beatTimestamp = Update(LoopLoopingState);
				BeatTimeSpan loopOffsetSpan = BeatTimeSpan.Between(LastKnownLoopOffsetBeat, beatTimestamp);
				if (!loopOffsetSpan.IsEmpty())
				{
					if (loopOffsetSpan.BeatFromExclusive > loopOffsetSpan.BeatToInclusive)
					{
						LyricsRandomPerLoop = LyricsRandom.Next();
					}
					BeatTimestamp windUpOffsetTimestamp = Update(WindUpLoopingState);
					LastKnownLoopOffsetBeat = beatTimestamp.Beat;
					return GetEvents(beatTimestamp, loopOffsetSpan, windUpOffsetTimestamp);
				}
			}
			return new List<BaseEvent>();
		}

		private BeatTimestamp Update(AudioLoopingState loopingState)
		{
			return loopingState.Update(AudioState.Time, AudioState.IsExtrapolated, AdditionalOffset());
		}

		private float AdditionalOffset()
		{
			return Config.AudioOffset.Value + track.BeatsOffsetInSeconds;
		}

		private List<BaseEvent> GetEvents(BeatTimestamp loopOffsetTimestamp, BeatTimeSpan loopOffsetSpan, BeatTimestamp windUpOffsetTimestamp)
		{
			List<BaseEvent> list = new List<BaseEvent>();
			if (windUpOffsetTimestamp.Beat >= 0f && !WindUpZeroBeatEventTriggered)
			{
				list.Add(new WindUpZeroBeatEvent());
				WindUpZeroBeatEventTriggered = true;
			}
			SetLightsColorEvent colorEvent = GetColorEvent(loopOffsetSpan, windUpOffsetTimestamp);
			if (colorEvent != null)
			{
				list.Add(colorEvent);
			}
			if (loopOffsetSpan.GetLastIndex(track.FlickerLightsTimeSeries).HasValue)
			{
				list.Add(new FlickerLightsEvent());
			}
			if (Config.DisplayLyrics.Value)
			{
				int? lastIndex = loopOffsetSpan.GetLastIndex(track.LyricsTimeSeries);
				if (lastIndex.HasValue)
				{
					int valueOrDefault = lastIndex.GetValueOrDefault();
					if (valueOrDefault < track.LyricsLines.Length)
					{
						string text = track.LyricsLines[valueOrDefault];
						string[] array = text.Split('\t');
						int num = LyricsRandomPerLoop % array.Length;
						string text2 = array[num];
						if (text2 != "")
						{
							list.Add(new LyricsEvent(text2));
						}
					}
				}
			}
			float? interpolation = GetInterpolation(loopOffsetTimestamp, track.DrunknessLoopOffsetTimeSeries, Easing.Linear);
			if (interpolation.HasValue)
			{
				float valueOrDefault2 = interpolation.GetValueOrDefault();
				float drunkness = (Config.ReduceVFXIntensity.Value ? (valueOrDefault2 * 0.3f) : valueOrDefault2);
				list.Add(new DrunkEvent(drunkness));
			}
			interpolation = GetInterpolation(loopOffsetTimestamp, track.CondensationLoopOffsetTimeSeries, Easing.Linear);
			if (interpolation.HasValue)
			{
				float valueOrDefault3 = interpolation.GetValueOrDefault();
				list.Add(new CondensationEvent(valueOrDefault3));
			}
			return list;
		}

		private SetLightsColorEvent? GetColorEvent(BeatTimeSpan loopOffsetSpan, BeatTimestamp windUpOffsetTimestamp)
		{
			SetLightsColorTransitionEvent setLightsColorTransitionEvent = FadeOut(loopOffsetSpan, windUpOffsetTimestamp);
			if (setLightsColorTransitionEvent != null)
			{
				return setLightsColorTransitionEvent;
			}
			SetLightsColorEvent setLightsColorEvent = ColorFromPaletteAtTimestamp(windUpOffsetTimestamp);
			if (setLightsColorEvent != null)
			{
				return setLightsColorEvent;
			}
			return null;
		}

		private SetLightsColorTransitionEvent? FadeOut(BeatTimeSpan loopOffsetSpan, BeatTimestamp windUpOffsetTimestamp)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			float fadeOutBeat = track.FadeOutBeat;
			float num = fadeOutBeat + track.FadeOutDuration;
			if (windUpOffsetTimestamp.Beat < 0f && track.FadeOutBeat < loopOffsetSpan.BeatToInclusive && loopOffsetSpan.BeatFromExclusive <= num)
			{
				float t = (loopOffsetSpan.BeatToInclusive - track.FadeOutBeat) / track.FadeOutDuration;
				return new SetLightsColorTransitionEvent(null, Color.black, Easing.Linear, t);
			}
			return null;
		}

		public SetLightsColorEvent? ColorFromPaletteAtTimestamp(BeatTimestamp timestamp)
		{
			if (timestamp.Beat <= 0f - track.ColorTransitionIn)
			{
				return null;
			}
			BeatTimestamp beatTimestamp = timestamp.Floor();
			BeatTimestamp beatTimestamp2 = beatTimestamp + 1f;
			float transitionLength = track.ColorTransitionIn + track.ColorTransitionOut;
			if ((double)transitionLength > 0.01)
			{
				if (BeatTimeSpan.Between(beatTimestamp, timestamp).Duration() < track.ColorTransitionOut)
				{
					return ColorTransition(beatTimestamp);
				}
				if (BeatTimeSpan.Between(timestamp, beatTimestamp2).Duration() < track.ColorTransitionIn)
				{
					return ColorTransition(beatTimestamp2);
				}
			}
			return new SetLightsColorStaticEvent(ColorAtWholeBeat(timestamp));
			Color? ColorAtWholeBeat(BeatTimestamp timestamp)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				if (timestamp.Beat >= 0f)
				{
					int index = Mathf.FloorToInt(timestamp.Beat);
					return Mod.Index(track.Palette.Colors, index);
				}
				if (!float.IsNaN(track.FadeOutBeat))
				{
					return Color.black;
				}
				return null;
			}
			SetLightsColorTransitionEvent ColorTransition(BeatTimestamp clipsBoundary)
			{
				BeatTimestamp beatTimestamp3 = clipsBoundary - track.ColorTransitionIn;
				BeatTimestamp timestamp2 = clipsBoundary + track.ColorTransitionOut;
				float t = BeatTimeSpan.Between(beatTimestamp3, timestamp).Duration() / transitionLength;
				if (track.ColorTransitionIn == 0f)
				{
					beatTimestamp3 -= 0.01f;
				}
				return new SetLightsColorTransitionEvent(ColorAtWholeBeat(beatTimestamp3), ColorAtWholeBeat(timestamp2), track.ColorTransitionEasing, t);
			}
		}

		private float? GetInterpolation(BeatTimestamp timestamp, TimeSeries<float> timeSeries, Easing easing)
		{
			if (timeSeries.Length == 0)
			{
				return null;
			}
			if (timeSeries.Length == 1)
			{
				return timeSeries.Values[0];
			}
			int? num = null;
			for (int num2 = timeSeries.Length - 1; num2 >= 0; num2--)
			{
				if (timeSeries.Beats[num2] <= timestamp.Beat)
				{
					num = num2;
					break;
				}
			}
			if (!num.HasValue && timestamp.IsLooping)
			{
				num = timeSeries.Length - 1;
			}
			int? num3 = null;
			for (int i = 0; i < timeSeries.Length; i++)
			{
				if (timeSeries.Beats[i] >= timestamp.Beat)
				{
					num3 = i;
					break;
				}
			}
			if (!num3.HasValue && timestamp.IsLooping)
			{
				for (int j = 0; j < timeSeries.Length; j++)
				{
					if (timeSeries.Beats[j] >= 0f)
					{
						num3 = j;
						break;
					}
				}
			}
			int? num4 = num;
			int? num5 = num3;
			if (!num4.HasValue)
			{
				if (num5.HasValue)
				{
					int valueOrDefault = num5.GetValueOrDefault();
					return timeSeries.Values[valueOrDefault];
				}
				return null;
			}
			int valueOrDefault2 = num4.GetValueOrDefault();
			if (num5.HasValue)
			{
				int valueOrDefault = num5.GetValueOrDefault();
				int n