Decompiled source of Benchwarp v1.2.0

plugins/Benchwarp.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using Benchwarp.Benches;
using Benchwarp.Components;
using Benchwarp.Data;
using Benchwarp.Deploy;
using Benchwarp.Doors;
using Benchwarp.Doors.Obstacles;
using Benchwarp.Events;
using Benchwarp.Hotkeys;
using Benchwarp.Patches;
using Benchwarp.Settings;
using Benchwarp.Util;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalEnums;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using PrepatcherPlugin;
using Silksong.AssetHelper.ManagedAssets;
using Silksong.DataManager;
using Silksong.FsmUtil;
using Silksong.ModMenu.Elements;
using Silksong.ModMenu.Plugin;
using TeamCherry.Localization;
using TeamCherry.NestedFadeGroup;
using TeamCherry.SharedUtils;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Benchwarp")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+f0c6c37a4a1b7e85197233c19d4b7598f49ebcbf")]
[assembly: AssemblyProduct("Benchwarp")]
[assembly: AssemblyTitle("Benchwarp")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/homothetyhk/Silksong.Benchwarp")]
[assembly: NeutralResourcesLanguage("EN")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		public string Name { get; }

		public ExtensionMarkerAttribute(string name)
		{
			Name = name;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class CompilerLoweringPreserveAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	[Embedded]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	[AttributeUsage(AttributeTargets.All)]
	[ExcludeFromCodeCoverage]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace Benchwarp
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("io.github.homothetyhk.benchwarp", "Benchwarp", "1.2.0")]
	public class BenchwarpPlugin : BaseUnityPlugin, IModMenuCustomElement, IModMenuInterface, ISaveDataMod<SaveSettingsData>, IRawSaveDataMod, IGlobalDataMod<SharedSettingsData>, IRawGlobalDataMod
	{
		private static BenchwarpPlugin? _instance;

		[CompilerGenerated]
		private TextButton <ModMenuEntryButton>k__BackingField;

		public const string Id = "io.github.homothetyhk.benchwarp";

		public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

		public static BenchwarpPlugin Instance => _instance ?? throw new NullReferenceException("Benchwarp has not loaded yet!");

		private bool StartCalled { get; set; }

		private string HarmonyID { get; } = Name + " (io.github.homothetyhk.benchwarp)";

		internal TextButton ModMenuEntryButton
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				if (<ModMenuEntryButton>k__BackingField == null || !Object.op_Implicit((Object)(object)<ModMenuEntryButton>k__BackingField.MenuButton))
				{
					SelectableElement val = default(SelectableElement);
					new ConfigEntryFactory().GenerateEntryButton(LocalizedText.op_Implicit("Benchwarp"), (BaseUnityPlugin)(object)this, ref val);
					<ModMenuEntryButton>k__BackingField = (TextButton)val;
				}
				return <ModMenuEntryButton>k__BackingField;
			}
		}

		public static ConfigSettings ConfigSettings { get; private set; } = null;

		public static SaveSettings SaveSettings { get; } = new SaveSettings(new SaveSettingsData());

		public static SharedSettings SharedSettings { get; } = new SharedSettings(new SharedSettingsData());

		SaveSettingsData? ISaveDataMod<SaveSettingsData>.SaveData
		{
			get
			{
				return SaveSettings.GetSerializationData();
			}
			set
			{
				SaveSettings.Load(value ?? new SaveSettingsData());
			}
		}

		SharedSettingsData? IGlobalDataMod<SharedSettingsData>.GlobalData
		{
			get
			{
				return SharedSettings.GetSerializationData();
			}
			set
			{
				SharedSettings.Load(value ?? new SharedSettingsData());
			}
		}

		public static string Name => "Benchwarp";

		public static string Version => "1.2.0";

		private BenchwarpPlugin()
		{
			_instance = this;
			ConfigSettings = DefineConfig();
		}

		private void Awake()
		{
			try
			{
				((Component)this).gameObject.AddComponent<RespawnChangeListener>();
				LoadAssets();
				LogHelper.Log("Plugin " + Name + " (io.github.homothetyhk.benchwarp) has loaded!");
			}
			catch (Exception e)
			{
				LogHelper.LogError(GetErrorMsg(e, "Awake"));
			}
		}

		private void OnEnable()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!StartCalled)
			{
				return;
			}
			try
			{
				new Harmony(HarmonyID).PatchAll(((object)this).GetType().Assembly);
				ShakraPDHook.Hook();
				DataManagerFix.Hook();
				RedeployPatch.Hook();
				StyxBenchFix.Hook();
				GUIController.Setup();
			}
			catch (Exception e)
			{
				LogHelper.LogError(GetErrorMsg(e, "OnEnable"));
			}
		}

		private void Start()
		{
			StartCalled = true;
			try
			{
				OnEnable();
				GUIController.LateSetup();
			}
			catch (Exception e)
			{
				LogHelper.LogError(GetErrorMsg(e, "Start"));
			}
		}

		private void OnDisable()
		{
			try
			{
				Harmony.UnpatchID(HarmonyID);
				ShakraPDHook.Unhook();
				DataManagerFix.Unhook();
				RedeployPatch.Unhook();
				StyxBenchFix.Unhook();
				GUIController.Unload();
			}
			catch (Exception e)
			{
				LogHelper.LogError(GetErrorMsg(e, "OnDisable"));
			}
		}

		private string GetErrorMsg(Exception e, [CallerMemberName] string? caller = "")
		{
			return $"Error during {((object)this).GetType().Name}.{caller}:\n{e}";
		}

		private void LoadAssets()
		{
			DeployAssets.Bench = ManagedAsset<GameObject>.FromSceneAsset("Bone_04", "RestBench");
		}

		SelectableElement IModMenuCustomElement.BuildCustomElement()
		{
			return (SelectableElement)(object)ModMenuEntryButton;
		}

		private ConfigSettings DefineConfig()
		{
			//IL_0010: 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_002b: Expected O, but got Unknown
			//IL_002b: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0057: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_0083: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00af: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_00db: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0108: Expected O, but got Unknown
			ConfigEntry<MenuMode> menuMode = ((BaseUnityPlugin)this).Config.Bind<MenuMode>(new ConfigDefinition("Menu", "MenuMode"), MenuMode.StandardBenchwarp, new ConfigDescription("See README.md for details on modes.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigEntry<bool> showScene = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Menu", "ShowScene"), false, new ConfigDescription("Displays a panel in the bottom-left with the active scene name.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigEntry<bool> alwaysToggleAll = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Menu", "AlwaysToggleAll"), false, new ConfigDescription("Auto-expand all dropdown panels.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigEntry<bool> enableDeploy = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Menu", "EnableDeploy"), true, new ConfigDescription("Enables placing a bench at the current location through the menu.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigEntry<bool> enableHotkeys = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Menu", "EnableHotkeys"), false, new ConfigDescription("See README.md for information on supported commands.", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigEntry<bool> recoveryMode = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("Menu", "RecoveryMode"), false, new ConfigDescription("Use if you get stuck. While active, any file loaded will spawn into the starting area in Moss Grotto.", (AcceptableValueBase)null, Array.Empty<object>()));
			return new ConfigSettings(new ConfigSettingsData
			{
				MenuMode = menuMode,
				ShowScene = showScene,
				AlwaysToggleAll = alwaysToggleAll,
				EnableDeploy = enableDeploy,
				EnableHotkeys = enableHotkeys,
				RecoveryMode = recoveryMode
			});
		}
	}
	public static class ChangeScene
	{
		private class DoorwarpSceneLoadInfo(IObstacleHandler handler, RoomData room, DoorData gate, IObstacleProvider provider) : SceneLoadInfo()
		{
			public override void NotifyFetchComplete()
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Expected O, but got Unknown
				((SceneLoadInfo)this).NotifyFetchComplete();
				GameManager.instance.sceneLoad.ActivationComplete += new ActivationCompleteDelegate(ActivationComplete);
			}

			private void ActivationComplete()
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				//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)
				GameManager.instance.sceneLoad.ActivationComplete -= new ActivationCompleteDelegate(ActivationComplete);
				Scene activeScene = SceneManager.GetActiveScene();
				handler.OnSceneChange(activeScene, room, gate, provider);
			}
		}

		public static void WarpToRespawn()
		{
			GameManager gm = GameManager.instance;
			if ((Object)(object)gm == (Object)null)
			{
				LogHelper.LogError("WarpToRespawn called while GameManager is null, aborting...");
				return;
			}
			ModEvents.InvokeOnBenchwarp();
			PlayerDataAccess.atBench = false;
			gm.SaveGame((Action<bool>)delegate(bool worked)
			{
				if (worked)
				{
					gm.LoadGameFromUI(gm.profileID);
				}
			});
			((MonoBehaviour)gm).StartCoroutine(gm.PauseGameToggle(false));
		}

		public static void WarpToDoor(RoomData room, DoorData gate)
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				LogHelper.LogError("WarpToRespawn called while GameManager is null, aborting...");
				return;
			}
			ModEvents.InvokeOnDoorwarp(room, gate);
			((MonoBehaviour)BenchwarpPlugin.Instance).StartCoroutine(DoWarpToDoor(room, gate));
		}

		private static IEnumerator DoWarpToDoor(RoomData room, DoorData gate)
		{
			if (GameManager.instance.IsGamePaused())
			{
				yield return GameManager.instance.PauseGameToggleByMenu();
			}
			PlayerDataAccess.atBench = false;
			if ((Object)(object)HeroController.SilentInstance != (Object)null)
			{
				if (HeroController.instance.cState.onConveyor || HeroController.instance.cState.onConveyorV || HeroController.instance.cState.inConveyorZone)
				{
					ConveyorMovementHero component = ((Component)HeroController.instance).GetComponent<ConveyorMovementHero>();
					if (component != null)
					{
						component.StopConveyorMove();
					}
					HeroController.instance.cState.inConveyorZone = false;
					HeroController.instance.cState.onConveyor = false;
					HeroController.instance.cState.onConveyorV = false;
				}
				HeroController.instance.cState.nearBench = false;
			}
			SceneLoad sceneLoad = GameManager.instance.sceneLoad;
			if (sceneLoad != null)
			{
				sceneLoad.Finish += new FinishDelegate(Warp);
			}
			else
			{
				Warp();
			}
			void Warp()
			{
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				IObstacleHandler doorwarpObstacleHandler = ModEvents.DoorwarpObstacleHandler;
				IObstacleProvider doorwarpObstacleProvider = ModEvents.DoorwarpObstacleProvider;
				doorwarpObstacleHandler.BeforeTransition(room, gate, doorwarpObstacleProvider);
				GameManager.instance.BeginSceneTransition((SceneLoadInfo)(object)new DoorwarpSceneLoadInfo(doorwarpObstacleHandler, room, gate, doorwarpObstacleProvider)
				{
					SceneName = gate.Self.SceneName,
					EntryGateName = gate.Self.GateName,
					PreventCameraFadeOut = false,
					WaitForSceneTransitionCameraFade = true,
					Visualization = (SceneLoadVisualizations)0,
					AlwaysUnloadUnusedAssets = true,
					IsFirstLevelForPlayer = false
				});
			}
		}
	}
}
namespace Benchwarp.Util
{
	public static class JsonUtil
	{
		private class Vector2Converter : JsonConverter<Vector2>
		{
			public override Vector2 ReadJson(JsonReader reader, Type objectType, Vector2 existingValue, bool hasExistingValue, JsonSerializer serializer)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Invalid comparison between Unknown and I4
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Invalid comparison between Unknown and I4
				float num = 0f;
				float num2 = 0f;
				while (reader.Read())
				{
					if ((int)reader.TokenType == 4)
					{
						string text = (string)reader.Value;
						if (!(text == "x"))
						{
							if (text == "y")
							{
								num2 = (float)reader.ReadAsDouble().Value;
							}
						}
						else
						{
							num = (float)reader.ReadAsDouble().Value;
						}
					}
					else if ((int)reader.TokenType == 13)
					{
						break;
					}
				}
				return new Vector2(num, num2);
			}

			public override void WriteJson(JsonWriter writer, Vector2 value, JsonSerializer serializer)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				writer.WriteStartObject();
				writer.WritePropertyName("x");
				writer.WriteValue(value.x);
				writer.WritePropertyName("y");
				writer.WriteValue(value.y);
				writer.WriteEndObject();
			}
		}

		private class Vector3Converter : JsonConverter<Vector3>
		{
			public override Vector3 ReadJson(JsonReader reader, Type objectType, Vector3 existingValue, bool hasExistingValue, JsonSerializer serializer)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Invalid comparison between Unknown and I4
				//IL_00a6: 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_0096: Invalid comparison between Unknown and I4
				float num = 0f;
				float num2 = 0f;
				float num3 = 0f;
				while (reader.Read())
				{
					if ((int)reader.TokenType == 4)
					{
						switch ((string)reader.Value)
						{
						case "x":
							num = (float)reader.ReadAsDouble().Value;
							break;
						case "y":
							num2 = (float)reader.ReadAsDouble().Value;
							break;
						case "z":
							num3 = (float)reader.ReadAsDouble().Value;
							break;
						}
					}
					else if ((int)reader.TokenType == 13)
					{
						break;
					}
				}
				return new Vector3(num, num2, num3);
			}

			public override void WriteJson(JsonWriter writer, Vector3 value, JsonSerializer serializer)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				writer.WriteStartObject();
				writer.WritePropertyName("x");
				writer.WriteValue(value.x);
				writer.WritePropertyName("y");
				writer.WriteValue(value.y);
				writer.WritePropertyName("z");
				writer.WriteValue(value.z);
				writer.WriteEndObject();
			}
		}

		public static readonly JsonSerializer _js;

		public static T Deserialize<T>(string embeddedResourcePath)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			using StreamReader streamReader = new StreamReader(typeof(JsonUtil).Assembly.GetManifestResourceStream(embeddedResourcePath));
			JsonTextReader val = new JsonTextReader((TextReader)streamReader);
			try
			{
				return _js.Deserialize<T>((JsonReader)(object)val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static T DeserializeString<T>(string json)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using StringReader stringReader = new StringReader(json);
			JsonTextReader val = new JsonTextReader((TextReader)stringReader);
			try
			{
				return _js.Deserialize<T>((JsonReader)(object)val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static T DeserializeFile<T>(string filepath)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			using StreamReader streamReader = new StreamReader(File.OpenRead(filepath));
			JsonTextReader val = new JsonTextReader((TextReader)streamReader);
			try
			{
				return _js.Deserialize<T>((JsonReader)(object)val);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SerializeFile(object o, string filePath)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using StreamWriter streamWriter = File.CreateText(filePath);
			JsonTextWriter val = new JsonTextWriter((TextWriter)streamWriter);
			try
			{
				_js.Serialize((JsonWriter)(object)val, o);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static void SerializeFileNearDLL(object o, string fileName)
		{
			File.WriteAllText(Path.Combine(Path.GetDirectoryName(typeof(JsonUtil).Assembly.Location), fileName), Serialize(o));
		}

		public static string Serialize(object o)
		{
			using StringWriter stringWriter = new StringWriter();
			_js.Serialize((TextWriter)stringWriter, o);
			stringWriter.Flush();
			return stringWriter.ToString();
		}

		static JsonUtil()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_001f: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			_js = new JsonSerializer
			{
				DefaultValueHandling = (DefaultValueHandling)1,
				Formatting = (Formatting)1,
				TypeNameHandling = (TypeNameHandling)4
			};
			((Collection<JsonConverter>)(object)_js.Converters).Add((JsonConverter)new StringEnumConverter());
			((Collection<JsonConverter>)(object)_js.Converters).Add((JsonConverter)(object)new Vector2Converter());
			((Collection<JsonConverter>)(object)_js.Converters).Add((JsonConverter)(object)new Vector3Converter());
		}
	}
	public class KeyedEvent<TKey, TDelegate> where TDelegate : Delegate
	{
		public interface IKeyedEventOwner
		{
			TDelegate? GetDelegate(TKey key);
		}

		private class KeyedEventOwner(KeyedEvent<TKey, TDelegate> e) : IKeyedEventOwner
		{
			public TDelegate? GetDelegate(TKey key)
			{
				if (!<e>P.lookup.TryGetValue(key, out TDelegate value))
				{
					return null;
				}
				return value;
			}
		}

		private readonly Dictionary<TKey, TDelegate?> lookup = new Dictionary<TKey, TDelegate>();

		private readonly IKeyedEventOwner _owner;

		public KeyedEvent(out IKeyedEventOwner owner)
		{
			owner = (_owner = new KeyedEventOwner(this));
		}

		public void Add(TKey key, TDelegate? value)
		{
			if (lookup.TryGetValue(key, out TDelegate value2))
			{
				lookup[key] = (TDelegate)Delegate.Combine(value2, value);
			}
			else
			{
				lookup.Add(key, value);
			}
		}

		public void Remove(TKey key, TDelegate? value)
		{
			if (lookup.TryGetValue(key, out TDelegate value2))
			{
				lookup[key] = (TDelegate)Delegate.Remove(value2, value);
			}
		}
	}
	public static class KeyedEventOwnerExtensions
	{
		[SpecialName]
		public sealed class <G>$C6A9B8DD00F1E45F26342E72D02C8C27<$T0>
		{
			[SpecialName]
			public static class <M>$E0AA760A0F8D6A1A9BBB3F6C99B2F6C4
			{
			}

			[ExtensionMarker("<M>$E0AA760A0F8D6A1A9BBB3F6C99B2F6C4")]
			public void Invoke($T0 key, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$526F89CC70AF37E7C53F29AE13CF9C13<$T0, $T1>
		{
			[SpecialName]
			public static class <M>$75DC55BFFF8E5AD2F3C72A4A5C4E024A
			{
			}

			[ExtensionMarker("<M>$75DC55BFFF8E5AD2F3C72A4A5C4E024A")]
			public void Invoke($T0 key, $T1 arg, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$AD3E2172C724280323F6120772B0167B<$T0, $T1, $T2>
		{
			[SpecialName]
			public static class <M>$CFD08ADC185F78A9B822255600266AF9
			{
			}

			[ExtensionMarker("<M>$CFD08ADC185F78A9B822255600266AF9")]
			public void Invoke($T0 key, $T1 arg1, $T2 arg2, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		public static void Invoke<TKey>(this KeyedEvent<TKey, Action>.IKeyedEventOwner owner, TKey key, [CallerMemberName] string? caller = "")
		{
			try
			{
				owner.GetDelegate(key)?.Invoke();
			}
			catch (Exception arg)
			{
				LogHelper.LogError($"Error invoking delegate from {caller} for key {key}:\n{arg}");
			}
		}

		public static void Invoke<TKey, TArg>(this KeyedEvent<TKey, Action<TArg>>.IKeyedEventOwner owner, TKey key, TArg arg, [CallerMemberName] string? caller = "")
		{
			try
			{
				owner.GetDelegate(key)?.Invoke(arg);
			}
			catch (Exception ex)
			{
				LogHelper.LogError($"Error invoking delegate from {caller} for key {key} with arg {arg}:\n{ex}");
			}
		}

		public static void Invoke<TKey, TArg1, TArg2>(this KeyedEvent<TKey, Action<TArg1, TArg2>>.IKeyedEventOwner owner, TKey key, TArg1 arg1, TArg2 arg2, [CallerMemberName] string? caller = "")
		{
			try
			{
				owner.GetDelegate(key)?.Invoke(arg1, arg2);
			}
			catch (Exception ex)
			{
				LogHelper.LogError($"Error invoking delegate from {caller} for key {key} with args {arg1}, {arg2}:\n{ex}");
			}
		}
	}
	internal static class Localization
	{
		private const string Sheet = "Mods.io.github.homothetyhk.benchwarp";

		public static string GetLanguageString(this string key)
		{
			return Language.Get(key, "Mods.io.github.homothetyhk.benchwarp");
		}
	}
	internal static class LogHelper
	{
		public static void Log(object? o)
		{
			BenchwarpPlugin.Instance.Logger.LogInfo(o);
		}

		public static void LogError(object? o)
		{
			BenchwarpPlugin.Instance.Logger.LogError(o);
		}

		public static void LogWarn(object? o)
		{
			BenchwarpPlugin.Instance.Logger.LogWarning(o);
		}
	}
	internal static class SceneExtensions
	{
		private static readonly List<GameObject> rootObjects = new List<GameObject>(500);

		public static GameObject? FindGameObject(this Scene s, string path, bool warnIfNotFound)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			((Scene)(ref s)).GetRootGameObjects(rootObjects);
			int num = path.IndexOf('/');
			GameObject val = null;
			if (num >= 0)
			{
				string text = path.Substring(0, num);
				foreach (GameObject rootObject in rootObjects)
				{
					if (!(((Object)rootObject).name != text))
					{
						Transform obj = rootObject.transform.Find(path.Substring(num + 1));
						val = ((obj != null) ? ((Component)obj).gameObject : null);
						if ((Object)(object)val != (Object)null)
						{
							break;
						}
					}
				}
			}
			else
			{
				val = ((IEnumerable<GameObject>)rootObjects).FirstOrDefault((Func<GameObject, bool>)((GameObject g) => ((Object)g).name == path));
			}
			if (!Object.op_Implicit((Object)(object)val) && warnIfNotFound)
			{
				LogHelper.LogWarn("Failed to find object " + path + " in scene " + ((Scene)(ref s)).name + ". Existing objects are " + s.Dump() + ".");
			}
			rootObjects.Clear();
			return val;
		}

		private static string Dump(this Scene s)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return string.Join("\n", from p in s.Traverse()
				select p.path);
		}

		private static List<(string path, GameObject go)> Traverse(this Scene s)
		{
			((Scene)(ref s)).GetRootGameObjects(rootObjects);
			List<(string, GameObject)> list = new List<(string, GameObject)>();
			foreach (GameObject rootObject in rootObjects)
			{
				TraverseInternal(string.Empty, rootObject.transform, list);
			}
			return list;
		}

		private static void TraverseInternal(string path, Transform t, List<(string, GameObject)> results)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			path = path + "/" + ((Object)t).name;
			results.Add((path, ((Component)t).gameObject));
			foreach (Transform item in t)
			{
				Transform t2 = item;
				TraverseInternal(path, t2, results);
			}
		}
	}
	public class SequentialEvent<TDelegate> where TDelegate : Delegate
	{
		public interface ISequentialEventOwner
		{
			event Action? OnSubscribersChanged;

			IReadOnlyList<TDelegate> GetSubscribers();
		}

		private class SequentialEventOwner(SequentialEvent<TDelegate> e) : ISequentialEventOwner
		{
			event Action? ISequentialEventOwner.OnSubscribersChanged
			{
				add
				{
					<e>P.OnSubscribersChanged += value;
				}
				remove
				{
					<e>P.OnSubscribersChanged -= value;
				}
			}

			IReadOnlyList<TDelegate> ISequentialEventOwner.GetSubscribers()
			{
				return <e>P.modifiers;
			}
		}

		private readonly List<TDelegate> modifiers = new List<TDelegate>();

		private event Action? OnSubscribersChanged;

		public SequentialEvent(out ISequentialEventOwner owner)
		{
			owner = new SequentialEventOwner(this);
		}

		public void Add(TDelegate value)
		{
			modifiers.Add(value);
			this.OnSubscribersChanged?.Invoke();
		}

		public void Remove(TDelegate value)
		{
			modifiers.Remove(value);
			this.OnSubscribersChanged?.Invoke();
		}
	}
	public static class SequentialEventOwnerExtensions
	{
		[SpecialName]
		public sealed class <G>$CB57ABAC9FA4DBD61648592FA42C6095<$T0>
		{
			[SpecialName]
			public static class <M>$4243BAC63842EF50C4174920157E6FF2
			{
			}

			[ExtensionMarker("<M>$4243BAC63842EF50C4174920157E6FF2")]
			public $T0 InvokeToTransform($T0 seed, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$F4F1B1619584B33AEBBA06C2121E2406<$T0, $T1>
		{
			[SpecialName]
			public static class <M>$5EF27F45C57A844E76D1FCF3BDDAC56E
			{
			}

			[ExtensionMarker("<M>$5EF27F45C57A844E76D1FCF3BDDAC56E")]
			public $T0 InvokeToTransform($T1 arg, $T0 seed, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$881BC38AE16CB7B346ABE66097582785<$T0>
		{
			[SpecialName]
			public static class <M>$6F70E36BFD44005BEBACCCB3BC775833
			{
			}

			[ExtensionMarker("<M>$6F70E36BFD44005BEBACCCB3BC775833")]
			public List<$T0> InvokeAndCollect([CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$6F70E36BFD44005BEBACCCB3BC775833")]
			public TResult InvokeAndAggregate<TResult>(TResult seed, Func<TResult, $T0, TResult> combiner, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$DFECCCE3C66174E09FBA0B45DD8E5E82<$T0, $T1>
		{
			[SpecialName]
			public static class <M>$3142026A3634B7EA2AB5FCFAB1CBE662
			{
			}

			[ExtensionMarker("<M>$3142026A3634B7EA2AB5FCFAB1CBE662")]
			public List<$T0> InvokeAndCollect($T1 arg, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$3142026A3634B7EA2AB5FCFAB1CBE662")]
			public TResult InvokeAndAggregate<TResult>($T1 arg, TResult seed, Func<TResult, $T0, TResult> combiner, [CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$6E033FA2D58B6339F639C8FC929EA571<$T0>
		{
			[SpecialName]
			public static class <M>$DCF101354DBCC7F6F23431DACBC4D482
			{
			}

			[ExtensionMarker("<M>$DCF101354DBCC7F6F23431DACBC4D482")]
			public List<$T0> InvokeAndCollectFlat([CallerMemberName] string? caller = "")
			{
				throw new NotSupportedException();
			}
		}

		public static TValue InvokeToTransform<TValue>(this SequentialEvent<Func<TValue, TValue>>.ISequentialEventOwner owner, TValue seed, [CallerMemberName] string? caller = "")
		{
			foreach (Func<TValue, TValue> subscriber in owner.GetSubscribers())
			{
				try
				{
					seed = subscriber(seed);
				}
				catch (Exception arg)
				{
					LogHelper.LogError($"Error invoking sequential transformer from {caller}:\n{arg}");
				}
			}
			return seed;
		}

		public static TValue InvokeToTransform<TValue, TArg>(this SequentialEvent<Func<TArg, TValue, TValue>>.ISequentialEventOwner owner, TArg arg, TValue seed, [CallerMemberName] string? caller = "")
		{
			foreach (Func<TArg, TValue, TValue> subscriber in owner.GetSubscribers())
			{
				try
				{
					seed = subscriber(arg, seed);
				}
				catch (Exception arg2)
				{
					LogHelper.LogError($"Error invoking sequential transformer from {caller}:\n{arg2}");
				}
			}
			return seed;
		}

		public static List<TValue> InvokeAndCollect<TValue>(this SequentialEvent<Func<TValue>>.ISequentialEventOwner owner, [CallerMemberName] string? caller = "")
		{
			IReadOnlyList<Func<TValue>> subscribers = owner.GetSubscribers();
			List<TValue> list = new List<TValue>(subscribers.Count);
			foreach (Func<TValue> item2 in subscribers)
			{
				try
				{
					TValue item = item2();
					list.Add(item);
				}
				catch (Exception arg)
				{
					LogHelper.LogError($"Error invoking subscriber to {caller}:\n{arg}");
				}
			}
			return list;
		}

		public static TResult InvokeAndAggregate<TValue, TResult>(this SequentialEvent<Func<TValue>>.ISequentialEventOwner owner, TResult seed, Func<TResult, TValue, TResult> combiner, [CallerMemberName] string? caller = "")
		{
			foreach (Func<TValue> subscriber in owner.GetSubscribers())
			{
				try
				{
					TValue arg = subscriber();
					seed = combiner(seed, arg);
				}
				catch (Exception arg2)
				{
					LogHelper.LogError($"Error invoking sequential aggreator from {caller}:\n{arg2}");
				}
			}
			return seed;
		}

		public static List<TValue> InvokeAndCollect<TValue, TArg>(this SequentialEvent<Func<TArg, TValue>>.ISequentialEventOwner owner, TArg arg, [CallerMemberName] string? caller = "")
		{
			IReadOnlyList<Func<TArg, TValue>> subscribers = owner.GetSubscribers();
			List<TValue> list = new List<TValue>(subscribers.Count);
			foreach (Func<TArg, TValue> item2 in subscribers)
			{
				try
				{
					TValue item = item2(arg);
					list.Add(item);
				}
				catch (Exception arg2)
				{
					LogHelper.LogError($"Error invoking subscriber to {caller}:\n{arg2}");
				}
			}
			return list;
		}

		public static TResult InvokeAndAggregate<TValue, TArg, TResult>(this SequentialEvent<Func<TArg, TValue>>.ISequentialEventOwner owner, TArg arg, TResult seed, Func<TResult, TValue, TResult> combiner, [CallerMemberName] string? caller = "")
		{
			foreach (Func<TArg, TValue> subscriber in owner.GetSubscribers())
			{
				try
				{
					TValue arg2 = subscriber(arg);
					seed = combiner(seed, arg2);
				}
				catch (Exception arg3)
				{
					LogHelper.LogError($"Error invoking sequential aggreator from {caller} with arg {arg}:\n{arg3}");
				}
			}
			return seed;
		}

		public static List<TValue> InvokeAndCollectFlat<TValue>(this SequentialEvent<Func<IEnumerable<TValue>>>.ISequentialEventOwner owner, [CallerMemberName] string? caller = "")
		{
			IReadOnlyList<Func<IEnumerable<TValue>>> subscribers = owner.GetSubscribers();
			List<TValue> list = new List<TValue>(subscribers.Count);
			foreach (Func<IEnumerable<TValue>> item in subscribers)
			{
				try
				{
					IEnumerable<TValue> collection = item();
					list.AddRange(collection);
				}
				catch (Exception arg)
				{
					LogHelper.LogError($"Error invoking subscriber to {caller}:\n{arg}");
				}
			}
			return list;
		}
	}
	internal static class SpriteManager
	{
		public static Texture2D LoadTexFromAssembly(string resourceName)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_007f: Expected O, but got Unknown
			using Stream stream = typeof(SpriteManager).Assembly.GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				LogHelper.LogError("Failed to load " + resourceName + ". The embedded resources are " + string.Join(", ", typeof(SpriteManager).Assembly.GetManifestResourceNames()));
				throw new KeyNotFoundException(resourceName);
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)72, false);
			ImageConversion.LoadImage(val, array);
			return val;
		}
	}
	internal class StableComparer<T> : IComparer<KeyValuePair<int, T>>
	{
		private readonly IComparer<T> comparer;

		public StableComparer(IComparer<T> comparison)
		{
			comparer = comparison;
		}

		public static Comparison<KeyValuePair<int, T>> GetStableComparison(Comparison<T> comparison)
		{
			return CompareTo;
			int CompareTo(KeyValuePair<int, T> x, KeyValuePair<int, T> y)
			{
				int num = comparison(x.Value, y.Value);
				if (num == 0)
				{
					return x.Key - y.Key;
				}
				return num;
			}
		}

		public int Compare(KeyValuePair<int, T> x, KeyValuePair<int, T> y)
		{
			int num = comparer.Compare(x.Value, y.Value);
			if (num == 0)
			{
				return x.Key - y.Key;
			}
			return num;
		}
	}
	internal static class StableSortExtension
	{
		internal static void StableSort<T>(this IList<T> ts, Comparison<T> comparison)
		{
			KeyValuePair<int, T>[] array = new KeyValuePair<int, T>[ts.Count];
			for (int i = 0; i < ts.Count; i++)
			{
				array[i] = new KeyValuePair<int, T>(i, ts[i]);
			}
			Array.Sort(array, StableComparer<T>.GetStableComparison(comparison));
			for (int j = 0; j < ts.Count; j++)
			{
				ts[j] = array[j].Value;
			}
		}
	}
}
namespace Benchwarp.Settings
{
	public class ConfigSettings
	{
		private readonly ConfigSettingsData data;

		public MenuMode MenuMode
		{
			get
			{
				return data.MenuMode.Value;
			}
			set
			{
				data.MenuMode.Value = value;
			}
		}

		public bool ShowScene
		{
			get
			{
				return data.ShowScene.Value;
			}
			set
			{
				data.ShowScene.Value = value;
			}
		}

		public bool AlwaysToggleAll
		{
			get
			{
				return data.AlwaysToggleAll.Value;
			}
			set
			{
				data.AlwaysToggleAll.Value = value;
			}
		}

		public bool EnableDeploy
		{
			get
			{
				return data.EnableDeploy.Value;
			}
			set
			{
				data.EnableDeploy.Value = value;
			}
		}

		public bool EnableHotkeys
		{
			get
			{
				return data.EnableHotkeys.Value;
			}
			set
			{
				data.EnableHotkeys.Value = value;
			}
		}

		public bool RecoveryMode
		{
			get
			{
				return data.RecoveryMode.Value;
			}
			set
			{
				data.RecoveryMode.Value = value;
			}
		}

		internal static event Action? OnMenuModeChanged;

		internal static event Action? OnShowSceneChanged;

		internal static event Action? OnAlwaysToggleAllChanged;

		internal static event Action? OnEnableDeployChanged;

		internal static event Action? OnEnableHotkeysChanged;

		internal static event Action? OnRecoveryModeChanged;

		public ConfigSettings(ConfigSettingsData data)
		{
			this.data = data;
			data.MenuMode.SettingChanged += delegate
			{
				Invoke(ConfigSettings.OnMenuModeChanged, ".ctor");
			};
			data.ShowScene.SettingChanged += delegate
			{
				Invoke(ConfigSettings.OnShowSceneChanged, ".ctor");
			};
			data.AlwaysToggleAll.SettingChanged += delegate
			{
				Invoke(ConfigSettings.OnAlwaysToggleAllChanged, ".ctor");
			};
			data.EnableHotkeys.SettingChanged += delegate
			{
				Invoke(ConfigSettings.OnEnableHotkeysChanged, ".ctor");
			};
			data.EnableDeploy.SettingChanged += delegate
			{
				Invoke(ConfigSettings.OnEnableDeployChanged, ".ctor");
			};
			data.RecoveryMode.SettingChanged += delegate
			{
				Invoke(ConfigSettings.OnRecoveryModeChanged, ".ctor");
			};
		}

		internal static void Invoke(Action? a, [CallerMemberName] string? caller = "")
		{
			try
			{
				a?.Invoke();
			}
			catch (Exception arg)
			{
				LogHelper.LogError($"Error in update event for {caller}:\n{arg}");
			}
		}

		internal static void Invoke<T>(Action<T>? a, T arg, [CallerMemberName] string? caller = "")
		{
			try
			{
				a?.Invoke(arg);
			}
			catch (Exception arg2)
			{
				LogHelper.LogError($"Error in update event for {caller}:\n{arg2}");
			}
		}
	}
	public class ConfigSettingsData
	{
		public required ConfigEntry<MenuMode> MenuMode { get; init; }

		public required ConfigEntry<bool> ShowScene { get; init; }

		public required ConfigEntry<bool> AlwaysToggleAll { get; init; }

		public required ConfigEntry<bool> EnableDeploy { get; init; }

		public required ConfigEntry<bool> EnableHotkeys { get; init; }

		public required ConfigEntry<bool> RecoveryMode { get; init; }
	}
	public enum MenuMode
	{
		[Description("StandardBenchwarp: warp to visited benches only.")]
		StandardBenchwarp,
		[Description("WarpOnly: warp to current respawn only.")]
		WarpOnly,
		[Description("UnlockAll: warp to any bench.")]
		UnlockAll,
		[Description("DoorWarp: warp to room transitions.")]
		DoorWarp
	}
	public class SaveSettings(SaveSettingsData data)
	{
		private SaveSettingsData data = data;

		private static readonly KeyedEvent<BenchKey, Action<bool>>.IKeyedEventOwner onSetVisitedLocalOwner;

		private static readonly KeyedEvent<BenchKey, Action<bool>>.IKeyedEventOwner onSetLockedLocalOwner;

		internal static KeyedEvent<BenchKey, Action<bool>> OnSetVisitedLocal { get; } = new KeyedEvent<BenchKey, Action<bool>>(out onSetVisitedLocalOwner);

		internal static KeyedEvent<BenchKey, Action<bool>> OnSetLockedLocal { get; } = new KeyedEvent<BenchKey, Action<bool>>(out onSetLockedLocalOwner);

		public DeployInfo? DeployInfo
		{
			get
			{
				return data.DeployInfo;
			}
			set
			{
				data.DeployInfo = value;
				Invoke(SaveSettings.OnDeployInfoChanged, "DeployInfo");
			}
		}

		internal static event Action<BenchKey, bool>? OnSetVisitedGlobal;

		internal static event Action<BenchKey, bool>? OnSetLocked;

		internal static event Action? OnDeployInfoChanged;

		internal static event Action? OnNewSettingsLoaded;

		public bool IsVisited(BenchKey key)
		{
			return data.VisitedBenches.Contains(key);
		}

		public bool IsLocked(BenchKey key)
		{
			return data.LockedBenches.Contains(key);
		}

		public void SetVisited(BenchKey key, bool value)
		{
			if (IsLocked(key))
			{
				return;
			}
			if (value)
			{
				if (data.VisitedBenches.Add(key))
				{
					Invoke(SaveSettings.OnSetVisitedGlobal, key, value, "SetVisited");
					onSetVisitedLocalOwner.Invoke(key, value, "SetVisited");
				}
			}
			else if (data.VisitedBenches.Remove(key))
			{
				Invoke(SaveSettings.OnSetVisitedGlobal, key, value, "SetVisited");
				onSetVisitedLocalOwner.Invoke(key, value, "SetVisited");
			}
		}

		public void SetLocked(BenchKey key, bool value)
		{
			if (value)
			{
				if (data.LockedBenches.Add(key))
				{
					Invoke(SaveSettings.OnSetLocked, key, value, "SetLocked");
					onSetLockedLocalOwner.Invoke(key, value, "SetLocked");
				}
			}
			else if (data.LockedBenches.Remove(key))
			{
				Invoke(SaveSettings.OnSetLocked, key, value, "SetLocked");
				onSetLockedLocalOwner.Invoke(key, value, "SetLocked");
			}
		}

		private static void Invoke(Action? a, [CallerMemberName] string? caller = "")
		{
			try
			{
				a?.Invoke();
			}
			catch (Exception arg)
			{
				LogHelper.LogError($"Error in update event for {caller}:\n{arg}");
			}
		}

		private static void Invoke<T1, T2>(Action<T1, T2>? a, T1 arg1, T2 arg2, [CallerMemberName] string? caller = "")
		{
			try
			{
				a?.Invoke(arg1, arg2);
			}
			catch (Exception arg3)
			{
				LogHelper.LogError($"Error invoking global update event for {caller}:\n{arg3}");
			}
		}

		internal SaveSettingsData GetSerializationData()
		{
			return data;
		}

		internal void Load(SaveSettingsData data)
		{
			this.data = data;
			try
			{
				SaveSettings.OnNewSettingsLoaded?.Invoke();
			}
			catch (Exception arg)
			{
				LogHelper.LogError($"Error invoking OnNewSettingsLoaded:\n{arg}");
			}
		}
	}
	public class SaveSettingsData
	{
		public DeployInfo? DeployInfo;

		public HashSet<BenchKey> VisitedBenches = new HashSet<BenchKey>();

		public HashSet<BenchKey> LockedBenches = new HashSet<BenchKey>();
	}
	public class SharedSettings(SharedSettingsData data)
	{
		private SharedSettingsData data = data;

		public DeployStyles DeployStyle
		{
			get
			{
				return data.DeployStyle;
			}
			set
			{
				data.DeployStyle = value;
				Invoke(SharedSettings.OnDeployStyleChanged, "DeployStyle");
			}
		}

		internal static event Action? OnDeployStyleChanged;

		internal static event Action? OnNewSettingsLoaded;

		internal string GetHotkey(string code)
		{
			if (!data.HotkeyOverrides.TryGetValue(code, out string value))
			{
				return code;
			}
			return value;
		}

		internal SharedSettingsData GetSerializationData()
		{
			return data;
		}

		internal void Load(SharedSettingsData data)
		{
			this.data = data;
			try
			{
				SharedSettings.OnNewSettingsLoaded?.Invoke();
			}
			catch (Exception arg)
			{
				LogHelper.LogError($"Error invoking OnNewSettingsLoaded:\n{arg}");
			}
		}

		internal static void Invoke(Action? a, [CallerMemberName] string? caller = "")
		{
			try
			{
				a?.Invoke();
			}
			catch (Exception arg)
			{
				LogHelper.LogError($"Error in update event for {caller}:\n{arg}");
			}
		}
	}
	public class SharedSettingsData
	{
		public DeployStyles DeployStyle = DeployStyles.Bone;

		public Dictionary<string, string> HotkeyOverrides = new Dictionary<string, string>();

		internal static SharedSettingsData CreateDefault()
		{
			return new SharedSettingsData
			{
				HotkeyOverrides = new Dictionary<string, string>
				{
					["LB"] = "LB",
					["SB"] = "SB",
					["DW"] = "DW",
					["NP"] = "NP",
					["WD"] = "WD",
					["DB"] = "DB"
				}
			};
		}
	}
}
namespace Benchwarp.Patches
{
	internal static class DataManagerFix
	{
		internal static void Hook()
		{
			SceneManager.activeSceneChanged += OnMenu;
		}

		internal static void Unhook()
		{
			SceneManager.activeSceneChanged -= OnMenu;
		}

		private static void OnMenu(Scene from, Scene to)
		{
			if (((Scene)(ref to)).name == "Menu_Title")
			{
				BenchwarpPlugin.SaveSettings.Load(new SaveSettingsData());
			}
		}
	}
	[HarmonyPatch(typeof(SceneAdditiveLoadConditional), "OnWasLoaded")]
	internal static class FleaGamesStartBenchFix
	{
		[HarmonyPostfix]
		public static void OnWasLoaded(SceneAdditiveLoadConditional __instance)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (!(__instance.SceneNameToLoad == "Aqueduct_05_festival") || !PlayerDataAccess.FleaGamesCanStart || PlayerDataAccess.FleaGamesStarted)
			{
				return;
			}
			RespawnInfo respawnInfo = RespawnInfo.FromPlayerData();
			if (!(respawnInfo.SceneName == "Aqueduct_05") || (!(respawnInfo.RespawnMarkerName == "RestBench") && !(respawnInfo.RespawnMarkerName == "RestBench Festival")))
			{
				return;
			}
			Scene s = Enumerable.Range(0, SceneManager.sceneCount).Select((Func<int, Scene>)SceneManager.GetSceneAt).First((Scene val2) => ((Scene)(ref val2)).name == "Aqueduct_05_festival");
			string[] array = new string[2] { "Caravan_States/Flea Festival/Festival_Feast/RestBench Festival", "Caravan_States/Flea Festival/Festival_Feast/Bench (1)" };
			foreach (string path in array)
			{
				GameObject val = s.FindGameObject(path, warnIfNotFound: true);
				if (!((Object)(object)val == (Object)null))
				{
					val.transform.SetParent((Transform)null, true);
					val.SetActive(true);
				}
			}
			if (respawnInfo.RespawnMarkerName != "RestBench Festival")
			{
				PlayerDataAccess.respawnMarkerName = "RestBench Festival";
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "GetRespawnInfo")]
	internal static class OverrideKnownRespawnPatch
	{
		[HarmonyPrefix]
		private static bool OverrideGetRespawnInfo(ref string scene, ref string marker)
		{
			DeployInfo deployInfo = BenchwarpPlugin.SaveSettings.DeployInfo;
			if ((object)deployInfo != null && deployInfo.IsCurrentRespawn())
			{
				scene = deployInfo.RespawnInfo.SceneName;
				marker = deployInfo.RespawnInfo.RespawnMarkerName;
				return false;
			}
			BenchData currentBenchRespawn = BenchList.CurrentBenchRespawn;
			if ((object)currentBenchRespawn != null)
			{
				RespawnInfo respawnInfo = currentBenchRespawn.RespawnInfo.GetRespawnInfo();
				scene = respawnInfo.SceneName;
				marker = respawnInfo.RespawnMarkerName;
				return false;
			}
			RespawnInfo startDef = BenchListModifiers.GetStartDef();
			if (startDef.IsCurrentRespawn())
			{
				scene = startDef.SceneName;
				marker = startDef.RespawnMarkerName;
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		private static void RecordGetRespawnInfoFallthrough(GameManager __instance, ref string scene, ref string marker)
		{
			if (scene == "Tut_01" && __instance.playerData.respawnScene != "Tut_01")
			{
				BenchwarpPlugin.Instance.Logger.LogWarning((object)("Unrecognized respawn at " + __instance.playerData.respawnMarkerName + " in " + __instance.playerData.respawnScene + ", GameManager.GetRespawnInfo will fall through to Tut_01."));
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "ContinueGame")]
	internal static class RecoveryModePatch
	{
		[HarmonyPrefix]
		private static void ModifyRespawn()
		{
			if (BenchwarpPlugin.ConfigSettings.RecoveryMode)
			{
				LogHelper.LogWarn("Recovery mode is enabled. Setting respawn location to Tut_01...");
				new RespawnInfo("Tut_01", "Death Respawn Marker Init", 0, (MapZone)13).SetRespawn();
			}
		}
	}
	internal static class RedeployPatch
	{
		internal static void Hook()
		{
			SceneManager.activeSceneChanged += OnActiveSceneChanged;
		}

		internal static void Unhook()
		{
			SceneManager.activeSceneChanged -= OnActiveSceneChanged;
		}

		private static void OnActiveSceneChanged(Scene from, Scene to)
		{
			DeployManager.Redeploy();
		}
	}
	internal static class ShakraPDHook
	{
		internal static void Hook()
		{
			PlayerDataVariableEvents.OnSetBool += UpdateShakraBenches;
		}

		internal static void Unhook()
		{
			PlayerDataVariableEvents.OnSetBool -= UpdateShakraBenches;
		}

		private static bool UpdateShakraBenches(PlayerData pd, string fieldName, bool current)
		{
			if (!(fieldName == "MapperLeftGreymoor"))
			{
				if (fieldName == "MapperLeftPeak" && current)
				{
					BenchwarpPlugin.SaveSettings.SetVisited(BaseBenchList.ShakraMountFay, value: true);
				}
			}
			else if (current)
			{
				BenchwarpPlugin.SaveSettings.SetVisited(BaseBenchList.ShakraGreymoor, value: true);
			}
			return current;
		}
	}
	internal class StyxBenchFix
	{
		internal static void Hook()
		{
			SceneManager.activeSceneChanged += OnActiveSceneChanged;
		}

		internal static void Unhook()
		{
			SceneManager.activeSceneChanged -= OnActiveSceneChanged;
		}

		private static void OnActiveSceneChanged(Scene from, Scene to)
		{
			//IL_0016: 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)
			if (!(((Scene)(ref to)).name == "Dust_11") || (int)PlayerDataAccess.permadeathMode != 0 || !GameManager.instance.RespawningHero || !BaseBenchList.Styx.RespawnInfo.IsCurrentRespawn() || !(PlayerDataAccess.blackThreadWorld ? (!PlayerDataAccess.silkFarmAbyssCoresCleared) : (!PlayerDataAccess.silkFarmBattle1_complete)))
			{
				return;
			}
			GameObject val = to.FindGameObject("Steel Soul States/Regular/NPC Control/Grub Farmer NPC", warnIfNotFound: true);
			if (Object.op_Implicit((Object)(object)val))
			{
				PlayMakerFSM val2 = FSMUtility.LocateMyFSM(val, "Control");
				string[] array = new string[2] { "Battle Active", "Abyss Battle Active" };
				foreach (string text in array)
				{
					FsmUtil.RemoveFirstActionOfType<SetPosition>(FsmUtil.MustGetState(val2, text));
				}
			}
		}
	}
}
namespace Benchwarp.Hotkeys
{
	public static class HotkeyActions
	{
		public const string LastBench = "LB";

		public const string StartBench = "SB";

		public const string DoorWarp = "DW";

		public const string NextPage = "NP";

		public const string WarpDeploy = "WD";

		public const string DeployBench = "DB";

		private static readonly Dictionary<string, Action> _hotkeys;

		public static ReadOnlyDictionary<string, Action> CurrentHotkeys { get; }

		public static ReadOnlyDictionary<string, Action> BaseHotkeys { get; }

		static HotkeyActions()
		{
			CurrentHotkeys = new ReadOnlyDictionary<string, Action>(_hotkeys = new Dictionary<string, Action>());
			BaseHotkeys = new ReadOnlyDictionary<string, Action>(new Dictionary<string, Action>
			{
				["LB"] = ChangeScene.WarpToRespawn,
				["SB"] = (Action)Delegate.Combine(new Action(BenchListModifiers.MenuSetToStart), new Action(ChangeScene.WarpToRespawn)),
				["WD"] = (Action)Delegate.Combine(new Action(DeployManager.MenuSetRespawnToDeploy), new Action(ChangeScene.WarpToRespawn)),
				["DW"] = delegate
				{
					if (BenchwarpPlugin.ConfigSettings.MenuMode != MenuMode.DoorWarp)
					{
						BenchwarpPlugin.ConfigSettings.MenuMode = MenuMode.DoorWarp;
					}
					else
					{
						BenchwarpPlugin.ConfigSettings.MenuMode = MenuMode.StandardBenchwarp;
					}
				},
				["DB"] = delegate
				{
					DeployManager.DeployAtHero();
				},
				["NP"] = delegate
				{
					GUIController.Instance.NextPage();
				}
			});
			RefreshHotkeys();
		}

		public static void RefreshHotkeys()
		{
			_hotkeys.Clear();
			foreach (var (code, a) in BaseHotkeys)
			{
				AddHotkey(_hotkeys, code, a);
			}
			foreach (var (text2, action2) in ModEvents.GetHotkeyRequests())
			{
				if (action2 == null)
				{
					_hotkeys.Remove(text2);
				}
				else
				{
					AddHotkey(_hotkeys, text2, action2);
				}
			}
		}

		internal static void AddHotkey(Dictionary<string, Action> dict, string code, Action a)
		{
			code = BenchwarpPlugin.SharedSettings.GetHotkey(code);
			if (code.Length != 2 || !char.IsLetter(code[0]) || !char.IsLetter(code[1]))
			{
				LogHelper.LogError("Invalid hotkey " + code + ": hotkeys must consist of exactly two letters.");
			}
			else
			{
				dict[code] = a;
			}
		}

		public static bool TryDoHotkeyAction(int groupIndex, int benchIndex)
		{
			if (BenchList.BenchGroups.Count > groupIndex && BenchList.BenchGroups[groupIndex].Benches.Count > benchIndex)
			{
				BenchList.BenchGroups[groupIndex].Benches[benchIndex].MenuSetBench();
				ChangeScene.WarpToRespawn();
				return true;
			}
			return false;
		}

		public static bool TryDoHotkeyAction(string code)
		{
			if (CurrentHotkeys.TryGetValue(code, out Action value))
			{
				try
				{
					value?.Invoke();
				}
				catch (Exception arg)
				{
					LogHelper.LogError($"Error invoking hotkey bound to {code}:\n{arg}");
				}
				return true;
			}
			return false;
		}
	}
	public readonly record struct HotkeyCode(HotkeyInput First, HotkeyInput Second)
	{
		public static HotkeyCode None { get; } = new HotkeyCode(HotkeyInput.None, HotkeyInput.None);

		public bool IsComplete
		{
			get
			{
				if (!First.IsNone)
				{
					return !Second.IsNone;
				}
				return false;
			}
		}

		public static HotkeyCode operator +(HotkeyCode code, HotkeyInput input)
		{
			return new HotkeyCode(code.Second, input);
		}

		public bool TryGetLetterNumCode(out int firstIndex, out int secondIndex)
		{
			if (First.IsLetter && Second.IsNum)
			{
				firstIndex = First.Num;
				secondIndex = Second.Num;
				return true;
			}
			firstIndex = 0;
			secondIndex = 0;
			return false;
		}

		public bool TryGetNumericCode(out int code)
		{
			if (First.IsNum && Second.IsNum)
			{
				code = First.Num * 10 + Second.Num;
				return true;
			}
			code = 0;
			return false;
		}

		public bool TryGetStringCode(out string code)
		{
			if (First.IsLetter && Second.IsLetter)
			{
				code = $"{First.Letter}{Second.Letter}";
				return true;
			}
			code = string.Empty;
			return false;
		}
	}
	public readonly record struct HotkeyInput(HotkeyType Type, int Num)
	{
		public static HotkeyInput None { get; } = new HotkeyInput(HotkeyType.None, 0);

		public bool IsNone => Type == HotkeyType.None;

		public bool IsLetter => Type == HotkeyType.Letter;

		public bool IsNum => Type == HotkeyType.Number;

		public char Letter => (char)(65 + Num);
	}
	public enum HotkeyType
	{
		None,
		Letter,
		Number
	}
}
namespace Benchwarp.Events
{
	public static class BenchListModifiers
	{
		private static readonly SequentialEvent<Func<RespawnInfo, RespawnInfo>>.ISequentialEventOwner onGetStartDefOwner;

		private static readonly SequentialEvent<Func<BenchData, bool>>.ISequentialEventOwner benchSuppressorsOwner;

		private static readonly SequentialEvent<Func<IEnumerable<BenchData>>>.ISequentialEventOwner benchInjectorsOwner;

		private static readonly SequentialEvent<Comparison<BenchData>>.ISequentialEventOwner benchComparisonsOwner;

		public static SequentialEvent<Func<RespawnInfo, RespawnInfo>> OnGetStartDef { get; }

		public static SequentialEvent<Func<BenchData, bool>> BenchSuppressors { get; }

		public static SequentialEvent<Func<IEnumerable<BenchData>>> BenchInjectors { get; }

		public static SequentialEvent<Comparison<BenchData>> BenchComparisons { get; }

		public static RespawnInfo GetStartDef()
		{
			return onGetStartDefOwner.InvokeToTransform(new RespawnInfo("Tut_01", "Death Respawn Marker Init", 0, (MapZone)13), "GetStartDef");
		}

		public static bool AtStart()
		{
			return GetStartDef().IsCurrentRespawn();
		}

		public static void MenuSetToStart()
		{
			if (BenchwarpPlugin.ConfigSettings.MenuMode != MenuMode.WarpOnly)
			{
				GetStartDef().SetRespawn();
			}
		}

		internal static bool ShouldSuppressBench(BenchData bench)
		{
			return benchSuppressorsOwner.InvokeAndAggregate(bench, seed: false, (bool b1, bool b2) => b1 || b2, "ShouldSuppressBench");
		}

		internal static IEnumerable<BenchData> GetInjectedBenches()
		{
			return benchInjectorsOwner.InvokeAndCollectFlat("GetInjectedBenches");
		}

		internal static void SortBenchList(List<BenchData> benches)
		{
			foreach (Comparison<BenchData> subscriber in benchComparisonsOwner.GetSubscribers())
			{
				benches.StableSort(subscriber);
			}
		}

		static BenchListModifiers()
		{
			OnGetStartDef = new SequentialEvent<Func<RespawnInfo, RespawnInfo>>(out onGetStartDefOwner);
			BenchSuppressors = new SequentialEvent<Func<BenchData, bool>>(out benchSuppressorsOwner);
			BenchInjectors = new SequentialEvent<Func<IEnumerable<BenchData>>>(out benchInjectorsOwner);
			BenchComparisons = new SequentialEvent<Comparison<BenchData>>(out benchComparisonsOwner);
			benchSuppressorsOwner.OnSubscribersChanged += BenchList.RefreshBenchList;
			benchInjectorsOwner.OnSubscribersChanged += BenchList.RefreshBenchList;
		}
	}
	public static class ModEvents
	{
		private static readonly SequentialEvent<Func<(string, Action?)>>.ISequentialEventOwner hotkeyRequestsOwner;

		public static IObstacleHandler DoorwarpObstacleHandler { get; set; }

		public static IObstacleProvider DoorwarpObstacleProvider { get; set; }

		public static SequentialEvent<Func<(string, Action?)>> HotkeyRequests { get; }

		public static event Action? OnBenchSelected;

		public static event Action? OnBenchwarp;

		public static event Action<RoomData, DoorData>? OnDoorwarp;

		internal static void InvokeOnBenchSelected()
		{
			try
			{
				ModEvents.OnBenchSelected?.Invoke();
			}
			catch (Exception o)
			{
				LogHelper.LogError(o);
			}
		}

		internal static void InvokeOnBenchwarp()
		{
			try
			{
				ModEvents.OnBenchwarp?.Invoke();
			}
			catch (Exception o)
			{
				LogHelper.LogError(o);
			}
		}

		internal static void InvokeOnDoorwarp(RoomData room, DoorData gate)
		{
			try
			{
				ModEvents.OnDoorwarp?.Invoke(room, gate);
			}
			catch (Exception o)
			{
				LogHelper.LogError(o);
			}
		}

		internal static IEnumerable<(string, Action?)> GetHotkeyRequests()
		{
			return hotkeyRequestsOwner.InvokeAndCollect("GetHotkeyRequests");
		}

		static ModEvents()
		{
			DoorwarpObstacleHandler = new NoSaveObstacleHandler();
			DoorwarpObstacleProvider = new BaseObstacleProvider();
			HotkeyRequests = new SequentialEvent<Func<(string, Action)>>(out hotkeyRequestsOwner);
			hotkeyRequestsOwner.OnSubscribersChanged += HotkeyActions.RefreshHotkeys;
		}
	}
	public static class WorldEvents
	{
		public static event Action<RespawnInfo, BenchData?>? OnRespawnChanged;

		internal static void InvokeOnRespawnChanged(RespawnInfo info)
		{
			BenchList.UpdateRespawn(info);
			try
			{
				WorldEvents.OnRespawnChanged?.Invoke(info, BenchList.CurrentBenchRespawn);
			}
			catch (Exception o)
			{
				LogHelper.LogError(o);
			}
		}
	}
}
namespace Benchwarp.Doors
{
	public class AreaRoomGroup
	{
		public required string MenuArea { get; init; }

		public required ReadOnlyCollection<RoomData> Rooms { get; init; }
	}
	public class DoorData
	{
		private static readonly ReadOnlyCollection<TransitionKey> emptyDynamicTargets = new ReadOnlyCollection<TransitionKey>(new List<TransitionKey>());

		private static readonly ReadOnlyCollection<ObstacleInfo> emptyObstacles = new ReadOnlyCollection<ObstacleInfo>(new List<ObstacleInfo>());

		public TransitionKey Self { get; }

		public TransitionKey? Target { get; }

		public TransitionKey? Source { get; }

		public ReadOnlyCollection<TransitionKey> DynamicTargets { get; init; } = emptyDynamicTargets;

		public ReadOnlyCollection<ObstacleInfo> Obstacles { get; init; } = emptyObstacles;

		public DoorData(TransitionKey self)
		{
			Self = self;
			Target = self;
		}

		public DoorData(TransitionKey self, TransitionKey sourcetarget)
		{
			Self = self;
			Target = sourcetarget;
			Source = sourcetarget;
		}

		public DoorData(TransitionKey self, TransitionKey? source, TransitionKey? target)
		{
			Self = self;
			Target = target;
			Source = source;
		}
	}
	public static class DoorList
	{
		public static ReadOnlyDictionary<string, RoomData> Rooms { get; }

		public static ReadOnlyDictionary<TransitionKey, DoorData> Doors { get; }

		public static ReadOnlyCollection<AreaRoomGroup> RoomGroups { get; }

		public static int RoomCount { get; }

		public static int DoorCount { get; }

		public static int MaxRoomsPerArea { get; }

		public static int MaxDoorsPerRoom { get; }

		static DoorList()
		{
			Rooms = new ReadOnlyDictionary<string, RoomData>((from p in typeof(BaseRoomList).GetProperties(BindingFlags.Static | BindingFlags.Public)
				where p.PropertyType == typeof(RoomData)
				select (RoomData)p.GetValue(null)).ToDictionary((RoomData d) => d.Name, (RoomData d) => d));
			Doors = new ReadOnlyDictionary<TransitionKey, DoorData>(Rooms.Values.SelectMany((RoomData r) => r.Gates).ToDictionary((DoorData g) => g.Self));
			List<AreaRoomGroup> list = new List<AreaRoomGroup>();
			list.AddRange(from g in (from r in Rooms.Values
					group r by r.TitledArea).Select(delegate(IGrouping<string, RoomData> g)
				{
					AreaRoomGroup obj = new AreaRoomGroup
					{
						MenuArea = g.Key
					};
					List<RoomData> list2 = new List<RoomData>();
					list2.AddRange(g);
					obj.Rooms = new ReadOnlyCollection<RoomData>(list2);
					return obj;
				})
				orderby g.MenuArea
				select g);
			RoomGroups = new ReadOnlyCollection<AreaRoomGroup>(list);
			RoomCount = ((IEnumerable<AreaRoomGroup>)RoomGroups).Sum((Func<AreaRoomGroup, int>)CountRooms);
			DoorCount = RoomGroups.Sum((AreaRoomGroup g) => ((IEnumerable<RoomData>)g.Rooms).Sum((Func<RoomData, int>)CountGates));
			MaxRoomsPerArea = ((IEnumerable<AreaRoomGroup>)RoomGroups).Max((Func<AreaRoomGroup, int>)CountRooms);
			MaxDoorsPerRoom = RoomGroups.Max((AreaRoomGroup g) => ((IEnumerable<RoomData>)g.Rooms).Max((Func<RoomData, int>)CountGates));
			static int CountGates(RoomData r)
			{
				return r.Gates.Count;
			}
			static int CountRooms(AreaRoomGroup g)
			{
				return g.Rooms.Count;
			}
		}
	}
	public class RoomData
	{
		public required string Name { get; init; }

		public required MapZone MapZone { get; init; }

		public required string MapArea { get; init; }

		public required string TitledArea { get; init; }

		public required ReadOnlyCollection<DoorData> Gates { get; init; }
	}
	public readonly record struct TransitionKey(string SceneName, string GateName)
	{
		public string Name { get; } = SceneName + "[" + GateName + "]";

		private static readonly Regex r = new Regex("^(\\w+)\\[([\\w\\s]+)\\]$");

		public static TransitionKey FromName(string name)
		{
			Match match = r.Match(name);
			if (match == null || !match.Success)
			{
				throw new ArgumentException("Illformated transition name" + name, "name");
			}
			return new TransitionKey(match.Groups[1].Value, match.Groups[2].Value);
		}
	}
}
namespace Benchwarp.Doors.Obstacles
{
	public class BaseObstacleProvider : IObstacleProvider
	{
		public IEnumerable<ObstacleInfo> GetGateObstacles(RoomData room, DoorData gate)
		{
			return gate.Obstacles;
		}
	}
	public record BehaviourObstacleInfo<T> : ObstacleInfo where T : Behaviour
	{
		public bool Enable { get; init; }

		public int Index { get; init; }

		public BehaviourObstacleInfo(string ObjPath, bool Enable, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null, int Index = 0)
		{
			this.Enable = Enable;
			this.Index = Index;
			base..ctor(ObjPath, Type, Severity, SaveInfo);
		}

		public Behaviour? FindBehaviour(Scene scene, bool warnIfNotFound = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindObj(scene, warnIfNotFound);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			object obj = val.GetComponents<T>().ElementAtOrDefault(Index);
			if (!Object.op_Implicit((Object)obj) && warnIfNotFound)
			{
				LogHelper.LogWarn($"GameObject at {base.ObjPath} did not have {Index + 1} components of type {typeof(T).Name}.");
			}
			return (Behaviour?)obj;
		}

		public override void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Behaviour val = FindBehaviour(scene);
			if (val != null && Object.op_Implicit((Object)(object)val))
			{
				val.enabled = Enable;
			}
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out bool Enable, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo, out int Index)
		{
			ObjPath = base.ObjPath;
			Enable = this.Enable;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
			Index = this.Index;
		}
	}
	public record FsmEventObstacleInfo : FsmObstacleInfo
	{
		public string FsmEventName { get; init; }

		public FsmEventObstacleInfo(string ObjPath, string FsmName, string FsmEventName, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null)
		{
			this.FsmEventName = FsmEventName;
			base..ctor(ObjPath, FsmName, Type, Severity, SaveInfo);
		}

		public override void Open(PlayMakerFSM fsm)
		{
			fsm.SendEvent(FsmEventName);
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out string FsmName, out string FsmEventName, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo)
		{
			ObjPath = base.ObjPath;
			FsmName = base.FsmName;
			FsmEventName = this.FsmEventName;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
		}
	}
	public abstract record FsmObstacleInfo : ObstacleInfo
	{
		public string FsmName { get; init; }

		protected FsmObstacleInfo(string ObjPath, string FsmName, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null)
		{
			this.FsmName = FsmName;
			base..ctor(ObjPath, Type, Severity, SaveInfo);
		}

		public abstract void Open(PlayMakerFSM fsm);

		public sealed override void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindObj(scene);
			if (!((Object)(object)val == (Object)null))
			{
				PlayMakerFSM val2 = FSMUtility.LocateMyFSM(val, FsmName);
				if (!((Object)(object)val2 == (Object)null))
				{
					Open(val2);
				}
			}
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out string FsmName, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo)
		{
			ObjPath = base.ObjPath;
			FsmName = this.FsmName;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
		}
	}
	public record FsmTransitionObstacleInfo : FsmObstacleInfo
	{
		public string FsmStateName { get; init; }

		public string FsmEventName { get; init; }

		public string ToState { get; init; }

		public FsmTransitionObstacleInfo(string ObjPath, string FsmName, string FsmStateName, string FsmEventName, string ToState, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null)
		{
			this.FsmStateName = FsmStateName;
			this.FsmEventName = FsmEventName;
			this.ToState = ToState;
			base..ctor(ObjPath, FsmName, Type, Severity, SaveInfo);
		}

		public override void Open(PlayMakerFSM fsm)
		{
			FsmUtil.ChangeTransition(FsmUtil.MustGetState(fsm, FsmStateName), FsmEventName, ToState);
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out string FsmName, out string FsmStateName, out string FsmEventName, out string ToState, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo)
		{
			ObjPath = base.ObjPath;
			FsmName = base.FsmName;
			FsmStateName = this.FsmStateName;
			FsmEventName = this.FsmEventName;
			ToState = this.ToState;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
		}
	}
	public record GameObjectActiveObstacleInfo : ObstacleInfo
	{
		public bool Active { get; init; }

		public GameObjectActiveObstacleInfo(string ObjPath, bool Active, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null)
		{
			this.Active = Active;
			base..ctor(ObjPath, Type, Severity, SaveInfo);
		}

		public override void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			GameObject? obj = FindObj(scene);
			if (obj != null)
			{
				obj.SetActive(Active);
			}
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out bool Active, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo)
		{
			ObjPath = base.ObjPath;
			Active = this.Active;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
		}
	}
	public interface IObstacleHandler
	{
		void BeforeTransition(RoomData room, DoorData gate, IObstacleProvider obstacleProvider);

		void OnSceneChange(Scene scene, RoomData room, DoorData gate, IObstacleProvider obstacleProvider);
	}
	public interface IObstacleProvider
	{
		IEnumerable<ObstacleInfo> GetGateObstacles(RoomData room, DoorData gate);
	}
	public class NoSaveObstacleHandler : ObstacleHandler
	{
		protected override bool HandleObstacleOnActiveSceneChange(Scene scene, RoomData room, DoorData gate, ObstacleInfo o, bool handledBeforeTransition)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return HandleObstacle(scene, room, gate, o);
		}

		public static bool HandleObstacle(Scene scene, RoomData room, DoorData gate, ObstacleInfo o)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			o.Open(scene);
			return true;
		}
	}
	public abstract class ObstacleHandler : IObstacleHandler
	{
		protected readonly HashSet<ObstacleInfo> handledObstacles = new HashSet<ObstacleInfo>();

		public void BeforeTransition(RoomData room, DoorData gate, IObstacleProvider obstacleProvider)
		{
			handledObstacles.Clear();
			foreach (ObstacleInfo gateObstacle in obstacleProvider.GetGateObstacles(room, gate))
			{
				try
				{
					if (HandleObstacleBeforeTransition(room, gate, gateObstacle))
					{
						handledObstacles.Add(gateObstacle);
					}
				}
				catch (Exception arg)
				{
					LogHelper.LogError($"Error handling obstacle {gateObstacle} before transition for gate {gate.Self}:\n{arg}");
				}
			}
		}

		public void OnSceneChange(Scene scene, RoomData room, DoorData gate, IObstacleProvider obstacleProvider)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			foreach (ObstacleInfo gateObstacle in obstacleProvider.GetGateObstacles(room, gate))
			{
				try
				{
					if (HandleObstacleOnActiveSceneChange(scene, room, gate, gateObstacle, handledObstacles.Contains(gateObstacle)))
					{
						handledObstacles.Add(gateObstacle);
					}
				}
				catch (Exception arg)
				{
					LogHelper.LogError($"Error handling obstacle {gateObstacle} on scene change for gate {gate.Self}:\n{arg}");
				}
			}
			IEnumerable<ObstacleInfo> enumerable = gate.Obstacles.Where((ObstacleInfo o) => !handledObstacles.Contains(o));
			if (enumerable.Any())
			{
				LogHelper.LogWarn("ObstacleHandler " + GetType().Name + " for gate " + gate.Self.Name + " did not handle the following obstacles: " + string.Join("; ", enumerable));
			}
			handledObstacles.Clear();
		}

		protected virtual bool HandleObstacleBeforeTransition(RoomData room, DoorData gate, ObstacleInfo o)
		{
			return false;
		}

		protected virtual bool HandleObstacleOnActiveSceneChange(Scene scene, RoomData room, DoorData gate, ObstacleInfo o, bool handledBeforeTransition)
		{
			return false;
		}
	}
	public record ObstacleInfo(string ObjPath, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null)
	{
		public string GetObjName()
		{
			return ObjPath.Split('/').Last();
		}

		public GameObject? FindObj(Scene scene, bool warnIfNotFound = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return scene.FindGameObject(ObjPath, warnIfNotFound);
		}

		public void DestroyObj(Scene scene, bool warnIfNotFound = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Object.Destroy((Object)(object)FindObj(scene, warnIfNotFound));
		}

		public virtual void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			DestroyObj(scene);
		}

		public bool TrySave(RoomData room, DoorData gate)
		{
			if ((object)SaveInfo != null)
			{
				SaveInfo.Save(room, gate, GetObjName());
				return true;
			}
			return false;
		}
	}
	public abstract record ObstacleSaveInfo
	{
		public abstract void Save(RoomData room, DoorData gate, string objName);
	}
	[Flags]
	public enum ObstacleSeverity
	{
		ModifiesSaveData = 1,
		InterruptsEntry = 2,
		LimitsRoomAccess = 4,
		LimitsExitAccess = 8,
		LimitsVisibility = 0x10,
		AbnormalVisual = 0x20
	}
	public enum ObstacleType
	{
		Mask,
		OneWayBreakableEntry,
		OneWayBreakableExit,
		TwoWayBreakable,
		OneWayMechanismEntry,
		OneWayMechanismExit,
		TwoWayMechanism,
		OpenAfterProgression,
		ClosedAfterProgression,
		Cutscene,
		Other
	}
	public class OverrideObstacleProvider : IObstacleProvider
	{
		public required IEnumerable<ObstacleInfo> Obstacles { get; init; }

		public IEnumerable<ObstacleInfo> GetGateObstacles(RoomData room, DoorData gate)
		{
			return gate.Obstacles;
		}
	}
	public class PermanentObstacleHandler : ObstacleHandler
	{
		protected override bool HandleObstacleBeforeTransition(RoomData room, DoorData gate, ObstacleInfo o)
		{
			return HandleObstacle(room, gate, o);
		}

		protected override bool HandleObstacleOnActiveSceneChange(Scene scene, RoomData room, DoorData gate, ObstacleInfo o, bool handledBeforeTransition)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (handledBeforeTransition)
			{
				return false;
			}
			return NoSaveObstacleHandler.HandleObstacle(scene, room, gate, o);
		}

		public static bool HandleObstacle(RoomData room, DoorData gate, ObstacleInfo o)
		{
			return o.TrySave(room, gate);
		}
	}
	public record PersistentBoolSaveInfo(string? SceneName = null, string? ID = null) : ObstacleSaveInfo()
	{
		public override void Save(RoomData room, DoorData gate, string objName)
		{
			SceneData.instance.PersistentBools.SetValue(new PersistentItemData<bool>
			{
				SceneName = (SceneName ?? room.Name),
				ID = (ID ?? objName),
				Value = true
			});
		}
	}
	public record PlayerDataBoolSaveInfo(string PlayerDataBoolName) : ObstacleSaveInfo()
	{
		public override void Save(RoomData room, DoorData gate, string objName)
		{
			PlayerData.instance.SetBool(PlayerDataBoolName, true);
		}
	}
	public record PlayerDataIntSaveInfo(string PlayerDataIntName, int Value) : ObstacleSaveInfo()
	{
		public override void Save(RoomData room, DoorData gate, string objName)
		{
			PlayerData.instance.SetInt(PlayerDataIntName, Value);
		}
	}
	public record TestObjObstacleInfo : BehaviourObstacleInfo<TestGameObjectActivator>
	{
		public bool Activate { get; init; }

		public TestObjObstacleInfo(string ObjPath, bool Activate, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null, int Index = 0)
		{
			this.Activate = Activate;
			base..ctor(ObjPath, Activate, Type, Severity, SaveInfo, Index);
		}

		public override void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Behaviour? obj = FindBehaviour(scene);
			TestGameObjectActivator val = (TestGameObjectActivator)(object)((obj is TestGameObjectActivator) ? obj : null);
			if (val != null && Object.op_Implicit((Object)(object)val))
			{
				((Behaviour)val).enabled = false;
				GameObject activateGameObject = val.activateGameObject;
				if (activateGameObject != null)
				{
					activateGameObject.SetActive(Activate);
				}
				GameObject deactivateGameObject = val.deactivateGameObject;
				if (deactivateGameObject != null)
				{
					deactivateGameObject.SetActive(!Activate);
				}
			}
		}

		[CompilerGenerated]
		public override int GetHashCode()
		{
			return base.GetHashCode() * -1521134295 + EqualityComparer<bool>.Default.GetHashCode(Activate);
		}

		[CompilerGenerated]
		protected TestObjObstacleInfo(TestObjObstacleInfo original)
			: base((BehaviourObstacleInfo<TestGameObjectActivator>)original)
		{
			Activate = original.Activate;
		}

		[CompilerGenerated]
		public new void Deconstruct(out string ObjPath, out bool Activate, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo, out int Index)
		{
			ObjPath = base.ObjPath;
			Activate = this.Activate;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
			Index = base.Index;
		}
	}
	public record TransitionObstacleInfo : BehaviourObstacleInfo<TransitionPoint>
	{
		public bool Enabled { get; init; }

		public TransitionObstacleInfo(string ObjPath, bool Enabled, ObstacleType Type, ObstacleSeverity Severity, ObstacleSaveInfo? SaveInfo = null)
		{
			this.Enabled = Enabled;
			base..ctor(ObjPath, Enabled, Type, Severity, SaveInfo, 0);
		}

		public override void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Behaviour? obj = FindBehaviour(scene);
			TransitionPoint val = (TransitionPoint)(object)((obj is TransitionPoint) ? obj : null);
			if (val != null && Object.op_Implicit((Object)(object)val))
			{
				((Behaviour)val).enabled = Enabled;
				val.isInactive = !Enabled;
				((InteractableBase)val).IsDisabled = !Enabled;
			}
		}

		[CompilerGenerated]
		public override int GetHashCode()
		{
			return base.GetHashCode() * -1521134295 + EqualityComparer<bool>.Default.GetHashCode(Enabled);
		}

		[CompilerGenerated]
		protected TransitionObstacleInfo(TransitionObstacleInfo original)
			: base((BehaviourObstacleInfo<TransitionPoint>)original)
		{
			Enabled = original.Enabled;
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out bool Enabled, out ObstacleType Type, out ObstacleSeverity Severity, out ObstacleSaveInfo? SaveInfo)
		{
			ObjPath = base.ObjPath;
			Enabled = this.Enabled;
			Type = base.Type;
			Severity = base.Severity;
			SaveInfo = base.SaveInfo;
		}
	}
	public record UnmaskerInfo : BehaviourObstacleInfo<Unmasker>
	{
		public UnmaskerInfo(string ObjPath, ObstacleSaveInfo? SaveInfo = null)
			: base(ObjPath, Enable: true, ObstacleType.Mask, ObstacleSeverity.LimitsVisibility, SaveInfo, 0)
		{
		}

		public override void Open(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Behaviour? obj = FindBehaviour(scene);
			Unmasker val = (Unmasker)(object)((obj is Unmasker) ? obj : null);
			if (val != null && Object.op_Implicit((Object)(object)val))
			{
				val.Uncover();
			}
		}

		[CompilerGenerated]
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		[CompilerGenerated]
		protected UnmaskerInfo(UnmaskerInfo original)
			: base((BehaviourObstacleInfo<Unmasker>)original)
		{
		}

		[CompilerGenerated]
		public void Deconstruct(out string ObjPath, out ObstacleSaveInfo? SaveInfo)
		{
			ObjPath = base.ObjPath;
			SaveInfo = base.SaveInfo;
		}
	}
}
namespace Benchwarp.Deploy
{
	internal static class DeployAssets
	{
		public const string DeployedRespawnMarkerName = "Benchwarp Deployed Respawn";

		public static ManagedAsset<GameObject>? Bench { get; set; }

		public static GameObject CreateMarker()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			GameObject val = new GameObject("Benchwarp Deployed Respawn");
			RespawnMarker obj = val.AddComponent<RespawnMarker>();
			obj.customFadeDuration = new OverrideFloat();
			obj.overrideMapZone = new OverrideMapZone();
			val.AddComponent<DeployComponent>();
			return val;
		}

		public static void PlaceMarkerRelativeToHero(GameObject go, Vector3 heroPos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			go.transform.position = heroPos;
		}

		public static GameObject CreateBench()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			((ManagedAssetBase<GameObject>)(object)Bench).Load().WaitForCompletion();
			GameObject obj = ManagedAssetExtensions.InstantiateAsset<GameObject>(Bench);
			((Object)obj).name = "Benchwarp Deployed Respawn";
			ModifyBench(obj);
			obj.AddComponent<DeployComponent>();
			return obj;
		}

		public static void PlaceBenchRelativeToHero(GameObject go, Vector3 heroPos)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			heroPos.y -= 0.6677f;
			heroPos.z += 0.0087f;
			go.transform.position = heroPos;
		}

		private static void ModifyBench(GameObject bench)
		{
			PlayMakerFSM obj = FSMUtility.LocateMyFSM(bench, "Bench Control");
			FsmUtil.ChangeTransition(FsmUtil.GetState(obj, "Craw Summons?"), "FINISHED", "Start Locked?").ThrowIfFalse();
			FsmUtil.ReplaceAllActions(FsmUtil.GetState(obj, "Craw Summons?"), Array.Empty<FsmStateAction>());
			FsmUtil.ChangeTransition(FsmUtil.GetState(obj, "Craw summons check"), "FINISHED", "Resting").ThrowIfFalse();
			FsmUtil.ReplaceAllActions(FsmUtil.GetState(obj, "Craw summons check"), Array.Empty<FsmStateAction>());
			FsmUtil.ReplaceAllActions(FsmUtil.GetState(obj, "Craw Summons Instant?"), Array.Empty<FsmStateAction>());
		}

		private static void ThrowIfFalse(this bool b)
		{
			if (!b)
			{
				throw new InvalidOperationException();
			}
		}
	}
	internal class DeployComponent : MonoBehaviour
	{
		private static DeployComponent? instance;

		private void Awake()
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				Object.Destroy((Object)(object)((Component)instance).gameObject);
			}
			instance = this;
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		public static void DestroyAll()
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				Object.Destroy((Object)(object)((Component)instance).gameObject);
			}
		}
	}
	public record DeployInfo : IRespawnInfo
	{
		public required RespawnInfo RespawnInfo { get; init; }

		public required float HeroX { get; init; }

		public required float HeroY { get; init; }

		public required float HeroZ { get; init; }

		public required DeployStyles Style { get; init; }

		[JsonIgnore]
		public string SceneName => RespawnInfo.SceneName;

		[JsonIgnore]
		public Vector3 HeroPosition => new Vector3(HeroX, HeroY, HeroZ);

		RespawnInfo IRespawnInfo.GetRespawnInfo()
		{
			return RespawnInfo;
		}

		[CompilerGenerated]
		[SetsRequiredMembers]
		protected DeployInfo(DeployInfo original)
		{
			RespawnInfo = original.RespawnInfo;
			HeroX = original.HeroX;
			HeroY = original.HeroY;
			HeroZ = original.HeroZ;
			Style = original.Style;
		}

		public DeployInfo()
		{
		}
	}
	internal static class DeployManager
	{
		public static GameObject DeployAtHero()
		{
			//IL_0015: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				DeployStyles deployStyle = BenchwarpPlugin.SharedSettings.DeployStyle;
				Vector3 position = HeroController.instance.transform.position;
				object result = deployStyle switch
				{
					DeployStyles.Marker => DeployMarkerAtHero(position), 
					DeployStyles.Bone => DeployBenchAtHero(position), 
					_ => throw new NotImplementedException($"Unimplemented deploy style: {BenchwarpPlugin.SharedSettings.DeployStyle}"), 
				};
				BenchwarpPlugin.SaveSettings.DeployInfo = new DeployInfo
				{
					RespawnInfo = new RespawnInfo(GameManager.instance.GetSceneNameString(), "Benchwarp Deployed Respawn", deployStyle.ToRespawnType(), GameManager.instance.sm.mapZone),
					HeroX = position.x,
					HeroY = position.y,
					HeroZ = position.z,
					Style = deployStyle
				};
				return (GameObject)result;
			}
			catch (Exception o)
			{
				LogHelper.LogError(o);
				throw;
			}
		}

		public static GameObject? Redeploy()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			DeployInfo deployInfo = BenchwarpPlugin.SaveSettings.DeployInfo;
			if ((object)deployInfo == null || GameManager.instance.GetSceneNameString() != deployInfo.SceneName)
			{
				return null;
			}
			try
			{
				Vector3 heroPosition = deployInfo.HeroPosition;
				return (GameObject?)(BenchwarpPlugin.SharedSettings.DeployStyle switch
				{
					DeployStyles.Marker => DeployMarkerAtHero(heroPosition), 
					DeployStyles.Bone => DeployBenchAtHero(heroPosition), 
					_ => throw new NotImplementedException($"Unimplemented deploy style: {BenchwarpPlugin.SharedSettings.DeployStyle}"), 
				});
			}
			catch (Exception o)
			{
				LogHelper.LogError(o);
				throw;
			}
		}

		public static GameObject DeployMarkerAtHero(Vector3 heroPos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = DeployAssets.CreateMarker();
			DeployAssets.PlaceMarkerRelativeToHero(obj, heroPos);
			return obj;
		}

		public static GameObject DeployBenchAtHero(Vector3 heroPos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = DeployAssets.CreateBench();
			DeployAssets.PlaceBenchRelativeToHero(obj, heroPos);
			return obj;
		}

		public static void Undeploy()
		{
			DeployComponent.DestroyAll();
			DeployInfo? deployInfo = BenchwarpPlugin.SaveSettings.DeployInfo;
			if ((object)deployInfo != null && deployInfo.IsCurrentRespawn())
			{
				BenchListModifiers.GetStartDef().SetRespawn();
			}
			BenchwarpPlugin.SaveSettings.DeployInfo = null;
		}

		public static void MenuSetRespawnToDeploy()
		{
			if (BenchwarpPlugin.ConfigSettings.MenuMode != MenuMode.WarpOnly)
			{
				BenchwarpPlugin.SaveSettings.DeployInfo?.SetRespawn();
			}
		}
	}
	public enum DeployStyles
	{
		Marker,
		Bone
	}
	public static class DeployStylesExtensions
	{
		[SpecialName]
		public sealed class <G>$D1CB0754BA300FE0865F6D28E6537FAA
		{
			[SpecialName]
			public static class <M>$0D16585C25657F0B27D8B3CE724D86E0
			{
			}

			[ExtensionMarker("<M>$0D16585C25657F0B27D8B3CE724D86E0")]
			public int ToRespawnType()
			{
				throw new NotSupportedException();
			}
		}

		public static int ToRespawnType(this DeployStyles style)
		{
			if (style == DeployStyles.Marker)
			{
				return 0;
			}
			return 1;
		}
	}
}
namespace Benchwarp.Data
{
	public static class BaseBenchList
	{
		public static BenchData RuinedChapel { get; } = new BenchData("Ruined Chapel", "Mosslands", new RespawnInfo("Tut_03", "RestBench", 1, (MapZone)18));

		public static BenchData BoneBottom { get; } = new BenchData("Bone Bottom", "Mosslands", new RespawnInfo("Bonetown", "RestBench", 1, (MapZone)12));

		public static BenchData MossDruid { get; } = new BenchData("Moss Druid", "Mosslands", new RespawnInfo("Mosstown_02c", "RestBench", 1, (MapZone)19));

		public static BenchData SnailShamans { get; } = new BenchData("Snail Shamans", "Mosslands", new RespawnInfo("Tut_04", "RestBench", 1, (MapZone)18));

		public static BenchData TollMarrow { get; } = new BenchData("Toll", "The Marrow", new RespawnInfo("Bone_01c", "RestBench", 1, (MapZone)2));

		public static BenchData MosshomeGate { get; } = new BenchData("Mosshome Gate", "The Marrow", new RespawnInfo("Bone_04", "RestBench", 1, (MapZone)19));

		public static BenchData BellshrineMarrow { get; } = new BenchData("Bellshrine", "The Marrow", new RespawnInfo("Bellshrine", "RestBench", 1, (MapZone)2));

		public static BenchData ShootingGallery { get; } = new BenchData("Shooting Gallery", "The Marrow", new PDConditionalRespawnInfo("act3_wokeUp", new RespawnInfo("Bone_12", "RestBench (1)", 1, (MapZone)2), new RespawnInfo("Bone_12", "RestBench", 1, (MapZone)2)));

		public static BenchData FleaCaravanMarrow { get; } = new BenchData("Flea Caravan", "The Marrow", new RespawnInfo("Bone_10", "RestBench", 1, (MapZone)2));

		public static BenchData TrapMarch { get; } = new BenchData("Trap", "Hunter's March", new PDConditionalRespawnInfo("antBenchTrapDefused", new RespawnInfo("Ant_17", "RestBench", 1, (MapZone)11), new RespawnInfo("Ant_17", "RestBench", 0, (MapZone)11)));

		public static BenchData TollDocks { get; } = new BenchData("Toll", "Deep Docks", new RespawnInfo("Dock_01", "RestBench", 1, (MapZone)15));

		public static BenchData Forge { get; } = new BenchData("Forge", "Deep Docks", new RespawnInfo("Room_Forge", "RestBench", 1, (MapZone)15));

		public static BenchData BellshrineDocks { get; } = new BenchData("Bellshrine", "Deep Docks", new RespawnInfo("Bellshrine_05", "RestBench", 1, (MapZone)15));

		public static BenchData Sauna { get; } = new BenchData("Sauna", "Deep Docks", new RespawnInfo("Dock_10", "RestBench", 1, (MapZone)15));

		public static BenchData DivingBell { get; } = new BenchData("Diving Bell", "Deep Docks", new RespawnInfo("Room_Diving_Bell", "RestBench", 1, (MapZone)15));

		public static BenchData AbyssExit { get; } = new BenchData("Abyss Exit", "Deep Docks", new RespawnInfo("Dock_06_Church", "RestBench (1)", 1, (MapZone)15));

		public static BenchData BellwayFields { get; } = new BenchData("Bellway", "Far Fields", new RespawnInfo("Bellway_03", "RestBench", 1, (MapZone)16));

		public static BenchData Seamstress { get; } = new BenchData("Seamstress", "Far Fields", new RespawnInfo("Bone_East_Umbrella", "RestBench", 1, (MapZone)16));

		public static BenchData PilgrimsRest { get; } =