Decompiled source of Divine Delivery v1.3.1

plugins/EndlessDelivery/EndlessDelivery.dll

Decompiled 5 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading.Tasks;
using AtlasLib.Utils;
using BepInEx;
using BepInEx.Bootstrap;
using EndlessDelivery.Anticheat;
using EndlessDelivery.Assets;
using EndlessDelivery.Components;
using EndlessDelivery.Config;
using EndlessDelivery.Gameplay;
using EndlessDelivery.Gameplay.EnemyGeneration;
using EndlessDelivery.Scores;
using EndlessDelivery.Scores.Server;
using EndlessDelivery.UI;
using EndlessDelivery.Utils;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using ProjectProphet;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UltraTweaker;
using UltraTweaker.Tweaks;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("EndlessDelivery")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+cd8dde03403f8f7e2181d2457477d30a0bcef32a")]
[assembly: AssemblyProduct("EndlessDelivery")]
[assembly: AssemblyTitle("EndlessDelivery")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace AtlasLib.Utils
{
	public static class PathUtils
	{
		public static string GameDirectory()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			string text = Application.dataPath;
			if ((int)Application.platform == 1)
			{
				text = Utility.ParentDirectory(text, 2);
			}
			else if ((int)Application.platform == 2)
			{
				text = Utility.ParentDirectory(text, 1);
			}
			return text;
		}

		public static string ModDirectory()
		{
			return Path.Combine(GameDirectory(), "BepInEx", "plugins");
		}

		public static string ModPath()
		{
			return Assembly.GetCallingAssembly().Location.Substring(0, Assembly.GetCallingAssembly().Location.LastIndexOf(Path.DirectorySeparatorChar));
		}
	}
	public static class UnityUtils
	{
		public static GameObject GetChild(this GameObject from, string name)
		{
			Transform obj = from.transform.Find(name);
			return ((obj != null) ? ((Component)obj).gameObject : null) ?? null;
		}

		public static List<GameObject> FindSceneObjects(string sceneName)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> list = new List<GameObject>();
			GameObject[] array = Object.FindObjectsOfType<GameObject>();
			foreach (GameObject val in array)
			{
				Scene scene = val.scene;
				if (((Scene)(ref scene)).name == sceneName)
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static List<GameObject> ChildrenList(this GameObject from)
		{
			List<GameObject> list = new List<GameObject>();
			for (int i = 0; i < from.transform.childCount; i++)
			{
				list.Add(((Component)from.transform.GetChild(i)).gameObject);
			}
			return list;
		}

		public static bool Contains(this LayerMask mask, int layer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return LayerMask.op_Implicit(mask) == (LayerMask.op_Implicit(mask) | (1 << layer));
		}
	}
}
namespace EndlessDelivery
{
	[BepInPlugin("waffle.ultrakill.christmasdelivery", "Endless Delivery", "1.3.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Name = "Endless Delivery";

		public const string Version = "1.3.0";

		public const string GUID = "waffle.ultrakill.christmasdelivery";

		private void Start()
		{
			Debug.Log((object)"Endless Delivery has started !!");
			AddressableManager.Setup();
			PatchThis.AddPatches();
			Option.Load();
		}

		private void OnDestroy()
		{
			Option.Save();
		}
	}
}
namespace EndlessDelivery.Utils
{
	public enum Axis
	{
		X,
		Y,
		Z
	}
	public static class MathsExtensions
	{
		public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
		{
			Random rng = new Random();
			T[] elements = source.ToArray();
			for (int i = elements.Length - 1; i >= 0; i--)
			{
				int swapIndex = rng.Next(i + 1);
				yield return elements[swapIndex];
				elements[swapIndex] = elements[i];
			}
		}

		public static List<T> ShuffleAndToList<T>(this IEnumerable<T> source)
		{
			List<T> list = new List<T>();
			Random random = new Random();
			T[] array = source.ToArray();
			for (int num = array.Length - 1; num >= 0; num--)
			{
				int num2 = random.Next(num + 1);
				list.Add(array[num2]);
				array[num2] = array[num];
			}
			return list;
		}

		public static T Pick<T>(this T[] array)
		{
			if (array.Length == 0)
			{
				return (T)(object)null;
			}
			return array[Random.Range(0, array.Length)];
		}

		public static T Pick<T>(this List<T> list)
		{
			if (list.Count == 0)
			{
				return (T)(object)null;
			}
			return list[Random.Range(0, list.Count)];
		}

		public static Vector3 Only(this Vector3 vector, params Axis[] axes)
		{
			//IL_0011: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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)
			return new Vector3(axes.Contains(Axis.X) ? vector.x : 0f, axes.Contains(Axis.Y) ? vector.y : 0f, axes.Contains(Axis.Z) ? vector.z : 0f);
		}
	}
	public class PatchThis : Attribute
	{
		public static Dictionary<Type, PatchThis> AllPatches = new Dictionary<Type, PatchThis>();

		private Harmony _harmony;

		public readonly string Name;

		public static void AddPatches()
		{
			foreach (Type item in from t in Assembly.GetExecutingAssembly().GetTypes()
				where t.GetCustomAttribute<PatchThis>() != null
				select t)
			{
				Debug.Log((object)("Adding patch " + item.Name + "..."));
				AllPatches.Add(item, item.GetCustomAttribute<PatchThis>());
			}
			PatchAll();
		}

		public static void PatchAll()
		{
			foreach (KeyValuePair<Type, PatchThis> allPatch in AllPatches)
			{
				PatchThis value = allPatch.Value;
				Debug.Log((object)("Patching " + allPatch.Key.Name + "..."));
				value._harmony.PatchAll(allPatch.Key);
			}
		}

		public PatchThis(string harmonyName)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			_harmony = new Harmony(harmonyName);
			Name = harmonyName;
		}
	}
	public static class TimeUtils
	{
		public static string Formatted(this TimeSpan span)
		{
			return span.ToString("mm\\:ss\\:fff", new CultureInfo("en-US"));
		}
	}
}
namespace EndlessDelivery.UI
{
	[PatchThis("waffle.ultrakill.christmasdelivery.AltPresentHud")]
	public class AltPresentHud : MonoBehaviour
	{
		public TMP_Text[] PresentTexts;

		public TMP_Text TimerText;

		public TMP_Text RoomText;

		public Color TimerColour;

		public Color TimerDangerColour;

		public void Update()
		{
			//IL_008e: 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)
			if (MonoSingleton<GameManager>.Instance.GameStarted)
			{
				TimerText.text = TimeSpan.FromSeconds(MonoSingleton<GameManager>.Instance.TimeLeft).Formatted();
				RoomText.text = (MonoSingleton<GameManager>.Instance.RoomsEntered - 1).ToString();
				if (MonoSingleton<GameManager>.Instance.TimeLeft < 10f)
				{
					((Graphic)TimerText).color = TimerDangerColour;
				}
				else
				{
					((Graphic)TimerText).color = TimerColour;
				}
				int num = 0;
				Room currentRoom = MonoSingleton<GameManager>.Instance.CurrentRoom;
				TMP_Text[] presentTexts = PresentTexts;
				foreach (TMP_Text val in presentTexts)
				{
					val.text = $"{currentRoom.AmountDelivered[(WeaponVariant)num]}/{currentRoom.PresentColourAmounts[num]}";
					num++;
				}
			}
		}

		[HarmonyPatch(typeof(HudController), "Start")]
		[HarmonyPostfix]
		private static void AddSelf(HudController __instance)
		{
			if (__instance.altHud && !MapInfoBase.InstanceAnyType.hideStockHUD && AddressableManager.InSceneFromThisMod)
			{
				GameObject val = AddressableManager.Load<GameObject>("Assets/Delivery/Prefabs/HUD/Classic Present Hud.prefab");
				Object.Instantiate<GameObject>(val, ((Component)__instance).gameObject.GetChild("Filler").transform);
			}
		}
	}
	[PatchThis("waffle.ultrakill.christmasdelivery.BlackFade")]
	public class BlackFade : MonoSingleton<BlackFade>
	{
		private Image _image;

		private float _timeBeforeFade;

		private void Start()
		{
			_image = ((Component)this).GetComponent<Image>();
		}

		private void Update()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			_timeBeforeFade = Mathf.MoveTowards(_timeBeforeFade, 0f, Time.deltaTime);
			if (_timeBeforeFade == 0f)
			{
				((Graphic)_image).color = new Color(0f, 0f, 0f, Mathf.MoveTowards(((Graphic)_image).color.a, 0f, Time.deltaTime / 1.5f));
			}
		}

		public void Flash(float timeBeforeFade = 0f)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			_timeBeforeFade = timeBeforeFade;
			((Graphic)_image).color = Color.black;
		}

		[HarmonyPatch(typeof(CanvasController), "Awake")]
		[HarmonyPostfix]
		private static void CreateSelf(CanvasController __instance)
		{
			Object.Instantiate<GameObject>(AddressableManager.Load<GameObject>("Assets/Delivery/Prefabs/HUD/Black Fade.prefab"), ((Component)__instance).transform);
		}
	}
	public class ColourSetter : MonoBehaviour
	{
		public static readonly Color[] DefaultColours = (Color[])(object)new Color[4]
		{
			new Color(0f, 0.91f, 1f),
			new Color(0.27f, 1f, 0.27f),
			new Color(1f, 0.24f, 0.24f),
			new Color(1f, 0.88f, 0.24f)
		};

		public int Colour;

		private void Start()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Text val = default(Text);
			if (((Component)this).TryGetComponent<Text>(ref val))
			{
				((Graphic)val).color = DefaultColours[Colour];
			}
			TMP_Text val2 = default(TMP_Text);
			if (((Component)this).TryGetComponent<TMP_Text>(ref val2))
			{
				((Graphic)val2).color = DefaultColours[Colour];
			}
		}
	}
	[PatchThis("waffle.ultrakill.christmasdelivery.DeliveryButton")]
	public class DeliveryButton
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__0_0;

			internal void <AddButton>b__0_0()
			{
				AddressableManager.LoadScene("Assets/Delivery/Scenes/Game Scene.unity");
			}
		}

		[HarmonyPatch(typeof(CanvasController), "Awake")]
		[HarmonyPostfix]
		private static void AddButton(CanvasController __instance)
		{
			//IL_003a: 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)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0074: 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_00bf: Expected O, but got Unknown
			GameObject child = ((Component)__instance).gameObject.GetChild("Chapter Select");
			if ((Object)(object)child == (Object)null)
			{
				return;
			}
			GameObject child2 = child.GetChild("The Cyber Grind");
			RectTransform component = child2.GetComponent<RectTransform>();
			component.sizeDelta -= new Vector2(55f, 0f);
			((Transform)component).position = ((Transform)component).position - new Vector3(27.5f, 0f, 0f);
			GameObject val = Object.Instantiate<GameObject>(AddressableManager.Load<GameObject>("Assets/Delivery/Prefabs/HUD/Jolly Chapter Select Button.prefab"), child.transform);
			ButtonClickedEvent onClick = val.GetComponent<Button>().onClick;
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
					AddressableManager.LoadScene("Assets/Delivery/Scenes/Game Scene.unity");
				};
				<>c.<>9__0_0 = val2;
				obj = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
		}
	}
	[PatchThis("waffle.ultrakill.christmasdelivery.EndScreen")]
	public class EndScreen : MonoSingleton<EndScreen>
	{
		public GameObject[] ToAppear;

		public GameObject AudioObject;

		public Image HighscoreFlash;

		public float Delay = 0.25f;

		public float SkippingDelay = 0.05f;

		[Space(10f)]
		public ReachValueText Rooms;

		public ReachValueText Kills;

		public ReachValueText Deliveries;

		public ReachValueText TimeElapsed;

		[Space(10f)]
		public Text BestRooms;

		public Text BestKills;

		public Text BestDeliveries;

		public Text BestTimeElapsed;

		[Space(10f)]
		public ReachValueText MoneyGainText;

		[Space(10f)]
		public GameObject Leaderboard;

		public GameObject EverythingButLeaderboard;

		[HideInInspector]
		public bool NewBest;

		[HideInInspector]
		public ReachValueText CurrentText;

		private int _currentIndex;

		private float _timeSinceComplete;

		private bool _appearedSelf;

		private bool _complete;

		private bool _leaderboardShown;

		public bool Skipping => MonoSingleton<InputManager>.Instance.InputSource.Fire1.WasPerformedThisFrame || MonoSingleton<InputManager>.Instance.InputSource.Jump.WasPerformedThisFrame;

		private void Awake()
		{
			GameObject[] toAppear = ToAppear;
			foreach (GameObject val in toAppear)
			{
				val.SetActive(false);
			}
		}

		public void Appear()
		{
			SetPanelValues(MonoSingleton<GameManager>.Instance.CurrentScore, Rooms, Kills, Deliveries, TimeElapsed);
			SetPanelValues(NewBest ? Score.PreviousHighscore : Score.Highscore, BestRooms, BestKills, BestDeliveries, BestTimeElapsed);
			MoneyGainText.Target = MonoSingleton<GameManager>.Instance.CurrentScore.MoneyGain;
			((MonoBehaviour)this).StartCoroutine(AppearCoroutine());
		}

		private IEnumerator AppearCoroutine()
		{
			TimeController timeController = MonoSingleton<TimeController>.Instance;
			timeController.controlTimeScale = false;
			while (timeController.timeScale > 0f)
			{
				timeController.timeScale = Mathf.MoveTowards(timeController.timeScale, 0f, Time.unscaledDeltaTime * (timeController.timeScale + 0.01f));
				Time.timeScale = timeController.timeScale * timeController.timeScaleModifier;
				MonoSingleton<AudioMixerController>.Instance.allSound.SetFloat("allPitch", timeController.timeScale);
				MonoSingleton<AudioMixerController>.Instance.allSound.SetFloat("allVolume", 0.5f + timeController.timeScale / 2f);
				MonoSingleton<AudioMixerController>.Instance.musicSound.SetFloat("allPitch", timeController.timeScale);
				MonoSingleton<MusicManager>.Instance.volume = 0.5f + timeController.timeScale / 2f;
				yield return null;
			}
			ShowNext();
			_appearedSelf = true;
			MonoSingleton<MusicManager>.Instance.forcedOff = true;
			MonoSingleton<MusicManager>.Instance.StopMusic();
			AudioObject.SetActive(!Option.GetValue<bool>("disable_copyrighted_music"));
		}

		private void SetPanelValues(Score score, ReachValueText rooms, ReachValueText kills, ReachValueText deliveries, ReachValueText time)
		{
			rooms.Target = score.Rooms;
			kills.Target = score.Kills;
			deliveries.Target = score.Deliveries;
			time.Target = score.Time;
		}

		private void SetPanelValues(Score score, Text rooms, Text kills, Text deliveries, Text time)
		{
			rooms.text = score.Rooms.ToString();
			kills.text = score.Kills.ToString();
			deliveries.text = score.Deliveries.ToString();
			time.text = TimeSpan.FromSeconds(score.Time).Formatted();
		}

		private void Update()
		{
			if (_appearedSelf)
			{
				ReachValueText currentText = CurrentText;
				if (currentText == null || currentText.Done)
				{
					_timeSinceComplete += Time.unscaledDeltaTime;
				}
				if ((_timeSinceComplete >= ((!Skipping) ? Delay : SkippingDelay) && _currentIndex != ToAppear.Length) || Skipping)
				{
					ShowNext();
					_timeSinceComplete = 0f;
				}
			}
		}

		private void ShowNext()
		{
			if (_currentIndex == ToAppear.Length)
			{
				if (!_leaderboardShown)
				{
					Leaderboard.SetActive(true);
					EverythingButLeaderboard.SetActive(false);
					_leaderboardShown = true;
				}
				else
				{
					MonoSingleton<NewMovement>.Instance.hp = 0;
					_complete = true;
				}
			}
			else
			{
				ToAppear[_currentIndex++].SetActive(true);
			}
		}

		public void DoFlashIfApplicable()
		{
			if (NewBest)
			{
				SetPanelValues(Score.Highscore, BestRooms, BestKills, BestDeliveries, BestTimeElapsed);
				((MonoBehaviour)this).StartCoroutine(DoHighscoreFlash());
			}
		}

		private IEnumerator DoHighscoreFlash()
		{
			((Graphic)HighscoreFlash).color = new Color(1f, 1f, 1f, 1f);
			((Component)HighscoreFlash).GetComponent<AudioSource>().Play();
			while (((Graphic)HighscoreFlash).color.a != 0f)
			{
				((Graphic)HighscoreFlash).color = new Color(1f, 1f, 1f, Mathf.MoveTowards(((Graphic)HighscoreFlash).color.a, 0f, Time.unscaledDeltaTime));
				yield return null;
			}
		}

		[HarmonyPatch(typeof(CanvasController), "Awake")]
		[HarmonyPostfix]
		private static void CreateSelf()
		{
			Object.Instantiate<GameObject>(AddressableManager.Load<GameObject>("Assets/Delivery/Prefabs/HUD/Delivery End Screen.prefab"));
		}
	}
	public class EndScreenLeaderboards : MonoBehaviour
	{
		public Text[] ConnectingToServerText;

		public Transform TopLeaderboardContainer;

		public Transform NearbyLeaderboardContainer;

		public GameObject EntryTemplate;

		public void OnEnable()
		{
			DoStuff();
		}

		private async Task DoStuff()
		{
			if (MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0) != 3)
			{
				Text[] connectingToServerText = ConnectingToServerText;
				foreach (Text text3 in connectingToServerText)
				{
					text3.text = "LEADERBOARDS ARE ONLY ON VIOLENT (FOR NOW)";
				}
				return;
			}
			if (!(await Endpoints.IsServerOnline()))
			{
				Text[] connectingToServerText2 = ConnectingToServerText;
				foreach (Text text2 in connectingToServerText2)
				{
					text2.text = "FAILED TO CONNECT :^(";
				}
				return;
			}
			if (MonoSingleton<EndScreen>.Instance.NewBest)
			{
				await Endpoints.SendScoreAndReturnPosition(Score.Highscore);
			}
			List<ScoreResult> nearScores = await Endpoints.GetUserPage(await Endpoints.GetUserPosition(SteamId.op_Implicit(SteamClient.SteamId)));
			List<ScoreResult> topScores = await Endpoints.GetScoreRange(0, 10);
			foreach (ScoreResult scoreResult2 in nearScores)
			{
				Object.Instantiate<GameObject>(EntryTemplate, NearbyLeaderboardContainer).GetComponent<LeaderboardEntry>().SetValuesAndEnable(scoreResult2);
			}
			foreach (ScoreResult scoreResult in topScores)
			{
				Object.Instantiate<GameObject>(EntryTemplate, TopLeaderboardContainer).GetComponent<LeaderboardEntry>().SetValuesAndEnable(scoreResult);
			}
			Text[] connectingToServerText3 = ConnectingToServerText;
			foreach (Text text in connectingToServerText3)
			{
				((Component)text).gameObject.SetActive(false);
			}
		}
	}
	public class JollyTerminal : MonoBehaviour
	{
		public TMP_Text ScoreText;

		public AudioSource Music;

		public GameObject[] DisableIfNotOnHighscoreDifficulty;

		private void OnEnable()
		{
			AssignScoreText();
			SetMusicStatus();
			bool active = MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0) == 3;
			GameObject[] disableIfNotOnHighscoreDifficulty = DisableIfNotOnHighscoreDifficulty;
			foreach (GameObject val in disableIfNotOnHighscoreDifficulty)
			{
				val.SetActive(active);
			}
		}

		public void AssignScoreText()
		{
			Score highscore = Score.Highscore;
			ScoreText.text = $"{highscore.Rooms}\n{highscore.Kills}\n{highscore.Deliveries}\n{TimeSpan.FromSeconds(highscore.Time).Formatted()}";
		}

		public void SetMusicStatus()
		{
			if (Option.GetValue<bool>("disable_copyrighted_music"))
			{
				Music.Pause();
			}
			else
			{
				Music.UnPause();
			}
		}
	}
	public class JollyTerminalLeaderboards : MonoBehaviour
	{
		public Button[] PageButtons;

		public LeaderboardEntry[] Entries;

		public TMP_Text PageText;

		private List<ScoreResult> _pageScores;

		private bool _hasLoadedScores;

		private int _page = 0;

		private int _pageAmount;

		public void Start()
		{
			SetStuff();
		}

		private async void SetStuff()
		{
			_pageAmount = Mathf.CeilToInt((float)(await Endpoints.GetScoreAmount()) / 5f);
		}

		public void OnEnable()
		{
			if (!_hasLoadedScores)
			{
				LeaderboardEntry[] entries = Entries;
				foreach (LeaderboardEntry leaderboardEntry in entries)
				{
					((Component)leaderboardEntry).gameObject.SetActive(false);
				}
				RefreshPage();
			}
		}

		public void ScrollPage(int amount)
		{
			if (_page + amount >= 0 && _page + amount <= _pageAmount - 1)
			{
				_page += amount;
			}
			PageText.text = (_page + 1).ToString();
			RefreshPage();
		}

		public void Refresh()
		{
			RefreshAsync();
		}

		private async void RefreshAsync()
		{
			((Component)((Component)this).transform.parent).gameObject.SetActive(false);
			await Score.GetServerScoreAndSetIfHigher();
			((Component)this).GetComponentInParent<JollyTerminal>().AssignScoreText();
			((Component)((Component)this).transform.parent).gameObject.SetActive(true);
		}

		public async Task RefreshPage()
		{
			if (!(await Endpoints.IsServerOnline()))
			{
				MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Server offline!", "", "", 0, false);
				((Component)this).gameObject.SetActive(false);
				return;
			}
			Button[] pageButtons = PageButtons;
			foreach (Button button in pageButtons)
			{
				((Selectable)button).interactable = false;
			}
			try
			{
				_pageScores = await Endpoints.GetScoreRange(_page * 5, 5);
				for (int i = 0; i < 5; i++)
				{
					if (i < _pageScores.Count)
					{
						Entries[i].SetValuesAndEnable(_pageScores[i]);
					}
					else
					{
						((Component)Entries[i]).gameObject.SetActive(false);
					}
				}
			}
			catch (Exception ex)
			{
				Endpoints.DisplayError("Failed to load scores!!" + ex);
			}
			Button[] pageButtons2 = PageButtons;
			foreach (Button button2 in pageButtons2)
			{
				((Selectable)button2).interactable = true;
			}
		}
	}
	public class LeaderboardEntry : MonoBehaviour
	{
		[Header("All monobehaviours here should implement IText")]
		public MonoBehaviour RankNumber;

		public MonoBehaviour Username;

		public MonoBehaviour Rooms;

		public MonoBehaviour Delivered;

		public Image ProfileActual;

		public async void SetValuesAndEnable(ScoreResult scoreResult)
		{
			Friend user = new Friend(SteamId.op_Implicit(scoreResult.SteamId));
			((IText)RankNumber).SetText((scoreResult.Index + 1).ToString());
			IText text = (IText)Username;
			text.SetText(string.Format(await SpecialUserResult.GetFormat(SteamId.op_Implicit(user.Id)), ((Friend)(ref user)).Name));
			((IText)Rooms).SetText(scoreResult.Score.Rooms.ToString());
			((IText)Delivered).SetText($"({scoreResult.Score.Deliveries})");
			SetAvatar(user);
			((Component)this).gameObject.SetActive(true);
		}

		private async void SetAvatar(Friend user)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Image? image = await ((Friend)(ref user)).GetMediumAvatarAsync();
			Texture2D texture2D = new Texture2D((int)image.Value.Width, (int)image.Value.Height, (TextureFormat)4, false);
			texture2D.LoadRawTextureData(image.Value.Data);
			texture2D.Apply();
			ProfileActual.sprite = Sprite.Create(texture2D, new Rect(0f, 0f, (float)((Texture)texture2D).width, (float)((Texture)texture2D).height), Vector2.one / 2f);
		}
	}
	[PatchThis("waffle.ultrakill.christmasdelivery.PresentTimeHud")]
	public class PresentTimeHud : MonoSingleton<PresentTimeHud>
	{
		public const float DangerTime = 10f;

		public Image[] PresentImages;

		public TMP_Text Timer;

		public TMP_Text CompleteRooms;

		public Color TimerColour;

		public Color TimerDangerColour;

		private float _lastSetSeconds;

		private float _lerpProgress;

		private float _originalFontSize;

		private Vector3 _timerStartPos;

		public void Start()
		{
			//IL_001e: 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)
			_originalFontSize = Timer.fontSize;
			_timerStartPos = Timer.transform.localPosition;
		}

		private void Update()
		{
			//IL_01d1: 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_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			if (!MonoSingleton<GameManager>.Instance.GameStarted)
			{
				return;
			}
			if (MonoSingleton<GameManager>.Instance.TimerActive)
			{
				Timer.text = TimeSpan.FromSeconds(MonoSingleton<GameManager>.Instance.TimeLeft).ToString("mm\\:ss\\.fff", new CultureInfo("en-US"));
				Timer.fontSize = Mathf.MoveTowards(Timer.fontSize, _originalFontSize, 75f * Time.deltaTime);
				_lastSetSeconds = MonoSingleton<GameManager>.Instance.TimeLeft;
				_lerpProgress = 0f;
			}
			else
			{
				if (MonoSingleton<GameManager>.Instance.TimeLeft > 10f)
				{
					MonoSingleton<CameraController>.Instance.StopShake();
				}
				float num = Mathf.Lerp(_lastSetSeconds, MonoSingleton<GameManager>.Instance.TimeLeft, _lerpProgress);
				Timer.text = TimeSpan.FromSeconds(num).Formatted();
				Timer.fontSize = _originalFontSize * (1f + _lerpProgress * 0.15f);
				_lerpProgress += Time.deltaTime / 0.5f;
			}
			if (MonoSingleton<GameManager>.Instance.TimeLeft <= 10f)
			{
				((Graphic)Timer).color = TimerDangerColour;
				Timer.transform.localPosition = _timerStartPos + new Vector3((float)Random.Range(-1, 1), (float)Random.Range(-1, 1), 0f);
				MonoSingleton<CameraController>.Instance.CameraShake((10f - MonoSingleton<GameManager>.Instance.TimeLeft) / 50f);
			}
			else
			{
				((Graphic)Timer).color = TimerColour;
				Timer.transform.localPosition = _timerStartPos;
			}
			if ((Object)(object)MonoSingleton<GameManager>.Instance.CurrentRoom != (Object)null)
			{
				for (int i = 0; i < 4; i++)
				{
					PresentImages[i].fillAmount = FindFill((WeaponVariant)i);
				}
			}
			CompleteRooms.text = (MonoSingleton<GameManager>.Instance.RoomsEntered - 1).ToString();
		}

		private float FindFill(WeaponVariant colour)
		{
			//IL_0010: 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)
			float num = MonoSingleton<GameManager>.Instance.CurrentRoom.PresentColourAmounts[colour];
			return 1f - (float)MonoSingleton<GameManager>.Instance.CurrentRoom.AmountDelivered[colour] / num;
		}

		[HarmonyPatch(typeof(HudController), "Start")]
		[HarmonyPostfix]
		private static void AddSelf(HudController __instance)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.altHud && !MapInfoBase.InstanceAnyType.hideStockHUD)
			{
				GameObject val = AddressableManager.Load<GameObject>("Assets/Delivery/Prefabs/HUD/Present Panel.prefab");
				GameObject val2 = Object.Instantiate<GameObject>(val, ((Component)__instance.hudpos).transform);
				val2.transform.localPosition = val.transform.localPosition;
				val2.gameObject.SetActive(false);
			}
		}
	}
	public class ReachValueText : MonoBehaviour
	{
		public enum IntOrFloat
		{
			Int,
			Float
		}

		public IntOrFloat Type;

		public Text Text;

		public float Target;

		public string Format;

		public string StartValue;

		public float ChangePerSecond;

		public bool IsTimestamp;

		private float _timeElapsed;

		private AudioSource _audio;

		private float _currentValue;

		[HideInInspector]
		public bool Done;

		private void OnEnable()
		{
			MonoSingleton<EndScreen>.Instance.CurrentText = this;
			Text.text = StartValue;
			_audio = ((Component)this).GetComponent<AudioSource>();
			AudioSource audio = _audio;
			if (audio != null)
			{
				audio.Play();
			}
		}

		private void Update()
		{
			if (MonoSingleton<EndScreen>.Instance.Skipping)
			{
				_currentValue = Target;
				SetText();
			}
			if (Target == _currentValue)
			{
				SetText();
				Done = true;
				((Behaviour)this).enabled = false;
				AudioSource audio = _audio;
				if (audio != null)
				{
					audio.Stop();
				}
			}
			else
			{
				_timeElapsed += Time.unscaledDeltaTime;
				_currentValue = Mathf.MoveTowards(_currentValue, Target, ChangePerSecond * Time.unscaledDeltaTime);
				SetText();
			}
		}

		private void SetText()
		{
			float num = ((Type == IntOrFloat.Int) ? Mathf.Floor(_currentValue) : _currentValue);
			Text.text = ((!IsTimestamp) ? string.Format(Format, num) : TimeSpan.FromSeconds(num).Formatted());
		}
	}
	public interface IText
	{
		void SetText(string text);
	}
	public class TmpText : MonoBehaviour, IText
	{
		private TMP_Text _text;

		public void SetText(string text)
		{
			if ((Object)(object)_text == (Object)null)
			{
				_text = ((Component)this).GetComponent<TMP_Text>();
			}
			_text.text = text;
		}
	}
	public class UnityText : MonoBehaviour, IText
	{
		private Text _text;

		public void SetText(string text)
		{
			if ((Object)(object)_text == (Object)null)
			{
				_text = ((Component)this).GetComponent<Text>();
			}
			_text.text = text;
		}
	}
}
namespace EndlessDelivery.Scores
{
	public static class BestTimes
	{
		private static Dictionary<int, float> _times;

		public static string TimesFilePath => Path.Combine(Option.SavePath, string.Format("besttimes_{0}.json", MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0)));

		public static float CurrentStartTime => GetRoomTime((int)((Option<long>)Option.AllOptions["start_wave"]).Value);

		public static Dictionary<int, float> Times
		{
			get
			{
				if (_times == null)
				{
					if (File.Exists(TimesFilePath))
					{
						_times = JsonConvert.DeserializeObject<Dictionary<int, float>>(File.ReadAllText(TimesFilePath));
					}
					else
					{
						_times = new Dictionary<int, float>();
					}
				}
				return _times;
			}
		}

		public static void SetIfHigher(int room, float time)
		{
			Debug.Log((object)$"Trying to save {room} at {time}");
			if (!Score.CanSubmit)
			{
				Debug.Log((object)"Early ret?");
				return;
			}
			Debug.Log((object)$"{room} at {time}");
			if (Times.ContainsKey(room))
			{
				Debug.Log((object)$"Checking if it's more than {Times[room]}");
				if (time > Times[room])
				{
					Debug.Log((object)"it is!");
					Times[room] = time;
				}
				Debug.Log((object)"it isnt?");
			}
			else
			{
				Debug.Log((object)"doesnt contain");
				Times.Add(room, time);
				Debug.Log((object)"add?");
				Save();
			}
		}

		public static float GetRoomTime(int room)
		{
			if (room != 0)
			{
				return Times[room];
			}
			return 45f;
		}

		private static async void Save()
		{
			Directory.CreateDirectory(Option.SavePath);
			using StreamWriter sw = new StreamWriter(TimesFilePath);
			await sw.WriteAsync(JsonConvert.SerializeObject((object)Times));
		}
	}
	public class Score
	{
		private static int _lastCheckedDifficulty;

		private static Score _highscore;

		public readonly int Rooms;

		public readonly int Kills;

		public readonly int Deliveries;

		public readonly float Time;

		public static string HighscoreFilePath => Path.Combine(Option.SavePath, string.Format("highscore_{0}.json", MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0)));

		public static bool CanSubmit => !EndlessDelivery.Anticheat.Anticheat.HasIllegalMods && !MonoSingleton<CheatsController>.Instance.cheatsEnabled;

		public static Score Highscore
		{
			get
			{
				if (_highscore == null || _lastCheckedDifficulty != MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0))
				{
					_lastCheckedDifficulty = MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0);
					Score score = (File.Exists(HighscoreFilePath) ? JsonConvert.DeserializeObject<Score>(File.ReadAllText(HighscoreFilePath)) : null);
					if (score == null)
					{
						Debug.Log((object)"Using fallback score!");
						Highscore = new Score(0, 0, 0, 0f);
					}
					else
					{
						Highscore = score;
					}
				}
				return _highscore;
			}
			set
			{
				PreviousHighscore = _highscore;
				_highscore = value;
				SaveScore(value);
			}
		}

		public static Score PreviousHighscore { get; private set; }

		[JsonIgnore]
		public int MoneyGain => (int)(Time * 10f);

		public static async Task GetServerScoreAndSetIfHigher()
		{
			Score serverScore = (await Endpoints.GetScoreRange(await Endpoints.GetUserPosition(SteamId.op_Implicit(SteamClient.SteamId)), 1))[0].Score;
			if (IsLargerThanOtherScore(serverScore, Highscore))
			{
				Highscore = serverScore;
			}
		}

		private static void SaveScore(Score score)
		{
			Directory.CreateDirectory(Option.SavePath);
			File.WriteAllText(HighscoreFilePath, JsonConvert.SerializeObject((object)score));
		}

		public static bool IsLargerThanOtherScore(Score score, Score other)
		{
			if (score.Rooms != other.Rooms)
			{
				if (score.Rooms > other.Rooms)
				{
					return true;
				}
				return false;
			}
			if (score.Deliveries != other.Deliveries)
			{
				if (score.Deliveries > other.Deliveries)
				{
					return true;
				}
				return false;
			}
			if (score.Kills != other.Kills)
			{
				if (score.Kills > other.Kills)
				{
					return true;
				}
				return false;
			}
			if (score.Time != other.Time)
			{
				if (score.Time < other.Time)
				{
					return true;
				}
				return false;
			}
			return false;
		}

		public Score(int rooms, int kills, int deliveries, float time)
		{
			Rooms = rooms;
			Kills = kills;
			Deliveries = deliveries;
			Time = time;
		}
	}
}
namespace EndlessDelivery.Scores.Server
{
	public class Endpoints
	{
		private static readonly HttpClient _client = new HttpClient();

		private const string Url = "http://159.65.214.169/";

		private const string ScoresGetRange = "http://159.65.214.169/scores/get_range?start={0}&count={1}";

		private const string ScoresGetAmount = "http://159.65.214.169/scores/get_length";

		private const string ScoresGetPosition = "http://159.65.214.169/scores/get_position?steamId={0}";

		private const string ScoresAdd = "http://159.65.214.169/scores/add_score?score={0}&ticket={1}&version={2}";

		private const string UsersSpecialGet = "http://159.65.214.169/users/get_special_users";

		public static async Task<bool> IsServerOnline()
		{
			return true;
		}

		public static async Task<List<SpecialUserResult>> GetSpecialUsers()
		{
			return JsonConvert.DeserializeObject<List<SpecialUserResult>>(await (await _client.GetAsync("http://159.65.214.169/users/get_special_users")).Content.ReadAsStringAsync());
		}

		public static async Task<List<ScoreResult>> GetScoreRange(int start, int count)
		{
			string responseBody = await (await _client.GetAsync($"http://159.65.214.169/scores/get_range?start={start}&count={count}")).Content.ReadAsStringAsync();
			Console.WriteLine(responseBody);
			return JsonConvert.DeserializeObject<List<ScoreResult>>(responseBody);
		}

		public static async Task<int> GetScoreAmount()
		{
			string responseBody = await (await _client.GetAsync("http://159.65.214.169/scores/get_length")).Content.ReadAsStringAsync();
			Debug.Log((object)(responseBody + " " + JsonConvert.DeserializeObject<Response>(responseBody).Value.GetType()));
			return (int)(long)JsonConvert.DeserializeObject<Response>(responseBody).Value;
		}

		public static async Task<int> GetUserPosition(ulong steamId)
		{
			try
			{
				Debug.Log((object)$"http://159.65.214.169/scores/get_position?steamId={steamId}");
				string responseBody = await (await _client.GetAsync($"http://159.65.214.169/scores/get_position?steamId={steamId}")).Content.ReadAsStringAsync();
				Debug.Log((object)"should be done");
				return (int)(long)JsonConvert.DeserializeObject<Response>(responseBody).Value;
			}
			catch
			{
				return -1;
			}
		}

		public static async Task<int> SendScoreAndReturnPosition(Score score)
		{
			try
			{
				string responseBody = await (await _client.GetAsync(string.Format("http://159.65.214.169/scores/add_score?score={0}&ticket={1}&version={2}", JsonConvert.SerializeObject((object)score), SteamAuth.GetTicket(), "1.3.0"))).Content.ReadAsStringAsync();
				Debug.Log((object)("received " + responseBody));
				return (int)(long)JsonConvert.DeserializeObject<Response>(responseBody).Value;
			}
			catch (Exception ex2)
			{
				Exception ex = ex2;
				DisplayError(ex.ToString());
				return -1;
			}
		}

		public static void DisplayError(string error)
		{
			MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("<color=red>AN ERROR HAS OCCURED WITH THE SERVER! Contact Waffle and send your logs.</color>", "", "", 0, false);
			Debug.LogError((object)("DISPLAYERROR: " + error));
		}

		public static async Task<List<ScoreResult>> GetUserPage(float index)
		{
			int pageNumber = (int)(index / 8f);
			return await GetScoreRange(pageNumber * 8, 10);
		}
	}
	public class Response
	{
		public object Value { get; set; }

		public int StatusCode { get; set; }
	}
	public class ScoreResult
	{
		public ulong SteamId { get; set; }

		public Score Score { get; set; }

		public int Index { get; set; }
	}
	public class SpecialUserResult
	{
		public static Dictionary<ulong, SpecialUserResult>? SteamIdToUser;

		public ulong SteamId { get; set; }

		public bool IsBanned { get; set; }

		public string NameFormat { get; set; }

		private static async Task EnsureDictSet()
		{
			if (SteamIdToUser == null)
			{
				SteamIdToUser = (await Endpoints.GetSpecialUsers()).ToDictionary((SpecialUserResult x) => x.SteamId, (SpecialUserResult y) => y);
			}
		}

		public static async Task<string> GetFormat(ulong steamId)
		{
			await EnsureDictSet();
			if (SteamIdToUser.TryGetValue(steamId, out SpecialUserResult result))
			{
				return result.NameFormat;
			}
			return "{0}";
		}
	}
	public static class SteamAuth
	{
		public static string GetTicket()
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			AuthTicket authSessionTicket = SteamUser.GetAuthSessionTicket(default(NetIdentity));
			return BitConverter.ToString(authSessionTicket.Data, 0, authSessionTicket.Data.Length).Replace("-", string.Empty);
		}
	}
}
namespace EndlessDelivery.Gameplay
{
	[PatchThis("waffle.ultrakill.christmasdelivery.GameManager")]
	public class GameManager : MonoSingleton<GameManager>
	{
		public const float StartTime = 45f;

		public const float TimeAddLength = 0.5f;

		public NavMeshSurface Navmesh;

		public AudioSource TimeAddSound;

		public RoomPool RoomPool;

		private Coroutine _pauseCoroutine;

		private List<RoomData> _remainingRooms = new List<RoomData>();

		private static readonly int _startingPoints = 10;

		public bool GameStarted { get; private set; }

		public float TimeLeft { get; private set; }

		public float TimeElapsed { get; private set; }

		public int DeliveredPresents { get; set; }

		public int RoomsEntered { get; private set; }

		public Room CurrentRoom { get; private set; }

		public Room PreviousRoom { get; private set; }

		public bool TimerActive { get; private set; }

		public int PointsPerWave { get; private set; }

		public Score CurrentScore => new Score(RoomsEntered - 1, MonoSingleton<StatsManager>.Instance.kills, DeliveredPresents, TimeElapsed);

		public static int GetRoomPoints(int roomNumber)
		{
			Debug.Log((object)$"sp {_startingPoints}");
			int num = _startingPoints;
			for (int i = 0; i < roomNumber; i++)
			{
				num += 3 + (i + 1) / 3;
				Debug.Log((object)$"p {_startingPoints} ( + {3 + (i + 1) / 3})");
			}
			Debug.Log((object)$"ret {num}");
			return num;
		}

		private void Awake()
		{
			Act3EnemyHack.AddToPools(EnemyGroup.Groups[DeliveryEnemyClass.Projectile], EnemyGroup.Groups[DeliveryEnemyClass.Uncommon]);
		}

		private void Update()
		{
			if (GameStarted && MonoSingleton<GunControl>.Instance.activated)
			{
				TimeLeft = Mathf.MoveTowards(TimeLeft, 0f, Time.deltaTime);
				TimeElapsed += Time.deltaTime;
				if (TimeLeft == 0f)
				{
					EndGame();
				}
				if (!CurrentRoom.RoomCleared && CurrentRoom.RoomActivated && MonoSingleton<EnemyTracker>.Instance.enemies.All((EnemyIdentifier enemy) => enemy.dead))
				{
					CurrentRoom.RoomCleared = true;
					MonoSingleton<MusicManager>.Instance.PlayCleanMusic();
					AddTime(4f, "<color=orange>FULL CLEAR</color>");
				}
			}
		}

		public void AddTime(float seconds, string reason)
		{
			AudioSource timeAddSound = TimeAddSound;
			if (timeAddSound != null)
			{
				timeAddSound.Play();
			}
			TimerActive = false;
			if (_pauseCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_pauseCoroutine);
			}
			_pauseCoroutine = ((MonoBehaviour)this).StartCoroutine(UnpauseTimer());
			MonoSingleton<StyleHUD>.Instance.AddPoints(5, $"{reason} <size=20>({seconds}s)</size>", (GameObject)null, (EnemyIdentifier)null, -1, "", "");
			TimeLeft += seconds;
		}

		public void SilentAddTime(float seconds)
		{
			TimeLeft += seconds;
		}

		private IEnumerator UnpauseTimer()
		{
			yield return (object)new WaitForSeconds(0.5f);
			TimerActive = true;
		}

		public Room GenerateNewRoom()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0038: 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)
			//IL_0045: 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_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)
			Collider component = ((Component)CurrentRoom).GetComponent<Collider>();
			GameObject prefab = GetRandomRoom().Prefab;
			Vector3 position = ((Component)CurrentRoom).gameObject.transform.position;
			Vector3 right = Vector3.right;
			Bounds bounds = component.bounds;
			return Object.Instantiate<GameObject>(prefab, position + right * ((Bounds)(ref bounds)).size.x * 2.5f, Quaternion.identity).GetComponent<Room>();
		}

		public RoomData GetRandomRoom()
		{
			if (_remainingRooms.Count == 0)
			{
				_remainingRooms.AddRange(RoomPool.Rooms);
			}
			RoomData roomData = _remainingRooms.Pick();
			_remainingRooms.Remove(roomData);
			return roomData;
		}

		public void RoomEnd()
		{
			if (CurrentRoom.RoomHasGameplay)
			{
				AddTime(8f, "<color=orange>ROOM CLEAR</color>");
				PointsPerWave += 3 + RoomsEntered / 3;
				BestTimes.SetIfHigher(RoomsEntered, TimeLeft);
			}
			SetRoom(GenerateNewRoom());
			Navmesh.BuildNavMesh();
		}

		public void SetRoom(Room room)
		{
			if (!GameStarted && room.RoomHasGameplay)
			{
				StartGame();
			}
			if ((Object)(object)CurrentRoom != (Object)(object)room)
			{
				RoomsEntered++;
				PreviousRoom = CurrentRoom;
				CurrentRoom = room;
				room.Initialize();
			}
			if (room.RoomHasGameplay && !room.RoomAlreadyVisited)
			{
				room.RoomAlreadyVisited = true;
			}
		}

		public void StartGame()
		{
			if (!GameStarted)
			{
				((Component)MonoSingleton<PresentTimeHud>.Instance).gameObject.SetActive(true);
				((Component)((Component)MonoSingleton<StatsManager>.Instance).GetComponentInChildren<MusicManager>(true)).gameObject.SetActive(true);
				MonoSingleton<MusicManager>.Instance.StartMusic();
				RoomsEntered = (int)Option.GetValue<long>("start_wave");
				PointsPerWave = GetRoomPoints(RoomsEntered);
				TimeLeft = BestTimes.CurrentStartTime;
				TimerActive = true;
				GameStarted = true;
			}
		}

		public void EndGame()
		{
			if (!GameStarted)
			{
				return;
			}
			if (!MonoSingleton<NewMovement>.Instance.dead)
			{
				MonoSingleton<NewMovement>.Instance.GetHurt(1000, false, 1f, false, false, 1f, false);
			}
			((Component)MonoSingleton<NewMovement>.Instance.blackScreen).gameObject.SetActive(false);
			MonoSingleton<NewMovement>.Instance.hp = 100;
			GameStarted = false;
			if (Score.IsLargerThanOtherScore(CurrentScore, Score.Highscore))
			{
				if (Score.CanSubmit)
				{
					Score.Highscore = CurrentScore;
					MonoSingleton<EndScreen>.Instance.NewBest = true;
				}
				else
				{
					MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Score not submitting due to other mods, or cheats enabled.", "", "", 0, false);
				}
			}
			MonoSingleton<EndScreen>.Instance.Appear();
			GameProgressSaver.AddMoney(CurrentScore.MoneyGain);
		}

		[HarmonyPatch(typeof(SeasonalHats), "Start")]
		[HarmonyPrefix]
		private static void EnableHats(SeasonalHats __instance)
		{
			if (AddressableManager.InSceneFromThisMod)
			{
				__instance.easter.SetActive(false);
				__instance.halloween.SetActive(false);
				__instance.christmas.SetActive(true);
			}
		}

		[HarmonyPatch(typeof(NewMovement), "GetHurt")]
		[HarmonyPostfix]
		private static void CustomDeath(NewMovement __instance)
		{
			if (__instance.dead && AddressableManager.InSceneFromThisMod)
			{
				MonoSingleton<GameManager>.Instance.EndGame();
			}
		}
	}
	public static class GenerationEquations
	{
		public static int PresentAmount(int wave)
		{
			int num = Mathf.CeilToInt(Mathf.Log((float)wave, 6.5f) * 3f);
			num = Mathf.Clamp(num, 4, 10);
			Debug.Log((object)$"{wave} presents: {num}");
			return num;
		}

		public static int[] DistributeBetween(int amount, int number)
		{
			int[] array = new int[amount];
			int num = 0;
			while (number >= 1)
			{
				array[num]++;
				number--;
				num++;
				if (num > amount - 1)
				{
					num = 0;
				}
			}
			return array;
		}
	}
	public class PlayerChimneyFixer : MonoSingleton<PlayerChimneyFixer>
	{
		private bool _isInChimney;

		private Chimney _currentChimney;

		public void EnterChimney(Chimney chimney)
		{
			_isInChimney = true;
			_currentChimney = chimney;
		}

		public void Exit()
		{
			_isInChimney = false;
		}

		private void Update()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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)
			if (_isInChimney)
			{
				Vector3 position = ((GameObject)(((Object)(object)_currentChimney != (Object)null) ? ((object)((Component)_currentChimney).gameObject) : ((object)MonoSingleton<GameManager>.Instance.CurrentRoom.SpawnPoint))).transform.position;
				position.y = ((Component)MonoSingleton<NewMovement>.Instance).transform.position.y;
				((Component)MonoSingleton<NewMovement>.Instance).transform.position = Vector3.MoveTowards(((Component)MonoSingleton<NewMovement>.Instance).transform.position, position, Time.deltaTime * 5f);
				MonoSingleton<NewMovement>.Instance.rb.velocity = MonoSingleton<NewMovement>.Instance.rb.velocity.Only(Axis.Y);
				((Behaviour)MonoSingleton<NewMovement>.Instance).enabled = false;
			}
		}
	}
	public class Room : MonoBehaviour
	{
		public GameObject SpawnPoint;

		public ActivateArena Arena;

		public EnemySpawnPoint[] SpawnPoints;

		public bool RoomHasGameplay = true;

		[HideInInspector]
		public bool RoomAlreadyVisited;

		[Space(15f)]
		[Header("Make sure that you have 4 chimneys, one for each colour.")]
		public List<Chimney> Chimneys = new List<Chimney>();

		[Space(15f)]
		[Header("Make sure that you have 10 presents (10 is the maximum, random ones will be chosen)")]
		public List<Present> Presents = new List<Present>();

		[HideInInspector]
		public int[] PresentColourAmounts = new int[4];

		[HideInInspector]
		public List<Collider> EnvColliders = new List<Collider>();

		[HideInInspector]
		public List<EnemyIdentifier> Enemies = new List<EnemyIdentifier>();

		[HideInInspector]
		public bool RoomCleared;

		[HideInInspector]
		public bool RoomActivated;

		public Dictionary<WeaponVariant, Chimney> AllChimneys = new Dictionary<WeaponVariant, Chimney>
		{
			{
				(WeaponVariant)0,
				null
			},
			{
				(WeaponVariant)1,
				null
			},
			{
				(WeaponVariant)2,
				null
			},
			{
				(WeaponVariant)3,
				null
			}
		};

		public Dictionary<WeaponVariant, int> AmountDelivered = new Dictionary<WeaponVariant, int>
		{
			{
				(WeaponVariant)0,
				0
			},
			{
				(WeaponVariant)1,
				0
			},
			{
				(WeaponVariant)2,
				0
			},
			{
				(WeaponVariant)3,
				0
			}
		};

		private Dictionary<EnemyType, int> _amountSpawned = new Dictionary<EnemyType, int>();

		private int _pointsLeft;

		private int _meleeSpawnsUsed;

		private int _projectileSpawnsUsed;

		private int _wavesSinceSpecial;

		public bool ChimneysDone => AmountDelivered.All((KeyValuePair<WeaponVariant, int> kvp) => PresentColourAmounts[kvp.Key] <= kvp.Value);

		public bool AllDead => Enemies.All((EnemyIdentifier enemy) => enemy?.dead ?? true);

		public bool Done(WeaponVariant colour)
		{
			//IL_0007: 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)
			return AmountDelivered[colour] == PresentColourAmounts[colour];
		}

		public void Deliver(WeaponVariant colour)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			MonoSingleton<GameManager>.Instance.DeliveredPresents++;
			AmountDelivered[colour]++;
			if (ChimneysDone)
			{
				CompleteRoom();
			}
		}

		private void CompleteRoom()
		{
			foreach (Chimney value in AllChimneys.Values)
			{
				if (value != null)
				{
					((Component)value.JumpPad).gameObject.SetActive(false);
				}
			}
		}

		public void Initialize()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (RoomHasGameplay)
			{
				PresentColourAmounts = GenerationEquations.DistributeBetween(4, GenerationEquations.PresentAmount(MonoSingleton<GameManager>.Instance.RoomsEntered));
			}
			DecideChimneyColours();
			DecidePresentColours();
			DecideSpawnPointEnemies();
			for (int i = 0; i < PresentColourAmounts.Length; i++)
			{
				Chimney chimney = AllChimneys[(WeaponVariant)i];
				if ((Object)(object)chimney != (Object)null)
				{
					chimney.AmountToDeliver = PresentColourAmounts[i];
				}
			}
			if (ChimneysDone)
			{
				CompleteRoom();
			}
			Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (LayerMaskDefaults.Get((LMD)1).Contains(((Component)val).gameObject.layer))
				{
					EnvColliders.Add(val);
				}
			}
		}

		private void DecideChimneyColours()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			WeaponVariant val = (WeaponVariant)0;
			foreach (Chimney item in Chimneys.Shuffle())
			{
				AllChimneys[val] = item;
				item.SetColour(val);
				item.Room = this;
				val = (WeaponVariant)(val + 1);
			}
		}

		private void DecidePresentColours()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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)
			Dictionary<WeaponVariant, int> dictionary = new Dictionary<WeaponVariant, int>();
			for (int i = 0; i < PresentColourAmounts.Length; i++)
			{
				if (PresentColourAmounts[i] != 0)
				{
					dictionary.Add((WeaponVariant)i, PresentColourAmounts[i]);
				}
			}
			foreach (Present item in Presents.Shuffle())
			{
				if (dictionary.Count != 0)
				{
					KeyValuePair<WeaponVariant, int> keyValuePair = dictionary.ToList().Pick();
					item.SetColour(keyValuePair.Key);
					dictionary[keyValuePair.Key]--;
					if (dictionary[keyValuePair.Key] == 0)
					{
						dictionary.Remove(keyValuePair.Key);
					}
				}
				else
				{
					((Component)item).gameObject.SetActive(false);
				}
			}
		}

		private void DecideSpawnPointEnemies()
		{
			_pointsLeft = MonoSingleton<GameManager>.Instance.PointsPerWave;
			Debug.Log((object)$"Spawning enemies: starts with {_pointsLeft}");
			List<EnemySpawnPoint> projectile = SpawnPoints.Where((EnemySpawnPoint sp) => sp.Class == DeliveryEnemyClass.Projectile).ShuffleAndToList();
			List<EnemySpawnPoint> list = SpawnPoints.Where((EnemySpawnPoint sp) => sp.Class == DeliveryEnemyClass.Melee).ShuffleAndToList();
			if (MonoSingleton<GameManager>.Instance.RoomsEntered > 10)
			{
				int max = MonoSingleton<GameManager>.Instance.RoomsEntered / 10 + 1;
				DecideUncommons(list, ref max);
				if (MonoSingleton<GameManager>.Instance.RoomsEntered >= 15)
				{
					DecideSpecials(list, ref max);
				}
			}
			DecideNormalMeleeAndProjectile(projectile, list);
		}

		private void DecideUncommons(List<EnemySpawnPoint> spawns, ref int max)
		{
			int num = Random.Range(1, max + 1);
			max -= num;
			Debug.Log((object)$"Spawning {num} uncommons!");
			List<EndlessEnemy> list = GetPotentialEnemies(EnemyGroup.Groups[DeliveryEnemyClass.Uncommon]).ShuffleAndToList();
			foreach (EndlessEnemy item in list)
			{
				Debug.Log((object)("    uc" + ((Object)item.prefab).name));
			}
			while (list.Count > 2)
			{
				list.RemoveAt(list.Count - 1);
			}
			if (list.Count == 0)
			{
				return;
			}
			if (list.Count == 1)
			{
				list.Add(list[0]);
			}
			Debug.Log((object)("Uncommons are " + ((Object)list[0].prefab).name + " and " + ((Object)list[1].prefab).name + "!!"));
			int[] array = new int[2];
			for (int i = 0; i < num; i++)
			{
				if (_meleeSpawnsUsed == spawns.Count)
				{
					Debug.Log((object)$"broke2 with {_pointsLeft}");
					break;
				}
				if (GetRealCost(list[0]) >= _pointsLeft && GetRealCost(list[1]) >= _pointsLeft)
				{
					Debug.Log((object)"uncommon break | cant afford");
					break;
				}
				int num2 = ((!(Random.value > 0.5f)) ? 1 : 0);
				if (GetRealCost(list[0]) >= _pointsLeft)
				{
					num2 = 1;
				}
				if (GetRealCost(list[1]) >= _pointsLeft)
				{
					num2 = 0;
				}
				array[num2]++;
				SetSpawnPoint(spawns[_meleeSpawnsUsed], list[num2], DeliveryEnemyClass.Melee);
			}
		}

		private void DecideSpecials(List<EnemySpawnPoint> spawns, ref int max)
		{
			int num = Random.Range(0, max + 1);
			if (num == 0)
			{
				if (Random.value < 1f - 1f / (float)_wavesSinceSpecial)
				{
					num++;
				}
				_wavesSinceSpecial++;
			}
			max -= num;
			Debug.Log((object)$"Spawning {num} specials!");
			foreach (EndlessEnemy item in GetPotentialEnemies(EnemyGroup.Groups[DeliveryEnemyClass.Special]).ShuffleAndToList())
			{
				Debug.Log((object)$"   {item}");
			}
			for (int i = 0; i < num; i++)
			{
				if (_meleeSpawnsUsed == spawns.Count)
				{
					Debug.Log((object)$"broke1 with {_pointsLeft}");
					break;
				}
				List<EndlessEnemy> list = GetPotentialEnemies(EnemyGroup.Groups[DeliveryEnemyClass.Special]).ShuffleAndToList();
				if (list.Count == 0)
				{
					break;
				}
				SetSpawnPoint(spawns[_meleeSpawnsUsed], list[0], DeliveryEnemyClass.Melee);
			}
		}

		private void DecideNormalMeleeAndProjectile(List<EnemySpawnPoint> projectile, List<EnemySpawnPoint> melee)
		{
			while (_pointsLeft != 0)
			{
				Debug.Log((object)$"has {_pointsLeft} points left!");
				if (_projectileSpawnsUsed == projectile.Count && _meleeSpawnsUsed == melee.Count)
				{
					Debug.Log((object)$"broke with {_pointsLeft}");
					break;
				}
				DeliveryEnemyClass deliveryEnemyClass = ((!((double)Random.value < 0.5)) ? DeliveryEnemyClass.Projectile : DeliveryEnemyClass.Melee);
				if (_projectileSpawnsUsed >= projectile.Count)
				{
					deliveryEnemyClass = DeliveryEnemyClass.Melee;
				}
				if (_meleeSpawnsUsed >= melee.Count)
				{
					deliveryEnemyClass = DeliveryEnemyClass.Projectile;
				}
				IEnumerable<EndlessEnemy> potentialEnemies = GetPotentialEnemies(EnemyGroup.Groups[deliveryEnemyClass]);
				foreach (EndlessEnemy item in potentialEnemies)
				{
					Debug.Log((object)("   pm " + ((Object)item.prefab).name));
				}
				EndlessEnemy val = potentialEnemies.ToList().Pick();
				if ((Object)(object)val == (Object)null)
				{
					break;
				}
				EnemySpawnPoint point = ((deliveryEnemyClass == DeliveryEnemyClass.Melee) ? melee[_meleeSpawnsUsed] : projectile[_projectileSpawnsUsed]);
				SetSpawnPoint(point, val, deliveryEnemyClass);
				Debug.Log((object)$"now at {_pointsLeft}");
			}
		}

		private IEnumerable<EndlessEnemy> GetPotentialEnemies(EnemyGroup group)
		{
			EndlessEnemy[] enemies = group.Enemies;
			foreach (EndlessEnemy enemy in enemies)
			{
				if (enemy.spawnWave <= MonoSingleton<GameManager>.Instance.RoomsEntered && GetRealCost(enemy) <= _pointsLeft)
				{
					yield return enemy;
				}
			}
		}

		private void SetSpawnPoint(EnemySpawnPoint point, EndlessEnemy enemy, DeliveryEnemyClass spawnType)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			point.Room = this;
			point.Enemy = enemy.prefab;
			_pointsLeft -= GetRealCost(enemy);
			Debug.Log((object)$"just spent {GetRealCost(enemy)}");
			_amountSpawned.TryAdd(enemy.enemyType, 0);
			_amountSpawned[enemy.enemyType]++;
			switch (spawnType)
			{
			case DeliveryEnemyClass.Melee:
				_meleeSpawnsUsed++;
				break;
			case DeliveryEnemyClass.Projectile:
				_projectileSpawnsUsed++;
				break;
			}
			Arena.enemies = CollectionExtensions.AddToArray<GameObject>(Arena.enemies, ((Component)point).gameObject);
		}

		private int GetRealCost(EndlessEnemy enemy)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			int num = (_amountSpawned.ContainsKey(enemy.enemyType) ? _amountSpawned[enemy.enemyType] : 0);
			return enemy.spawnCost + enemy.costIncreasePerSpawn * num;
		}

		private void OnTriggerEnter(Collider collider)
		{
			if ((Object)(object)((Component)collider).GetComponent<NewMovement>() != (Object)null && !RoomActivated)
			{
				RoomActivated = true;
				MonoSingleton<GameManager>.Instance.SetRoom(this);
				ActivateArena arena = Arena;
				if (arena != null)
				{
					arena.Activate();
				}
			}
		}
	}
	public class RoomData : ScriptableObject
	{
		public string Name = "My Super Cool Room";

		public string Author = "Waffle";

		[Space(15f)]
		public GameObject Prefab;
	}
	public class RoomPool : ScriptableObject
	{
		public RoomData[] Rooms;
	}
	[PatchThis("$waffle.ultrakill.christmasdelivery.TimeBonusPatches")]
	public class TimeBonusPatches
	{
		[HarmonyPatch(typeof(StyleCalculator), "AddPoints")]
		[HarmonyPrefix]
		private static void AddBigKillTime(ref string pointName)
		{
			if (AddressableManager.InSceneFromThisMod && pointName == "ultrakill.bigkill")
			{
				MonoSingleton<GameManager>.Instance.AddTime(2f, "<color=orange>BIG KILL</color>");
				pointName = "";
			}
		}
	}
}
namespace EndlessDelivery.Gameplay.EnemyGeneration
{
	public static class Act3EnemyHack
	{
		private static bool _hasAdded;

		public static void AddToPools(params EnemyGroup[] groups)
		{
			if (!_hasAdded)
			{
				_hasAdded = true;
				PrefabDatabase database = AddressableManager.Load<PrefabDatabase>("Assets/Data/Cyber Grind Patterns/Data/Prefab Database.asset");
				foreach (EnemyGroup group in groups)
				{
					AddEnemies(group, database);
				}
			}
		}

		private static void AddEnemies(EnemyGroup group, PrefabDatabase database)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0046: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Invalid comparison between Unknown and I4
			//IL_006a: 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)
			List<EndlessEnemy> list = group.Enemies.ToList();
			switch (group.Class)
			{
			case DeliveryEnemyClass.Projectile:
			{
				EndlessEnemy[] projectileEnemies = database.projectileEnemies;
				foreach (EndlessEnemy val2 in projectileEnemies)
				{
					EnemyType enemyType = val2.enemyType;
					if (((int)enemyType == 31 || (int)enemyType == 33) ? true : false)
					{
						Debug.Log((object)$"Added {val2.enemyType} to {((Object)group).name}!");
						list.Add(val2);
					}
				}
				break;
			}
			case DeliveryEnemyClass.Uncommon:
			{
				EndlessEnemy[] uncommonEnemies = database.uncommonEnemies;
				foreach (EndlessEnemy val in uncommonEnemies)
				{
					if ((int)val.enemyType == 34)
					{
						Debug.Log((object)$"Added {val.enemyType} to {((Object)group).name}!");
						list.Add(val);
					}
				}
				break;
			}
			}
			group.Enemies = list.ToArray();
		}
	}
	public enum DeliveryEnemyClass
	{
		Melee,
		Projectile,
		Uncommon,
		Special,
		Boss
	}
	public class EnemyGroup : ScriptableObject
	{
		public static Dictionary<DeliveryEnemyClass, EnemyGroup> Groups = new Dictionary<DeliveryEnemyClass, EnemyGroup>();

		public DeliveryEnemyClass Class;

		[Space(10f)]
		public EndlessEnemy[] Enemies;

		public static void SetGroups(IEnumerable<EnemyGroup> groups)
		{
			foreach (EnemyGroup group in groups)
			{
				Groups.Add(group.Class, group);
			}
		}
	}
	public class EnemySpawnPoint : MonoBehaviour
	{
		[Header("SpawnPoints should only be Melee, Projectile, or Boss.")]
		public DeliveryEnemyClass Class;

		[HideInInspector]
		public GameObject Enemy;

		[HideInInspector]
		public Room Room;

		private void Awake()
		{
			((Component)this).gameObject.SetActive(false);
		}

		private void OnEnable()
		{
			Room.Enemies.Add(Object.Instantiate<GameObject>(Enemy, ((Component)this).transform).GetComponent<EnemyIdentifier>());
		}
	}
}
namespace EndlessDelivery.Config
{
	public class Option
	{
		protected static Dictionary<string, object> AllOptionValues = new Dictionary<string, object>();

		public static Dictionary<string, Option> AllOptions = new Dictionary<string, Option>
		{
			{
				"start_wave",
				new Option<long>("start_wave", 0L)
			},
			{
				"disable_copyrighted_music",
				new Option<bool>("disable_copyrighted_music", defaultValue: false)
			}
		};

		public static string SavePath => Path.Combine(PathUtils.ModPath(), "Savedata");

		public static string OptionFilePath => Path.Combine(SavePath, "settings.json");

		public static T GetValue<T>(string id)
		{
			return (AllOptions[id] as Option<T>).Value;
		}

		public static void Save()
		{
			Directory.CreateDirectory(SavePath);
			File.WriteAllText(OptionFilePath, JsonConvert.SerializeObject((object)AllOptionValues));
		}

		public static void Load()
		{
			if (File.Exists(OptionFilePath))
			{
				AllOptionValues = JsonConvert.DeserializeObject<Dictionary<string, object>>(File.ReadAllText(OptionFilePath));
			}
		}
	}
	public class Option<T> : Option
	{
		private string _id;

		private T _defaultValue;

		public T Value
		{
			get
			{
				if (!Option.AllOptionValues.ContainsKey(_id))
				{
					Option.AllOptionValues.Add(_id, _defaultValue);
				}
				return (T)Option.AllOptionValues[_id];
			}
			set
			{
				if (!Option.AllOptionValues.ContainsKey(_id))
				{
					Option.AllOptionValues.Add(_id, value);
				}
				else
				{
					Option.AllOptionValues[_id] = value;
				}
			}
		}

		public Option(string id, T defaultValue)
		{
			_id = id;
			_defaultValue = defaultValue;
		}
	}
}
namespace EndlessDelivery.Config.Elements
{
	public class BoolElement : MonoBehaviour
	{
		public TMP_Text EnabledText;

		public string Id;

		public UltrakillEvent OnToggled;

		private Option<bool> _option;

		private void Start()
		{
			_option = (Option<bool>)Option.AllOptions[Id];
			UpdateText();
		}

		public void Toggle()
		{
			_option.Value = !_option.Value;
			UpdateText();
		}

		private void UpdateText()
		{
			EnabledText.text = (_option.Value ? "ENABLED" : "DISABLED");
			if (_option.Value)
			{
				OnToggled.Invoke();
			}
			else
			{
				OnToggled.Revert();
			}
		}
	}
	public class RoomElement : MonoBehaviour
	{
		public TMP_Text RoomText;

		public TMP_Text TimeText;

		private Option<long> _option;

		private void Start()
		{
			_option = (Option<long>)Option.AllOptions["start_wave"];
			UpdateText();
		}

		public void ChangeBy(int change)
		{
			int num = Mathf.Min(Score.Highscore.Rooms / 2, BestTimes.Times.Count);
			_option.Value = Mathf.Clamp((int)(_option.Value + change), 0, num);
			UpdateText();
		}

		private void UpdateText()
		{
			RoomText.text = $"ROOM {_option.Value}";
			TimeText.text = TimeSpan.FromSeconds(BestTimes.GetRoomTime((int)_option.Value)).Formatted();
		}
	}
}
namespace EndlessDelivery.Components
{
	public class Chimney : MonoBehaviour
	{
		public GameObject Glow;

		public TMP_Text DeliveredText;

		public int AmountToDeliver;

		public JumpPad JumpPad;

		public AudioSource DeliverSound;

		public Animator Animator;

		public GameObject Teleporter;

		public ParticleSystem Particles;

		[HideInInspector]
		public Room Room;

		private Renderer _glowRenderer;

		private float _glowAlpha;

		private Coroutine _currentAnimation;

		private bool _chimneyEntered;

		[field: SerializeField]
		public WeaponVariant VariantColour { get; private set; }

		private Color _color => ColourSetter.DefaultColours[VariantColour];

		private void Start()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			SetRenderer();
			SetColour(VariantColour);
		}

		private void SetRenderer()
		{
			_glowRenderer = Glow.GetComponent<Renderer>();
			_glowAlpha = _glowRenderer.material.GetFloat("_OpacScale");
		}

		public void SetColour(WeaponVariant colour)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_glowRenderer == (Object)null)
			{
				SetRenderer();
			}
			VariantColour = colour;
			Particles.startColor = _color;
			_glowRenderer.material.color = _color;
		}

		private void Update()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)DeliveredText == (Object)null) && !((Object)(object)Room == (Object)null))
			{
				DeliveredText.text = $"{Room.AmountDelivered[VariantColour]}/{AmountToDeliver}";
				((Graphic)DeliveredText).color = _color;
			}
		}

		private void DeliverEffect()
		{
			DeliverSound.Play();
			if (_currentAnimation != null)
			{
				((MonoBehaviour)this).StopCoroutine(_currentAnimation);
			}
			_currentAnimation = ((MonoBehaviour)this).StartCoroutine(DeliverEffectAnimation());
		}

		private IEnumerator DeliverEffectAnimation()
		{
			Animator.Play("Glow Animation");
			yield return (object)new WaitForSeconds(1f / 6f);
			Material glowMaterial = _glowRenderer.material;
			while (glowMaterial.GetFloat("_OpacScale") != 0f)
			{
				glowMaterial.SetFloat("_OpacScale", Mathf.MoveTowards(glowMaterial.GetFloat("_OpacScale"), 0f, Time.deltaTime * 2f));
				yield return null;
			}
			if (!Room.Done(VariantColour))
			{
				yield return (object)new WaitForSeconds(1f);
				while (glowMaterial.GetFloat("_OpacScale") != _glowAlpha)
				{
					glowMaterial.SetFloat("_OpacScale", Mathf.MoveTowards(glowMaterial.GetFloat("_OpacScale"), _glowAlpha, Time.deltaTime));
					yield return null;
				}
				yield break;
			}
			Vector3 target = DeliveredText.transform.localScale;
			target.y = 0f;
			while (glowMaterial.GetFloat("_OpacScale") != _glowAlpha / 2f)
			{
				glowMaterial.SetFloat("_OpacScale", Mathf.MoveTowards(glowMaterial.GetFloat("_OpacScale"), _glowAlpha / 2f, Time.deltaTime));
				yield return null;
			}
			while (DeliveredText.transform.localScale.y != 0f)
			{
				DeliveredText.transform.localScale = Vector3.MoveTowards(DeliveredText.transform.localScale, target, Time.deltaTime * 2f);
				yield return null;
			}
		}

		private void OnTriggerEnter(Collider collider)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Present present = default(Present);
			if (((Component)collider).TryGetComponent<Present>(ref present) && present.VariantColour == VariantColour && !present.Destroyed)
			{
				present.Deliver(this);
				DeliverEffect();
			}
			if ((Object)(object)((Component)collider).GetComponent<NewMovement>() != (Object)null && Room.ChimneysDone)
			{
				ChimneyEnter();
			}
			EnemyIdentifierIdentifier val = default(EnemyIdentifierIdentifier);
			if (((Component)collider).gameObject.TryGetComponent<EnemyIdentifierIdentifier>(ref val))
			{
				EnemyIdentifier eid = val.eid;
				if (eid == null || eid.dead)
				{
					Object.Destroy((Object)(object)((Component)collider).gameObject);
				}
			}
		}

		public void ChimneyEnter()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (_chimneyEntered)
			{
				return;
			}
			MonoSingleton<GameManager>.Instance.RoomEnd();
			MonoSingleton<NewMovement>.Instance.rb.velocity = MonoSingleton<NewMovement>.Instance.rb.velocity.Only(Axis.Y);
			((Behaviour)MonoSingleton<NewMovement>.Instance).enabled = false;
			((Behaviour)MonoSingleton<NewMovement>.Instance.gc).enabled = false;
			foreach (Collider envCollider in MonoSingleton<GameManager>.Instance.PreviousRoom.EnvColliders)
			{
				Physics.IgnoreCollision((Collider)(object)MonoSingleton<NewMovement>.Instance.playerCollider, envCollider, true);
			}
			((Behaviour)((Component)MonoSingleton<NewMovement>.Instance).GetComponent<KeepInBounds>()).enabled = false;
			MonoSingleton<PlayerChimneyFixer>.Instance.EnterChimney(this);
			_chimneyEntered = true;
		}

		public void ChimneyLeave()
		{
			((Behaviour)MonoSingleton<NewMovement>.Instance).enabled = true;
			((Behaviour)MonoSingleton<NewMovement>.Instance.gc).enabled = true;
			((Behaviour)((Component)MonoSingleton<NewMovement>.Instance).GetComponent<KeepInBounds>()).enabled = true;
			MonoSingleton<PlayerChimneyFixer>.Instance.Exit();
		}

		public void WarpPlayerToNextRoom()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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)
			Object.Destroy((Object)(object)((Component)MonoSingleton<GameManager>.Instance.PreviousRoom).gameObject);
			Vector3 vector = ((Component)MonoSingleton<NewMovement>.Instance).transform.position - Teleporter.transform.position;
			((Component)MonoSingleton<NewMovement>.Instance).transform.position = MonoSingleton<GameManager>.Instance.CurrentRoom.SpawnPoint.transform.position + vector.Only(Axis.X, Axis.Z);
			MonoSingleton<PlayerChimneyFixer>.Instance.EnterChimney(null);
		}
	}
	[PatchThis("waffle.ultrakill.christmasdelivery.MauriceFitter")]
	public class MauriceFitter : MonoBehaviour
	{
		private float _startHeight;

		private float _targetHeight;

		private EnemyIdentifier _eid;

		private void Start()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			_startHeight = ((Component)this).transform.localPosition.y;
			_eid = ((Component)this).GetComponent<EnemyIdentifier>();
		}

		private void Update()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0077: 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_0091: 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_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)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (!_eid.dead)
			{
				RaycastHit val = default(RaycastHit);
				if (Physics.Raycast(((Component)this).transform.parent.position, Vector3.up, ref val, 20f, LayerMask.op_Implicit(LayerMaskDefaults.Get((LMD)1))))
				{
					_targetHeight = ((RaycastHit)(ref val)).distance - 1f;
				}
				else
				{
					_targetHeight = _startHeight;
				}
				((Component)this).transform.localPosition = Vector3.MoveTowards(((Component)this).transform.localPosition, ((Component)this).transform.localPosition.Only(Axis.X, Axis.Z) + Vector3.up * _targetHeight, Time.deltaTime * 5f);
			}
		}

		[HarmonyPatch(typeof(SpiderBody), "Start")]
		[HarmonyPostfix]
		private static void AddMauriceFitter(SpiderBody __instance)
		{
			if (AddressableManager.InSceneFromThisMod)
			{
				((Component)__instance).gameObject.AddComponent<MauriceFitter>();
			}
		}
	}
	[PatchThis("waffle.ultrakill.christmasdelivery.Present")]
	public class Present : MonoBehaviour
	{
		private static List<Collider> _allPresentColliders = new List<Collider>();

		public WeaponVariant VariantColour;

		public GameObject Particles;

		public SpriteRenderer Glow;

		private ItemIdentifier _item;

		private Collider _collider;

		[HideInInspector]
		public bool Destroyed;

		private Color _colour => ColourSetter.DefaultColours[VariantColour];

		private void Start()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			_collider = ((Component)this).GetComponent<Collider>();
			_item = ((Component)this).GetComponent<ItemIdentifier>();
			_allPresentColliders.Add(_collider);
			SetColour(VariantColour);
		}

		private void Update()
		{
			((Component)Glow).gameObject.layer = 0;
		}

		private void OnDisable()
		{
			_allPresentColliders.Remove(_collider);
		}

		private void OnDestroy()
		{
			_allPresentColliders.Remove(_collider);
		}

		public void SetColour(WeaponVariant colour)
		{
			//IL_0002: 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)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			VariantColour = colour;
			((Component)this).GetComponent<Renderer>().material.color = _colour;
			((Component)this).GetComponent<Light>().color = _colour;
			((Component)this).GetComponent<ParticleSystem>().startColor = _colour;
			Glow.color = new Color(_colour.r, _colour.g, _colour.b, 0.5f);
		}

		public void Deliver(Chimney chimney)
		{
			//IL_0008: 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)
			chimney.Room.Deliver(VariantColour);
			MonoSingleton<GameManager>.Instance.AddTime(6f, "<color=#" + ColorUtility.ToHtmlStringRGB(_colour) + ">DELIVERY</color>");
			CreateParticles();
			Destroyed = true;
			if (_item.hooked)
			{
				MonoSingleton<HookArm>.Instance.StopThrow(0f, false);
			}
			if ((Object)(object)MonoSingleton<FistControl>.Instance.currentPunch.heldItem == (Object)(object)_item)
			{
				MonoSingleton<FistControl>.Instance.currentPunch.ForceThrow();
			}
			Object.Destroy((Object)(object)_item);
			((Component)this).GetComponent<Collider>().enabled = false;
			((Component)this).GetComponent<Rigidbody>().detectCollisions = false;
			((MonoBehaviour)this).StartCoroutine(DestroyAnimation());
		}

		public void CreateParticles()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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)
			ParticleSystem component = Object.Instantiate<GameObject>(Particles, ((Component)this).transform.position, Quaternion.identity).GetComponent<ParticleSystem>();
			((Component)component).GetComponentInChildren<Light>().color = _colour;
			component.startColor = _colour;
		}

		private IEnumerator DestroyAnimation()
		{
			yield return (object)new WaitForSeconds(0.25f);
			while (((Component)this).transform.localScale != Vector3.zero)
			{
				((Component)this).transform.localScale = Vector3.MoveTowards(((Component)this).transform.localScale, Vector3.zero, Time.deltaTime * 2f);
				yield return null;
			}
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		private void OnTriggerStay(Collider collider)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Chimney chimney = default(Chimney);
			if (!Destroyed && ((Component)collider).TryGetComponent<Chimney>(ref chimney) && chimney.VariantColour != VariantColour)
			{
				Vector3 vector = (((Component)MonoSingleton<NewMovement>.Instance).transform.position - ((Component)this).transform.position) * 2.5f;
				Vector3 velocity = Vector3.up * 25f + vector.Only(Axis.X, Axis.Z);
				((Component)this).GetComponent<Rigidbody>().velocity = velocity;
			}
		}

		[HarmonyPatch(typeof(Explosion), "Start")]
		[HarmonyPostfix]
		private static void DisableExplosionToPresentCollisions(Explosion __instance)
		{
			if (!AddressableManager.InSceneFromThisMod)
			{
				return;
			}
			foreach (Collider allPresentCollider in _allPresentColliders)
			{
				Physics.IgnoreCollision(allPresentCollider, (Collider)(object)__instance.scol);
			}
		}
	}
	public class PresentDragZone : MonoBehaviour
	{
		public float PullStrength;

		public Chimney Chimney;

		private void OnTriggerStay(Collider collider)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			Present present = default(Present);
			if (((Component)collider).TryGetComponent<Present>(ref present) && present.VariantColour == Chimney.VariantColour)
			{
				Rigidbody component = ((Component)collider).GetComponent<Rigidbody>();
				Vector3 val = (((Component)collider).transform.position - ((Component)this).transform.position).Only(Axis.X, Axis.Z);
				Vector3 val2 = -((Vector3)(ref val)).normalized;
				Vector3 velocity = component.velocity;
				Vector3 val3 = val2 * ((Vector3)(ref velocity)).magnitude + component.velocity.y * Vector3.up * 1.25f;
				component.velocity = Vector3.MoveTowards(component.velocity, val3, Time.deltaTime * PullStrength);
			}
		}
	}
	public class PreventItemHooking : MonoBehaviour
	{
		public float EnableWhippingAtDistance = 7f;

		private void Update()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0067: Invalid comparison between Unknown and I4
			if (((Component)this).gameObject.layer != 13)
			{
				if (Vector3.Distance(((Component)this).transform.position, ((Component)MonoSingleton<NewMovement>.instance).transform.position) <= EnableWhippingAtDistance)
				{
					((Component)this).gameObject.layer = 22;
				}
				else
				{
					((Component)this).gameObject.layer = (((int)MonoSingleton<HookArm>.Instance.state != 1) ? 22 : 0);
				}
			}
		}
	}
	public class RandomToggler : MonoBehaviour
	{
		public List<GameObject> Objects;

		private void Start()
		{
			foreach (GameObject @object in Objects)
			{
				@object.SetActive(false);
			}
			Objects.Pick().SetActive(true);
		}
	}
}
namespace EndlessDelivery.Cheats
{
	[PatchThis("waffle.ultrakill.christmasdelivery.CheatManager")]
	public static class CheatManager
	{
		[HarmonyPatch(typeof(CheatsManager), "Start")]
		[HarmonyPrefix]
		private static void AddIfShould(CheatsManager __instance)
		{
			if (AddressableManager.InSceneFromThisMod)
			{
				__instance.RegisterExternalCheat((ICheat)(object)new CompleteRoom());
				__instance.RegisterExternalCheat((ICheat)(object)new InfiniteTime());
			}
		}
	}
	public class CompleteRoom : ICheat
	{
		public string LongName => "Deliver All Presents";

		public string Identifier => "waffle.ultrakill.christmasdelivery.deliverall";

		public string ButtonEnabledOverride => null;

		public string ButtonDisabledOverride => "DELIVER";

		public string Icon => "death";

		public bool IsActive => false;

		public bool DefaultState => false;

		public StatePersistenceMode PersistenceMode => (StatePersistenceMode)0;

		public void Enable()
		{
			MonoSingleton<GameManager>.Instance.CurrentRoom.AmountDelivered = new Dictionary<WeaponVariant, int>
			{
				{
					(WeaponVariant)0,
					10
				},
				{
					(WeaponVariant)1,
					10
				},
				{
					(WeaponVariant)2,
					10
				},
				{
					(WeaponVariant)3,
					10
				}
			};
			foreach (Chimney chimney in MonoSingleton<GameManager>.Instance.CurrentRoom.Chimneys)
			{
				((Component)chimney.JumpPad).gameObject.SetActive(false);
			}
		}

		public void Disable()
		{
		}

		public void Update()
		{
		}
	}
	public class InfiniteTime : ICheat
	{
		private bool _active;

		public string LongName => "Infinite Time";

		public string Identifier => "waffle.ultrakill.christmasdelivery.inftime";

		public string ButtonEnabledOverride { get; }

		public string ButtonDisabledOverride { get; }

		public string Icon => "death";

		public bool IsActive => _active;

		public bool DefaultState { get; }

		public StatePersistenceMode PersistenceMode => (StatePersistenceMode)0;

		public void Enable()
		{
			_active = true;
		}

		public void Disable()
		{
			_active = false;
		}

		public void Update()
		{
			MonoSingleton<GameManager>.Instance.SilentAddTime(Time.deltaTime);
		}
	}
}
namespace EndlessDelivery.Assets
{
	[PatchThis("waffle.ultrakill.christmasdelivery.AddressableManager")]
	public static class AddressableManager
	{
		private static List<string> _scenesFromThisMod;

		private static bool _dontSanitizeScenes;

		public static string AssetPathLocation => "{" + typeof(AddressableManager).FullName + ".AssetPath}";

		public static string MonoScriptBundleName => "monoscript_endlessdelivery_monoscripts.bundle";

		public static string AssetPath => Path.Combine(PathUtils.ModPath(), "Assets");

		public static string CatalogPath => Path.Combine(AssetPath, "catalog.json");

		public static string ModDataPath => Path.Combine(AssetPath, "data.json");

		public static bool InSceneFromThisMod => _scenesFromThisMod.Contains(SceneHelper.CurrentScene);

		public static void Setup()
		{
			//IL_0008: 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)
			Addressables.LoadContentCatalogAsync(CatalogPath, true, (string)null).WaitForCompletion();
			LoadDataFile();
		}

		private static void LoadDataFile()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Dictionary<string, List<string>> dictionary = null;
			using (StreamReader streamReader = new StreamReader(File.OpenRead(ModDataPath)))
			{
				JsonSerializer val = new JsonSerializer();
				dictionary = val.Deserialize<Dictionary<string, List<string>>>((JsonReader)new JsonTextReader((TextReader)streamReader));
			}
			if (dictionary.ContainsKey(typeof(EnemyGroup).FullName))
			{
				EnemyGroup.SetGroups(GetDataOfType<EnemyGroup>(dictionary));
			}
			if (dictionary.ContainsKey(typeof(Scene).FullName))
			{
				_scenesFromThisMod = dictionary[typeof(Scene).FullName];
			}
		}

		private static IEnumerable<T> GetDataOfType<T>(Dictionary<string, List<string>> data) where T : Object
		{
			if (!data.ContainsKey(typeof(T).FullName))
			{
				return Array.Empty<T>();
			}
			return data[typeof(T).FullName].Select(Load<T>);
		}

		public static T Load<T>(string path)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return Addressables.LoadAssetAsync<T>((object)path).WaitForCompletion();
		}

		public static void LoadScene(string path)
		{
			_dontSanitizeScenes = true;
			try
			{
				SceneHelper.LoadScene(path, false);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex.ToString());
			}
			_dontSanitizeScenes = false;
		}

		[HarmonyPatch(typeof(SceneHelper), "SanitizeLevelPath")]
		[HarmonyPrefix]
		private static bool PreventSanitization(string scene, ref string __result)
		{
			if (_dontSanitizeScenes)
			{
				__result = scene;
				return false;
			}
			return true;
		}
	}
}
namespace EndlessDelivery.Anticheat
{
	public abstract class Anticheat
	{
		private static List<Anticheat> _anticheats = new List<Anticheat>
		{
			new DetectPresenceAnticheat(),
			new MasqueradeDivinityAnticheat(),
			new UltraTweakerAnticheat()
		};

		public static bool HasIllegalMods = !_anticheats.All((Anticheat ac) => ac.ShouldSubmit);

		protected abstract bool ShouldSubmit { get; }
	}
	public class DetectPresenceAnticheat : Anticheat
	{
		private string[] _mods = new string[4] { "ironfarm.uk.uc", "ironfarm.uk.muda", "plonk.rocketgatling", "maranara_whipfix" };

		protected override bool ShouldSubmit => _mods.All((string mod) => !Chainloader.PluginInfos.ContainsKey(mod));
	}
	public class MasqueradeDivinityAnticheat : Anticheat
	{
		public const string GUID = "maranara_project_prophet";

		protected override bool ShouldSubmit
		{
			get
			{
				if (!Chainloader.PluginInfos.ContainsKey("maranara_project_prophet"))
				{
					return true;
				}
				return GabeOn();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private bool GabeOn()
		{
			return ProjectProphet.gabeOn;
		}
	}
	public class UltraTweakerAnticheat : Anticheat
	{
		private const string GUID = "waffle.ultrakill.ultratweaker";

		protected override bool ShouldSubmit
		{
			get
			{
				if (!Chainloader.PluginInfos.ContainsKey("waffle.ultrakill.ultratweaker"))
				{
					return true;
				}
				if (HasBadTweaks())
				{
					return false;
				}
				return true;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private bool HasBadTweaks()
		{
			foreach (Tweak value in UltraTweaker.AllTweaks.Values)
			{
				Attribute? customAttribute = Attribute.GetCustomAttribute(((object)value).GetType(), typeof(TweakMetadata));
				TweakMetadata val = (TweakMetadata)(object)((customAttribute is TweakMetadata) ? customAttribute : null);
				if (value.IsEnabled && (val == null || !val.AllowCG))
				{
					return true;
				}
			}
			return false;
		}
	}
}