Decompiled source of FireworksShow v0.9.3

plugins/FireworksShow.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FireworksShow.UI;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FireworksShow
{
	public class ContinuousRunner
	{
		private readonly FireworkLauncher _launcher;

		private readonly Queue<GameObject> _pacingQueue = new Queue<GameObject>();

		private float _nextContinuousTime;

		private bool _pacingPumping;

		private bool _continuousRunning;

		public bool Running => _continuousRunning;

		public ContinuousRunner(FireworkLauncher launcher)
		{
			_launcher = launcher;
		}

		public void Toggle()
		{
			if (!ModConfig.ContinuousEnabled.Value)
			{
				_launcher.ShowNotice(Lang.L("连续烟花未启用", "Continuous fireworks disabled"));
				return;
			}
			_continuousRunning = !_continuousRunning;
			_nextContinuousTime = 0f;
			ResetPacing();
			_launcher.ShowNotice(_continuousRunning ? Lang.L("连续烟花:开始", "Continuous: started") : Lang.L("连续烟花:停止", "Continuous: stopped"));
		}

		public void Stop()
		{
			_continuousRunning = false;
		}

		public void Update(bool handleToggle)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.ContinuousEnabled.Value)
			{
				_continuousRunning = false;
				return;
			}
			if (handleToggle && Pressed(ModConfig.ContinuousKey.Value))
			{
				Toggle();
			}
			if (_continuousRunning)
			{
				if (ModConfig.PacingEnabled.Value)
				{
					HandlePaced();
				}
				else
				{
					HandleDirect();
				}
			}
		}

		public void EnqueuePaced(GameObject go)
		{
			if ((Object)(object)go != (Object)null)
			{
				_pacingQueue.Enqueue(go);
			}
		}

		private void HandleDirect()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (_pacingPumping)
			{
				ResetPacing();
			}
			if (_launcher.CanSpawn() && !(Time.time < _nextContinuousTime))
			{
				Character localCharacter = Character.localCharacter;
				if (!((Object)(object)localCharacter == (Object)null) && FireworkPointPicker.TryFindContinuousPoint(localCharacter.Center, _launcher.ActivePoints, out var point))
				{
					TickRate();
					_launcher.StartSpawn(point, ModConfig.LightDelay.Value, paced: false);
				}
			}
		}

		private void HandlePaced()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (!_pacingPumping)
			{
				((MonoBehaviour)_launcher).StartCoroutine(PacingPump());
			}
			if (_launcher.CanSpawn() && !(Time.time < _nextContinuousTime))
			{
				Character localCharacter = Character.localCharacter;
				if (!((Object)(object)localCharacter == (Object)null) && FireworkPointPicker.TryFindContinuousPoint(localCharacter.Center, _launcher.ActivePoints, out var point))
				{
					TickRate();
					_launcher.StartSpawn(point, -1f, paced: true);
				}
			}
		}

		private void TickRate()
		{
			float num = Mathf.Max(0.1f, ModConfig.ContinuousRate.Value);
			_nextContinuousTime = Time.time + 1f / num;
		}

		private IEnumerator PacingPump()
		{
			if (_pacingPumping)
			{
				yield break;
			}
			_pacingPumping = true;
			float interval = Mathf.Max(0.05f, ModConfig.BlossomInterval.Value);
			int groupSize = Mathf.Clamp(ModConfig.SimultaneousCount.Value, 1, 30);
			float num = Mathf.Max(0f, ModConfig.LightDelay.Value);
			if (num > 0f)
			{
				yield return (object)new WaitForSeconds(num);
			}
			while (_continuousRunning && ModConfig.Enabled.Value && ModConfig.ContinuousEnabled.Value)
			{
				for (int i = 0; i < groupSize; i++)
				{
					while (_pacingQueue.Count > 0 && (Object)(object)_pacingQueue.Peek() == (Object)null)
					{
						_pacingQueue.Dequeue();
					}
					if (_pacingQueue.Count == 0)
					{
						break;
					}
					GameObject val = _pacingQueue.Dequeue();
					if (!((Object)(object)val == (Object)null))
					{
						Rocketpack component = val.GetComponent<Rocketpack>();
						if (!((Object)(object)component == (Object)null) && !((Object)(object)component.view == (Object)null))
						{
							component.Light();
						}
					}
				}
				yield return (object)new WaitForSeconds(interval);
			}
			_pacingPumping = false;
			ResetPacing();
		}

		private void ResetPacing()
		{
			_pacingPumping = false;
			while (_pacingQueue.Count > 0)
			{
				GameObject val = _pacingQueue.Dequeue();
				if (!((Object)(object)val == (Object)null))
				{
					Rocketpack component = val.GetComponent<Rocketpack>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.view == (Object)null))
					{
						component.Light();
					}
				}
			}
		}

		private static bool Pressed(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key != 0)
			{
				return Input.GetKeyDown(key);
			}
			return false;
		}
	}
	public enum SpawnCategory
	{
		Normal,
		Heart,
		Pattern
	}
	public class FireworkLauncher : MonoBehaviour
	{
		private struct SpawnedItem
		{
			public GameObject go;

			public Vector3 point;

			public SpawnCategory category;

			public int spawnMode;
		}

		private readonly List<SpawnedItem> _items = new List<SpawnedItem>();

		private readonly List<Vector3> _activePoints = new List<Vector3>();

		private ShowScheduler _scheduler;

		private float _nextClickTime;

		private string _noticeText;

		private float _noticeUntil;

		private GUIStyle _noticeStyle;

		private const float KeepLitInterval = 2f;

		public static FireworkLauncher Instance { get; private set; }

		public ContinuousRunner Continuous { get; private set; }

		public int ActiveCount
		{
			get
			{
				int num = 0;
				for (int i = 0; i < _items.Count; i++)
				{
					if (_items[i].spawnMode == 0)
					{
						num++;
					}
				}
				return num;
			}
		}

		public bool ContinuousRunning
		{
			get
			{
				if (Continuous != null)
				{
					return Continuous.Running;
				}
				return false;
			}
		}

		public IList<Vector3> ActivePoints => _activePoints;

		public float SetupDelay => Mathf.Max(0f, ModConfig.LightDelay.Value);

		public int HeartCount => CountCategory(SpawnCategory.Heart);

		public int PatternCount => CountCategory(SpawnCategory.Pattern);

		private void Awake()
		{
			Instance = this;
			Continuous = new ContinuousRunner(this);
			_scheduler = new ShowScheduler(this);
			((MonoBehaviour)this).StartCoroutine(KeepLitRoutine());
		}

		private void Update()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			PruneSpawned();
			if (!ModConfig.Enabled.Value)
			{
				Continuous.Stop();
				_noticeUntil = 0f;
				return;
			}
			if (FireworksPanel.IsOpen)
			{
				Continuous.Update(handleToggle: false);
				return;
			}
			if (Pressed(ModConfig.Hotkey.Value))
			{
				TrySpawnBatch();
			}
			if (Pressed(ModConfig.HeartKey.Value))
			{
				TrySpawnHeart();
			}
			if (Pressed(ModConfig.SquirtleKey.Value) && ModConfig.SquirtleEnabled.Value)
			{
				TrySpawnSquirtle();
			}
			Continuous.Update(handleToggle: true);
			HandleMiddleClick();
		}

		private void OnGUI()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time >= _noticeUntil) && !string.IsNullOrEmpty(_noticeText))
			{
				if (_noticeStyle == null)
				{
					_noticeStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontSize = 28,
						fontStyle = (FontStyle)1
					};
					_noticeStyle.normal.textColor = Color.white;
				}
				float num = 420f;
				float num2 = 60f;
				Rect val = new Rect(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.12f, num, num2);
				Color color = GUI.color;
				GUI.color = new Color(0f, 0f, 0f, 0.6f);
				GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
				GUI.Label(val, _noticeText, _noticeStyle);
			}
		}

		public void TrySpawnBatch()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom)
			{
				Plugin.Log.LogInfo((object)"未进入房间,无法释放烟花。");
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			int num = Mathf.Clamp(ModConfig.Count.Value, 1, 30);
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				if (!HasBudget())
				{
					break;
				}
				if (FireworkPointPicker.TryFindBatchPoint(localCharacter.Center, _activePoints, out var point))
				{
					float startDelay = (float)i * Mathf.Max(0f, ModConfig.BatchInterval.Value);
					StartSpawn(point, startDelay, paced: false);
					num2++;
				}
			}
			if (num2 == 0)
			{
				Plugin.Log.LogInfo((object)"附近没有合适的露天位置,烟花未释放。");
			}
		}

		public void TrySpawnHeart()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom)
			{
				Plugin.Log.LogInfo((object)"未进入房间,无法释放烟花。");
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			int count = Mathf.Clamp(Mathf.RoundToInt(24f * ((float)ModConfig.HeartDensity.Value / 45f) * (ModConfig.HeartSize.Value / 12f)), 8, 120);
			Vector3[] array = ShowcaseLayout.BuildHeartPoints(localCharacter.Center, ModConfig.HeartSize.Value, count);
			if (array.Length == 0)
			{
				return;
			}
			int num = Mathf.Clamp(ModConfig.PatternSpawnMode.Value, 0, 2);
			if (num == 0)
			{
				float interval = Mathf.Max(0f, ModConfig.HeartInterval.Value);
				float[] array2 = ShowcaseLayout.OrderHeartDelays(array, ModConfig.HeartOrder.Value, interval);
				float setupDelay = SetupDelay;
				for (int i = 0; i < array2.Length; i++)
				{
					array2[i] += setupDelay;
				}
				((MonoBehaviour)this).StartCoroutine(_scheduler.RunSimultaneous(array, array2, 0, SpawnCategory.Heart));
				ShowNotice(Lang.L("心形礼花:准备绽放", "Heart: blooming"));
			}
			else
			{
				((MonoBehaviour)this).StartCoroutine(_scheduler.RunDisplay(array, num, SpawnCategory.Heart));
				ShowNotice(Lang.L("心形礼花:已生成图案", "Heart: pattern placed"));
			}
		}

		public void TrySpawnSquirtle()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom)
			{
				Plugin.Log.LogInfo((object)"未进入房间,无法释放烟花。");
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null))
			{
				((MonoBehaviour)this).StartCoroutine(PatternRoutine(localCharacter.Center));
			}
		}

		private IEnumerator PatternRoutine(Vector3 center)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			int pattern = Mathf.Clamp(ModConfig.SquirtlePattern.Value, 0, PatternCatalog.Names.Length - 1);
			float num = Mathf.Max(10f, ModConfig.SquirtleWidth.Value);
			int num2 = Mathf.Clamp(ModConfig.SquirtleDensity.Value, 10, 120);
			int num3 = Mathf.Clamp(Mathf.RoundToInt(213f * ((float)num2 / 45f) * (num / 45f)), 40, 400);
			List<Vector3>[] array = PatternCatalog.Build(pattern, num3);
			if (array == null || array.Length == 0)
			{
				ShowNotice(Lang.L("图案烟花点数太少", "Pattern has too few points"));
				yield break;
			}
			List<Vector3>[] array2 = ShowcaseLayout.BuildTextPointGroups(array, center, num, ModConfig.SquirtleDistance.Value, ModConfig.SquirtleHeightOffset.Value);
			if (array2 == null || array2.Length == 0)
			{
				ShowNotice(Lang.L("图案烟花点数太少", "Pattern has too few points"));
				yield break;
			}
			int num4 = Mathf.Clamp(ModConfig.PatternSpawnMode.Value, 0, 2);
			string text = PatternCatalog.LocalizedName(pattern);
			if (num4 != 0)
			{
				int num5 = 0;
				for (int i = 0; i < array2.Length; i++)
				{
					num5 += array2[i].Count;
				}
				Vector3[] array3 = (Vector3[])(object)new Vector3[num5];
				int num6 = 0;
				foreach (List<Vector3> list in array2)
				{
					for (int k = 0; k < list.Count; k++)
					{
						array3[num6++] = list[k];
					}
				}
				((MonoBehaviour)this).StartCoroutine(_scheduler.RunDisplay(array3, num4, SpawnCategory.Pattern));
				ShowNotice(Lang.L("图案烟花:", "Pattern: ") + text + Lang.L("(展示)", " (display)"));
				yield break;
			}
			float num7 = Mathf.Clamp(1f / (float)num2, 0.012f, 0.12f);
			float num8 = 0.6f;
			int num9 = 0;
			for (int l = 0; l < array2.Length; l++)
			{
				num9 += array2[l].Count;
			}
			Vector3[] array4 = (Vector3[])(object)new Vector3[num9];
			float[] array5 = new float[num9];
			int num10 = 0;
			float num11 = 0f;
			foreach (List<Vector3> list2 in array2)
			{
				for (int n = 0; n < list2.Count; n++)
				{
					array4[num10] = list2[n];
					array5[num10] = num11 + (float)n * num7;
					num10++;
				}
				num11 += (float)Mathf.Max(1, list2.Count) * num7 + num8;
			}
			int concurrentCap = Mathf.Clamp(num3, 40, 300);
			((MonoBehaviour)this).StartCoroutine(_scheduler.RunRolling(array4, array5, concurrentCap, 0, SpawnCategory.Pattern));
			ShowNotice(Lang.L("图案烟花:", "Pattern: ") + text);
		}

		public void LaunchFirework(Vector3 point, float startDelay)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom && HasBudget())
			{
				StartSpawn(point, startDelay, paced: false);
			}
		}

		public void ToggleContinuous()
		{
			Continuous.Toggle();
		}

		public void ShowNotice(string text)
		{
			_noticeText = text;
			_noticeUntil = Time.time + 2f;
		}

		private void PruneSpawned()
		{
			for (int num = _items.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)_items[num].go == (Object)null)
				{
					_items.RemoveAt(num);
					if (num < _activePoints.Count)
					{
						_activePoints.RemoveAt(num);
					}
				}
			}
			while (_activePoints.Count > _items.Count)
			{
				_activePoints.RemoveAt(_activePoints.Count - 1);
			}
		}

		private void RegisterSpawned(GameObject go, Vector3 point, bool paced, SpawnCategory category, int spawnMode)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			_items.Add(new SpawnedItem
			{
				go = go,
				point = point,
				category = category,
				spawnMode = spawnMode
			});
			_activePoints.Add(point);
			if (paced && (Object)(object)go != (Object)null && (Object)(object)go.GetComponent<Rocketpack>() != (Object)null && (Object)(object)go.GetComponent<PhotonView>() != (Object)null)
			{
				Continuous.EnqueuePaced(go);
			}
		}

		private bool HasBudget()
		{
			return ActiveCount < ModConfig.MaxConcurrent.Value;
		}

		public bool CanSpawn()
		{
			if (PhotonNetwork.InRoom)
			{
				return HasBudget();
			}
			return false;
		}

		private static bool Pressed(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key != 0)
			{
				return Input.GetKeyDown(key);
			}
			return false;
		}

		private void HandleMiddleClick()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.MiddleClickEnabled.Value && Input.GetMouseButton(2) && !(Time.time < _nextClickTime) && CanSpawn() && FireworkPointPicker.TryGetAimPoint(out var point))
			{
				_nextClickTime = Time.time + Mathf.Max(0.02f, ModConfig.Interval.Value);
				StartSpawn(point, 0f, paced: false);
			}
		}

		public void StartSpawn(Vector3 point, float startDelay, bool paced, float lightDelayOverride = -1f, int spawnMode = 0, SpawnCategory category = SpawnCategory.Normal)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviour)this).StartCoroutine(SpawnRoutine(point, startDelay, paced, lightDelayOverride, spawnMode, category));
		}

		private IEnumerator SpawnRoutine(Vector3 point, float startDelay, bool paced, float lightDelayOverride, int spawnMode, SpawnCategory category)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (startDelay > 0f)
			{
				yield return (object)new WaitForSeconds(startDelay);
			}
			if (!PhotonNetwork.InRoom)
			{
				yield break;
			}
			string text = FireworkPrefabRegistry.ResolvePrefabPath();
			if (string.IsNullOrEmpty(text))
			{
				yield break;
			}
			GameObject spawned;
			try
			{
				spawned = PhotonNetwork.Instantiate(text, point, Quaternion.identity, (byte)0, (object[])null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("生成烟花失败:" + ex.Message));
				yield break;
			}
			if ((Object)(object)spawned == (Object)null)
			{
				yield break;
			}
			Rocketpack rocket = spawned.GetComponent<Rocketpack>();
			if ((Object)(object)rocket == (Object)null)
			{
				Plugin.Log.LogWarning((object)"生成物不包含 Rocketpack 组件,已销毁。");
				PhotonNetwork.Destroy(spawned);
				yield break;
			}
			if ((Object)(object)rocket.backpack != (Object)null)
			{
				((Item)rocket.backpack).blockInteraction = true;
				if ((Object)(object)((Item)rocket.backpack).rig != (Object)null)
				{
					((Item)rocket.backpack).rig.isKinematic = true;
				}
			}
			RegisterSpawned(spawned, point, paced, category, spawnMode);
			if (paced)
			{
				yield break;
			}
			switch (spawnMode)
			{
			case 1:
				yield break;
			case 2:
			{
				float num = ((lightDelayOverride >= 0f) ? lightDelayOverride : Mathf.Max(0.15f, ModConfig.LightDelay.Value));
				if (num > 0f)
				{
					yield return (object)new WaitForSeconds(num);
				}
				if (!((Object)(object)spawned == (Object)null))
				{
					if ((Object)(object)rocket.view != (Object)null)
					{
						rocket.view.RPC("RPCLightRocket", (RpcTarget)0, Array.Empty<object>());
					}
					if ((Object)(object)rocket.rocketFX != (Object)null)
					{
						rocket.rocketFX.RocketLight(0f);
					}
				}
				yield break;
			}
			}
			float num2 = ((lightDelayOverride >= 0f) ? lightDelayOverride : Mathf.Max(0f, ModConfig.LightDelay.Value));
			if (num2 > 0f)
			{
				yield return (object)new WaitForSeconds(num2);
			}
			if (!((Object)(object)spawned == (Object)null))
			{
				if ((Object)(object)rocket.view == (Object)null)
				{
					Plugin.Log.LogWarning((object)"火箭背包缺少 PhotonView,无法同步点燃。");
				}
				else
				{
					rocket.Light();
				}
			}
		}

		private int CountCategory(SpawnCategory cat)
		{
			int num = 0;
			for (int i = 0; i < _items.Count; i++)
			{
				if ((Object)(object)_items[i].go != (Object)null && _items[i].category == cat)
				{
					num++;
				}
			}
			return num;
		}

		public void LightCategory(SpawnCategory cat)
		{
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < _items.Count; i++)
			{
				SpawnedItem value = _items[i];
				if (!((Object)(object)value.go == (Object)null) && value.category == cat)
				{
					Rocketpack component = value.go.GetComponent<Rocketpack>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.view == (Object)null))
					{
						value.spawnMode = 0;
						_items[i] = value;
						component.Light();
						num++;
					}
				}
			}
			if (num > 0)
			{
				ShowNotice(Lang.L("已点燃 ", "Lit ") + num + Lang.L(" 枚", " items"));
			}
		}

		public void DeleteCategory(SpawnCategory cat)
		{
			int num = DestroyWhere((SpawnedItem it) => it.category == cat);
			if (num > 0)
			{
				ShowNotice(Lang.L("已删除 ", "Deleted ") + num + Lang.L(" 枚", " items"));
			}
		}

		public void DeleteAll()
		{
			int num = DestroyWhere((SpawnedItem _) => true);
			if (num > 0)
			{
				ShowNotice(Lang.L("已删除全部 ", "Deleted all ") + num + Lang.L(" 枚", " items"));
			}
		}

		private int DestroyWhere(Predicate<SpawnedItem> predicate)
		{
			int num = 0;
			for (int i = 0; i < _items.Count; i++)
			{
				if (predicate(_items[i]) && TryDestroy(_items[i].go))
				{
					num++;
				}
			}
			PruneSpawned();
			return num;
		}

		private static bool TryDestroy(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			PhotonView component = go.GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			if (!component.IsMine && !PhotonNetwork.IsMasterClient)
			{
				return false;
			}
			try
			{
				PhotonNetwork.Destroy(go);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("删除火箭背包失败:" + ex.Message));
				return false;
			}
		}

		private IEnumerator KeepLitRoutine()
		{
			WaitForSeconds wait = new WaitForSeconds(2f);
			while (true)
			{
				yield return wait;
				if (!PhotonNetwork.InRoom)
				{
					continue;
				}
				for (int i = 0; i < _items.Count; i++)
				{
					if ((Object)(object)_items[i].go == (Object)null || _items[i].spawnMode != 2)
					{
						continue;
					}
					Rocketpack component = _items[i].go.GetComponent<Rocketpack>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.view == (Object)null))
					{
						component.view.RPC("RPCLightRocket", (RpcTarget)0, Array.Empty<object>());
						if ((Object)(object)component.rocketFX != (Object)null)
						{
							component.rocketFX.RocketLight(0f);
						}
					}
				}
			}
		}
	}
	internal static class FireworkPointPicker
	{
		private static int _cachedSegment = int.MinValue;

		private static Bounds _segmentBounds;

		private static bool _haveSegmentBounds;

		public static bool HasPointClearance(Vector3 point, IList<Vector3> activePoints)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			float value = ModConfig.MinSpawnDistance.Value;
			if (value <= 0f || activePoints == null || activePoints.Count == 0)
			{
				return true;
			}
			float num = value * value;
			int count = activePoints.Count;
			for (int i = 0; i < count; i++)
			{
				Vector3 val = activePoints[i] - point;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return false;
				}
			}
			return true;
		}

		private static bool IsPointUsable(Vector3 candidate, Vector3 anchor, float clearance, bool needLos, bool needSky, float skyHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			LayerMask terrainMapMask = HelperFunctions.terrainMapMask;
			if (clearance > 0f && Physics.CheckSphere(candidate, clearance, LayerMask.op_Implicit(terrainMapMask), (QueryTriggerInteraction)1))
			{
				return false;
			}
			RaycastHit val = default(RaycastHit);
			if (needLos && Physics.Linecast(anchor, candidate, ref val, LayerMask.op_Implicit(terrainMapMask), (QueryTriggerInteraction)1))
			{
				return false;
			}
			if (needSky && !IsOpenSky(candidate, skyHeight))
			{
				return false;
			}
			return true;
		}

		private static bool IsOpenSky(Vector3 point, float checkHeight)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (checkHeight <= 0f)
			{
				return true;
			}
			RaycastHit val = default(RaycastHit);
			return !Physics.Raycast(point, Vector3.up, ref val, checkHeight, LayerMask.op_Implicit(HelperFunctions.terrainMapMask), (QueryTriggerInteraction)1);
		}

		public static bool TryFindBatchPoint(Vector3 anchor, IList<Vector3> activePoints, out Vector3 point)
		{
			//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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			point = Vector3.zero;
			int num = Mathf.Clamp(ModConfig.RingCount.Value, 1, 10);
			float num2 = Mathf.Max(1f, ModConfig.Radius.Value);
			float num3 = Mathf.Max(1f, ModConfig.Height.Value);
			float value = ModConfig.Clearance.Value;
			bool value2 = ModConfig.RequireLineOfSight.Value;
			bool value3 = ModConfig.RequireOpenSky.Value;
			float value4 = ModConfig.SkyCheckHeight.Value;
			for (int i = 0; i < 12; i++)
			{
				int num4 = Random.Range(0, num);
				float num5 = num2 * (float)(num4 + 1);
				Vector2 val = RandomDir();
				Vector3 val2 = anchor + new Vector3(val.x, 0f, val.y) * num5 + Vector3.up * num3;
				if (IsPointUsable(val2, anchor, value, value2, value3, value4) && HasPointClearance(val2, activePoints))
				{
					point = val2;
					return true;
				}
			}
			return false;
		}

		public static bool TryFindContinuousPoint(Vector3 anchor, IList<Vector3> activePoints, out Vector3 point)
		{
			//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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			point = Vector3.zero;
			float num = Mathf.Max(0f, ModConfig.ContinuousInnerRadius.Value);
			float num2 = Mathf.Max(num + 0.1f, ModConfig.ContinuousOuterRadius.Value);
			float num3 = Mathf.Max(1f, ModConfig.Height.Value);
			float value = ModConfig.Clearance.Value;
			bool value2 = ModConfig.RequireLineOfSight.Value;
			bool value3 = ModConfig.RequireOpenSky.Value;
			float value4 = ModConfig.SkyCheckHeight.Value;
			for (int i = 0; i < 12; i++)
			{
				Vector2 val = RandomDir();
				float num4 = Mathf.Sqrt(Random.Range(num * num / (num2 * num2), 1f)) * num2;
				Vector3 val2 = anchor + new Vector3(val.x, 0f, val.y) * num4 + Vector3.up * num3;
				if (IsPointUsable(val2, anchor, value, value2, value3, value4) && HasPointClearance(val2, activePoints))
				{
					point = val2;
					return true;
				}
			}
			return false;
		}

		public static bool TryGetAimPoint(out Vector3 point)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			point = Vector3.zero;
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return false;
			}
			Vector3 val = (Vector3)(((int)Cursor.lockState == 1) ? new Vector3((float)Screen.width * 0.5f, (float)Screen.height * 0.5f, 0f) : Input.mousePosition);
			Ray val2 = main.ScreenPointToRay(val);
			float num = Mathf.Max(1f, ModConfig.RayDistance.Value);
			LayerMask terrainMapMask = HelperFunctions.terrainMapMask;
			RaycastHit val3 = default(RaycastHit);
			if (!Physics.Raycast(val2, ref val3, num, LayerMask.op_Implicit(terrainMapMask), (QueryTriggerInteraction)1))
			{
				return false;
			}
			point = ((RaycastHit)(ref val3)).point + ((RaycastHit)(ref val3)).normal * ModConfig.SurfaceOffset.Value;
			return true;
		}

		public static bool TryFindFestivalPoint(Vector3 anchor, IList<Vector3> activePoints, out Vector3 point)
		{
			//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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			point = Vector3.zero;
			float num = Mathf.Max(20f, ModConfig.FestivalAltitude.Value);
			float checkHeight = Mathf.Max(num * 1.2f, ModConfig.SkyCheckHeight.Value);
			float value = ModConfig.Clearance.Value;
			bool num2 = ModConfig.FestivalScope.Value == 1;
			Bounds bounds = default(Bounds);
			bool flag = num2 && TryGetSegmentBounds(out bounds);
			Vector3 val = default(Vector3);
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < 20; i++)
			{
				if (flag)
				{
					float num3 = Mathf.Max(1f, ((Bounds)(ref bounds)).extents.x);
					float num4 = Mathf.Max(1f, ((Bounds)(ref bounds)).extents.z);
					((Vector3)(ref val))..ctor(((Bounds)(ref bounds)).center.x + (Random.value - 0.5f) * 2f * num3, 0f, ((Bounds)(ref bounds)).center.z + (Random.value - 0.5f) * 2f * num4);
				}
				else
				{
					float num5 = Mathf.Max(5f, ModConfig.FestivalRadius.Value);
					Vector2 val2 = RandomDir();
					float num6 = Mathf.Sqrt(Random.value) * num5;
					val = anchor + new Vector3(val2.x, 0f, val2.y) * num6;
				}
				float num7 = SampleGroundY(val, anchor.y);
				((Vector3)(ref val3))..ctor(val.x, num7 + num, val.z);
				if (IsOpenSky(val3, checkHeight) && (!(value > 0f) || !Physics.CheckSphere(val3, value, LayerMask.op_Implicit(HelperFunctions.terrainMapMask), (QueryTriggerInteraction)1)) && HasPointClearance(val3, activePoints))
				{
					point = val3;
					return true;
				}
			}
			return false;
		}

		private static float SampleGroundY(Vector3 ground, float fallback)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Vector3(ground.x, fallback + 500f, ground.z), Vector3.down, ref val, 1000f, LayerMask.op_Implicit(HelperFunctions.terrainMapMask), (QueryTriggerInteraction)1))
			{
				return ((RaycastHit)(ref val)).point.y;
			}
			return fallback;
		}

		public static bool TryGetSegmentBounds(out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected I4, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			try
			{
				if (!MapHandler.Exists)
				{
					return false;
				}
				int num = (int)MapHandler.CurrentSegmentNumber;
				if (_haveSegmentBounds && _cachedSegment == num)
				{
					bounds = _segmentBounds;
					return true;
				}
				if ((Object)(object)Singleton<MapHandler>.Instance == (Object)null || Singleton<MapHandler>.Instance.segments == null)
				{
					return false;
				}
				if (num < 0 || num >= Singleton<MapHandler>.Instance.segments.Length)
				{
					return false;
				}
				GameObject segmentParent = Singleton<MapHandler>.Instance.segments[num].segmentParent;
				if ((Object)(object)segmentParent == (Object)null)
				{
					return false;
				}
				Renderer[] componentsInChildren = segmentParent.GetComponentsInChildren<Renderer>(true);
				if (componentsInChildren == null || componentsInChildren.Length == 0)
				{
					return false;
				}
				Bounds bounds2 = componentsInChildren[0].bounds;
				for (int i = 1; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null)
					{
						((Bounds)(ref bounds2)).Encapsulate(componentsInChildren[i].bounds);
					}
				}
				Vector3 size = ((Bounds)(ref bounds2)).size;
				if (((Vector3)(ref size)).sqrMagnitude < 1f)
				{
					return false;
				}
				_cachedSegment = num;
				_segmentBounds = bounds2;
				_haveSegmentBounds = true;
				bounds = bounds2;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static Vector2 RandomDir()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = Random.insideUnitCircle;
			if (((Vector2)(ref val)).sqrMagnitude < 0.0001f)
			{
				val = Vector2.right;
			}
			return ((Vector2)(ref val)).normalized;
		}
	}
	internal static class FireworkPrefabRegistry
	{
		private const string RocketpackResourcePath = "0_Items/Rocketpack";

		private static string _resolved;

		private static bool _searched;

		public static string ResolvePrefabPath()
		{
			string text = ModConfig.PrefabName?.Value;
			if (!string.IsNullOrWhiteSpace(text))
			{
				text = text.Trim();
				if (!text.Contains("/"))
				{
					return "0_Items/" + text;
				}
				return text;
			}
			if (!string.IsNullOrEmpty(_resolved))
			{
				return _resolved;
			}
			if (_searched)
			{
				return null;
			}
			_searched = true;
			GameObject val = Resources.Load<GameObject>("0_Items/Rocketpack");
			if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<Rocketpack>() != (Object)null)
			{
				_resolved = "0_Items/Rocketpack";
				return _resolved;
			}
			GameObject[] array = Resources.LoadAll<GameObject>("0_Items");
			foreach (GameObject val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.GetComponent<Rocketpack>() != (Object)null)
				{
					_resolved = "0_Items/" + ((Object)val2).name;
					return _resolved;
				}
			}
			Plugin.Log.LogError((object)"未能自动定位火箭背包预制体,请在配置文件中手动填写「预制体名」。");
			return null;
		}

		public static void Reset()
		{
			_resolved = null;
			_searched = false;
		}
	}
	internal static class ModConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<KeyCode> Hotkey;

		public static ConfigEntry<bool> MiddleClickEnabled;

		public static ConfigEntry<string> PrefabName;

		public static ConfigEntry<int> Count;

		public static ConfigEntry<float> Radius;

		public static ConfigEntry<int> RingCount;

		public static ConfigEntry<float> BatchInterval;

		public static ConfigEntry<float> Height;

		public static ConfigEntry<float> Interval;

		public static ConfigEntry<int> MaxConcurrent;

		public static ConfigEntry<float> MinSpawnDistance;

		public static ConfigEntry<bool> ContinuousEnabled;

		public static ConfigEntry<KeyCode> ContinuousKey;

		public static ConfigEntry<float> ContinuousRate;

		public static ConfigEntry<float> ContinuousInnerRadius;

		public static ConfigEntry<float> ContinuousOuterRadius;

		public static ConfigEntry<bool> PacingEnabled;

		public static ConfigEntry<float> BlossomInterval;

		public static ConfigEntry<int> SimultaneousCount;

		public static ConfigEntry<float> LightDelay;

		public static ConfigEntry<bool> RequireOpenSky;

		public static ConfigEntry<bool> RequireLineOfSight;

		public static ConfigEntry<float> Clearance;

		public static ConfigEntry<float> SkyCheckHeight;

		public static ConfigEntry<float> SurfaceOffset;

		public static ConfigEntry<float> RayDistance;

		public static ConfigEntry<bool> FestivalEnabled;

		public static ConfigEntry<KeyCode> FestivalKey;

		public static ConfigEntry<int> FestivalScope;

		public static ConfigEntry<float> FestivalRadius;

		public static ConfigEntry<float> FestivalAltitude;

		public static ConfigEntry<float> FestivalRate;

		public static ConfigEntry<KeyCode> HeartKey;

		public static ConfigEntry<int> HeartDensity;

		public static ConfigEntry<float> HeartSize;

		public static ConfigEntry<float> HeartInterval;

		public static ConfigEntry<float> HeartForward;

		public static ConfigEntry<int> HeartOrder;

		public static ConfigEntry<int> PatternSpawnMode;

		public static ConfigEntry<KeyCode> PanelKey;

		public static ConfigEntry<float> PanelScale;

		public static ConfigEntry<float> PanelX;

		public static ConfigEntry<float> PanelY;

		public static ConfigEntry<float> PanelWidth;

		public static ConfigEntry<float> PanelHeight;

		public static ConfigEntry<int> Language;

		public static ConfigEntry<bool> SquirtleEnabled;

		public static ConfigEntry<KeyCode> SquirtleKey;

		public static ConfigEntry<int> SquirtlePattern;

		public static ConfigEntry<int> SquirtleDensity;

		public static ConfigEntry<float> SquirtleWidth;

		public static ConfigEntry<float> SquirtleDistance;

		public static ConfigEntry<float> SquirtleHeightOffset;

		public static void Bind(ConfigFile config)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Expected O, but got Unknown
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Expected O, but got Unknown
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Expected O, but got Unknown
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Expected O, but got Unknown
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Expected O, but got Unknown
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Expected O, but got Unknown
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Expected O, but got Unknown
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Expected O, but got Unknown
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Expected O, but got Unknown
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Expected O, but got Unknown
			//IL_0547: Unknown result type (might be due to invalid IL or missing references)
			//IL_0551: Expected O, but got Unknown
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Expected O, but got Unknown
			//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c1: Expected O, but got Unknown
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Expected O, but got Unknown
			//IL_0639: Unknown result type (might be due to invalid IL or missing references)
			//IL_0643: Expected O, but got Unknown
			//IL_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_067b: Expected O, but got Unknown
			//IL_06a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b3: Expected O, but got Unknown
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06df: Expected O, but got Unknown
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_070b: Expected O, but got Unknown
			//IL_0758: Unknown result type (might be due to invalid IL or missing references)
			//IL_0762: Expected O, but got Unknown
			//IL_0800: Unknown result type (might be due to invalid IL or missing references)
			//IL_080a: Expected O, but got Unknown
			//IL_0862: Unknown result type (might be due to invalid IL or missing references)
			//IL_086c: Expected O, but got Unknown
			//IL_0891: Unknown result type (might be due to invalid IL or missing references)
			//IL_089b: Expected O, but got Unknown
			//IL_08c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d3: Expected O, but got Unknown
			//IL_0901: Unknown result type (might be due to invalid IL or missing references)
			//IL_090b: Expected O, but got Unknown
			//IL_0939: Unknown result type (might be due to invalid IL or missing references)
			//IL_0943: Expected O, but got Unknown
			Enabled = config.Bind<bool>("0-总开关", "启用", true, "烟花秀总开关。关闭后快捷键与中键点选均不再生成烟花(已在空中的烟花不受影响)。");
			Hotkey = config.Bind<KeyCode>("1-按键", "快捷键", (KeyCode)0, "在附近空中释放烟花的按键。默认留空(未绑定),可在面板中设置。");
			MiddleClickEnabled = config.Bind<bool>("1-按键", "中键点选", true, "是否启用鼠标中键点选生成烟花;按住中键可连续生成。");
			Count = config.Bind<int>("2-烟花规模", "数量", 6, new ConfigDescription("按快捷键时单次释放的烟花(火箭背包)数量。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>()));
			Radius = config.Bind<float>("2-烟花规模", "散布半径", 15f, new ConfigDescription("烟花围绕玩家水平散布的半径(米),同时也是多圈烟花的圈距。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			RingCount = config.Bind<int>("2-烟花规模", "圈数", 1, new ConfigDescription("多圈烟花的圈数;设为 3、散布半径 15m 时,会在半径 15/30/45m 三个圆上生成烟花。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			BatchInterval = config.Bind<float>("2-烟花规模", "每圈间隔", 0.15f, new ConfigDescription("按快捷键释放时,同批烟花每枚之间的生成间隔(秒),用于形成接连绽放的观感。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			Height = config.Bind<float>("2-烟花规模", "高度", 12f, new ConfigDescription("烟花相对玩家位置抬升的高度(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			Interval = config.Bind<float>("2-烟花规模", "生成间隔", 0.15f, new ConfigDescription("中键连续点选时两次生成之间的最短间隔(秒)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 2f), Array.Empty<object>()));
			MaxConcurrent = config.Bind<int>("2-烟花规模", "最大同时存在", 30, new ConfigDescription("同时存在的烟花数量上限,达到上限后停止生成,直到旧烟花消失。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), Array.Empty<object>()));
			MinSpawnDistance = config.Bind<float>("2-烟花规模", "最小间距", 8f, new ConfigDescription("任意两个尚未爆炸的烟花之间的最小水平距离(米),避免生成在同一位置后互相叠加爆炸。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
			ContinuousEnabled = config.Bind<bool>("5-连续烟花", "启用", true, "是否允许使用连续烟花功能(按 G 键开启/停止持续释放)。");
			ContinuousKey = config.Bind<KeyCode>("5-连续烟花", "开关按键", (KeyCode)0, "开启/停止连续释放烟花的按键。默认留空(未绑定),可在面板中设置。");
			ContinuousRate = config.Bind<float>("5-连续烟花", "每秒个数", 3f, new ConfigDescription("连续释放时每秒生成的烟花数量。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 20f), Array.Empty<object>()));
			ContinuousInnerRadius = config.Bind<float>("5-连续烟花", "内圈半径", 10f, new ConfigDescription("连续释放时生成区域的圆环内半径(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			ContinuousOuterRadius = config.Bind<float>("5-连续烟花", "外圈半径", 30f, new ConfigDescription("连续释放时生成区域的圆环外半径(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 80f), Array.Empty<object>()));
			PacingEnabled = config.Bind<bool>("5-连续烟花", "绽放节奏", false, "开启后按「每秒个数」「绽放间隔」「同期点火数」自动安排每个火箭背包的点火时间,使烟花持续在空中绽放而不是同时炸完。");
			BlossomInterval = config.Bind<float>("5-连续烟花", "绽放间隔", 0.5f, new ConfigDescription("开启绽放节奏后,每组烟花点火之间相隔的时间(秒)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), Array.Empty<object>()));
			SimultaneousCount = config.Bind<int>("5-连续烟花", "同期点火数", 3, new ConfigDescription("开启绽放节奏后,每组同时点火的烟花个数;例如每秒 6 个、间隔 0.5 秒、同期 3 个时,每 3 个一组、每组间隔 0.5 秒点火。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>()));
			PrefabName = config.Bind<string>("3-生成", "预制体名", "", "留空自动探测,一般无需修改。默认对应游戏资源 0_Items/Rocketpack。");
			LightDelay = config.Bind<float>("3-生成", "点燃延迟", 0.3f, new ConfigDescription("生成后延迟多少秒再点燃,确保其他玩家已收到生成事件。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			RequireOpenSky = config.Bind<bool>("4-位置校验", "仅露天", true, "按快捷键释放时,跳过上方被地形或建筑遮挡的位置,避免烟花卡在洞里。");
			RequireLineOfSight = config.Bind<bool>("4-位置校验", "需要视线", true, "按快捷键释放时,跳过与玩家之间被地形遮挡的位置。");
			Clearance = config.Bind<float>("4-位置校验", "空间检测半径", 0.6f, new ConfigDescription("生成点周围多大范围内不允许有地形(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			SkyCheckHeight = config.Bind<float>("4-位置校验", "露天检测高度", 60f, new ConfigDescription("向上探测多高以内有遮挡就视为不露天(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>()));
			SurfaceOffset = config.Bind<float>("4-位置校验", "点选表面偏移", 0.8f, new ConfigDescription("中键点选时,生成点沿命中表面法线外移的距离(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			RayDistance = config.Bind<float>("4-位置校验", "点选射线距离", 120f, new ConfigDescription("中键点选时的最大射线距离(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 500f), Array.Empty<object>()));
			FestivalEnabled = config.Bind<bool>("6-春节模式", "启用", true, "是否允许使用春节模式(按开关按键开始/停止在高空持续撒烟花)。");
			FestivalKey = config.Bind<KeyCode>("6-春节模式", "开关按键", (KeyCode)0, "开启/停止春节模式的按键。默认留空(未绑定),可在面板中设置。");
			FestivalScope = config.Bind<int>("6-春节模式", "范围", 0, new ConfigDescription("0=跟随玩家:以玩家为中心、按「范围半径」撒点;1=整个地图:覆盖当前区域全部地面。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1), Array.Empty<object>()));
			FestivalRadius = config.Bind<float>("6-春节模式", "范围半径", 60f, new ConfigDescription("跟随玩家模式下撒点的半径(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 300f), Array.Empty<object>()));
			FestivalAltitude = config.Bind<float>("6-春节模式", "高空高度", 90f, new ConfigDescription("烟花至少抬升到地表以上多高(米),保证足够高、无遮挡。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 300f), Array.Empty<object>()));
			FestivalRate = config.Bind<float>("6-春节模式", "每秒个数", 5f, new ConfigDescription("春节模式每秒生成的烟花数量。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>()));
			HeartKey = config.Bind<KeyCode>("7-心形礼花", "快捷键", (KeyCode)0, "在玩家正前方高空放一颗由烟花组成的爱心。默认留空(未绑定),可在面板中设置。");
			HeartDensity = config.Bind<int>("7-心形礼花", "密度", 45, new ConfigDescription("爱心轮廓上烟花的疏密程度(与杰尼龟图案同一套密度含义)。越大越清晰,同时生成的烟花与网络压力也越大;烟花数量与点火节奏会按密度和爱心大小自动推算。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 120), Array.Empty<object>()));
			HeartSize = config.Bind<float>("7-心形礼花", "爱心大小", 12f, new ConfigDescription("爱心形状的大小(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 40f), Array.Empty<object>()));
			HeartInterval = config.Bind<float>("7-心形礼花", "绽放间隔", 0.06f, new ConfigDescription("爱心烟花逐朵点火的时间间隔(秒)。所有烟花先同时生成,再按间隔依次点燃。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
			HeartForward = config.Bind<float>("7-心形礼花", "爱心距离", 18f, new ConfigDescription("爱心中心相对玩家的水平距离(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			HeartOrder = config.Bind<int>("7-心形礼花", "点火顺序", 0, new ConfigDescription("爱心烟花的点火顺序:0=对称下落(从顶部中点左右对称逐行向下、最后到心尖),1=整圈描边(沿周长绕一圈),2=心尖向上(从下往上),3=随机。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>()));
			PatternSpawnMode = config.Bind<int>("7-心形礼花", "生成模式", 0, new ConfigDescription("心形与图案烟花共用的生成模式:0=点燃绽放(生成后按时点燃、升空爆炸);1=生成不点燃(仅生成背包静置空中,配合「删除」按钮清理,不爆炸);2=点燃不发射(持续燃烧、永不升空爆炸,配合「删除」按钮清理)。1、2 模式无爆炸,适合低性能电脑展示图案,且可随时用「点燃」按钮把它们变为真实烟花。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			PanelKey = config.Bind<KeyCode>("8-面板", "面板开关按键", (KeyCode)286, "打开/关闭本 Mod 控制面板的按键。");
			PanelScale = config.Bind<float>("8-面板", "面板缩放", 1f, new ConfigDescription("面板整体缩放比例,可在面板底部用「+/-」调整。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2.5f), Array.Empty<object>()));
			PanelX = config.Bind<float>("8-面板", "面板位置X", 28f, "面板左上角 X 坐标,拖动面板后自动保存。");
			PanelY = config.Bind<float>("8-面板", "面板位置Y", 28f, "面板左上角 Y 坐标,拖动面板后自动保存。");
			PanelWidth = config.Bind<float>("8-面板", "面板宽度", 680f, "面板宽度,拖拽右下角后自动保存。");
			PanelHeight = config.Bind<float>("8-面板", "面板高度", 560f, "面板高度,拖拽右下角后自动保存。");
			Language = config.Bind<int>("8-面板", "语言/Language", 0, new ConfigDescription("面板语言:0=中文,1=English。也可在面板底部的语言按钮中切换。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1), Array.Empty<object>()));
			SquirtleEnabled = config.Bind<bool>("9-杰尼龟的烟花", "启用", true, "是否允许使用杰尼龟图案烟花(按快捷键在玩家前方用烟花组成预设图案)。");
			SquirtleKey = config.Bind<KeyCode>("9-杰尼龟的烟花", "快捷键", (KeyCode)0, "在玩家正前方用烟花组成预设图案的按键。默认留空(未绑定),可在面板中设置。");
			SquirtlePattern = config.Bind<int>("9-杰尼龟的烟花", "图案", 0, new ConfigDescription("杰尼龟烟花使用的预设图案:0=囍、1=笑脸、2=PEAK、3=杰尼龟(>ε< 颜文字)。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>()));
			SquirtleDensity = config.Bind<int>("9-杰尼龟的烟花", "密度", 45, new ConfigDescription("图案的烟花疏密程度(每米图案轮廓上的烟花数)。越大越清晰,同时生成的烟花与网络压力也越大;数量与点火节奏会按密度和大小自动推算。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 120), Array.Empty<object>()));
			SquirtleWidth = config.Bind<float>("9-杰尼龟的烟花", "大小", 45f, new ConfigDescription("整个图案横向占据的总宽度(米)。同时决定图案的点数与点火节奏:越大图案越壮观、烟花越多。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>()));
			SquirtleDistance = config.Bind<float>("9-杰尼龟的烟花", "放置距离", 25f, new ConfigDescription("图案相对玩家正前方的水平距离(米)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			SquirtleHeightOffset = config.Bind<float>("9-杰尼龟的烟花", "高度偏移", 0f, new ConfigDescription("图案相对玩家中心的垂直偏移(米),正值抬高、负值降低。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-20f, 20f), Array.Empty<object>()));
		}

		public static void Save()
		{
			Plugin instance = Plugin.Instance;
			if (instance != null)
			{
				ConfigFile config = ((BaseUnityPlugin)instance).Config;
				if (config != null)
				{
					config.Save();
				}
			}
		}
	}
	internal static class PatternCatalog
	{
		public const int PatternXi = 0;

		public const int PatternSmile = 1;

		public const int PatternPeak = 2;

		public const int PatternSquirtle = 3;

		public static readonly string[] Names = new string[4] { "囍", "笑脸", "PEAK", "杰尼龟" };

		public static readonly string[] NamesEn = new string[4] { "Double Happiness", "Smiley", "PEAK", "Squirtle" };

		private static readonly string[] XiRows = new string[17]
		{
			"....#.......#....", "#################", "#################", "....#.......#....", ".#######.#######.", ".................", ".#######.#######.", ".#....##.##....#.", ".#######.#######.", "..#..#.....#..#..",
			"..#..#.....#..#..", "########.########", ".................", ".#######.#######.", ".#....##.##....#.", ".#######.#######.", ".#....##.##....#."
		};

		private const string SquirtleHeart = "0.00,0.35 0.00,0.38 0.03,0.46 0.11,0.56 0.22,0.64 0.37,0.66 0.53,0.62 0.65,0.52 0.72,0.38 0.72,0.22 0.65,0.06 0.53,-0.09 0.37,-0.23 0.22,-0.36 0.11,-0.47 0.03,-0.57 0.00,-0.64 0.00,-0.66 -0.00,-0.64 -0.03,-0.57 -0.11,-0.47 -0.22,-0.36 -0.37,-0.23 -0.53,-0.09 -0.65,0.06 -0.72,0.22 -0.72,0.38 -0.65,0.52 -0.53,0.62 -0.37,0.66 -0.22,0.64 -0.11,0.56 -0.03,0.46 -0.00,0.38";

		private const string SquirtleEyeSharp = "-2.76,4.32 -2.57,4.20 -2.37,4.08 -2.17,3.97 -1.97,3.85 -1.78,3.73 -1.58,3.61 -1.38,3.49 -1.19,3.37 -0.99,3.26 -0.79,3.14 -0.59,3.02 -0.40,2.90 -0.40,2.90 -0.64,2.86 -0.89,2.82 -1.14,2.78 -1.38,2.74 -1.63,2.70 -1.88,2.66 -2.12,2.62 -2.37,2.58 -2.62,2.54 -2.86,2.51 -3.11,2.47 -3.36,2.43";

		private const string SquirtleEyeLess = "4.34,2.78 4.11,2.73 3.89,2.68 3.66,2.63 3.43,2.58 3.21,2.53 2.98,2.49 2.75,2.44 2.53,2.39 2.30,2.34 2.07,2.29 1.84,2.24 1.62,2.19 1.62,2.19 1.83,2.08 2.03,1.97 2.24,1.86 2.45,1.76 2.65,1.65 2.86,1.54 3.07,1.43 3.28,1.32 3.48,1.21 3.69,1.10 3.90,1.00 4.11,0.89";

		private const string SquirtleMouth = "0.00,0.92 -0.25,0.91 -0.49,0.88 -0.71,0.83 -0.89,0.77 -1.04,0.69 -1.14,0.60 -1.19,0.51 -1.19,0.41 -1.14,0.32 -1.04,0.23 -0.89,0.15 -0.71,0.09 -0.49,0.04 -0.25,0.01 -0.00,0.00 0.00,0.00 -0.26,-0.01 -0.51,-0.04 -0.74,-0.09 -0.94,-0.16 -1.12,-0.24 -1.25,-0.33 -1.35,-0.44 -1.39,-0.54 -1.39,-0.66 -1.35,-0.76 -1.25,-0.87 -1.12,-0.96 -0.94,-1.04 -0.74,-1.11 -0.51,-1.16 -0.26,-1.19 -0.00,-1.20";

		private const string SquirtleHandLeft = "-0.79,-2.08 -0.98,-2.01 -1.12,-1.87 -1.27,-1.72 -1.33,-1.54 -1.40,-1.36 -1.53,-1.20 -1.53,-0.99 -1.53,-0.78 -1.53,-0.57 -1.53,-0.36 -1.46,-0.18 -1.40,0.00 -1.34,0.18 -1.28,0.37 -1.13,0.52 -0.98,0.66 -0.92,0.84 -0.78,0.99 -0.63,1.14 -0.48,1.29 -0.33,1.44 -0.19,1.58 -0.03,1.71 0.14,1.79 0.29,1.94 0.48,2.00 0.65,2.08 0.86,2.08 1.07,2.08 1.28,2.08 1.28,1.87 1.40,1.71 1.53,1.55 1.53,1.34 1.53,1.14 1.53,0.93 1.53,0.72 1.46,0.54 1.40,0.35 1.33,0.17 1.27,-0.01 1.16,-0.17 1.15,-0.38 1.00,-0.52 0.92,-0.70";

		private const string SquirtleHandRight = "2.92,-2.07 3.09,-2.07 3.22,-2.01 3.37,-1.96 3.53,-1.96 3.68,-1.91 3.81,-1.84 3.98,-1.84 4.03,-1.72 4.19,-1.72 4.36,-1.72 4.52,-1.72 4.65,-1.64 4.80,-1.60 4.97,-1.60 5.13,-1.60 5.30,-1.60 5.45,-1.64 5.58,-1.72 5.74,-1.72 5.87,-1.82 5.98,-1.94 6.00,-2.10 6.00,-2.26 6.00,-2.43 5.96,-2.55 5.88,-2.64 5.87,-2.80 5.75,-2.91 5.63,-3.03 5.52,-3.15 5.40,-3.27 5.28,-3.38 5.17,-3.50 5.05,-3.61 4.93,-3.66 4.84,-3.73 4.72,-3.83 4.60,-3.95 4.45,-3.98 4.33,-4.09 4.18,-4.13 4.06,-4.25 3.93,-4.32 3.76,-4.32 3.72,-4.44 3.55,-4.44 3.42,-4.53 3.27,-4.57 3.15,-4.68 2.99,-4.68 2.92,-4.78 2.78,-4.80 2.61,-4.80 2.45,-4.80";

		private static readonly string[] SquirtleParts = new string[6] { "-5.10,4.20,0.78", "-1.90,3.40,1.00", "2.60,1.90,1.00", "-0.20,0.20,1.00", "-4.60,-1.30,1.02", "4.50,-2.60,1.02" };

		public static string LocalizedName(int pattern)
		{
			int num = Mathf.Clamp(pattern, 0, Names.Length - 1);
			if (!Lang.English)
			{
				return Names[num];
			}
			return NamesEn[num];
		}

		public static List<Vector3>[] Build(int pattern, int count)
		{
			count = Mathf.Max(4, count);
			return pattern switch
			{
				1 => new List<Vector3>[1] { BuildSmile(count) }, 
				2 => BuildPeak(count), 
				3 => new List<Vector3>[1] { BuildSquirtle(count) }, 
				_ => new List<Vector3>[1] { BuildXi(count) }, 
			};
		}

		private static List<Vector3> BuildXi(int count)
		{
			return RowsToPoints(XiRows, '#');
		}

		private static List<Vector3> BuildSmile(int count)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>(count + 16);
			int num = Mathf.Max(8, Mathf.RoundToInt((float)count * 0.6f));
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)Math.PI * 2f * (float)i / (float)num;
				float num3 = 5f - ((i % 3 == 0) ? 0.15f : 0f);
				list.Add(new Vector3(Mathf.Cos(num2) * num3, Mathf.Sin(num2) * num3, 0f));
			}
			int n = Mathf.Max(3, Mathf.RoundToInt((float)count * 0.09f));
			AddDot(list, new Vector3(-2f, 2f, 0f), 0.8f, n);
			AddDot(list, new Vector3(2f, 2f, 0f), 0.8f, n);
			float num4 = 3.2f;
			float num5 = 1.2f;
			float num6 = 1.8f;
			int num7 = Mathf.Max(6, count - list.Count);
			for (int j = 0; j < num7; j++)
			{
				float num8 = (float)Math.PI * (float)j / (float)Mathf.Max(1, num7 - 1);
				list.Add(new Vector3(num4 * Mathf.Cos(num8), 0f - num5 - num6 * Mathf.Sin(num8), 0f));
			}
			return list;
		}

		private static void AddDot(List<Vector3> points, Vector3 center, float radius, int n)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < n; i++)
			{
				float num2 = Random.Range(0f, (float)Math.PI * 2f);
				float num3 = radius * Mathf.Sqrt(Random.Range(0f, 1f));
				points.Add(center + new Vector3(Mathf.Cos(num2) * num3, Mathf.Sin(num2) * num3, 0f));
				num++;
			}
		}

		private static List<Vector3> BuildSquirtle(int count)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[6] { "0.00,0.35 0.00,0.38 0.03,0.46 0.11,0.56 0.22,0.64 0.37,0.66 0.53,0.62 0.65,0.52 0.72,0.38 0.72,0.22 0.65,0.06 0.53,-0.09 0.37,-0.23 0.22,-0.36 0.11,-0.47 0.03,-0.57 0.00,-0.64 0.00,-0.66 -0.00,-0.64 -0.03,-0.57 -0.11,-0.47 -0.22,-0.36 -0.37,-0.23 -0.53,-0.09 -0.65,0.06 -0.72,0.22 -0.72,0.38 -0.65,0.52 -0.53,0.62 -0.37,0.66 -0.22,0.64 -0.11,0.56 -0.03,0.46 -0.00,0.38", "-2.76,4.32 -2.57,4.20 -2.37,4.08 -2.17,3.97 -1.97,3.85 -1.78,3.73 -1.58,3.61 -1.38,3.49 -1.19,3.37 -0.99,3.26 -0.79,3.14 -0.59,3.02 -0.40,2.90 -0.40,2.90 -0.64,2.86 -0.89,2.82 -1.14,2.78 -1.38,2.74 -1.63,2.70 -1.88,2.66 -2.12,2.62 -2.37,2.58 -2.62,2.54 -2.86,2.51 -3.11,2.47 -3.36,2.43", "4.34,2.78 4.11,2.73 3.89,2.68 3.66,2.63 3.43,2.58 3.21,2.53 2.98,2.49 2.75,2.44 2.53,2.39 2.30,2.34 2.07,2.29 1.84,2.24 1.62,2.19 1.62,2.19 1.83,2.08 2.03,1.97 2.24,1.86 2.45,1.76 2.65,1.65 2.86,1.54 3.07,1.43 3.28,1.32 3.48,1.21 3.69,1.10 3.90,1.00 4.11,0.89", "0.00,0.92 -0.25,0.91 -0.49,0.88 -0.71,0.83 -0.89,0.77 -1.04,0.69 -1.14,0.60 -1.19,0.51 -1.19,0.41 -1.14,0.32 -1.04,0.23 -0.89,0.15 -0.71,0.09 -0.49,0.04 -0.25,0.01 -0.00,0.00 0.00,0.00 -0.26,-0.01 -0.51,-0.04 -0.74,-0.09 -0.94,-0.16 -1.12,-0.24 -1.25,-0.33 -1.35,-0.44 -1.39,-0.54 -1.39,-0.66 -1.35,-0.76 -1.25,-0.87 -1.12,-0.96 -0.94,-1.04 -0.74,-1.11 -0.51,-1.16 -0.26,-1.19 -0.00,-1.20", "-0.79,-2.08 -0.98,-2.01 -1.12,-1.87 -1.27,-1.72 -1.33,-1.54 -1.40,-1.36 -1.53,-1.20 -1.53,-0.99 -1.53,-0.78 -1.53,-0.57 -1.53,-0.36 -1.46,-0.18 -1.40,0.00 -1.34,0.18 -1.28,0.37 -1.13,0.52 -0.98,0.66 -0.92,0.84 -0.78,0.99 -0.63,1.14 -0.48,1.29 -0.33,1.44 -0.19,1.58 -0.03,1.71 0.14,1.79 0.29,1.94 0.48,2.00 0.65,2.08 0.86,2.08 1.07,2.08 1.28,2.08 1.28,1.87 1.40,1.71 1.53,1.55 1.53,1.34 1.53,1.14 1.53,0.93 1.53,0.72 1.46,0.54 1.40,0.35 1.33,0.17 1.27,-0.01 1.16,-0.17 1.15,-0.38 1.00,-0.52 0.92,-0.70", "2.92,-2.07 3.09,-2.07 3.22,-2.01 3.37,-1.96 3.53,-1.96 3.68,-1.91 3.81,-1.84 3.98,-1.84 4.03,-1.72 4.19,-1.72 4.36,-1.72 4.52,-1.72 4.65,-1.64 4.80,-1.60 4.97,-1.60 5.13,-1.60 5.30,-1.60 5.45,-1.64 5.58,-1.72 5.74,-1.72 5.87,-1.82 5.98,-1.94 6.00,-2.10 6.00,-2.26 6.00,-2.43 5.96,-2.55 5.88,-2.64 5.87,-2.80 5.75,-2.91 5.63,-3.03 5.52,-3.15 5.40,-3.27 5.28,-3.38 5.17,-3.50 5.05,-3.61 4.93,-3.66 4.84,-3.73 4.72,-3.83 4.60,-3.95 4.45,-3.98 4.33,-4.09 4.18,-4.13 4.06,-4.25 3.93,-4.32 3.76,-4.32 3.72,-4.44 3.55,-4.44 3.42,-4.53 3.27,-4.57 3.15,-4.68 2.99,-4.68 2.92,-4.78 2.78,-4.80 2.61,-4.80 2.45,-4.80" };
			List<Vector3>[] array2 = new List<Vector3>[array.Length];
			int num = 0;
			for (int i = 0; i < array.Length && i < SquirtleParts.Length; i++)
			{
				List<Vector3> list = new List<Vector3>(64);
				AppendEncoded(list, array[i]);
				if (list.Count == 0)
				{
					array2[i] = list;
					continue;
				}
				float[] array3 = ParseLayout(SquirtleParts[i]);
				if (array3 != null)
				{
					float num2 = float.MaxValue;
					float num3 = float.MinValue;
					float num4 = float.MaxValue;
					float num5 = float.MinValue;
					for (int j = 0; j < list.Count; j++)
					{
						Vector3 val = list[j];
						if (val.x < num2)
						{
							num2 = val.x;
						}
						if (val.x > num3)
						{
							num3 = val.x;
						}
						if (val.y < num4)
						{
							num4 = val.y;
						}
						if (val.y > num5)
						{
							num5 = val.y;
						}
					}
					float num6 = (num2 + num3) * 0.5f;
					float num7 = (num4 + num5) * 0.5f;
					float num8 = array3[2];
					for (int k = 0; k < list.Count; k++)
					{
						Vector3 val2 = list[k];
						list[k] = new Vector3(array3[0] + (val2.x - num6) * num8, array3[1] + (val2.y - num7) * num8, 0f);
					}
				}
				array2[i] = list;
				num += list.Count;
			}
			List<Vector3> list2 = new List<Vector3>(count + 32);
			if (num <= 0)
			{
				return list2;
			}
			foreach (List<Vector3> list3 in array2)
			{
				if (list3 != null && list3.Count != 0)
				{
					int num9 = Mathf.RoundToInt((float)count * (float)list3.Count / (float)num);
					int num10 = Mathf.Min(8, list3.Count);
					num9 = Mathf.Clamp(num9, num10, 600);
					list2.AddRange(ResamplePath(list3, num9));
				}
			}
			return list2;
		}

		private static List<Vector3> ResamplePath(List<Vector3> path, int target)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (path.Count < 2 || target < 2)
			{
				return path;
			}
			float[] array = new float[path.Count];
			float num = 0f;
			for (int i = 1; i < path.Count; i++)
			{
				num = (array[i] = num + Vector3.Distance(path[i - 1], path[i]));
			}
			if (num <= 0.0001f)
			{
				return path;
			}
			List<Vector3> list = new List<Vector3>(target);
			int j = 1;
			for (int k = 0; k < target; k++)
			{
				float num2;
				for (num2 = num * (float)k / (float)(target - 1); j < path.Count - 1 && array[j] < num2; j++)
				{
				}
				float num3 = array[j] - array[j - 1];
				float num4 = ((num3 > 1E-06f) ? ((num2 - array[j - 1]) / num3) : 0f);
				list.Add(Vector3.Lerp(path[j - 1], path[j], Mathf.Clamp01(num4)));
			}
			return list;
		}

		private static float[] ParseLayout(string s)
		{
			string[] array = s.Split(new char[1] { ',' });
			if (array.Length < 3)
			{
				return null;
			}
			float[] array2 = new float[3];
			for (int i = 0; i < 3; i++)
			{
				if (!float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out array2[i]))
				{
					return null;
				}
			}
			return array2;
		}

		private static void AppendEncoded(List<Vector3> points, string encoded)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			int i = 0;
			int length = encoded.Length;
			while (i < length)
			{
				for (; i < length && encoded[i] == ' '; i++)
				{
				}
				int num = encoded.IndexOf(',', i);
				if (num >= 0)
				{
					int num2 = encoded.IndexOf(' ', num);
					if (num2 < 0)
					{
						num2 = length;
					}
					float num3 = float.Parse(encoded.Substring(i, num - i), CultureInfo.InvariantCulture);
					float num4 = float.Parse(encoded.Substring(num + 1, num2 - num - 1), CultureInfo.InvariantCulture);
					points.Add(new Vector3(num3, num4, 0f));
					i = num2 + 1;
					continue;
				}
				break;
			}
		}

		private static List<Vector3>[] BuildPeak(int count)
		{
			int count2 = Mathf.Max(4, count / 4);
			return new List<Vector3>[4]
			{
				LetterP(count2),
				LetterE(count2),
				LetterA(count2),
				LetterK(count2)
			};
		}

		private static List<Vector3> LetterP(int count)
		{
			new List<Vector3>(16);
			return RowsToPoints(new string[7] { "11110", "10001", "10001", "11110", "10000", "10000", "10000" }, '1');
		}

		private static List<Vector3> LetterE(int count)
		{
			return RowsToPoints(new string[7] { "11111", "10000", "10000", "11110", "10000", "10000", "11111" }, '1');
		}

		private static List<Vector3> LetterA(int count)
		{
			return RowsToPoints(new string[7] { "01110", "10001", "10001", "11111", "10001", "10001", "10001" }, '1');
		}

		private static List<Vector3> LetterK(int count)
		{
			return RowsToPoints(new string[7] { "10001", "10010", "10100", "11000", "10100", "10010", "10001" }, '1');
		}

		private static List<Vector3> RowsToPoints(string[] rows, char marker)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			int num = rows.Length;
			int length = rows[0].Length;
			List<Vector3> list = new List<Vector3>(num * length);
			for (int i = 0; i < num; i++)
			{
				string text = rows[i];
				for (int j = 0; j < length; j++)
				{
					if (j < text.Length && text[j] == marker)
					{
						list.Add(new Vector3((float)j, (float)(num - 1 - i), 0f));
					}
				}
			}
			return list;
		}
	}
	[BepInPlugin("peak.fireworksshow", "烟花秀", "0.9.3")]
	public class Plugin : BaseUnityPlugin
	{
		private GameObject _host;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_host = new GameObject("FireworksShow_Host");
			((Object)_host).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)_host);
			FireworkLauncher launcher = _host.AddComponent<FireworkLauncher>();
			_host.AddComponent<SpringFestivalMode>().Launcher = launcher;
			PanelTheme.Log = delegate(string msg)
			{
				Log.LogInfo((object)msg);
			};
			PanelHost panelHost = _host.AddComponent<PanelHost>();
			panelHost.Panel = new FireworksPanel();
			panelHost.ToggleKey = () => ModConfig.PanelKey.Value;
			panelHost.LogError = delegate(string msg)
			{
				Log.LogError((object)msg);
			};
			Log.LogInfo((object)"烟花秀 v0.9.3 已加载。");
		}

		private void OnDestroy()
		{
			if ((Object)(object)_host != (Object)null)
			{
				Object.Destroy((Object)(object)_host);
			}
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "peak.fireworksshow";

		public const string Name = "烟花秀";

		public const string Version = "0.9.3";
	}
	internal static class ShowcaseLayout
	{
		public static Vector3[] BuildHeartPoints(Vector3 anchor, float size, int count)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			count = Mathf.Clamp(count, 8, 100);
			size = Mathf.Max(2f, size);
			Camera main = Camera.main;
			Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.forward : Vector3.forward);
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				val = Vector3.forward;
			}
			val = ((Vector3)(ref val)).normalized;
			Vector3 val2 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.right : Vector3.right);
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
			{
				val2 = Vector3.right;
			}
			val2 = ((Vector3)(ref val2)).normalized;
			Vector3 val3 = anchor + val * Mathf.Max(1f, ModConfig.HeartForward.Value);
			float num = Mathf.Max(2f, ModConfig.Height.Value);
			float num2 = size / 32f;
			Vector3[] array = (Vector3[])(object)new Vector3[count];
			float num3 = float.MaxValue;
			float num4 = float.MinValue;
			for (int i = 0; i < count; i++)
			{
				float num5 = (float)Math.PI * 2f * (float)i / (float)count;
				float num6 = 16f * Mathf.Pow(Mathf.Sin(num5), 3f);
				float num7 = 13f * Mathf.Cos(num5) - 5f * Mathf.Cos(2f * num5) - 2f * Mathf.Cos(3f * num5) - Mathf.Cos(4f * num5);
				array[i] = new Vector3(num6 * num2, num7 * num2, 0f);
				if (num7 < num3)
				{
					num3 = num7;
				}
				if (num7 > num4)
				{
					num4 = num7;
				}
			}
			float num8 = (num3 + num4) * 0.5f * num2;
			Vector3[] array2 = (Vector3[])(object)new Vector3[count];
			for (int j = 0; j < count; j++)
			{
				array2[j] = val3 + val2 * array[j].x + Vector3.up * (num + array[j].y - num8);
			}
			return array2;
		}

		public static float[] OrderHeartDelays(Vector3[] points, int order, float interval)
		{
			int num = points.Length;
			float[] array = new float[num];
			if (num == 0)
			{
				return array;
			}
			switch (order)
			{
			case 1:
			{
				for (int num10 = 0; num10 < num; num10++)
				{
					array[num10] = (float)num10 * interval;
				}
				break;
			}
			case 2:
			{
				int[] array4 = new int[num];
				for (int num11 = 0; num11 < num; num11++)
				{
					array4[num11] = num11;
				}
				Array.Sort(array4, (int a, int b) => points[a].y.CompareTo(points[b].y));
				for (int num12 = 0; num12 < num; num12++)
				{
					array[array4[num12]] = (float)num12 * interval;
				}
				break;
			}
			case 3:
			{
				int[] array3 = new int[num];
				for (int num5 = 0; num5 < num; num5++)
				{
					array3[num5] = num5;
				}
				for (int num6 = num - 1; num6 > 0; num6--)
				{
					int num7 = Random.Range(0, num6 + 1);
					int num8 = array3[num6];
					array3[num6] = array3[num7];
					array3[num7] = num8;
				}
				for (int num9 = 0; num9 < num; num9++)
				{
					array[array3[num9]] = (float)num9 * interval;
				}
				break;
			}
			default:
			{
				int[] array2 = new int[num];
				for (int i = 0; i < num; i++)
				{
					array2[i] = i;
				}
				Array.Sort(array2, delegate(int a, int b)
				{
					int num13 = points[b].y.CompareTo(points[a].y);
					return (num13 == 0) ? points[a].x.CompareTo(points[b].x) : num13;
				});
				float num2 = float.NaN;
				int num3 = -1;
				for (int num4 = 0; num4 < num; num4++)
				{
					if (float.IsNaN(num2) || Mathf.Abs(points[array2[num4]].y - num2) > 0.001f)
					{
						num2 = points[array2[num4]].y;
						num3++;
					}
					array[array2[num4]] = (float)num3 * interval;
				}
				break;
			}
			}
			return array;
		}

		public static Vector3[] BuildTextPoints(List<Vector3>[] chars, Vector3 anchor, float totalWidth, float distance, float heightOffset)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3>[] array = BuildTextPointGroups(chars, anchor, totalWidth, distance, heightOffset);
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				num += array[i].Count;
			}
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			int num2 = 0;
			for (int j = 0; j < array.Length; j++)
			{
				for (int k = 0; k < array[j].Count; k++)
				{
					array2[num2++] = array[j][k];
				}
			}
			return array2;
		}

		public static List<Vector3>[] BuildTextPointGroups(List<Vector3>[] chars, Vector3 anchor, float totalWidth, float distance, float heightOffset)
		{
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			int num = chars.Length;
			List<Vector3>[] array = new List<Vector3>[num];
			float num2 = float.MaxValue;
			float num3 = float.MinValue;
			float[] array2 = new float[num];
			float num4 = 0f;
			for (int i = 0; i < num; i++)
			{
				List<Vector3> list = chars[i];
				if (list == null || list.Count == 0)
				{
					array[i] = new List<Vector3>(0);
					continue;
				}
				float num5 = float.MaxValue;
				float num6 = float.MinValue;
				for (int j = 0; j < list.Count; j++)
				{
					Vector3 val = list[j];
					if (val.x < num5)
					{
						num5 = val.x;
					}
					if (val.x > num6)
					{
						num6 = val.x;
					}
					if (val.y < num2)
					{
						num2 = val.y;
					}
					if (val.y > num3)
					{
						num3 = val.y;
					}
				}
				array2[i] = Mathf.Max(0.5f, num6 - num5);
				num4 += array2[i];
			}
			if (num4 <= 0f)
			{
				return array;
			}
			Camera main = Camera.main;
			Vector3 val2 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.forward : Vector3.forward);
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
			{
				val2 = Vector3.forward;
			}
			val2 = ((Vector3)(ref val2)).normalized;
			Vector3 val3 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.right : Vector3.right);
			val3.y = 0f;
			if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
			{
				val3 = Vector3.right;
			}
			val3 = ((Vector3)(ref val3)).normalized;
			float num7 = totalWidth * 0.03f;
			float num8 = num4 + num7 * (float)Mathf.Max(0, num - 1);
			float num9 = Mathf.Max(0.05f, totalWidth / Mathf.Max(0.5f, num8));
			float num10 = Mathf.Max(0.5f, num3 - num2) * num9 * 0.5f;
			Vector3 val4 = anchor + val2 * Mathf.Max(1f, distance);
			float num11 = 0f;
			for (int k = 0; k < num; k++)
			{
				List<Vector3> list2 = chars[k];
				if (list2 == null || list2.Count == 0)
				{
					continue;
				}
				float num12 = float.MaxValue;
				for (int l = 0; l < list2.Count; l++)
				{
					if (list2[l].x < num12)
					{
						num12 = list2[l].x;
					}
				}
				List<Vector3> list3 = new List<Vector3>(list2.Count);
				for (int m = 0; m < list2.Count; m++)
				{
					Vector3 val5 = list2[m];
					float num13 = (num11 + (val5.x - num12)) * num9 - totalWidth * 0.5f;
					float num14 = (val5.y - num2) * num9 - num10 + heightOffset;
					list3.Add(val4 + val3 * num13 + Vector3.up * num14);
				}
				array[k] = list3;
				num11 += array2[k] + num7;
			}
			return array;
		}
	}
	internal sealed class ShowScheduler
	{
		private const float FlightSeconds = 6f;

		private const int MaxSpawnPerFrame = 6;

		private readonly FireworkLauncher _launcher;

		public ShowScheduler(FireworkLauncher launcher)
		{
			_launcher = launcher;
		}

		public IEnumerator RunSimultaneous(Vector3[] points, float[] lightDelays, int spawnMode, SpawnCategory category)
		{
			int num = Mathf.Min(points.Length, lightDelays.Length);
			for (int i = 0; i < num; i++)
			{
				_launcher.StartSpawn(points[i], 0f, paced: false, Mathf.Max(0f, lightDelays[i]), spawnMode, category);
			}
			yield break;
		}

		public IEnumerator RunRolling(Vector3[] points, float[] lightDelays, int concurrentCap, int spawnMode, SpawnCategory category)
		{
			float setup = Mathf.Max(0.15f, _launcher.SetupDelay);
			float start = Time.time;
			int index = 0;
			int count = Mathf.Min(points.Length, lightDelays.Length);
			while (index < count)
			{
				float num = Time.time - start;
				int num2 = 0;
				while (index < count && num2 < 6)
				{
					float num3 = lightDelays[index] - 6f;
					if (num < num3 - setup || _launcher.ActiveCount >= concurrentCap)
					{
						break;
					}
					_launcher.StartSpawn(points[index], 0f, paced: false, setup, spawnMode, category);
					index++;
					num2++;
				}
				yield return null;
			}
		}

		public IEnumerator RunDisplay(Vector3[] points, int spawnMode, SpawnCategory category)
		{
			float setup = Mathf.Max(0.15f, _launcher.SetupDelay);
			int index = 0;
			while (index < points.Length)
			{
				int num = 0;
				while (index < points.Length && num < 6)
				{
					_launcher.StartSpawn(points[index], 0f, paced: false, setup, spawnMode, category);
					index++;
					num++;
				}
				yield return null;
			}
		}
	}
	public class SpringFestivalMode : MonoBehaviour
	{
		public FireworkLauncher Launcher;

		private bool _running;

		private float _nextSpawn;

		public static SpringFestivalMode Instance { get; private set; }

		public bool IsRunning => _running;

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Enabled.Value || !ModConfig.FestivalEnabled.Value)
			{
				Stop();
				return;
			}
			if (!FireworksPanel.IsOpen && Pressed(ModConfig.FestivalKey.Value))
			{
				Toggle();
			}
			if (_running && PhotonNetwork.InRoom && !(Time.time < _nextSpawn))
			{
				Character localCharacter = Character.localCharacter;
				if (!((Object)(object)localCharacter == (Object)null) && FireworkPointPicker.TryFindFestivalPoint(localCharacter.Center, Launcher.ActivePoints, out var point))
				{
					float num = Mathf.Max(0.5f, ModConfig.FestivalRate.Value);
					_nextSpawn = Time.time + 1f / num;
					Launcher.LaunchFirework(point, ModConfig.LightDelay.Value);
				}
			}
		}

		public void Toggle()
		{
			_running = !_running;
			_nextSpawn = 0f;
			Launcher?.ShowNotice(_running ? Lang.L("春节烟花:已开启", "Spring Festival: started") : Lang.L("春节烟花:已停止", "Spring Festival: stopped"));
		}

		public void Stop()
		{
			if (_running)
			{
				_running = false;
				Launcher?.ShowNotice(Lang.L("春节烟花:已停止", "Spring Festival: stopped"));
			}
		}

		private static bool Pressed(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key != 0)
			{
				return Input.GetKeyDown(key);
			}
			return false;
		}
	}
}
namespace FireworksShow.UI
{
	internal sealed class FireworksPanel : ModPanelBase
	{
		private readonly Dictionary<ConfigEntryBase, string> _buffers = new Dictionary<ConfigEntryBase, string>();

		private float _nextSave;

		public static FireworksPanel Instance { get; private set; }

		public static bool IsOpen
		{
			get
			{
				if (Instance != null)
				{
					return Instance.Visible;
				}
				return false;
			}
		}

		protected override string Title => Lang.L("烟花秀 v", "Fireworks Show v") + "0.9.3";

		protected override string TitleNote => Lang.L("全房可见 · 纯视觉", "Visible to everyone · Visual only");

		protected override string[] TabLabels => new string[5]
		{
			Lang.L("概览", "Overview"),
			Lang.L("常规烟花", "Normal"),
			Lang.L("连续烟花", "Continuous"),
			Lang.L("春节模式", "Festival"),
			Lang.L("高级", "Advanced")
		};

		protected override int WindowId => 61802;

		public FireworksPanel()
		{
			Instance = this;
		}

		protected override float LoadScale()
		{
			return ModConfig.PanelScale.Value;
		}

		protected override void SaveScale(float value)
		{
			ModConfig.PanelScale.Value = value;
			SaveSoon();
		}

		protected override Rect LoadWindowRect()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(ModConfig.PanelX.Value, ModConfig.PanelY.Value, ModConfig.PanelWidth.Value, ModConfig.PanelHeight.Value);
		}

		protected override void SaveWindowRect(Rect rect)
		{
			ModConfig.PanelX.Value = ((Rect)(ref rect)).x;
			ModConfig.PanelY.Value = ((Rect)(ref rect)).y;
			ModConfig.PanelWidth.Value = ((Rect)(ref rect)).width;
			ModConfig.PanelHeight.Value = ((Rect)(ref rect)).height;
			SaveSoon();
		}

		protected override void OnOpen()
		{
			_buffers.Clear();
		}

		protected override void DrawStatusStrip()
		{
			int num = FireworkLauncher.Instance?.ActiveCount ?? 0;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(Lang.L($"在场 {num}", $"In air {num}"), PanelTheme.Sub, Array.Empty<GUILayoutOption>());
			GUILayout.Space(16f);
			GUILayout.Label(ContinuousState(), PanelTheme.Sub, Array.Empty<GUILayoutOption>());
			GUILayout.Space(16f);
			GUILayout.Label(FestivalState(), PanelTheme.Sub, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Space(4f);
		}

		protected override void DrawFooterHint()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(Lang.L("按 " + KeyName(ModConfig.PanelKey.Value) + " 开关面板 · 改动即时生效", "Press " + KeyName(ModConfig.PanelKey.Value) + " to toggle · changes apply instantly"), PanelTheme.Hint, Array.Empty<GUILayoutOption>());
		}

		protected override void DrawFooterExtras()
		{
			GUILayout.Space(8f);
			if (GUILayout.Button(Lang.L("English", "中文"), PanelTheme.Mini, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(58f),
				GUILayout.Height(18f)
			}))
			{
				Lang.Toggle();
				_buffers.Clear();
				Notify(Lang.L("已切换为中文。", "Switched to English."));
			}
		}

		private unsafe static string KeyName(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key != 0)
			{
				return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
			}
			return Lang.L("(未绑定)", "(unbound)");
		}

		private string ContinuousState()
		{
			FireworkLauncher instance = FireworkLauncher.Instance;
			if (instance ==