Decompiled source of ArchipelaGun Multiworld Randomizer v0.1.5

plugins/ArchipelaGun.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using Alexandria.ItemAPI;
using Alexandria.Misc;
using Alexandria.SoundAPI;
using ArchiGungeon.ArchipelagoServer;
using ArchiGungeon.Character;
using ArchiGungeon.Data;
using ArchiGungeon.DebugTools;
using ArchiGungeon.EnemyHandlers;
using ArchiGungeon.GungeonEventHandlers;
using ArchiGungeon.ItemArchipelago;
using ArchiGungeon.UserInterface;
using Archipelago.MultiClient.Net;
using Archipelago.MultiClient.Net.BounceFeatures.DeathLink;
using Archipelago.MultiClient.Net.Colors;
using Archipelago.MultiClient.Net.ConcurrentCollection;
using Archipelago.MultiClient.Net.Converters;
using Archipelago.MultiClient.Net.DataPackage;
using Archipelago.MultiClient.Net.Enums;
using Archipelago.MultiClient.Net.Exceptions;
using Archipelago.MultiClient.Net.Extensions;
using Archipelago.MultiClient.Net.Helpers;
using Archipelago.MultiClient.Net.MessageLog.Messages;
using Archipelago.MultiClient.Net.MessageLog.Parts;
using Archipelago.MultiClient.Net.Models;
using Archipelago.MultiClient.Net.Packets;
using BepInEx;
using BepInEx.Logging;
using Dungeonator;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using SGUI;
using UnityEngine;
using WebSocketSharp;
using WebSocketSharp.Net;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Mod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Mod")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d6d7a494-722e-4763-959b-c2d6b6a42b01")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ArchiGungeon
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("maoboulve.etg.archipelagogungeon", "Archipelago Gungeon Randomizer", "0.1.5")]
	public class ArchipelaGunPlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static LogCallback <0>__OnCatchException;
		}

		public const string GUID = "maoboulve.etg.archipelagogungeon";

		public const string NAME = "Archipelago Gungeon Randomizer";

		public const string VERSION = "0.1.5";

		public const string TEXT_COLOR = "#B6FFB8";

		public const string MOD_ITEM_PREFIX = "arch";

		public const string AP_WORLD_VERSION = "0.1.1";

		private static bool isInit;

		public static ArchipelagoGUI ArchipelagoModMenu { get; protected set; }

		public void Start()
		{
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Starting ArchipelaGunPlugin");
			ETGModMainBehaviour.WaitForGameManagerStart((Action<GameManager>)GMStart);
		}

		public void GMStart(GameManager g)
		{
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "GameManager started");
			InitItemHooks();
			RegisterItems();
			InitEnemyHooks();
			InitModMenu();
			Log("Archipelago Gungeon Randomizer v0.1.5 started successfully.", "#B6FFB8");
			isInit = true;
			StartPostInitializationSetup();
		}

		private void InitItemHooks()
		{
		}

		private void RegisterItems()
		{
			Archipelagun.Register();
			APPickUpItem.RegisterItemBase();
			ReverseCurse.RegisterItem();
			ReverseCurseReversal.RegisterItem();
			BulletParadoxItem.RegisterItem();
			PilotParadoxItem.RegisterItem();
			ConvictParadoxItem.RegisterItem();
			MarineParadoxItem.RegisterItem();
			RobotParadoxItem.RegisterItem();
			HunterParadoxItem.RegisterItem();
		}

		private void InitEnemyHooks()
		{
			EnemySwapping.InitializeEnemySwapper();
		}

		private void InitModMenu()
		{
			ArchipelagoModMenu = new ArchipelagoGUI();
			((ETGModMenu)ArchipelagoModMenu).Start();
		}

		private void StartPostInitializationSetup()
		{
			StartGungeonPlayerListener();
			InitExceptionCatcher();
		}

		private void StartGungeonPlayerListener()
		{
			GungeonPlayerEventListener.StartSystemEventListens();
		}

		private void InitExceptionCatcher()
		{
			//IL_0023: 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)
			//IL_002e: Expected O, but got Unknown
			ArchDebugPrint.InitDebugLog();
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Init Exception Catcher");
			object obj = <>O.<0>__OnCatchException;
			if (obj == null)
			{
				LogCallback val = ArchDebugPrint.OnCatchException;
				<>O.<0>__OnCatchException = val;
				obj = (object)val;
			}
			Application.logMessageReceived += (LogCallback)obj;
		}

		private static void Log(string text, string color = "#FFFFFF")
		{
			ETGModConsole.Log((object)("<color=" + color + ">" + text + "</color>"), false);
		}

		public void Update()
		{
			if (isInit)
			{
				((ETGModMenu)ArchipelagoModMenu).Update();
				SessionHandler.TickCheckItemQueue();
			}
		}
	}
	public class Archipelagun : GunBehaviour
	{
		public delegate void ArchipelagunEvents();

		public static ArchipelagunEvents OnPickup;

		private static bool isStartOfRun = true;

		public static int SpawnItemID = -1;

		private static bool canBeWielded = true;

		private static PlayerController playerWithArchipelagun;

		private static int equippedslot = -1;

		private static string itemName = "Archipelagun";

		private static string shortDesc = "Fire - Menu, Reload - Goals";

		private static string longDesc = "A Breach to other worlds. Fire to open the main mod menu, reload to see goals.";

		public static void Register()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Registering ArchipelaGun");
			Gun val = Databases.Items.NewGun(itemName, "archipelagun");
			((Component)val).gameObject.AddComponent<Archipelagun>();
			GunExt.SetupSprite(val, (tk2dSpriteCollectionData)null, "archipelagun_idle_001", 4);
			GunExt.AddProjectileModuleFrom(val, "dart_gun", true, false);
			((PickupObject)val).quality = (ItemQuality)(-100);
			val.DefaultModule.ammoCost = 1;
			val.reloadTime = 4f;
			val.DefaultModule.numberOfShotsInClip = 9999;
			val.LocalInfiniteAmmo = true;
			val.DefaultModule.cooldownTime = 2f;
			val.doesScreenShake = false;
			((PickupObject)val).CanBeDropped = false;
			((PickupObject)val).CanBeSold = false;
			((PickupObject)val).ShouldBeExcludedFromShops = true;
			((PickupObject)val).RespawnsIfPitfall = true;
			((PickupObject)val).IgnoredByRat = true;
			val.CanReloadNoMatterAmmo = true;
			val.gunSwitchGroup = "arch_" + itemName;
			SoundManager.AddCustomSwitchData("WPN_Guns", val.gunSwitchGroup, "Play_WPN_Gun_Shot_01", (SwitchedEvent[])(object)new SwitchedEvent[1] { SwitchedEvent.op_Implicit("Play_WPN_radgun_noice_01") });
			SoundManager.AddCustomSwitchData("WPN_Guns", val.gunSwitchGroup, "Play_WPN_Gun_Reload_01", (SwitchedEvent[])(object)new SwitchedEvent[1] { SwitchedEvent.op_Implicit("Play_WPN_LowerCaseR_Magical_Kadabra_01") });
			Projectile val2 = Object.Instantiate<Projectile>(val.DefaultModule.projectiles[0]);
			((Component)val2).gameObject.SetActive(false);
			FakePrefab.MarkAsFakePrefab(((Component)val2).gameObject);
			Object.DontDestroyOnLoad((Object)(object)val2);
			val.DefaultModule.projectiles[0] = val2;
			val2.baseData.damage = 0f;
			val2.baseData.speed = 1.7f;
			val2.baseData.range = 0f;
			val2.baseData.force = 0f;
			ItemBuilder.SetupItem((PickupObject)(object)val, shortDesc, longDesc, "bas");
			SpawnItemID = PickupObjectDatabase.GetId((PickupObject)(object)val);
		}

		public override void OnPlayerPickup(PlayerController playerOwner)
		{
			OnPickup();
			isStartOfRun = true;
			canBeWielded = true;
			playerWithArchipelagun = playerOwner;
			equippedslot = playerWithArchipelagun.inventory.AllGuns.IndexOf(playerWithArchipelagun.inventory.CurrentGun);
			ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, $"Archipelagun is in slot {equippedslot}");
			PlayerController obj = playerWithArchipelagun;
			obj.OnReloadPressed = (Action<PlayerController, Gun>)Delegate.Combine(obj.OnReloadPressed, new Action<PlayerController, Gun>(OnReloadPressed));
			PlayerController obj2 = playerWithArchipelagun;
			obj2.OnEnteredCombat = (Action)Delegate.Combine(obj2.OnEnteredCombat, new Action(OnEnterCombat));
			playerWithArchipelagun.OnRoomClearEvent += OnRoomClear;
			if (SessionHandler.Session != null)
			{
				SessionHandler.CallRetrieveDataCoroutine();
			}
		}

		private void OnRoomClear(PlayerController controller)
		{
			canBeWielded = true;
		}

		private void OnEnterCombat()
		{
			if (isStartOfRun)
			{
				isStartOfRun = false;
				ArchDebugPrint.DebugLog(DebugCategory.CharacterSystems, "Handling last checks for character swapper");
			}
			canBeWielded = false;
			if (((object)((GameActor)playerWithArchipelagun).CurrentGun).ToString().Contains("archipelagun"))
			{
				ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Forcing swap to starter gun");
				playerWithArchipelagun.ChangeToGunSlot(0, false);
			}
		}

		private void OnReloadPressed(PlayerController controller, Gun gun)
		{
			if (((object)((GameActor)playerWithArchipelagun).CurrentGun).ToString().Contains("archipelagun"))
			{
				if (SessionHandler.IsGoalsTextBoxOpen)
				{
					SessionHandler.HideGoalsTextbox();
				}
				else
				{
					SessionHandler.ShowGoalsTextbox();
				}
			}
		}

		public override void OnSwitchedToPlayer(PlayerController owner, GunInventory inventory, Gun oldGun, bool isNewGun)
		{
			if (!canBeWielded)
			{
				owner.ChangeToGunSlot(inventory.AllGuns.IndexOf(oldGun), false);
			}
		}

		public override void OnSwitchedAwayFromPlayer(PlayerController owner, GunInventory inventory, Gun newGun, bool isNewGun)
		{
			if (SessionHandler.IsGoalsTextBoxOpen)
			{
				SessionHandler.HideGoalsTextbox();
			}
		}

		public override void OnPostFired(PlayerController player, Gun gun)
		{
			if (!player.IsInCombat)
			{
				ArchipelagoGUI instance = ArchipelagoGUI.Instance;
				if (instance != null)
				{
					((ETGModMenu)instance).OnOpen();
				}
			}
		}
	}
}
namespace ArchiGungeon.UserInterface
{
	public delegate void MenuEvent();
	public class ArchipelagoGUI : ETGModMenu
	{
		public static bool IsOpen;

		private static bool IsHoldingInput = true;

		public static MenuEvent OnMenuClose;

		public static MenuEvent OnMenuOpen;

		private static ManualLogSource Logger = ETGModConsole.Logger;

		private List<string> lastCommands = new List<string>();

		private int currentCommandIndex = -1;

		protected static char[] _SplitArgsCharacters = new char[1] { ' ' };

		public static string passwordInput = null;

		public static string manualNameInput = "UNSET";

		private static ArchipelConsoleCommandParser archipelagoCommands = new ArchipelConsoleCommandParser();

		public static ArchipelagoGUI Instance { get; protected set; }

		public ArchipelagoGUI()
		{
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Creating ArchiGungeon GUI");
			Instance = this;
			Logger = Logger.CreateLogSource("Archipelago Mod Menu");
		}

		public override void Start()
		{
			InitGUI();
		}

		private void InitGUI()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0045: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00c0: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_0127: Expected O, but got Unknown
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Initializing text for GUI");
			((ETGModMenu)this).GUI = new SGroup
			{
				Visible = false,
				OnUpdateStyle = delegate(SElement elem)
				{
					//IL_0024: 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)
					elem.Fill(100f);
					elem.Position = new Vector2(elem.Position.x, elem.Position.y);
				},
				Children = { (SElement)new SGroup
				{
					Background = new Color(0f, 153f, 0f, 0f),
					AutoLayout = (SGroup g) => g.AutoLayoutVertical,
					ScrollDirection = (EDirection)5,
					OnUpdateStyle = delegate(SElement elem)
					{
						//IL_000f: Unknown result type (might be due to invalid IL or missing references)
						//IL_002a: Unknown result type (might be due to invalid IL or missing references)
						//IL_002f: Unknown result type (might be due to invalid IL or missing references)
						//IL_0034: Unknown result type (might be due to invalid IL or missing references)
						elem.Fill(16f);
						elem.Size -= new Vector2(0f, elem.Backend.LineHeight - 4f);
					}
				} },
				Children = { (SElement)new STextField
				{
					OnUpdateStyle = delegate(SElement elem)
					{
						//IL_000d: 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)
						elem.Size.x = elem.Parent.InnerSize.x;
						elem.Position.x = 0f;
						elem.Position.y = elem.Parent.InnerSize.y - elem.Size.y;
					},
					OverrideTab = true,
					OnKey = delegate(STextField field, bool keyDown, KeyCode keyCode)
					{
						//IL_0004: Unknown result type (might be due to invalid IL or missing references)
						ParseKeyboardInput(field, keyDown, keyCode);
					},
					OnSubmit = delegate(STextField elem, string text)
					{
						int index = lastCommands.Count - 1;
						if (text != string.Empty && (lastCommands.Count <= 0 || text != lastCommands[index]))
						{
							lastCommands.Add(text);
						}
						currentCommandIndex = lastCommands.Count;
						if (text.Length != 0)
						{
							ParseCommandForArchipelago(text.Trim());
						}
					}
				} }
			};
			PrintHelpTextToConsole();
		}

		private void PrintHelpTextToConsole()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			foreach (SLabel item in ModMenuText.HelpCommandText)
			{
				((SElement)((ETGModMenu)this).GUI)[0].Children.Add((SElement)(object)item);
				((SGroup)((SElement)((ETGModMenu)this).GUI)[0]).ScrollPosition.y = float.MaxValue;
			}
		}

		private void PrintDebugTextToConsole()
		{
			ConsoleLog("==================  FOLLOWING ARE DEBUG COMMANDS");
			foreach (string key in DebugCommands.InputToCommand.Keys)
			{
				ConsoleLog(key);
			}
		}

		protected virtual SLabel _Log(object text, Texture image)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			Logger.LogMessage(text);
			SLabel val = new SLabel(text.ToString())
			{
				Icon = image
			};
			try
			{
				((SElement)((ETGModMenu)this).GUI)[0].Children.Add((SElement)(object)val);
			}
			catch (IndexOutOfRangeException)
			{
				((SElement)((ETGModMenu)this).GUI)[0].Children.Clear();
				((SGroup)((SElement)((ETGModMenu)this).GUI)[0]).ContentSize.y = 0f;
				((SGroup)((SElement)((ETGModMenu)this).GUI)[0]).ScrollPosition.y = 0f;
				PrintHelpTextToConsole();
				((SElement)((ETGModMenu)this).GUI)[0].Children.Add((SElement)(object)val);
			}
			((SGroup)((SElement)((ETGModMenu)this).GUI)[0]).ScrollPosition.y = float.MaxValue;
			return val;
		}

		public static SLabel ConsoleLog(object text, bool debuglog = false)
		{
			DebugFileWriter.AppendToLocalDebugLog(text.ToString());
			if (Instance == null)
			{
				new ArchipelagoGUI();
			}
			SLabel result = Instance?._Log(text, null);
			if (debuglog)
			{
				Debug.Log(text);
			}
			ETGModConsole.Log(text, false);
			return result;
		}

		private string[] SplitArgsBySpace(string args)
		{
			return args.Split(_SplitArgsCharacters, StringSplitOptions.RemoveEmptyEntries);
		}

		private void ParseKeyboardInput(STextField field, bool keyDown, KeyCode keyCode)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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)
			if (keyDown && (int)keyCode == 0)
			{
				return;
			}
			if (keyCode == ETGModGUI.CloseAllKey || (int)keyCode == 27)
			{
				((ETGModMenu)this).OnClose();
			}
			else
			{
				if (keyCode != ETGModGUI.ConsolePreviousCommand && keyCode != ETGModGUI.ConsoleNextCommand)
				{
					return;
				}
				IsHoldingInput = false;
				if (lastCommands.Count <= 0)
				{
					field.Text = string.Empty;
					return;
				}
				if (keyCode == ETGModGUI.ConsolePreviousCommand)
				{
					currentCommandIndex--;
					if (currentCommandIndex <= 0)
					{
						currentCommandIndex = 0;
					}
				}
				else if (keyCode == ETGModGUI.ConsoleNextCommand)
				{
					currentCommandIndex++;
					if (currentCommandIndex >= lastCommands.Count)
					{
						currentCommandIndex = lastCommands.Count - 1;
					}
				}
				field.Text = lastCommands[currentCommandIndex];
				field.MoveCursor(field.Text.Length, (int?)null);
			}
		}

		public override void Update()
		{
			if (IsOpen && IsHoldingInput)
			{
				((SElement)((ETGModMenu)this).GUI)[1].Focus();
			}
			if (!IsHoldingInput)
			{
				IsHoldingInput = true;
			}
		}

		public override void OnOpen()
		{
			((ETGModMenu)this).OnOpen();
			((SElement)((ETGModMenu)this).GUI)[1].Focus();
			IsOpen = true;
		}

		public override void OnClose()
		{
			if (SessionHandler.IsGoalsTextBoxOpen)
			{
				ArchDebugPrint.DebugLog(DebugCategory.UserInterface, "Closing goals box first");
				SessionHandler.HideGoalsTextbox();
			}
			else
			{
				((ETGModMenu)this).OnClose();
				OnMenuClose();
				IsOpen = false;
			}
		}

		public void SendCommandFromEtGConsoleToArchipelago(string[] commands)
		{
			string command = string.Join(" ", commands);
			ParseCommandForArchipelago(command);
		}

		protected void ParseCommandForArchipelago(string command)
		{
			string[] array = SplitArgsBySpace(command);
			string[] array2 = array.Skip(1).ToArray();
			string text = array[0];
			string command2;
			switch (text)
			{
			case "connect":
				if (array2.Length > 3)
				{
					ConsoleLog("ERROR: Too many inputs - [Connect] expected input [IP Address] [Port] [Player Slot Name]");
					ConsoleLog("If name contains spaces or server has a password, please use the 'set' & 'fullconnect' commands");
					return;
				}
				command2 = "arch connect " + command;
				break;
			case "retrieve":
				command2 = "arch retrieve ";
				break;
			case "enemy":
			{
				int result;
				if (array2.Length > 1)
				{
					ConsoleLog("ERROR: Too many inputs - [Enemy Shuffle] expected input [Enemy Shuffle Mode Number]");
				}
				else if (int.TryParse(array2[0], out result))
				{
					SessionHandler.SetEnemyShuffleMode(result);
				}
				else
				{
					ConsoleLog("ERROR: Invalid input - [Enemy Shuffle] expected input [Enemy Shuffle Mode Number]");
				}
				return;
			}
			case "set":
			{
				string textValue = string.Join(" ", array.Skip(2).ToArray());
				SetConnectionParameter(array2[0], textValue);
				return;
			}
			case "fullconnect":
				if (array2.Length > 2)
				{
					ConsoleLog("ERROR: Too many inputs - [fullconnect] expected input [IP Address] [Port]");
					ConsoleLog("Use 'set' for name & password");
				}
				else
				{
					SessionHandler.ArchipelagoConnect(array2[0], array2[1], manualNameInput, passwordInput);
				}
				return;
			case "disconnect":
				SessionHandler.DisconnectFromSession();
				return;
			case "reconnect":
				SessionHandler.ReconnectSession();
				return;
			case "deathlink":
			{
				int result2;
				if (array2.Length > 1)
				{
					ConsoleLog("ERROR: Too many inputs - [Deathlink] expected input [Deathlink Mode Number]");
				}
				else if (int.TryParse(array2[0], out result2))
				{
					SessionHandler.SetDeathLinkMode(result2);
				}
				else
				{
					ConsoleLog("ERROR: Invalid input - [Deathlink] expected input [Deathlink Mode Number]");
				}
				return;
			}
			case "debug":
				if (array2.Length > 1)
				{
					DebugCommands.HandleCommand(array2[0], array2[1]);
				}
				else if (array2.Length != 0)
				{
					DebugCommands.HandleCommand(array2[0]);
				}
				else
				{
					PrintDebugTextToConsole();
				}
				return;
			case "test":
				UnitTests.HandleUnitTestCommand(array2[0]);
				return;
			case "help":
				PrintHelpTextToConsole();
				return;
			default:
				ConsoleLog("ERROR: '" + text + "' not recognized as a command");
				return;
			}
			archipelagoCommands.SendETGConsoleCommand(command2);
		}

		public static void SetConnectionParameter(string paramToSet, string textValue)
		{
			if (!(paramToSet == "name"))
			{
				if (paramToSet == "password")
				{
					SetPasswordInput(textValue);
					ConsoleLog("Password set to: " + textValue);
				}
				else
				{
					ConsoleLog(paramToSet + "is not a valid connection setting to change.");
				}
			}
			else
			{
				SetNameInput(textValue);
				ConsoleLog("Name set to: " + textValue);
			}
		}

		private static void SetNameInput(string nameToSet)
		{
			manualNameInput = nameToSet;
		}

		private static void SetPasswordInput(string password)
		{
			passwordInput = password;
		}
	}
	public class ModMenuText
	{
		public static List<SLabel> HelpCommandText { get; } = new List<SLabel>
		{
			new SLabel("==== <color=#ffffffff>Archipelago</color> Gungeon Menu ====")
			{
				Foreground = Color.green
			},
			new SLabel("Press <color=#f4d03f>ESC</color> at any time to close")
			{
				Foreground = Color.white
			},
			new SLabel("Enter <color=#f4d03f>'help'</color> to print all commands\n")
			{
				Foreground = Color.blue
			},
			new SLabel("The following commands are available:\n")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>connect</color> [IP address] [port] [player slot]")
			{
				Foreground = Color.white
			},
			new SLabel("    Connect to Archipelago")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>reconnect</color>")
			{
				Foreground = Color.white
			},
			new SLabel("    Reconnect to last valid connection. Disconnects and connects if already online")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>fullconnect</color> [IP address] [port]")
			{
				Foreground = Color.white
			},
			new SLabel("    Connect to Archipelago using set Name & Password using the 'set' command")
			{
				Foreground = Color.green
			},
			new SLabel("    Use for player name with spaces OR server with password")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>set</color> [setting name] [value]")
			{
				Foreground = Color.white
			},
			new SLabel("    Set 'name' or 'password' for use with the 'fullconnect' command")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>disconnect</color>")
			{
				Foreground = Color.white
			},
			new SLabel("    Disconnect from any connected sessions\n\n")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>retrieve</color>")
			{
				Foreground = Color.white
			},
			new SLabel("    Collect items from server (once per item per Run)")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>deathlink</color> [deathlink mode number]")
			{
				Foreground = Color.white
			},
			new SLabel("    Set deathlink mode")
			{
				Foreground = Color.green
			},
			new SLabel("    0 - Deathlink OFF, 1 - Basic Deathlink, 2 - Advanced Co-Op Deathlink")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>enemy</color> [enemy shuffle mode number]")
			{
				Foreground = Color.white
			},
			new SLabel("    Set enemy shuffle mode")
			{
				Foreground = Color.green
			},
			new SLabel("    0 - Enemy Shuffle OFF, 1 - Enemy Shuffle ON")
			{
				Foreground = Color.green
			},
			new SLabel("<color=#f4d03f>debug</color> [command string]")
			{
				Foreground = Color.blue
			},
			new SLabel("    Handle Mod Debug, leave command empty to print available commands ----------")
			{
				Foreground = Color.yellow
			},
			new SLabel("")
			{
				Foreground = Color.green
			}
		};

	}
	public class ArchipelConsoleCommandParser
	{
		public const string archipelagoCommandGroup = "arch";

		public const string connectCmd = "connect";

		public const string reconnectCmd = "reconnect";

		public const string fullConnectCmd = "fullconnect";

		public const string setConnectionParameterCmd = "set";

		public const string disconnectCmd = "disconnect";

		public const string retrieveCmd = "retrieve";

		public const string deathlinkCmd = "deathlink";

		public const string enemyShuffleCmd = "enemy";

		public const string debugCmd = "debug";

		public const string unitTestCmd = "test";

		public static ArchipelConsoleCommandParser Instance { get; protected set; }

		public ArchipelConsoleCommandParser()
		{
			Instance = this;
			ETGModConsole.CommandDescriptions.Add("arch", "-- Archipelago Multiworld randomizer mod --");
			ETGModConsole.CommandDescriptions.Add("arch connect", "[ip] [port] [player name] - Connect to server, seperated by spaces");
			ETGModConsole.CommandDescriptions.Add("arch reconnect", "Connect to last valid connection, disconnects and connects if already online");
			ETGModConsole.CommandDescriptions.Add("arch disconnect", "Disconnect from server");
			ETGModConsole.CommandDescriptions.Add("arch retrieve", "Force pull received location items from server (once per run)");
			ETGModConsole.CommandDescriptions.Add("arch console", "[input #1] [input #2] [etc] - Send commands to Archipelago console manager");
			ETGModConsole.Commands.AddGroup("arch");
			new SessionHandler();
			ETGModConsole.Commands.GetGroup("arch").AddGroup("connect", (Action<string[]>)delegate(string[] args)
			{
				if (args.Length > 3)
				{
					SessionHandler.ArchipelagoConnect(args[1], args[2], args[3]);
				}
				else
				{
					SessionHandler.ArchipelagoConnect(args[0], args[1], args[2]);
				}
			});
			ETGModConsole.Commands.GetGroup("arch").AddGroup("reconnect", (Action<string[]>)delegate
			{
				SessionHandler.ReconnectSession();
			});
			ETGModConsole.Commands.GetGroup("arch").AddGroup("disconnect", (Action<string[]>)delegate
			{
				SessionHandler.DisconnectFromSession();
			});
			ETGModConsole.Commands.GetGroup("arch").AddGroup("retrieve", (Action<string[]>)delegate
			{
				SessionHandler.RetrieveItemsFromServer();
			});
			ETGModConsole.Commands.GetGroup("arch").AddGroup("console", (Action<string[]>)delegate(string[] args)
			{
				ArchipelagoGUI.Instance.SendCommandFromEtGConsoleToArchipelago(args);
			});
		}

		public void SendETGConsoleCommand(string command)
		{
			ETGModConsole instance = ETGModConsole.Instance;
			if (instance != null)
			{
				instance.ParseCommand(command);
			}
		}
	}
	public class TextBoxHandler
	{
		private static List<PlayerController> playersWithPossibleTextbox = new List<PlayerController>();

		public static void ShowArchipelagoLetterBox(PlayerController playerReference, string textToShow)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = ((BraveBehaviour)playerReference).sprite.WorldCenter + new Vector2(0f, 1f);
			float num = -1f;
			TextBoxManager.ShowLetterBox(Vector2.op_Implicit(val), ((BraveBehaviour)playerReference).transform, num, textToShow, true, false);
			if (!playersWithPossibleTextbox.Contains(playerReference))
			{
				playersWithPossibleTextbox.Add(playerReference);
			}
		}

		public static void ShowItemEventTextBox(PlayerController playerReference, string textToShow, float textDuration)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = ((BraveBehaviour)playerReference).sprite.WorldCenter + new Vector2(0f, -3f);
			TextBoxManager.ShowNote(Vector2.op_Implicit(val), ((BraveBehaviour)playerReference).transform, textDuration, textToShow, false, false);
			if (!playersWithPossibleTextbox.Contains(playerReference))
			{
				playersWithPossibleTextbox.Add(playerReference);
			}
		}

		public static void ClearAllTextboxes()
		{
			foreach (PlayerController item in playersWithPossibleTextbox)
			{
				if ((Object)(object)item != (Object)null)
				{
					TextBoxManager.ClearTextBoxImmediate(((BraveBehaviour)item).transform);
				}
			}
		}
	}
}
namespace ArchiGungeon.ItemArchipelago
{
	public class ReverseCurse : PassiveItem
	{
		public static int SpawnItemID = -1;

		private static string displayName = "Reverse Curse";

		private static string spriteDirectory = "ArchiGungeon/Resources/reverseCurse.png";

		public static void RegisterItem()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Registering Reverse Curse");
			GameObject val = new GameObject(displayName);
			ReverseCurse reverseCurse = val.AddComponent<ReverseCurse>();
			ItemBuilder.AddSpriteToObject(displayName, spriteDirectory, val, (Assembly)null);
			ItemBuilder.SetupItem((PickupObject)(object)reverseCurse, "Curses from beyond..", "Tainted objects from a world architect who chose to make things difficult. Adds 1 curse.", "arch");
			((PickupObject)reverseCurse).ShouldBeExcludedFromShops = true;
			((PickupObject)reverseCurse).CanBeDropped = false;
			((PickupObject)reverseCurse).CanBeSold = false;
			((PickupObject)reverseCurse).IgnoredByRat = true;
			((PickupObject)reverseCurse).quality = (ItemQuality)(-100);
			ItemBuilder.AddPassiveStatModifier((PickupObject)(object)reverseCurse, (StatType)14, 1f, (ModifyMethod)0);
			SpawnItemID = PickupObjectDatabase.GetId((PickupObject)(object)reverseCurse);
		}

		public override void Pickup(PlayerController player)
		{
			((PassiveItem)this).Pickup(player);
		}
	}
	public class ReverseCurseReversal : PassiveItem
	{
		public static int SpawnItemID = -1;

		private static string displayName = "Reverse Curse Reversal";

		private static string spriteDirectory = "ArchiGungeon/Resources/reverseCurseReverse.png";

		public static void RegisterItem()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Registering Reverse Curse Reversal");
			GameObject val = new GameObject(displayName);
			ReverseCurseReversal reverseCurseReversal = val.AddComponent<ReverseCurseReversal>();
			ItemBuilder.AddSpriteToObject(displayName, spriteDirectory, val, (Assembly)null);
			ItemBuilder.SetupItem((PickupObject)(object)reverseCurseReversal, "Tried and true counter", "A technique to reverse another's sneaky attack. Ruins friendships. Removes 1 curse.", "arch");
			ItemBuilder.AddPassiveStatModifier((PickupObject)(object)reverseCurseReversal, (StatType)14, -1f, (ModifyMethod)0);
			((PickupObject)reverseCurseReversal).ShouldBeExcludedFromShops = true;
			((PickupObject)reverseCurseReversal).CanBeDropped = false;
			((PickupObject)reverseCurseReversal).CanBeSold = false;
			((PickupObject)reverseCurseReversal).IgnoredByRat = true;
			((PickupObject)reverseCurseReversal).quality = (ItemQuality)(-100);
			SpawnItemID = PickupObjectDatabase.GetId((PickupObject)(object)reverseCurseReversal);
		}

		public override void Pickup(PlayerController player)
		{
			((PassiveItem)this).Pickup(player);
		}
	}
	public class APPickUpItem : PassiveItem
	{
		private static List<long> remainingLocationIDs = new List<long>();

		public static int SpawnItemID = -1;

		private static string displayName = "AP Item";

		private static string spriteDirectory = "ArchiGungeon/Resources/archipelago.png";

		private static long APItemStartID { get; } = 8755000L;


		public static void RegisterItemBase()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Registering APPickUpItem");
			GameObject val = new GameObject(displayName);
			APPickUpItem aPPickUpItem = val.AddComponent<APPickUpItem>();
			ItemBuilder.AddSpriteToObject(displayName, spriteDirectory, val, (Assembly)null);
			ItemBuilder.SetupItem((PickupObject)(object)aPPickUpItem, "A crossover!", "A cool item from another world", "arch");
			((PickupObject)aPPickUpItem).ShouldBeExcludedFromShops = true;
			((PickupObject)aPPickUpItem).CanBeDropped = false;
			((PickupObject)aPPickUpItem).CanBeSold = false;
			((PickupObject)aPPickUpItem).IgnoredByRat = true;
			((PickupObject)aPPickUpItem).quality = (ItemQuality)(-100);
			SpawnItemID = PickupObjectDatabase.GetId((PickupObject)(object)aPPickUpItem);
		}

		public static void RegisterAPItemLocations(int APItemCount)
		{
			for (int i = 0; i < APItemCount; i++)
			{
				remainingLocationIDs.Add(APItemStartID + i);
			}
			ReadOnlyCollection<long> allLocationsChecked = SessionHandler.Session.Locations.AllLocationsChecked;
			foreach (long item in allLocationsChecked)
			{
				if (remainingLocationIDs.Contains(item))
				{
					ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "APItem Location Check already cleared: " + item);
					remainingLocationIDs.Remove(item);
				}
			}
		}

		public static int GetBaseAPItemAmount(int userOptionCase)
		{
			return userOptionCase switch
			{
				0 => 16, 
				1 => 25, 
				2 => 40, 
				_ => 25, 
			};
		}

		public override void Pickup(PlayerController player)
		{
			((PassiveItem)this).Pickup(player);
			if (remainingLocationIDs.Count > 0)
			{
				ArchDebugPrint.DebugLog(DebugCategory.ServerSend, $"Sending location ID {remainingLocationIDs[0]}");
				SessionHandler.DataSender.SendFoundLocationCheck(remainingLocationIDs[0]);
				remainingLocationIDs.RemoveAt(0);
			}
		}

		public static bool HasAPItemChecksRemaining()
		{
			return remainingLocationIDs.Count > 0;
		}
	}
	internal class AchievementLocationCheckHandler
	{
		private static Dictionary<CountStats, List<long>> StatToLocationIDs = new Dictionary<CountStats, List<long>>();

		private static Dictionary<CountStats, long> StatToStartLocationID { get; } = new Dictionary<CountStats, long>
		{
			{
				CountStats.RoomPoints,
				8755200L
			},
			{
				CountStats.ChestsOpened,
				8755300L
			},
			{
				CountStats.CashSpent,
				8755400L
			},
			{
				CountStats.PastKills,
				8755600L
			},
			{
				CountStats.Floor1Clears,
				8755700L
			},
			{
				CountStats.Floor2Clears,
				8755720L
			},
			{
				CountStats.Floor3Clears,
				8755740L
			},
			{
				CountStats.Floor4Clears,
				8755760L
			},
			{
				CountStats.Floor5Clears,
				8755780L
			},
			{
				CountStats.FloorHellClears,
				8755800L
			},
			{
				CountStats.FloorGoopClears,
				8755820L
			},
			{
				CountStats.FloorAbbeyClears,
				8755840L
			},
			{
				CountStats.FloorRatClears,
				8755860L
			},
			{
				CountStats.FloorDeptClears,
				8755880L
			}
		};


		public static void SendStatLocationChecks(CountStats statCategory, int numberOfChecks)
		{
			if (!StatToLocationIDs.ContainsKey(statCategory))
			{
				ArchDebugPrint.DebugLog(DebugCategory.ServerSend, $"{statCategory} trying to send check but not in stat:LocationID dict.");
				return;
			}
			List<long> list = StatToLocationIDs[statCategory];
			List<long> range = list.GetRange(0, numberOfChecks);
			ArchDebugPrint.DebugLog(DebugCategory.ServerSend, $"Sending {statCategory} location check: {range}");
			SessionHandler.DataSender.SendFoundLocationCheck(range.ToArray());
			list.RemoveRange(0, numberOfChecks);
			StatToLocationIDs[statCategory] = list;
		}

		public static void SetStatLocationIDsFromGoalList(CountStats statToSet)
		{
			int countOfStatGoals = CountGoalManager.GetCountOfStatGoals(statToSet);
			if (countOfStatGoals >= 1)
			{
				List<long> list = new List<long>();
				for (int i = 0; i < countOfStatGoals; i++)
				{
					long item = StatToStartLocationID[statToSet] + i;
					list.Add(item);
				}
				ArchDebugPrint.DebugLog(DebugCategory.InitializingGameState, $"Setting {statToSet} with location IDs count {list.Count}");
				StatToLocationIDs[statToSet] = list;
			}
		}
	}
	internal class ShopAPItemHandler
	{
	}
}
namespace ArchiGungeon.GungeonEventHandlers
{
	internal class EffectsController
	{
		public static void PlayCurseVFX()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			PlayerController firstAlivePlayer = GungeonPlayerEventListener.GetFirstAlivePlayer();
			if ((Object)(object)firstAlivePlayer != (Object)null)
			{
				? val = firstAlivePlayer;
				Object obj = ResourceCache.Acquire("Global VFX/VFX_Curse");
				((GameActor)val).PlayEffectOnActor((GameObject)(object)((obj is GameObject) ? obj : null), Vector3.zero, true, false, false);
			}
		}

		public static void PlaySynergyVFX()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			PlayerController firstAlivePlayer = GungeonPlayerEventListener.GetFirstAlivePlayer();
			if ((Object)(object)firstAlivePlayer != (Object)null)
			{
				? val = firstAlivePlayer;
				Object obj = ResourceCache.Acquire("Global VFX/VFX_Synergy");
				((GameActor)val).PlayEffectOnActor((GameObject)(object)((obj is GameObject) ? obj : null), Vector3.zero, true, false, false);
			}
		}

		public static void PlayTestVFX()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			LootEngine.DoDefaultPurplePoof(Vector2.zero, false);
		}
	}
	public class GungeonPlayerEventListener
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static MenuEvent <0>__OnArchipelagoMenuOpen;

			public static MenuEvent <1>__OnArchipelagoMenuClose;

			public static Action<PlayerController, PlayerController, GameMode> <2>__OnRunStarted;

			public static Action<HealthHaver, bool> <3>__OnBossKilled;

			public static Action<PlayerController> <4>__OnPlayerControllerSpawned;

			public static Action<RewardPedestal> <5>__OnRewardPedestalSpawn;

			public static Action<RewardPedestal, PlayerController, ValidPedestalContents> <6>__OnRewardPedestalDetermineContent;

			public static Action<ShopItemController> <7>__OnShopItemCreated;

			public static DOnPreOpen <8>__OnChestPreOpen;

			public static Action<Chest, PlayerController> <9>__OnChestOpen;

			public static Archipelagun.ArchipelagunEvents <10>__OnArchipelagunPickup;

			public static Action<PlayerController> <11>__OnPlayerTwoDeath;

			public static Action<PlayerController> <12>__OnPlayerOneDeath;

			public static Action<PlayerController> <13>__OnNewFloorLoad;

			public static Action <14>__OnPlayerEnterCombat;

			public static Action<PlayerController> <15>__OnRoomClear;

			public static Action<PlayerController, ShopItemController> <16>__OnItemPurchased;

			public static Action<PlayerController, HealthHaver> <17>__OnKilledEnemy;

			public static Action<FlippableCover> <18>__OnTableFlip;
		}

		private static int triggerTwinKills;

		private static int killPillarKills;

		private static int roomsClearedThisRun;

		private static int lastFloorLoaded;

		private static PlayerController PlayerOne { get; set; }

		private static PlayerController PlayerTwo { get; set; }

		private static bool IsOnOddCountChest { get; set; } = true;


		private static List<BaseShopController> BaseShopControllers { get; } = new List<BaseShopController>();


		private static int ItemCountToReachToReplaceShopItem { get; } = 3;


		private static int CurrentShopItemCount { get; set; }

		private static bool PickedUpArchipelagun { get; set; }

		public static bool IsStartOfRun { get; private set; } = false;


		private static List<string> PastKillsGuids { get; } = new List<string> { "8d441ad4e9924d91b6070d5b3438d066", "dc3cd41623d447aeba77c77c99598426", "8b913eea3d174184be1af362d441910d", "b98b10fca77d469e80fb45f3c5badec5", "880bbe4ce1014740ba6b4e2ea521e49d", "39dca963ae2b4688b016089d926308ab" };


		private static Dictionary<string, CountStats> GameCompletionGUIds { get; } = new Dictionary<string, CountStats>
		{
			{
				"1b5810fafbec445d89921a4efb4e42b7",
				CountStats.BlobulordKills
			},
			{
				"5729c8b5ffa7415bb3d01205663a33ef",
				CountStats.OldKingKills
			},
			{
				"4d164ba3f62648809a4a82c90fc22cae",
				CountStats.RatKills
			},
			{
				"41ee1c8538e8474a82a74c4aff99c712",
				CountStats.DeptAgunimKills
			},
			{
				"05b8afe0b6cc4fffa9dc6036fa24c8ec",
				CountStats.AdvancedDragunKills
			},
			{
				"465da2bb086a4a88a803f79fe3a27677",
				CountStats.DragunKills
			},
			{
				"7c5d5f09911e49b78ae644d2b50ff3bf",
				CountStats.LichKills
			},
			{
				"8d441ad4e9924d91b6070d5b3438d066",
				CountStats.PastHunter
			},
			{
				"dc3cd41623d447aeba77c77c99598426",
				CountStats.PastMarine
			},
			{
				"8b913eea3d174184be1af362d441910d",
				CountStats.PastConvict
			},
			{
				"b98b10fca77d469e80fb45f3c5badec5",
				CountStats.PastPilot
			},
			{
				"880bbe4ce1014740ba6b4e2ea521e49d",
				CountStats.PastRobot
			},
			{
				"39dca963ae2b4688b016089d926308ab",
				CountStats.PastBullet
			}
		};


		private static Dictionary<string, CountStats> BossGUIDToStat { get; } = new Dictionary<string, CountStats>
		{
			{
				"ffca09398635467da3b1f4a54bcfda80",
				CountStats.Floor1Clears
			},
			{
				"ec6b674e0acd4553b47ee94493d66422",
				CountStats.Floor1Clears
			},
			{
				"da797878d215453abba824ff902e21b4",
				CountStats.Floor2Clears
			},
			{
				"4b992de5b4274168a8878ef9bf7ea36b",
				CountStats.Floor2Clears
			},
			{
				"c367f00240a64d5d9f3c26484dc35833",
				CountStats.Floor2Clears
			},
			{
				"5e0af7f7d9de4755a68d2fd3bbc15df4",
				CountStats.Floor3Clears
			},
			{
				"fa76c8cfdf1c4a88b55173666b4bc7fb",
				CountStats.Floor3Clears
			},
			{
				"8b0dd96e2fe74ec7bebc1bc689c0008a",
				CountStats.Floor3Clears
			},
			{
				"9189f46c47564ed588b9108965f975c9",
				CountStats.Floor3Clears
			},
			{
				"f3b04a067a65492f8b279130323b41f0",
				CountStats.Floor4Clears
			},
			{
				"6c43fddfd401456c916089fdd1c99b1c",
				CountStats.Floor4Clears
			},
			{
				"b98b10fca77d469e80fb45f3c5badec5",
				CountStats.Floor5Clears
			},
			{
				"880bbe4ce1014740ba6b4e2ea521e49d",
				CountStats.Floor5Clears
			},
			{
				"7c5d5f09911e49b78ae644d2b50ff3bf",
				CountStats.FloorHellClears
			},
			{
				"1b5810fafbec445d89921a4efb4e42b7",
				CountStats.FloorGoopClears
			},
			{
				"5729c8b5ffa7415bb3d01205663a33ef",
				CountStats.FloorAbbeyClears
			},
			{
				"4d164ba3f62648809a4a82c90fc22cae",
				CountStats.FloorRatClears
			},
			{
				"41ee1c8538e8474a82a74c4aff99c712",
				CountStats.FloorDeptClears
			}
		};


		private static List<string> TriggerTwinGuids { get; } = new List<string> { "ea40fcc863d34b0088f490f4e57f8913", "c00390483f394a849c36143eb878998f" };


		private static List<string> KillPillarNames { get; } = new List<string> { "AK47", "Shotgun", "Uzi", "DesertEagle" };


		public static PlayerController GetFirstAlivePlayer()
		{
			if (((BraveBehaviour)PlayerOne).healthHaver.IsAlive)
			{
				return PlayerOne;
			}
			if (((BraveBehaviour)PlayerTwo).healthHaver.IsAlive)
			{
				return PlayerTwo;
			}
			return null;
		}

		public static void StartSystemEventListens()
		{
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Expected O, but got Unknown
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Starting Gungeon Event Listener");
			ArchipelagoGUI.OnMenuOpen = (MenuEvent)Delegate.Combine(ArchipelagoGUI.OnMenuOpen, new MenuEvent(OnArchipelagoMenuOpen));
			ArchipelagoGUI.OnMenuClose = (MenuEvent)Delegate.Combine(ArchipelagoGUI.OnMenuClose, new MenuEvent(OnArchipelagoMenuClose));
			CustomActions.OnRunStart = (Action<PlayerController, PlayerController, GameMode>)Delegate.Combine(CustomActions.OnRunStart, new Action<PlayerController, PlayerController, GameMode>(OnRunStarted));
			CustomActions.OnBossKilled = (Action<HealthHaver, bool>)Delegate.Combine(CustomActions.OnBossKilled, new Action<HealthHaver, bool>(OnBossKilled));
			CustomActions.OnNewPlayercontrollerSpawned = (Action<PlayerController>)Delegate.Combine(CustomActions.OnNewPlayercontrollerSpawned, new Action<PlayerController>(OnPlayerControllerSpawned));
			CustomActions.OnRewardPedestalSpawned = (Action<RewardPedestal>)Delegate.Combine(CustomActions.OnRewardPedestalSpawned, new Action<RewardPedestal>(OnRewardPedestalSpawn));
			CustomActions.OnRewardPedestalDetermineContents = (Action<RewardPedestal, PlayerController, ValidPedestalContents>)Delegate.Combine(CustomActions.OnRewardPedestalDetermineContents, new Action<RewardPedestal, PlayerController, ValidPedestalContents>(OnRewardPedestalDetermineContent));
			CustomActions.OnShopItemStarted = (Action<ShopItemController>)Delegate.Combine(CustomActions.OnShopItemStarted, new Action<ShopItemController>(OnShopItemCreated));
			DOnPreOpen onPreOpen = Chest.OnPreOpen;
			object obj = <>O.<8>__OnChestPreOpen;
			if (obj == null)
			{
				DOnPreOpen val = OnChestPreOpen;
				<>O.<8>__OnChestPreOpen = val;
				obj = (object)val;
			}
			Chest.OnPreOpen = (DOnPreOpen)Delegate.Combine((Delegate?)(object)onPreOpen, (Delegate?)obj);
			Chest.OnPostOpen = (Action<Chest, PlayerController>)Delegate.Combine(Chest.OnPostOpen, new Action<Chest, PlayerController>(OnChestOpen));
			Archipelagun.OnPickup = (Archipelagun.ArchipelagunEvents)Delegate.Combine(Archipelagun.OnPickup, new Archipelagun.ArchipelagunEvents(OnArchipelagunPickup));
		}

		private static void OnShopItemCreated(ShopItemController obj)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			if ((Object)(object)obj.m_baseParentShop == (Object)null)
			{
				return;
			}
			if ((int)obj.CurrencyType == 1 || (int)obj.m_baseParentShop.baseShopType == 6)
			{
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Shop Item replacement ignoring meta shop items");
				return;
			}
			CurrentShopItemCount++;
			if (CurrentShopItemCount >= ItemCountToReachToReplaceShopItem)
			{
				CurrentShopItemCount = 0;
				BaseShopController baseParentShop = obj.m_baseParentShop;
				BaseShopControllers.Add(baseParentShop);
				tk2dBaseSprite sprite = ((BraveBehaviour)obj).sprite;
				sprite.HeightOffGround -= 0.5f;
				obj.item = PickupObjectDatabase.GetById(APPickUpItem.SpawnItemID);
				((BraveBehaviour)obj).sprite.FlipY = true;
			}
		}

		private static void OnPlayerControllerSpawned(PlayerController controller)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Invalid comparison between Unknown and I4
			if ((int)controller.characterIdentity == 7)
			{
				ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Player Two Controller Listener Started");
				PlayerTwo = controller;
				PlayerController playerTwo = PlayerTwo;
				playerTwo.OnRealPlayerDeath = (Action<PlayerController>)Delegate.Combine(playerTwo.OnRealPlayerDeath, new Action<PlayerController>(OnPlayerTwoDeath));
				ArchipelagoGungeonBridge.SetPlayerTwo(PlayerTwo);
			}
			else
			{
				if (CharSwap.IsParadoxModeOn && (int)controller.characterIdentity == 9 && PickedUpArchipelagun)
				{
					CharSwap.HandleLostItemsOnCharacterSwap(controller);
				}
				ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Player One Controller Listener Started");
				PlayerOne = controller;
				PlayerController playerOne = PlayerOne;
				playerOne.OnRealPlayerDeath = (Action<PlayerController>)Delegate.Combine(playerOne.OnRealPlayerDeath, new Action<PlayerController>(OnPlayerOneDeath));
				ArchipelagoGungeonBridge.SetPlayerOne(PlayerOne);
			}
			StartPlayerControllerEventListens(controller);
		}

		private static void OnArchipelagunPickup()
		{
			ArchDebugPrint.DebugLog(DebugCategory.UserInterface, "Archipelagun picked up, valid for events");
			PickedUpArchipelagun = true;
		}

		private static void CheckToForceArchipelagunOwnership()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (!PickedUpArchipelagun)
			{
				PickupObject byId = PickupObjectDatabase.GetById(Archipelagun.SpawnItemID);
				GetFirstAlivePlayer().inventory.AddGunToInventory((Gun)byId, true);
				PickedUpArchipelagun = true;
			}
		}

		private static void OnArchipelagoMenuOpen()
		{
			ArchDebugPrint.DebugLog(DebugCategory.UserInterface, "Menu opened, blocking character input");
			PlayerInputModifier.BlockPlayerInputToCharacter(isBlocking: true);
		}

		private static void OnArchipelagoMenuClose()
		{
			ArchDebugPrint.DebugLog(DebugCategory.UserInterface, "Menu closed, resuming input");
			PlayerInputModifier.BlockPlayerInputToCharacter(isBlocking: false);
		}

		private static bool OnChestPreOpen(bool shouldOpen, Chest chest, PlayerController player)
		{
			if (SessionHandler.Session == null || !SessionHandler.Session.Socket.Connected)
			{
				return shouldOpen;
			}
			if (!shouldOpen)
			{
				return shouldOpen;
			}
			CheckToForceArchipelagunOwnership();
			ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Chest Pre-Open Call");
			if (APPickUpItem.HasAPItemChecksRemaining())
			{
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "AP Item checks still available");
				if (IsOnOddCountChest)
				{
					ModifyChestContentsByChestType(chest);
					IsOnOddCountChest = false;
				}
				else
				{
					IsOnOddCountChest = true;
				}
			}
			SaveDataManagement.AddToCountSaveDataEntry(CountStats.ChestsOpened, 1);
			return shouldOpen;
		}

		private static void ModifyChestContentsByChestType(Chest chestToEdit)
		{
			//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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Invalid comparison between Unknown and I4
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Invalid comparison between Unknown and I4
			ItemQuality quality = chestToEdit.contents[0].quality;
			if (chestToEdit.IsRainbowChest)
			{
				chestToEdit.forceContentIds = new List<int>
				{
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID
				};
			}
			if ((int)chestToEdit.ChestIdentifier == 1)
			{
				chestToEdit.forceContentIds = new List<int>
				{
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID
				};
			}
			else if ((int)quality == 5)
			{
				chestToEdit.forceContentIds = new List<int>
				{
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID
				};
			}
			else if ((int)quality == 4)
			{
				chestToEdit.forceContentIds = new List<int>
				{
					APPickUpItem.SpawnItemID,
					APPickUpItem.SpawnItemID
				};
			}
			else
			{
				chestToEdit.forceContentIds = new List<int> { APPickUpItem.SpawnItemID };
			}
		}

		private static void OnChestOpen(Chest chest, PlayerController controller)
		{
		}

		private static void OnRunStarted(PlayerController controller1, PlayerController controller2, GameMode mode)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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)
			PickedUpArchipelagun = false;
			ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Run started!");
			EnemySwapping.ResetEnemyDamageMult();
			roomsClearedThisRun = 0;
			killPillarKills = 0;
			triggerTwinKills = 0;
			IsStartOfRun = true;
			CharSwap.EndParadoxModeForReset();
			SessionHandler.ResetVariablesToStartOfRun();
			GameObject gameObject = ((Component)PickupObjectDatabase.GetById(Archipelagun.SpawnItemID)).gameObject;
			LootEngine.SpawnItem(gameObject, Vector2.op_Implicit(((GameActor)controller1).CenterPosition), Vector2.zero, 0f, true, false, false);
		}

		private static void OnBossKilled(HealthHaver haver, bool arg2)
		{
			CheckToForceArchipelagunOwnership();
			ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Boss killed: " + ((Object)haver).name);
			ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Boss GUID: " + ((BraveBehaviour)haver).aiActor.EnemyGuid);
			string enemyGuid = ((BraveBehaviour)haver).aiActor.EnemyGuid;
			if (PastKillsGuids.Contains(enemyGuid))
			{
				SaveDataManagement.AddToCountSaveDataEntry(CountStats.PastKills, 1);
			}
			if (BossGUIDToStat.ContainsKey(enemyGuid))
			{
				SaveDataManagement.AddToCountSaveDataEntry(BossGUIDToStat[enemyGuid], 1);
			}
			else if (TriggerTwinGuids.Contains(enemyGuid))
			{
				triggerTwinKills++;
				if (triggerTwinKills == 2)
				{
					SaveDataManagement.AddToCountSaveDataEntry(CountStats.Floor1Clears, 1);
				}
			}
			else if (KillPillarNames.Contains(((Object)haver).name))
			{
				killPillarKills++;
				if (killPillarKills == 4)
				{
					SaveDataManagement.AddToCountSaveDataEntry(CountStats.Floor4Clears, 1);
				}
			}
			if (GameCompletionGUIds.ContainsKey(enemyGuid))
			{
				ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Possible completion boss: " + ((Object)haver).name);
				SaveDataManagement.AddToCountSaveDataEntry(GameCompletionGUIds[enemyGuid], 1);
				SaveDataManagement.SaveCurrentRandomizerProgress();
				SessionHandler.DataSender.CheckForGameCompletion();
			}
		}

		private static void OnRewardPedestalSpawn(RewardPedestal pedestal)
		{
		}

		private static void OnRewardPedestalDetermineContent(RewardPedestal pedestal, PlayerController controller, ValidPedestalContents contents)
		{
			if (!APPickUpItem.HasAPItemChecksRemaining())
			{
				return;
			}
			if (pedestal.IsBossRewardPedestal)
			{
				if (GameManager.Instance.CurrentFloor == 2 || GameManager.Instance.CurrentFloor == 4)
				{
					ArchipelagoGungeonBridge.SpawnAPItem(1);
				}
			}
			else
			{
				ArchipelagoGungeonBridge.SpawnAPItem(1);
			}
		}

		private static void StartPlayerControllerEventListens(PlayerController playerToListen)
		{
			playerToListen.OnNewFloorLoaded = (Action<PlayerController>)Delegate.Combine(playerToListen.OnNewFloorLoaded, new Action<PlayerController>(OnNewFloorLoad));
			playerToListen.OnEnteredCombat = (Action)Delegate.Combine(playerToListen.OnEnteredCombat, new Action(OnPlayerEnterCombat));
			playerToListen.OnRoomClearEvent += OnRoomClear;
			playerToListen.OnItemPurchased += OnItemPurchased;
			playerToListen.OnKilledEnemyContext += OnKilledEnemy;
			playerToListen.OnTableFlipped = (Action<FlippableCover>)Delegate.Combine(playerToListen.OnTableFlipped, new Action<FlippableCover>(OnTableFlip));
			ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, $"Listening to {playerToListen}");
		}

		private static void OnNewFloorLoad(PlayerController playerController)
		{
			if (GameManager.Instance.CurrentFloor != lastFloorLoaded)
			{
				lastFloorLoaded = GameManager.Instance.CurrentFloor;
				ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, $"Floor loaded: {GameManager.Instance.CurrentFloor}");
				EnemySwapping.ReduceEnemyDamageMult(1);
				SaveDataManagement.SaveCurrentRandomizerProgress();
			}
		}

		private static void OnPlayerEnterCombat()
		{
			IsStartOfRun = false;
		}

		private static void OnPlayerOneDeath(PlayerController controller)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)PlayerTwo != (Object)null) || ((BraveBehaviour)PlayerTwo).healthHaver.IsDead)
			{
				controller.characterIdentity = (PlayableCharacters)0;
				PickedUpArchipelagun = false;
				SaveDataManagement.SaveCurrentRandomizerProgress();
				string causeOfDeath = "Died to " + ((BraveBehaviour)controller).healthHaver.lastIncurredDamageSource + " in the Gungeon";
				SessionHandler.DataSender.SendDeathlink("Gungeoneer", causeOfDeath);
			}
		}

		private static void OnPlayerTwoDeath(PlayerController controller)
		{
			if (((BraveBehaviour)PlayerOne).healthHaver.IsDead)
			{
				SaveDataManagement.SaveCurrentRandomizerProgress();
				string causeOfDeath = "Died to " + ((BraveBehaviour)controller).healthHaver.lastIncurredDamageSource + " in the Gungeon";
				SessionHandler.DataSender.SendDeathlink("Gungeoneer", causeOfDeath);
			}
		}

		private static void OnRoomClear(PlayerController playerController)
		{
			CheckToForceArchipelagunOwnership();
			roomsClearedThisRun++;
			EnemySwapping.ResetShuffleCountOnRoomClear();
			ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Adding room points: " + roomsClearedThisRun);
			SaveDataManagement.AddToCountSaveDataEntry(CountStats.RoomPoints, roomsClearedThisRun);
		}

		private static void OnItemPurchased(PlayerController playerController, ShopItemController shopItem)
		{
			if (!((Object)(object)shopItem == (Object)null))
			{
				CheckToForceArchipelagunOwnership();
				int currentPrice = shopItem.CurrentPrice;
				ArchDebugPrint.DebugLog(DebugCategory.PlayerEventListener, "Adding cash spent: " + currentPrice);
				SaveDataManagement.AddToCountSaveDataEntry(CountStats.CashSpent, currentPrice);
			}
		}

		private static void OnKilledEnemy(PlayerController playerController, HealthHaver enemy)
		{
			string name = ((Object)enemy).name;
		}

		private static void OnTableFlip(FlippableCover tableFlipped)
		{
		}
	}
	public class PlayerInputModifier
	{
		public static void BlockPlayerInputToCharacter(bool isBlocking)
		{
			GameManager instance = GameManager.Instance;
			if (!((Object)(object)((instance != null) ? instance.PrimaryPlayer : null) == (Object)null))
			{
				bool enabled = !isBlocking;
				((Behaviour)GameManager.Instance.PrimaryPlayer).enabled = enabled;
				Camera main = Camera.main;
				CameraController val = ((main != null) ? ((Component)main).GetComponent<CameraController>() : null);
				if ((Object)(object)val != (Object)null)
				{
					((Behaviour)val).enabled = enabled;
				}
			}
		}
	}
	public class ConsumableSpawnHandler
	{
		public static bool IsSpawnValid { get; protected set; } = true;


		public static void SetCanSpawn(bool newState)
		{
			IsSpawnValid = newState;
		}

		public static void SpawnConsumableByCase(int itemCase)
		{
			if (IsSpawnValid)
			{
				PlayerController firstAlivePlayer = GungeonPlayerEventListener.GetFirstAlivePlayer();
				EffectsController.PlaySynergyVFX();
				switch (itemCase)
				{
				case 0:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "glass_guon_stone");
					break;
				case 1:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "50_casing");
					break;
				case 2:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "key");
					break;
				case 3:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "blank");
					break;
				case 4:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "armor");
					break;
				case 5:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "heart");
					break;
				case 6:
					PlayerControllerExt.GiveItem(firstAlivePlayer, "ammo");
					break;
				default:
					ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, $"Consumable received invalid ID: {itemCase}");
					break;
				}
			}
		}
	}
	public class RandomizedByQualityItems
	{
		private static Random random = new Random();

		private static Gun GetRandomGunByQualities(ItemQuality[] itemQuals)
		{
			return PickupObjectDatabase.GetRandomGunOfQualities(random, new List<int>(), itemQuals);
		}

		private static PassiveItem GetRandomPassiveByQualities(ItemQuality[] itemQuals)
		{
			return PickupObjectDatabase.GetRandomPassiveOfQualities(random, new List<int>(), itemQuals);
		}

		public static void GivePlayerRandomGun(ItemQuality[] itemquals)
		{
			PlayerController firstAlivePlayer = GungeonPlayerEventListener.GetFirstAlivePlayer();
			Gun randomGunByQualities = GetRandomGunByQualities(itemquals);
			ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Giving random gun: " + ((Object)randomGunByQualities).name);
			firstAlivePlayer.inventory.AddGunToInventory(randomGunByQualities, false);
		}

		public static void GivePlayerRandomPassive(ItemQuality[] itemquals)
		{
			PlayerController firstAlivePlayer = GungeonPlayerEventListener.GetFirstAlivePlayer();
			PassiveItem randomPassiveByQualities = GetRandomPassiveByQualities(itemquals);
			ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Giving random passive: " + ((Object)randomPassiveByQualities).name);
			firstAlivePlayer.AcquirePassiveItem(randomPassiveByQualities);
		}

		public static void GiveRandomizedItemByCase(int itemCase)
		{
			EffectsController.PlaySynergyVFX();
			switch (itemCase)
			{
			case 0:
				GivePlayerRandomGun((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)1 });
				break;
			case 1:
				GivePlayerRandomGun((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)2 });
				break;
			case 2:
				GivePlayerRandomGun((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)3 });
				break;
			case 3:
				GivePlayerRandomGun((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)4 });
				break;
			case 4:
				GivePlayerRandomGun((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)5 });
				break;
			case 5:
				GivePlayerRandomPassive((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)1 });
				break;
			case 6:
				GivePlayerRandomPassive((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)2 });
				break;
			case 7:
				GivePlayerRandomPassive((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)3 });
				break;
			case 8:
				GivePlayerRandomPassive((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)4 });
				break;
			case 9:
				GivePlayerRandomPassive((ItemQuality[])(object)new ItemQuality[1] { (ItemQuality)5 });
				break;
			default:
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, $"Random Gun/Passive received invalid ID: {itemCase}");
				break;
			}
		}
	}
	public class ProgressionItemSpawnHandler
	{
		public static void SpawnProgressionItem(int itemCase)
		{
			EffectsController.PlaySynergyVFX();
			switch (itemCase)
			{
			case 1:
				PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "gnawed_key");
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Giving gnawed key");
				break;
			case 2:
				PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "old_crest");
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Giving Old Crest");
				break;
			case 3:
				PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "weird_egg");
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Spawning weird egg");
				break;
			default:
				ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, $"PROGRESSION received invalid ID: {itemCase}");
				break;
			}
		}

		public static void GivePastBullet()
		{
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "bullet_that_can_kill_the_past");
			ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Giving bullet");
		}

		public static void GiveRatNotes()
		{
			ArchDebugPrint.DebugLog(DebugCategory.ItemHandling, "Giving Rat Notes");
			List<string> list = new List<string> { "infuriating_note_1", "infuriating_note_2", "infuriating_note_3", "infuriating_note_4", "infuriating_note_5", "infuriating_note_6" };
			foreach (string item in list)
			{
				PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), item);
			}
		}
	}
	public class TrapSpawnHandler
	{
		public static bool IsSpawnValid { get; protected set; } = true;


		public static void SetCanSpawn(bool newState)
		{
			IsSpawnValid = newState;
		}

		public static void SpawnTrapByCase(int trapCase)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			if (!IsSpawnValid)
			{
				return;
			}
			PlayerController firstAlivePlayer = GungeonPlayerEventListener.GetFirstAlivePlayer();
			if (!((Object)(object)firstAlivePlayer == (Object)null))
			{
				switch (trapCase)
				{
				case 0:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Rats??");
					ETGModConsole.Spawn(new string[2] { "rat", "20" });
					break;
				case 1:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Mimic gun");
					EffectsController.PlayCurseVFX();
					firstAlivePlayer.inventory.AddGunToInventory((Gun)PickupObjectDatabase.GetByName("mimic_gun"), false);
					break;
				case 2:
				{
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: +1 Curse");
					EffectsController.PlayCurseVFX();
					PickupObject byId = PickupObjectDatabase.GetById(ReverseCurse.SpawnItemID);
					firstAlivePlayer.AcquirePassiveItemPrefabDirectly((PassiveItem)byId);
					break;
				}
				case 3:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Drop gun jumpscare");
					EffectsController.PlayCurseVFX();
					firstAlivePlayer.ForceDropGun(((GameActor)firstAlivePlayer).CurrentGun);
					break;
				case 4:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Fire!!");
					EffectsController.PlayCurseVFX();
					firstAlivePlayer.IncreaseFire(0.5f);
					break;
				case 5:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Poison");
					EffectsController.PlayCurseVFX();
					firstAlivePlayer.CurrentPoisonMeterValue += 0.5f;
					TrapStatModifier.CheckToPoison(firstAlivePlayer);
					break;
				case 6:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Curse pot");
					EffectsController.PlayCurseVFX();
					firstAlivePlayer.CurrentCurseMeterValue += 0.5f;
					break;
				case 7:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, "Sending trap: Shelleton, maybe");
					EffectsController.PlayCurseVFX();
					ETGModConsole.Spawn(new string[2] { "shelleton", "3" });
					break;
				default:
					ArchDebugPrint.DebugLog(DebugCategory.TrapHandling, $"Trap Handling received invalid ID: {trapCase}");
					break;
				}
			}
		}
	}
	public class TrapStatModifier
	{
		public static void CheckToCurse(PlayerController targetPlayer)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0034: 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)
			if (targetPlayer.CurrentCurseMeterValue >= 1f)
			{
				targetPlayer.CurrentCurseMeterValue = 0f;
				StatModifier val = new StatModifier();
				val.amount = 1f;
				val.modifyType = (ModifyMethod)0;
				val.statToBoost = (StatType)14;
				targetPlayer.ownerlessStatModifiers.Add(val);
				targetPlayer.stats.RecalculateStats(targetPlayer, false, false);
			}
		}

		public static void CheckToPoison(PlayerController targetPlayer)
		{
			if (targetPlayer.CurrentPoisonMeterValue >= 1f)
			{
				targetPlayer.CurrentPoisonMeterValue -= 1f;
				targetPlayer.stats.RecalculateStats(targetPlayer, false, false);
			}
		}
	}
}
namespace ArchiGungeon.EnemyHandlers
{
	internal class EnemySwapping : MonoBehaviour
	{
		private static float enemyDamageMult = 4f;

		private static int enemiesToShufflePerRoom = 15;

		private static int currentShuffleCount = 0;

		private static List<AIActor> actorsValidForShuffling = new List<AIActor>();

		private static Dictionary<string, string> ShuffledEnemyGUIDs { get; set; } = new Dictionary<string, string>();


		public static void InitializeEnemySwapper()
		{
			ArchDebugPrint.DebugLog(DebugCategory.PluginStartup, "Starting Enemy Swapper");
			AIActor.OnPreStart = (Action<AIActor>)Delegate.Combine(AIActor.OnPreStart, new Action<AIActor>(OnActorPreStart));
			AIActor.OnPostStart = (Action<AIActor>)Delegate.Combine(AIActor.OnPostStart, new Action<AIActor>(OnActorPostStart));
		}

		public static void MakeNormalShuffleEnemies(int seed)
		{
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, $"Normal Enemy Shuffling with key: {seed}");
			ShuffledEnemyGUIDs = EnemyGuidDatabase.GetShuffledGUIDList(EnemyShuffleCategories.NormalDifficultyShuffle, seed);
		}

		public static void MakeDifficultShuffleEnemies(int seed)
		{
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, $"Difficult Enemy Shuffling with key: {seed}");
			ShuffledEnemyGUIDs = EnemyGuidDatabase.GetShuffledGUIDList(EnemyShuffleCategories.HardDifficultyShuffle, seed);
		}

		public static void MakeBossShuffle(int seed)
		{
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, $"Boss Shuffling with key: {seed}");
		}

		public static void ClearAllShuffleLists()
		{
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, "Resetting enemy randomization");
			ShuffledEnemyGUIDs.Clear();
		}

		private static void OnActorPreStart(AIActor actor)
		{
			if (currentShuffleCount <= enemiesToShufflePerRoom)
			{
				actorsValidForShuffling.Add(actor);
				CheckToShuffleEnemySpawn(actor);
			}
		}

		public static void ResetShuffleCountOnRoomClear()
		{
			currentShuffleCount = 0;
		}

		private static void CheckToShuffleEnemySpawn(AIActor actor)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, ((Object)actor).name);
			string enemyGuid = actor.EnemyGuid;
			if (ShuffledEnemyGUIDs.ContainsKey(enemyGuid))
			{
				currentShuffleCount++;
				string text = ShuffledEnemyGUIDs[enemyGuid];
				Vector2 centerPosition = ((GameActor)actor).CenterPosition;
				RoomHandler parentRoom = actor.parentRoom;
				ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, "Current: " + (object)EnemyDatabase.GetOrLoadByGuid(enemyGuid));
				ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, "Swapped to: " + (object)EnemyDatabase.GetOrLoadByGuid(text));
				actor.invisibleUntilAwaken = true;
				SpawnReplacementEnemy(text, centerPosition, parentRoom);
			}
		}

		private static void SpawnReplacementEnemy(string enemyID, Vector2 position, RoomHandler parentRoom)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			AIActor orLoadByGuid = EnemyDatabase.GetOrLoadByGuid(enemyID);
			if (!((Object)(object)orLoadByGuid == (Object)null))
			{
				orLoadByGuid.EnemyGuid = "SWAP_" + orLoadByGuid.EnemyGuid;
				orLoadByGuid.HasDonePlayerEnterCheck = true;
				orLoadByGuid.IsInReinforcementLayer = true;
				orLoadByGuid.reinforceType = (ReinforceType)2;
				orLoadByGuid.HandleReinforcementFallIntoRoom(0.5f);
				((BraveBehaviour)orLoadByGuid).healthHaver.AllDamageMultiplier = enemyDamageMult;
				AIActor.Spawn(orLoadByGuid, position, parentRoom, true, (AwakenAnimationType)0, true);
			}
		}

		public static void ResetEnemyDamageMult()
		{
			enemyDamageMult = 4f;
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, $"Enemy damage mult is: {enemyDamageMult}");
		}

		public static void ReduceEnemyDamageMult(int stepsToReduce)
		{
			enemyDamageMult -= (float)stepsToReduce * 0.25f;
			if (enemyDamageMult < 1f)
			{
				enemyDamageMult = 1f;
			}
			ArchDebugPrint.DebugLog(DebugCategory.EnemyRandomization, $"Enemy damage mult is: {enemyDamageMult}");
		}

		private static void OnActorPostStart(AIActor actor)
		{
			if (actorsValidForShuffling.Contains(actor))
			{
				actorsValidForShuffling.Remove(actor);
				string enemyGuid = actor.EnemyGuid;
				if (ShuffledEnemyGUIDs.ContainsKey(enemyGuid))
				{
					actor.EraseFromExistenceWithRewards(true);
				}
			}
		}
	}
}
namespace ArchiGungeon.DebugTools
{
	public class DebugCommands
	{
		public static Dictionary<string, AvailableDebugCMD> InputToCommand { get; } = new Dictionary<string, AvailableDebugCMD>
		{
			{
				"item",
				AvailableDebugCMD.SpawnAPItem
			},
			{
				"sendDeath",
				AvailableDebugCMD.SendDeathlink
			},
			{
				"receiveDeath",
				AvailableDebugCMD.ReceiveDeathlink
			},
			{
				"chest",
				AvailableDebugCMD.AddChest
			},
			{
				"room",
				AvailableDebugCMD.Add1RoomPoint
			},
			{
				"cash",
				AvailableDebugCMD.Add100CashSpent
			},
			{
				"speedrun",
				AvailableDebugCMD.Speedrun
			},
			{
				"fullDebug",
				AvailableDebugCMD.FullDebug
			},
			{
				"noDebug",
				AvailableDebugCMD.NoDebug
			},
			{
				"floor1",
				AvailableDebugCMD.LoadFloor1
			},
			{
				"floor2",
				AvailableDebugCMD.LoadFloor2
			},
			{
				"floor3",
				AvailableDebugCMD.LoadFloor3
			},
			{
				"floor4",
				AvailableDebugCMD.LoadFloor4
			},
			{
				"floor5",
				AvailableDebugCMD.LoadFloor5
			},
			{
				"hell",
				AvailableDebugCMD.LoadHell
			},
			{
				"sewers",
				AvailableDebugCMD.LoadSewers
			},
			{
				"abbey",
				AvailableDebugCMD.LoadAbbey
			},
			{
				"rat",
				AvailableDebugCMD.LoadRat
			},
			{
				"dept",
				AvailableDebugCMD.LoadDept
			},
			{
				"pastmarine",
				AvailableDebugCMD.PastMarine
			},
			{
				"pastconvict",
				AvailableDebugCMD.PastConvict
			},
			{
				"pasthunter",
				AvailableDebugCMD.PastHunter
			},
			{
				"pastpilot",
				AvailableDebugCMD.PastPilot
			},
			{
				"pastrobot",
				AvailableDebugCMD.PastRobot
			},
			{
				"pastbullet",
				AvailableDebugCMD.PastBullet
			},
			{
				"pastgunslinger",
				AvailableDebugCMD.PastGunslinger
			},
			{
				"pastcoop",
				AvailableDebugCMD.PastCoop
			},
			{
				"receive",
				AvailableDebugCMD.ReceiveItem
			}
		};


		private static Dictionary<AvailableDebugCMD, string> CommandToLevel { get; } = new Dictionary<AvailableDebugCMD, string>
		{
			{
				AvailableDebugCMD.LoadFloor1,
				"keep"
			},
			{
				AvailableDebugCMD.LoadFloor2,
				"proper"
			},
			{
				AvailableDebugCMD.LoadFloor3,
				"mines"
			},
			{
				AvailableDebugCMD.LoadFloor4,
				"hollow"
			},
			{
				AvailableDebugCMD.LoadFloor5,
				"forge"
			},
			{
				AvailableDebugCMD.LoadHell,
				"hell"
			},
			{
				AvailableDebugCMD.LoadSewers,
				"sewers"
			},
			{
				AvailableDebugCMD.LoadAbbey,
				"abbey"
			},
			{
				AvailableDebugCMD.LoadRat,
				"ratlair"
			},
			{
				AvailableDebugCMD.LoadDept,
				"rng_dept"
			},
			{
				AvailableDebugCMD.PastMarine,
				"marinepast"
			},
			{
				AvailableDebugCMD.PastConvict,
				"convictpast"
			},
			{
				AvailableDebugCMD.PastHunter,
				"hunterpast"
			},
			{
				AvailableDebugCMD.PastPilot,
				"pilotpast"
			},
			{
				AvailableDebugCMD.PastRobot,
				"robotpast"
			},
			{
				AvailableDebugCMD.PastBullet,
				"bulletpast"
			},
			{
				AvailableDebugCMD.PastGunslinger,
				"gunslingerpast"
			},
			{
				AvailableDebugCMD.PastCoop,
				"cultistpast"
			}
		};


		private static void DebugSpawnAPItem()
		{
			ArchipelagoGungeonBridge.SpawnAPItem(1);
		}

		private static void DebugSendDeathlink()
		{
			SessionHandler.DataSender.SendDeathlink();
		}

		private static void DebugReceiveDeathlink()
		{
			string text = "TESTING";
			string causeOfDeath = "Deathlink by " + text;
			ArchipelagoGungeonBridge.DeathlinkKillPlayer(causeOfDeath);
		}

		private static void DebugChest(int chestNum)
		{
			SaveDataManagement.AddToCountSaveDataEntry(CountStats.ChestsOpened, chestNum);
		}

		private static void DebugRoomPoint(int pointNum)
		{
			SaveDataManagement.AddToCountSaveDataEntry(CountStats.RoomPoints, pointNum);
		}

		private static void DebugCash(int cashNum)
		{
			SaveDataManagement.AddToCountSaveDataEntry(CountStats.CashSpent, cashNum);
		}

		private static void SpeedrunDebug()
		{
			ETGModConsole instance = ETGModConsole.Instance;
			if (instance != null)
			{
				instance.ParseCommand("quick_kill");
			}
			ETGModConsole instance2 = ETGModConsole.Instance;
			if (instance2 != null)
			{
				instance2.ParseCommand("flight");
			}
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
			PlayerControllerExt.GiveItem(GungeonPlayerEventListener.GetFirstAlivePlayer(), "shotgun_coffee");
		}

		private static void SetNewDebugOutputState(bool isActive)
		{
			ArchDebugPrint.SetDebugState(isActive);
		}

		private static void DebugLoadLevel(AvailableDebugCMD levelToLoad)
		{
			if (CommandToLevel.ContainsKey(levelToLoad))
			{
				string text = "load_level " + CommandToLevel[levelToLoad];
				ETGModConsole instance = ETGModConsole.Instance;
				if (instance != null)
				{
					instance.ParseCommand(text);
				}
			}
		}

		public static void HandleCommand(string inputString, string additionalInput = "")
		{
			if (!InputToCommand.ContainsKey(inputString))
			{
				ArchipelagoGUI.ConsoleLog(inputString + " is not a debug command");
				return;
			}
			AvailableDebugCMD availableDebugCMD = InputToCommand[inputString];
			switch (availableDebugCMD)
			{
			case AvailableDebugCMD.SpawnAPItem:
				DebugSpawnAPItem();
				break;
			case AvailableDebugCMD.SendDeathlink:
				DebugSendDeathlink();
				break;
			case AvailableDebugCMD.ReceiveDeathlink:
				DebugReceiveDeathlink();
				break;
			case AvailableDebugCMD.AddChest:
				if (additionalInput == "")
				{
					DebugChest(1);
				}
				else
				{
					DebugChest(Convert.ToInt32(additionalInput));
				}
				break;
			case AvailableDebugCMD.Add1RoomPoint:
				if (additionalInput == "")
				{
					DebugRoomPoint(1);
				}
				else
				{
					DebugRoomPoint(Convert.ToInt32(additionalInput));
				}
				break;
			case AvailableDebugCMD.Add100CashSpent:
				if (additionalInput == "")
				{
					DebugCash(100);
				}
				else
				{
					DebugCash(Convert.ToInt32(additionalInput));
				}
				break;
			case AvailableDebugCMD.Speedrun:
				SpeedrunDebug();
				break;
			case AvailableDebugCMD.FullDebug:
				SetNewDebugOutputState(isActive: true);
				break;
			case AvailableDebugCMD.NoDebug:
				SetNewDebugOutputState(isActive: false);
				break;
			case AvailableDebugCMD.ReceiveItem:
				ArchipelagoGungeonBridge.GiveGungeonItem((long)Convert.ToDouble(additionalInput));
				break;
			default:
				DebugLoadLevel(availableDebugCMD);
				break;
			}
		}
	}
	public class ArchDebugPrint
	{
		private static Dictionary<DebugCategory, bool> DebugActiveStates { get; set; } = new Dictionary<DebugCategory, bool>
		{
			{
				DebugCategory.PluginStartup,
				false
			},
			{
				DebugCategory.PlayerEventListener,
				false
			},
			{
				DebugCategory.LocalSaveData,
				true
			},
			{
				DebugCategory.ServerReceive,
				true
			},
			{
				DebugCategory.ServerSend,
				true
			},
			{
				DebugCategory.CountingGoal,
				true
			},
			{
				DebugCategory.EnemyRandomization,
				false
			},
			{
				DebugCategory.InitializingGameState,
				false
			},
			{
				DebugCategory.ItemHandling,
				false
			},
			{
				DebugCategory.TrapHandling,
				false
			},
			{
				DebugCategory.UserInterface,
				false
			},
			{
				DebugCategory.GameCompletion,
				false
			},
			{
				DebugCategory.CharacterSystems,
				false
			}
		};


		public static void InitDebugLog()
		{
			DebugFileWriter.CheckForOldestDebugFile();
			DebugFileWriter.ClearLocalOldestFile();
			DebugFileWriter.StartWritingDebugToLocal();
		}

		public static void DebugLog(DebugCategory debugGroup, string textToLog)
		{
			if (DebugActiveStates.ContainsKey(debugGroup))
			{
				if (DebugActiveStates[debugGroup])
				{
					ArchipelagoGUI.ConsoleLog($"Group: {debugGroup} -- " + textToLog);
				}
				else
				{
					DebugFileWriter.AppendToLocalDebugLog($"Group: {debugGroup} -- " + textToLog);
				}
			}
		}

		internal static void OnCatchException(string condition, string stackTrace, LogType type)
		{
			DebugFileWriter.AppendToLocalDebugLog(condition);
			DebugFileWriter.AppendToLocalDebugLog(stackTrace);
		}

		public static void SetDebugState(bool newState)
		{
			Dictionary<DebugCategory, bool> dictionary = new Dictionary<DebugCategory, bool>();
			foreach (DebugCategory key in DebugActiveStates.Keys)
			{
				dictionary.Add(key, newState);
			}
			DebugActiveStates = dictionary;
			if (newState)
			{
				DebugFileWriter.StartWritingDebugToLocal();
			}
		}

		public static void SetDebugState(DebugCategory debugGroup, bool newState)
		{
			DebugActiveStates[debugGroup] = newState;
		}
	}
	public class UnitTests
	{
		private static string[] unitTestCommands;

		private static int commandIndex = -1;

		public static void HandleUnitTestCommand(string commandText)
		{
			switch (commandText)
			{
			case "0":
			case "next":
				GoToNextUnitTestStep();
				break;
			case "1":
				LoadUnitTest1();
				break;
			case "2":
				LoadUnitTest2();
				break;
			case "3":
				LoadUnitTest3();
				break;
			case "4":
				LoadUnitTest4();
				break;
			case "5":
				LoadUnitTest5();
				break;
			case "6":
				LoadUnitTest6();
				break;
			case "7":
				LoadUnitTest7();
				break;
			default:
				ArchipelagoGUI.ConsoleLog("ERROR: '" + commandText + "' not a unit test command");
				break;
			}
		}

		public static void GoToNextUnitTestStep()
		{
			if (commandIndex < unitTestCommands.Length - 1)
			{
				commandIndex++;
				string[] stepCommand = SplitStepString(unitTestCommands[commandIndex]);
				ParseStepCommand(stepCommand);
			}
		}

		private static string[] SplitStepString(string text)
		{
			string[] separator = new string[1] { " " };
			return text.Split(separator, 2, StringSplitOptions.None);
		}

		private static void ParseStepCommand(string[] stepCommand)
		{
			switch (stepCommand[0])
			{
			case "cmd":
				SendConsoleCommand(stepCommand[1]);
				break;
			case "print":
				SendOutputString(stepCommand[1]);
				GoToNextUnitTestStep();
				break;
			case "wait":
				break;
			case "func":
				ParseUnitTestFunctionCase(stepCommand[1]);
				break;
			}
		}

		private static void SendConsoleCommand(string consoleString)
		{
			ETGModConsole instance = ETGModConsole.Instance;
			if (instance != null)
			{
				instance.ParseCommand(consoleString);
			}
		}

		private static void SendOutputString(string outputString)
		{
			ArchipelagoGUI.ConsoleLog("UNIT TEST: " + outputString);
		}

		private static void ParseUnitTestFunctionCase(string functionCase)
		{
			switch (functionCase)
			{
			case "sendDeathlink":
				SessionHandler.DataSender.SendDeathlink("Gungeoneer", "Died by Unit Test");
				break;
			case "bossOutput":
				ArchDebugPrint.SetDebugState(DebugCategory.PlayerEventListener, newState: true);
				break;
			case "spawnAP":
				ArchipelagoGungeonBridge.SpawnAPItem(5);
				break;
			case "identityItems":
				CharSwap.ReceiveParadoxModeItem(0);
				CharSwap.ReceiveParadoxModeItem(1);
				CharSwap.ReceiveParadoxModeItem(2);
				CharSwap.ReceiveParadoxModeItem(3);
				CharSwap.ReceiveParadoxModeItem(4);
				CharSwap.ReceiveParadoxModeItem(5);
				break;
			case "bulletSpawn":
				ETGModConsole.SpawnItem(new string[2] { "bullet_that_can_kill_the_past", "1" });
				break;
			}
		}

		private static void LoadUnitTest1()
		{
			List<PlayerCompletionGoals> archipelagoRequiredGoals = ArchipelagoCompletion.ArchipelagoRequiredGoals;
			List<string> list = new List<string>();
			using (List<PlayerCompletionGoals>.Enumerator enumerator = archipelagoRequiredGoals.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					switch (enumerator.Current)
					{
					case PlayerCompletionGoals.SecretChamber:
						list.Add("print Sewers level loading, repeat 'test next' for teleport");
						list.Add("cmd load_level sewers");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd visit_all_rooms");
						list.Add("print Abbey level loading");
						list.Add("cmd load_level abbey");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd visit_all_rooms");
						break;
					case PlayerCompletionGoals.Dragun:
						list.Add("print Forge level loading");
						list.Add("cmd load_level forge");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd visit_all_rooms");
						break;
					case PlayerCompletionGoals.Lich:
						list.Add("print Hell level loading");
						list.Add("cmd load_level hell");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd visit_all_rooms");
						break;
					case PlayerCompletionGoals.AdvancedGungeon:
						list.Add("print Forge, level loading, repeat TWICE 'test next' for teleport and weird egg");
						list.Add("cmd load_level forge");
						list.Add("cmd visit_all_rooms");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd spawn item weird_egg");
						list.Add("print RAT level loading, repeat 'test next' for teleport");
						list.Add("cmd load_level ratlair");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd visit_all_rooms");
						break;
					case PlayerCompletionGoals.FarewellArms:
						list.Add("print RNG Dept loading, repeat 'test next' for teleport");
						list.Add("cmd load_level rng_dept");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd visit_all_rooms");
						break;
					case PlayerCompletionGoals.PastsBase:
						list.Add("print =========== CAUTION. Pasts are VERY glitchy if you start them with quick_kill on. Next test_next will DISABLE IT");
						list.Add("wait --");
						list.Add("cmd quick_kill");
						list.Add("print Marine Past loading");
						list.Add("cmd load_level marinepast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Convict Past loading");
						list.Add("cmd load_level convictpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Hunter Past loading");
						list.Add("cmd load_level hunterpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Pilot Past loading");
						list.Add("cmd load_level pilotpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						break;
					case PlayerCompletionGoals.PastsFull:
						list.Add("print =========== CAUTION. Pasts are VERY glitchy if you start them with quick_kill on. Next test_next will DISABLE IT");
						list.Add("wait --");
						list.Add("cmd quick_kill");
						list.Add("print Marine Past loading");
						list.Add("cmd load_level marinepast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Convict Past loading");
						list.Add("cmd load_level convictpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Hunter Past loading");
						list.Add("cmd load_level hunterpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Pilot Past loading");
						list.Add("cmd load_level pilotpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Robot Past loading");
						list.Add("cmd load_level robotpast");
						list.Add("cmd quick_kill");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						list.Add("print Bullet Past loading");
						list.Add("cmd load_level bulletpast");
						list.Add("cmd character bullet");
						list.Add("print Enter 'test next' to load NEXT goal level");
						list.Add("cmd quick_kill");
						break;
					}
				}
			}
			list.Add("print ------------------- END OF UNIT TEST ------------------------");
			List<string> list2 = new List<string> { "print GAME COMPLETION UNIT TEST", "print Requires connection to Archipelago, otherwise nothing happens", "print Enter 'test next' x2 to initialize quick_kill", "cmd quick_kill", "cmd godmode", "print Enter 'test next' to load NEXT goal level", "wait --" };
			list2.AddRange(list);
			unitTestCommands = list2.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}

		private static void LoadUnitTest2()
		{
			List<string> list = new List<string>
			{
				"print BULLET TO PAST ITEM TEST", "print Enter 'test next' to initialize Paradox Mode", "wait ---", "print Enter 'test next' to spawn bullet to past", "cmd character paradox", "print Enter 'test next' to spawn identity items", "func bulletSpawn", "print Enter 'test next' x3 to 1] Load Forge, 2] Visit All Floor 3] Quick_Kill", "func identityItems", "cmd load_level forge",
				"cmd visit_all_rooms", "print ------------ END OF UNIT TEST ----------------", "cmd quick_kill"
			};
			unitTestCommands = list.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}

		private static void LoadUnitTest3()
		{
			List<string> list = new List<string> { "print BOSS OUTPUT UNIT TEST", "print Test requires going to Boss Rush", "print Enter 'test next' to enable quick_kill", "wait --", "print Enter 'test next' to force output to true for boss kills", "cmd quick_kill", "------------ END OF UNIT TEST -------------", "func bossOutput" };
			unitTestCommands = list.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}

		private static void LoadUnitTest4()
		{
			List<string> list = new List<string> { "print DEATHLINK RECEIVE UNIT TEST", "print Connect another client to the server (ie. AP Sudoku)", "print Enter 'test next' to enable Deathlink", "wait --", "print Send Deathlink from other client and see if Gungeon player dies", "print ----------------- END OF UNIT TEST ------------------", "cmd deathlink 1" };
			unitTestCommands = list.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}

		private static void LoadUnitTest5()
		{
			List<string> list = new List<string> { "print DEATHLINK SEND UNIT TEST", "print Connect another client to server to test Deathlink", "print Send 'test next' to send a Deathlink event", "wait ---", "print Check if deathlink sent", "print ---------- END OF UNIT TEST ---------------", "func sendDeathlink" };
			unitTestCommands = list.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}

		private static void LoadUnitTest6()
		{
			List<string> list = new List<string>
			{
				"print PASSWORD & NAME ARCHIPEL CONNECT UNIT TEST", "print Create APWorld with slot name 'Gun Gie 2Test' and password 'testPass' ", "print Send 'test next' to set Slot Name for fullconnect", "wait ---", "print Send 'test next' to set Password for fullconnect", "cmd set name Gun Gie 2Test", "print Send 'test next' to fullconnect", "cmd set password testPass", "print Try connection with IP Address and port", "print ---------- END OF UNIT TEST --------------",
				"wait --"
			};
			unitTestCommands = list.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}

		private static void LoadUnitTest7()
		{
			List<string> list = new List<string> { "print AP ITEM MULTI SEND UNIT TEST", "print Send 'test next' to spawn 5 AP Items", "wait ---", "print Send 'test next' to spawn another 5 AP Items", "func spawnAP", "print -------------- END OF UNIT TEST ----------------", "func spawnAP" };
			unitTestCommands = list.ToArray();
			commandIndex = -1;
			GoToNextUnitTestStep();
		}
	}
}
namespace ArchiGungeon.CustomItemClass
{
	internal class CustomBlankModItem : BlankModificationItem
	{
		public static void InitHooks()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Hook val = new Hook((MethodBase)typeof(SilencerInstance).GetMethod("ProcessBlankModificationItemAdditionalEffects", BindingFlags.Instance | BindingFlags.NonPublic), typeof(CustomBlankModItem).GetMethod("BlankModificationHook"));
		}

		public static void BlankModificationHook(Action<SilencerInstance, BlankModificationItem, Vector2, PlayerController> blankAction, SilencerInstance self, BlankModificationItem blackModItem, Vector2 centerPoint, PlayerController user)
		{
			//IL_0004: 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)
			blankAction(self, blackModItem, centerPoint, user);
			if (blackModItem is CustomBlankModItem)
			{
				(blackModItem as CustomBlankModItem).OnBlank(self, centerPoint, user);
			}
		}

		protected virtual void OnBlank(SilencerInstance silencerInstance, Vector2 centerPoint, PlayerController user)
		{
		}
	}
	public class CustomOrbital : PassiveItem
	{
		public PlayerOrbital OrbitalPrefab;

		public PlayerOrbitalFollower OrbitalFollowerPrefab;

		public bool HasUpgradeSynergy;

		public CustomSynergyType UpgradeSynergy;

		public GameObject UpgradeOrbitalPrefab;

		public GameObject UpgradeOrbitalFollowerPrefab;

		public bool CanBeMimicked;

		public DamageTypeModifier[] modifiers;

		public DamageTypeModifier[] synergyModifiers;

		public bool BreaksUponContact;

		public bool BreaksUponOwnerDamage;

		public GameObject BreakVFX;

		protected GameObject m_extantOrbital;

		protected bool m_synergyUpgradeActive;

		public bool HasAdvancedUpgradeSynergy;

		public string AdvancedUpgradeSynergy;

		public GameObject AdvancedUpgradeOrbitalPrefab;

		public GameObject AdvancedUpgradeOrbitalFollowerPrefab;

		public List<DamageTypeModifier> advancedSynergyModifiers = new List<DamageTypeModifier>();

		protected bool m_advancedSynergyUpgradeActive;

		private void CreateOrbital(PlayerController owner)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			GameObject val = ((!((Object)(object)OrbitalPrefab != (Object)null)) ? ((Component)OrbitalFollowerPrefab).gameObject : ((Component)OrbitalPrefab).gameObject);
			if (HasUpgradeSynergy && m_synergyUpgradeActive)
			{
				val = ((!((Object)(object)UpgradeOrbitalPrefab != (Object)null)) ? UpgradeOrbitalFollowerPrefab.gameObject : UpgradeOrbitalPrefab.gameObject);
			}
			if (HasAdvancedUpgradeSynergy && m_advancedSynergyUpgradeActive)
			{
				val = ((!((Object)(object)AdvancedUpgradeOrbitalPrefab != (Object)null)) ? AdvancedUpgradeOrbitalFollowerPrefab.gameObject : AdvancedUpgradeOrbitalPrefab.gameObject);
			}
			m_extantOrbital = PlayerOrbitalItem.CreateOrbital(owner, val, (Object)(object)OrbitalFollowerPrefab != (Object)null, (PlayerOrbitalItem)null);
			if (BreaksUponContact && Object.op_Implicit((Object)(object)m_extantOrbital))
			{
				SpeculativeRigidbody component = m_extantOrbital.GetComponent<SpeculativeRigidbody>();
				if (Object.op_Implicit((Object)(object)component))
				{
					SpeculativeRigidbody val2 = component;
					val2.OnRigidbodyCollision = (OnRigidbodyCollisionDelegate)Delegate.Combine((Delegate?)(object)val2.OnRigidbodyCollision, (Delegate?)new OnRigidbodyCollisionDelegate(HandleBreakOnCollision));
				}
			}
			if (BreaksUponOwnerDamage && Object.op_Implicit((Object)(object)