Decompiled source of FsmMaster v0.3.6

plugins/FsmMaster.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DebugMod;
using DebugMod.SaveStates;
using HarmonyLib;
using HutongGames.PlayMaker;
using InControl;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
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("FsmMaster")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.6.0")]
[assembly: AssemblyInformationalVersion("0.3.6")]
[assembly: AssemblyProduct("FsmMaster")]
[assembly: AssemblyTitle("FsmMaster")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ConstructiveCynicism/FsmMaster")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	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")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace FsmMaster
{
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? Browsable;

		public bool? IsAdvanced;
	}
	internal sealed class DebugModCompat : IDebugModCompat
	{
		private const string ActiveEditsCustomDataKey = "FsmMaster.ActiveEdits";

		private const float PendingReloadTimeoutSeconds = 5f;

		private readonly FsmEditManager _editManager;

		private readonly Action _rescanLiveFsms;

		private readonly ManualLogSource _logger;

		private object? _pendingReloadState;

		private float _pendingReloadDeadline;

		internal DebugModCompat(FsmEditManager editManager, Action rescanLiveFsms, ManualLogSource logger)
		{
			_editManager = editManager;
			_rescanLiveFsms = rescanLiveFsms;
			_logger = logger;
		}

		internal void Hook()
		{
			SaveState.OnSave += HandleSave;
			SaveState.BeforeLoad += HandlePrimeBeforeLoad;
			SaveState.AfterLoad += HandleAfterLoad;
			DebugMod.Log("FsmMaster detected DebugMod - hooking savestate save/load to persist active FSM edits.");
		}

		public void Unhook()
		{
			SaveState.OnSave -= HandleSave;
			SaveState.BeforeLoad -= HandlePrimeBeforeLoad;
			SaveState.AfterLoad -= HandleAfterLoad;
		}

		private void HandleSave(SaveState state)
		{
			try
			{
				List<FsmEditSet> list = new List<FsmEditSet>();
				foreach (string editedFsmKey in _editManager.GetEditedFsmKeys())
				{
					if (_editManager.GetLiveInstances(editedFsmKey).Count != 0)
					{
						FsmEditSet activeEditSet = _editManager.GetActiveEditSet(editedFsmKey);
						if (activeEditSet != null)
						{
							list.Add(activeEditSet);
						}
					}
				}
				if (list.Count != 0)
				{
					state.data.customData["FsmMaster.ActiveEdits"] = FsmSaveDataStore.SerializeEditSets(list);
					DebugMod.Log($"FsmMaster saved {list.Count} active FSM edit set(s) into this savestate.");
				}
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("[FsmMaster] Failed to save FSM edits into DebugMod savestate: " + ex.Message));
			}
		}

		private void HandlePrimeBeforeLoad(SaveState state)
		{
			try
			{
				if (!state.data.customData.TryGetValue("FsmMaster.ActiveEdits", out var value) || string.IsNullOrEmpty(value))
				{
					return;
				}
				foreach (FsmEditSet item in FsmSaveDataStore.DeserializeEditSets(value))
				{
					_editManager.PrimeActiveEditSet(item);
				}
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("[FsmMaster] Failed to prime FSM edits ahead of DebugMod savestate load: " + ex.Message));
			}
		}

		private void HandleAfterLoad(SaveState state)
		{
			ReapplyPersistedEdits(state);
			if ((Object)(object)GameManager.UnsafeInstance != (Object)null && GameManager.UnsafeInstance.isLoading)
			{
				_pendingReloadState = state;
				_pendingReloadDeadline = Time.realtimeSinceStartup + 5f;
			}
		}

		public void PollPendingReload()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			if (_pendingReloadState == null)
			{
				return;
			}
			bool flag = (Object)(object)GameManager.UnsafeInstance != (Object)null && GameManager.UnsafeInstance.isLoading;
			if (!flag || !(Time.realtimeSinceStartup < _pendingReloadDeadline))
			{
				if (flag)
				{
					_logger.LogWarning((object)"[FsmMaster] GameManager.isLoading never cleared after a savestate load; reapplying anyway.");
				}
				SaveState state = (SaveState)_pendingReloadState;
				_pendingReloadState = null;
				ReapplyPersistedEdits(state);
			}
		}

		private void ReapplyPersistedEdits(SaveState state)
		{
			try
			{
				_rescanLiveFsms();
				HashSet<string> hashSet = new HashSet<string>();
				if (state.data.customData.TryGetValue("FsmMaster.ActiveEdits", out var value) && !string.IsNullOrEmpty(value))
				{
					List<FsmEditSet> list = FsmSaveDataStore.DeserializeEditSets(value);
					foreach (FsmEditSet item in list)
					{
						_editManager.ApplyEditSet(item);
						hashSet.Add(item.FsmKey);
					}
					DebugMod.Log($"FsmMaster restored {list.Count} FSM edit set(s) from this savestate.");
				}
				foreach (string item2 in new List<string>(_editManager.GetEditedFsmKeys()))
				{
					if (!hashSet.Contains(item2))
					{
						FsmEditSet activeEditSet = _editManager.GetActiveEditSet(item2);
						if (activeEditSet != null)
						{
							_editManager.ApplyEditSet(activeEditSet);
						}
					}
				}
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("[FsmMaster] Failed to restore FSM edits from DebugMod savestate: " + ex.Message));
			}
		}
	}
	internal interface IDebugModCompat
	{
		void Unhook();

		void PollPendingReload();
	}
	internal static class DebugModCompatFactory
	{
		public static IDebugModCompat? TryCreate(FsmEditManager editManager, Action rescanLiveFsms, ManualLogSource logger)
		{
			if (!Chainloader.PluginInfos.ContainsKey("io.github.hk-speedrunning.debugmod"))
			{
				return null;
			}
			return CreateAndHook(editManager, rescanLiveFsms, logger);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static IDebugModCompat CreateAndHook(FsmEditManager editManager, Action rescanLiveFsms, ManualLogSource logger)
		{
			DebugModCompat debugModCompat = new DebugModCompat(editManager, rescanLiveFsms, logger);
			debugModCompat.Hook();
			return debugModCompat;
		}
	}
	[HarmonyPatch(typeof(HollowKnightInputModule), "ProcessMove")]
	internal static class FocusOnHoverSuppressionPatch
	{
		[HarmonyPrefix]
		private static void Prefix(HollowKnightInputModule __instance, out bool __state)
		{
			__state = __instance.focusOnMouseHover;
			if (CanvasTextField.AnyFieldFocused)
			{
				__instance.focusOnMouseHover = false;
			}
		}

		[HarmonyPostfix]
		private static void Postfix(HollowKnightInputModule __instance, bool __state)
		{
			__instance.focusOnMouseHover = __state;
		}
	}
	internal sealed class BepInExConfigValue<T> : IFsmConfigValue<T>
	{
		private readonly ConfigEntry<T> _entry;

		public T Value
		{
			get
			{
				return _entry.Value;
			}
			set
			{
				_entry.Value = value;
			}
		}

		public BepInExConfigValue(ConfigEntry<T> entry)
		{
			_entry = entry;
		}
	}
	internal sealed class BepInExHotkey : IFsmHotkey
	{
		private readonly ConfigEntry<KeyboardShortcut> _entry;

		public BepInExHotkey(ConfigEntry<KeyboardShortcut> entry)
		{
			_entry = entry;
		}

		public bool IsDown()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = _entry.Value;
			return ((KeyboardShortcut)(ref value)).IsDown();
		}
	}
	internal sealed class BepInExLog : IFsmLog
	{
		private readonly ManualLogSource _logger;

		public BepInExLog(ManualLogSource logger)
		{
			_logger = logger;
		}

		public void LogInfo(string message)
		{
			_logger.LogInfo((object)message);
		}

		public void LogWarning(string message)
		{
			_logger.LogWarning((object)message);
		}

		public void LogError(string message)
		{
			_logger.LogError((object)message);
		}
	}
	internal sealed class FsmGraphColorConfig : IFsmGraphColorConfig
	{
		private const string StateSection = "Graph Colors - State Palette";

		private const string TransitionSection = "Graph Colors - Transition Palette";

		private const string OverlaySection = "Graph Colors - Overlay";

		public IFsmConfigValue<Color>[] StateColors { get; }

		public IFsmConfigValue<Color>[] TransitionColors { get; }

		public IFsmConfigValue<Color> GlobalTransitionColor { get; }

		public IFsmConfigValue<Color> VignetteColor { get; }

		public IFsmConfigValue<Color> GlobalPseudoNodeColor { get; }

		public IFsmConfigValue<Color> GlobalPseudoNodeOutlineColor { get; }

		public IFsmConfigValue<Color> GlobalPseudoNodeTextColor { get; }

		public IFsmConfigValue<Color> NodeOutlineColor { get; }

		public IFsmConfigValue<Color> TransitionRowBackgroundColor { get; }

		public IFsmConfigValue<Color> ActiveStateColor { get; }

		public IFsmConfigValue<Color> ActiveTitleBackgroundColor { get; }

		public IFsmConfigValue<Color> ActiveTitleTextColor { get; }

		public IFsmConfigValue<Color> SelectedStateColor { get; }

		public IFsmConfigValue<Color> DisabledOutlineColor { get; }

		public IFsmConfigValue<Color> DisabledTitleTextColor { get; }

		public IFsmConfigValue<Color> DisabledEventTextColor { get; }

		public IFsmConfigValue<Color> DisabledTransitionLineColor { get; }

		public IFsmConfigValue<Color> DragTransitionColor { get; }

		private FsmGraphColorConfig(IFsmConfigValue<Color>[] stateColors, IFsmConfigValue<Color>[] transitionColors, IFsmConfigValue<Color> globalTransitionColor, IFsmConfigValue<Color> vignetteColor, IFsmConfigValue<Color> globalPseudoNodeColor, IFsmConfigValue<Color> globalPseudoNodeOutlineColor, IFsmConfigValue<Color> globalPseudoNodeTextColor, IFsmConfigValue<Color> nodeOutlineColor, IFsmConfigValue<Color> transitionRowBackgroundColor, IFsmConfigValue<Color> activeStateColor, IFsmConfigValue<Color> activeTitleBackgroundColor, IFsmConfigValue<Color> activeTitleTextColor, IFsmConfigValue<Color> selectedStateColor, IFsmConfigValue<Color> disabledOutlineColor, IFsmConfigValue<Color> disabledTitleTextColor, IFsmConfigValue<Color> disabledEventTextColor, IFsmConfigValue<Color> disabledTransitionLineColor, IFsmConfigValue<Color> dragTransitionColor)
		{
			StateColors = stateColors;
			TransitionColors = transitionColors;
			GlobalTransitionColor = globalTransitionColor;
			VignetteColor = vignetteColor;
			GlobalPseudoNodeColor = globalPseudoNodeColor;
			GlobalPseudoNodeOutlineColor = globalPseudoNodeOutlineColor;
			GlobalPseudoNodeTextColor = globalPseudoNodeTextColor;
			NodeOutlineColor = nodeOutlineColor;
			TransitionRowBackgroundColor = transitionRowBackgroundColor;
			ActiveStateColor = activeStateColor;
			ActiveTitleBackgroundColor = activeTitleBackgroundColor;
			ActiveTitleTextColor = activeTitleTextColor;
			SelectedStateColor = selectedStateColor;
			DisabledOutlineColor = disabledOutlineColor;
			DisabledTitleTextColor = disabledTitleTextColor;
			DisabledEventTextColor = disabledEventTextColor;
			DisabledTransitionLineColor = disabledTransitionLineColor;
			DragTransitionColor = dragTransitionColor;
		}

		public static FsmGraphColorConfig Bind(ConfigFile config)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[8]
			{
				new Color(0.5019608f, 0.5019608f, 0.5019608f),
				new Color(67f / 85f, 0.45490196f, 0.6784314f),
				new Color(0.22745098f, 0.7137255f, 0.6509804f),
				new Color(31f / 85f, 0.6431373f, 0.20784314f),
				new Color(0.88235295f, 0.99607843f, 10f / 51f),
				new Color(47f / 51f, 0.5137255f, 0.18039216f),
				new Color(11f / 15f, 0.29411766f, 0.29411766f),
				new Color(39f / 85f, 0.20784314f, 0.6431373f)
			};
			Color[] array2 = (Color[])(object)new Color[8]
			{
				Color.white,
				new Color(0.972549f, 0.77254903f, 77f / 85f),
				new Color(53f / 85f, 0.88235295f, 72f / 85f),
				new Color(61f / 85f, 0.88235295f, 53f / 85f),
				new Color(0.88235295f, 0.99607843f, 0.4f),
				new Color(1f, 66f / 85f, 0.59607846f),
				new Color(0.88235295f, 53f / 85f, 32f / 51f),
				new Color(0.77254903f, 53f / 85f, 0.88235295f)
			};
			IFsmConfigValue<Color>[] array3 = new IFsmConfigValue<Color>[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array3[i] = BindColor(config, "Graph Colors - State Palette", $"State Color {i}", array[i], $"Fill color for a state whose FsmState.ColorIndex is {i} (colorIndex 0 is PlayMaker's \"no color set\" default).");
			}
			IFsmConfigValue<Color>[] array4 = new IFsmConfigValue<Color>[array2.Length];
			for (int j = 0; j < array2.Length; j++)
			{
				array4[j] = BindColor(config, "Graph Colors - Transition Palette", $"Transition Color {j}", array2[j], $"Transition name/line color for a state whose FsmState.ColorIndex is {j}.");
			}
			Color val = default(Color);
			((Color)(ref val))..ctor(0f, 1f, 1f);
			return new FsmGraphColorConfig(array3, array4, BindColor(config, "Graph Colors - Overlay", "Global Transition Color", new Color(0.6f, 0.6f, 0.6f), "Line color for a global transition's connecting arrow."), BindColor(config, "Graph Colors - Overlay", "Vignette Color", new Color(0f, 0f, 0f, 0.6f), "Dimming fill drawn over the graph wherever the selection panel isn't."), BindColor(config, "Graph Colors - Overlay", "Global Pseudo Node Color", new Color(0.82f, 0.82f, 0.82f), "Fill color of a global transition's pseudo-node box."), BindColor(config, "Graph Colors - Overlay", "Global Pseudo Node Outline Color", Color.black, "Outline color of a global transition's pseudo-node box."), BindColor(config, "Graph Colors - Overlay", "Global Pseudo Node Text Color", Color.black, "Event label color on a global transition's pseudo-node box."), BindColor(config, "Graph Colors - Overlay", "Node Outline Color", Color.white, "Default (non-active, non-disabled) inner ring and title/row divider color on a state node."), BindColor(config, "Graph Colors - Overlay", "Transition Row Background Color", new Color(0.2f, 0.2f, 0.2f), "Background color of a state's transition rows."), BindColor(config, "Graph Colors - Overlay", "Active State Color", val, "Outer halo, inner-ring fallback, and outgoing-line color for the FSM's currently active state."), BindColor(config, "Graph Colors - Overlay", "Active Title Background Color", Color.Lerp(val, Color.white, 0.5f), "Title band background for the currently active state."), BindColor(config, "Graph Colors - Overlay", "Active Title Text Color", Color.black, "Title text color for the currently active state."), BindColor(config, "Graph Colors - Overlay", "Selected State Color", Color.yellow, "Outline and outgoing-line color for whichever state is currently selected."), BindColor(config, "Graph Colors - Overlay", "Disabled Outline Color", new Color(0.5f, 0.5f, 0.5f), "Inner ring and title/row divider color for a disabled state."), BindColor(config, "Graph Colors - Overlay", "Disabled Title Text Color", new Color(0.75f, 0.75f, 0.75f), "Title text color for a disabled state."), BindColor(config, "Graph Colors - Overlay", "Disabled Event Text Color", Color.black, "Transition row text color for a disabled state."), BindColor(config, "Graph Colors - Overlay", "Disabled Transition Line Color", new Color(0.55f, 0.55f, 0.55f), "Line color for a disabled transition."), BindColor(config, "Graph Colors - Overlay", "Drag Transition Color", new Color(0f, 1f, 0f), "Rubber-band preview line color while dragging a transition endpoint."));
		}

		private static IFsmConfigValue<Color> BindColor(ConfigFile config, string section, string key, Color defaultValue, string description)
		{
			//IL_0003: 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
			return new BepInExConfigValue<Color>(config.Bind<Color>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					IsAdvanced = true
				}
			})));
		}
	}
	internal sealed class FsmGraphPerformanceConfig : IFsmGraphPerformanceConfig
	{
		public IFsmConfigValue<GraphLineStyle> LineStyle { get; }

		public IFsmConfigValue<GraphBoxStyle> BoxStyle { get; }

		public IFsmConfigValue<bool> DiagnosticsEnabled { get; }

		public int Generation { get; private set; }

		private FsmGraphPerformanceConfig(ConfigEntry<GraphLineStyle> lineStyle, ConfigEntry<GraphBoxStyle> boxStyle, ConfigEntry<bool> diagnostics)
		{
			LineStyle = new BepInExConfigValue<GraphLineStyle>(lineStyle);
			BoxStyle = new BepInExConfigValue<GraphBoxStyle>(boxStyle);
			DiagnosticsEnabled = new BepInExConfigValue<bool>(diagnostics);
		}

		public static FsmGraphPerformanceConfig Bind(ConfigFile config)
		{
			ConfigEntry<GraphLineStyle> lineStyle = config.Bind<GraphLineStyle>("Performance", "Line Style", GraphLineStyle.Thin, "How transition lines are drawn. Thick: antialiased curved lines with arrowheads (most detailed, most expensive). Thin: the same curves drawn as hard-edged 1px lines with arrowheads. Straight: a plain straight segment between each transition's endpoints, no arrowhead (cheapest).");
			ConfigEntry<GraphBoxStyle> boxStyle = config.Bind<GraphBoxStyle>("Performance", "Box Style", GraphBoxStyle.Detailed, "How state/event boxes are drawn. Detailed: rounded corners, a border ring on every box, and divider lines between the title and its transition rows. Standard: square corners, no border ring unless the state is active or selected, and no divider lines (cheapest).");
			ConfigEntry<bool> diagnostics = config.Bind<bool>("Performance", "Diagnostics", false, "Logs a periodic per-phase timing breakdown of the graph overlay's rendering (layout, line/box gathering, GL emission, labels) to the console while the overlay is open. For diagnosing why a large FSM's graph is expensive to draw; leave off for normal play.");
			FsmGraphPerformanceConfig instance = new FsmGraphPerformanceConfig(lineStyle, boxStyle, diagnostics);
			config.SettingChanged += delegate
			{
				instance.Generation++;
			};
			return instance;
		}
	}
	internal sealed class FsmPanelLayoutConfig : IFsmPanelLayoutConfig
	{
		private const string Section = "UI Layout";

		private static readonly Vector2 Unset = new Vector2(-1f, -1f);

		private readonly ConfigEntry<Vector2> _position;

		private readonly ConfigEntry<Vector2> _size;

		public IFsmConfigValue<Vector2> Position { get; }

		public IFsmConfigValue<Vector2> Size { get; }

		public bool HasSavedPosition
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				if (_position.Value.x >= 0f)
				{
					return _position.Value.y >= 0f;
				}
				return false;
			}
		}

		public bool HasSavedSize
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				if (_size.Value.x >= 0f)
				{
					return _size.Value.y >= 0f;
				}
				return false;
			}
		}

		private FsmPanelLayoutConfig(ConfigEntry<Vector2> position, ConfigEntry<Vector2> size)
		{
			_position = position;
			_size = size;
			Position = new BepInExConfigValue<Vector2>(position);
			Size = new BepInExConfigValue<Vector2>(size);
		}

		public static FsmPanelLayoutConfig Bind(ConfigFile config, string panelName)
		{
			//IL_0023: 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_004d: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Browsable = false
			};
			ConfigEntry<Vector2> position = config.Bind<Vector2>("UI Layout", panelName + " Position", Unset, new ConfigDescription("Saved screen position of the " + panelName + ", in pixels from the top-left. (-1, -1) means no saved position yet.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			ConfigEntry<Vector2> size = config.Bind<Vector2>("UI Layout", panelName + " Size", Unset, new ConfigDescription("Saved size of the " + panelName + ", in pixels. (-1, -1) means no saved size yet.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			return new FsmPanelLayoutConfig(position, size);
		}
	}
	[BepInDependency("org.silksong-modding.modlist", "0.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("io.github.constructivecynicism.fsmmaster", "FsmMaster", "0.3.6")]
	public class FsmMasterPlugin : BaseUnityPlugin
	{
		private IFsmLog? _log;

		private FsmEditManager? _editManager;

		private IDebugModCompat? _debugModCompat;

		private FsmVariableTracker? _variableTracker;

		private FsmTabManager? _tabManager;

		private FsmGraphOverlay? _graphOverlay;

		private UICommon? _uiCommon;

		private GameObject? _canvasGameObject;

		private bool _ownsEventSystem;

		private FsmRightPanel? _rightPanel;

		private FsmMonitorPanel? _monitorPanel;

		private FsmPanelLayoutConfig? _rightPanelLayout;

		private FsmPanelLayoutConfig? _monitorPanelLayout;

		private ConfigEntry<bool>? _autoLoadConfig;

		private ConfigEntry<KeyboardShortcut>? _toggleOverlayHotkey;

		private ConfigEntry<bool>? _firstRunComplete;

		private ConfigFile? _uiStateConfig;

		private readonly List<CanvasNode> _rightPanelSubtreeBuffer = new List<CanvasNode>();

		private readonly List<CanvasNode> _monitorPanelSubtreeBuffer = new List<CanvasNode>();

		private int _rightPanelSubtreeVersion = -1;

		private int _monitorPanelSubtreeVersion = -1;

		private static Harmony? _harmony;

		private bool _cursorPatchInstalled;

		private static readonly MethodInfo SetCursorVisibleMethod = AccessTools.Method(typeof(InputHandler), "SetCursorVisible", (Type[])null, (Type[])null);

		private static readonly HarmonyMethod ForceCursorVisiblePrefix = new HarmonyMethod(typeof(ForceCursorVisiblePatch), "Prefix", (Type[])null);

		private bool _uiInputUnlocked;

		public const string Id = "io.github.constructivecynicism.fsmmaster";

		internal static FsmEditManager? ActiveEditManagerForPatches { get; private set; }

		internal static FsmMasterPlugin? ActiveInstanceForPatches { get; private set; }

		internal static bool ForceCursorVisible { get; private set; }

		public static bool ShowEditIndicator
		{
			get
			{
				return FsmGraphOverlay.ShowEditIndicator;
			}
			set
			{
				FsmGraphOverlay.ShowEditIndicator = value;
			}
		}

		public static bool FirstRunComplete
		{
			get
			{
				FsmMasterPlugin activeInstanceForPatches = ActiveInstanceForPatches;
				if (activeInstanceForPatches != null)
				{
					ConfigEntry<bool> firstRunComplete = activeInstanceForPatches._firstRunComplete;
					if (firstRunComplete != null)
					{
						return firstRunComplete.Value;
					}
				}
				return false;
			}
			set
			{
				FsmMasterPlugin activeInstanceForPatches = ActiveInstanceForPatches;
				if (activeInstanceForPatches != null)
				{
					ConfigEntry<bool> firstRunComplete = activeInstanceForPatches._firstRunComplete;
					if (firstRunComplete != null)
					{
						firstRunComplete.Value = value;
					}
				}
			}
		}

		internal FsmVariableTracker? VariableTracker => _variableTracker;

		public static string Name => "FsmMaster";

		public static string Version => "0.3.6";

		public static string GetActiveEdits()
		{
			return FsmSaveDataStore.SerializeEditSets(ActiveInstanceForPatches?._editManager?.GetAllActiveEditSets() ?? new List<FsmEditSet>());
		}

		private void PatchCursorOverride()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.Patch((MethodBase)SetCursorVisibleMethod, ForceCursorVisiblePrefix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private void UnpatchCursorOverride()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.Unpatch((MethodBase)SetCursorVisibleMethod, (HarmonyPatchType)1, _harmony.Id);
			}
		}

		private void Awake()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " silk_0.3.6 (io.github.constructivecynicism.fsmmaster) has loaded!"));
			_log = new BepInExLog(((BaseUnityPlugin)this).Logger);
			_harmony = Harmony.CreateAndPatchAll(typeof(FsmActivatedPatch), (string)null);
			_harmony.PatchAll(typeof(GameFileLoadedPatch));
			_harmony.PatchAll(typeof(FocusOnHoverSuppressionPatch));
			_toggleOverlayHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Toggle Overlay", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Shows or hides the FSM graph overlay and its right-side panel.");
			ConfigEntry<KeyboardShortcut> entry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Toggle Minimal View", KeyboardShortcut.Empty, "While the overlay is visible, switches between the full selection UI and a minimal graph-only view. Unbound by default.");
			FsmGraphColorConfig colors = FsmGraphColorConfig.Bind(((BaseUnityPlugin)this).Config);
			FsmGraphPerformanceConfig performance = FsmGraphPerformanceConfig.Bind(((BaseUnityPlugin)this).Config);
			_autoLoadConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Auto Load Last Configuration", false, "When enabled, each FSM's most recently saved/loaded named configuration is automatically reapplied whenever a scene containing that FSM loads. Toggled in-game by the panel's Auto button.");
			Directory.CreateDirectory(FsmSaveDataStore.DataDirectory);
			_uiStateConfig = new ConfigFile(Path.Combine(FsmSaveDataStore.DataDirectory, "io.github.constructivecynicism.fsmmaster.UIState.cfg"), false);
			_rightPanelLayout = FsmPanelLayoutConfig.Bind(_uiStateConfig, "FsmMaster Panel");
			_monitorPanelLayout = FsmPanelLayoutConfig.Bind(_uiStateConfig, "Monitor Panel");
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Browsable = false
			};
			_firstRunComplete = _uiStateConfig.Bind<bool>("General", "First Run Complete", false, new ConfigDescription("Set automatically once the mod has shown its first-run hotkey hint after a save file loads. Not meant to be hand-edited.", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }));
			_editManager = new FsmEditManager(_log);
			ActiveEditManagerForPatches = _editManager;
			ActiveInstanceForPatches = this;
			_debugModCompat = DebugModCompatFactory.TryCreate(_editManager, RescanLiveFsmsForDebugModLoad, ((BaseUnityPlugin)this).Logger);
			_variableTracker = new FsmVariableTracker((string fsmKey) => _editManager.GetLiveInstances(fsmKey));
			_tabManager = new FsmTabManager();
			_graphOverlay = new FsmGraphOverlay(_log, _editManager, _tabManager, new BepInExHotkey(_toggleOverlayHotkey), new BepInExHotkey(entry), colors, performance);
			string safeSceneName = FsmSceneNaming.GetSafeSceneName(delegate
			{
				//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)
				Scene activeScene = SceneManager.GetActiveScene();
				return ((Scene)(ref activeScene)).name;
			}, _log);
			PlayMakerFSM[] components = Object.FindObjectsByType<PlayMakerFSM>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			Dictionary<string, List<PlayMakerFSM>> groupsByFsmKey = ApplyPersistedEditsForScene(safeSceneName, components);
			_graphOverlay.RefreshSnapshot(safeSceneName, components);
			_tabManager.RebindAfterRefresh(groupsByFsmKey);
			BuildRightPanel();
			TryUnlockUiInput();
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void TryUnlockUiInput()
		{
			if (!_uiInputUnlocked)
			{
				GameManager instance = GameManager.instance;
				InputHandler val = ((instance != null) ? instance.inputHandler : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.StartUIInput();
					_uiInputUnlocked = true;
				}
			}
		}

		internal void ShowFirstRunUiIfNeeded()
		{
			//IL_004f: 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)
			ConfigEntry<bool> firstRunComplete = _firstRunComplete;
			if (firstRunComplete != null && !firstRunComplete.Value && _graphOverlay != null && _rightPanel != null && _uiCommon != null && _toggleOverlayHotkey != null)
			{
				_graphOverlay.Show();
				_rightPanel.ShowStatus($"{_toggleOverlayHotkey.Value} to toggle UI", _uiCommon.AccentColor, 12f);
				_firstRunComplete.Value = true;
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			_debugModCompat?.Unhook();
			_debugModCompat = null;
			_editManager?.RevertAllForUnload();
			_editManager = null;
			ActiveEditManagerForPatches = null;
			ActiveInstanceForPatches = null;
			_variableTracker = null;
			_tabManager = null;
			_graphOverlay?.Shutdown();
			_graphOverlay = null;
			ForceCursorVisible = false;
			DestroyRightPanel();
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			_cursorPatchInstalled = false;
			_uiStateConfig = null;
		}

		private void Update()
		{
			_editManager?.PollPendingActivations();
			_debugModCompat?.PollPendingReload();
			if (!_uiInputUnlocked)
			{
				TryUnlockUiInput();
			}
			_graphOverlay?.Update();
			bool flag = _graphOverlay?.IsVisible ?? false;
			if (flag != _cursorPatchInstalled)
			{
				if (flag)
				{
					PatchCursorOverride();
				}
				else
				{
					UnpatchCursorOverride();
				}
				_cursorPatchInstalled = flag;
			}
			ForceCursorVisible = flag;
			if (flag)
			{
				EventSystem current = EventSystem.current;
				BaseInputModule obj = ((current != null) ? current.currentInputModule : null);
				InControlInputModule val = (InControlInputModule)(object)((obj is InControlInputModule) ? obj : null);
				if (val != null)
				{
					val.allowMouseInput = true;
				}
			}
			if (_rightPanel != null)
			{
				bool flag2 = flag && _graphOverlay.SelectionUiVisible;
				_rightPanel.ActiveSelf = flag2;
				if (flag2)
				{
					FsmTabState fsmTabState = _tabManager?.GetActive();
					FsmInfo fsm = ((fsmTabState == null || !fsmTabState.IsLive) ? null : _graphOverlay?.ResolveFsmInfo(fsmTabState.FsmKey));
					_rightPanel.ActiveStatePanel.Refresh(fsm, fsmTabState?.SelectedStateName, fsmTabState?.FsmKey);
					int? num = fsmTabState?.PendingScrollActionIndex;
					if (num.HasValue)
					{
						int valueOrDefault = num.GetValueOrDefault();
						_rightPanel.ActiveStatePanel.ScrollToAction(valueOrDefault);
						fsmTabState.PendingScrollActionIndex = null;
					}
					_rightPanel.ActiveStatePanel.RefreshLiveValues();
					if (_rightPanelSubtreeVersion != CanvasPanel.StructureVersion)
					{
						_rightPanelSubtreeBuffer.Clear();
						_rightPanel.CollectSubtree(_rightPanelSubtreeBuffer);
						_rightPanelSubtreeVersion = CanvasPanel.StructureVersion;
					}
					foreach (CanvasNode item in _rightPanelSubtreeBuffer)
					{
						if (item.ActiveInHierarchy)
						{
							item.Update();
						}
					}
				}
			}
			if (_monitorPanel == null)
			{
				return;
			}
			_monitorPanel.ActiveSelf = flag;
			if (!flag)
			{
				return;
			}
			_monitorPanel.Locked = !_graphOverlay.SelectionUiVisible;
			_monitorPanel.RefreshRows(_variableTracker);
			if (_monitorPanelSubtreeVersion != CanvasPanel.StructureVersion)
			{
				_monitorPanelSubtreeBuffer.Clear();
				_monitorPanel.CollectSubtree(_monitorPanelSubtreeBuffer);
				_monitorPanelSubtreeVersion = CanvasPanel.StructureVersion;
			}
			foreach (CanvasNode item2 in _monitorPanelSubtreeBuffer)
			{
				if (item2.ActiveInHierarchy)
				{
					item2.Update();
				}
			}
		}

		private void OnGUI()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			Rect? rightPanelScreenRect = null;
			FsmRightPanel rightPanel = _rightPanel;
			if (rightPanel != null && rightPanel.ActiveInHierarchy)
			{
				rightPanelScreenRect = new Rect(_rightPanel.Position.x, _rightPanel.Position.y, _rightPanel.Size.x, _rightPanel.Size.y);
			}
			Rect? monitorPanelScreenRect = null;
			FsmMonitorPanel monitorPanel = _monitorPanel;
			if (monitorPanel != null && monitorPanel.ActiveInHierarchy)
			{
				monitorPanelScreenRect = _monitorPanel.ScreenRect;
			}
			Rect? openDropdownScreenRect = _rightPanel?.OpenDropdownScreenRect;
			_graphOverlay?.OnGUI(_tabManager?.GetActive(), rightPanelScreenRect, monitorPanelScreenRect, openDropdownScreenRect);
		}

		private void BuildRightPanel()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Object.FindFirstObjectByType<EventSystem>() == (Object)null)
			{
				GameObject val = new GameObject("FsmMasterEventSystem");
				val.AddComponent<EventSystem>();
				val.AddComponent<StandaloneInputModule>();
				_ownsEventSystem = true;
			}
			_canvasGameObject = new GameObject("FsmMasterCanvas");
			_canvasGameObject.transform.SetParent(((Component)this).transform, false);
			_canvasGameObject.AddComponent<Canvas>().renderMode = (RenderMode)0;
			_canvasGameObject.AddComponent<GraphicRaycaster>();
			_uiCommon = new UICommon();
			_rightPanel = new FsmRightPanel(_uiCommon, _tabManager, _editManager, _variableTracker, () => _graphOverlay?.CurrentSnapshot, _log, _rightPanelLayout, new BepInExConfigValue<bool>(_autoLoadConfig), delegate
			{
				_graphOverlay?.Hide();
			});
			_rightPanel.ActiveSelf = false;
			_rightPanel.Build(_canvasGameObject.transform);
			_monitorPanel = new FsmMonitorPanel(_uiCommon, _variableTracker, _monitorPanelLayout);
			_monitorPanel.ActiveSelf = false;
			_monitorPanel.Build(_canvasGameObject.transform);
		}

		private void DestroyRightPanel()
		{
			_rightPanel?.Destroy();
			_rightPanel = null;
			_monitorPanel?.Destroy();
			_monitorPanel = null;
			if ((Object)(object)_canvasGameObject != (Object)null)
			{
				Object.Destroy((Object)(object)_canvasGameObject);
				_canvasGameObject = null;
			}
			if (_ownsEventSystem)
			{
				EventSystem val = Object.FindFirstObjectByType<EventSystem>();
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				_ownsEventSystem = false;
			}
			_uiCommon?.Destroy();
			_uiCommon = null;
		}

		internal void RescanLiveFsmsForDebugModLoad()
		{
			string safeSceneName = FsmSceneNaming.GetSafeSceneName(delegate
			{
				//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)
				Scene activeScene = SceneManager.GetActiveScene();
				return ((Scene)(ref activeScene)).name;
			}, _log);
			PlayMakerFSM[] components = Object.FindObjectsByType<PlayMakerFSM>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			Dictionary<string, List<PlayMakerFSM>> groupsByFsmKey = ApplyPersistedEditsForScene(safeSceneName, components);
			_graphOverlay?.RefreshSnapshot(safeSceneName, components);
			_tabManager?.RebindAfterRefresh(groupsByFsmKey);
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			string safeSceneName = FsmSceneNaming.GetSafeSceneName(() => ((Scene)(ref scene)).name, _log);
			PlayMakerFSM[] components = Object.FindObjectsByType<PlayMakerFSM>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			Dictionary<string, List<PlayMakerFSM>> groupsByFsmKey = ApplyPersistedEditsForScene(safeSceneName, components);
			_graphOverlay?.RefreshSnapshot(FsmSceneNaming.GetSafeSceneName(delegate
			{
				//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)
				Scene activeScene = SceneManager.GetActiveScene();
				return ((Scene)(ref activeScene)).name;
			}, _log), components);
			_tabManager?.RebindAfterRefresh(groupsByFsmKey);
		}

		private Dictionary<string, List<PlayMakerFSM>> ApplyPersistedEditsForScene(string sceneName, PlayMakerFSM[] components)
		{
			if (_editManager == null || _tabManager == null)
			{
				return new Dictionary<string, List<PlayMakerFSM>>();
			}
			Dictionary<string, List<PlayMakerFSM>> dictionary = FsmIdentity.DiscoverFsmGroups(components);
			_editManager.ReplaceLiveInstances(dictionary.ToDictionary((KeyValuePair<string, List<PlayMakerFSM>> g) => g.Key, (KeyValuePair<string, List<PlayMakerFSM>> g) => g.Value.Select((PlayMakerFSM c) => c.Fsm).ToList()));
			ConfigEntry<bool> autoLoadConfig = _autoLoadConfig;
			if (autoLoadConfig == null || !autoLoadConfig.Value)
			{
				return dictionary;
			}
			IEnumerable<string> fsmKeysPresent = _tabManager.Tabs.Select((FsmTabState tab) => tab.FsmKey).Where(dictionary.ContainsKey);
			foreach (FsmEditSet item in FsmSaveDataStore.LoadLastChosenForScene(sceneName, fsmKeysPresent))
			{
				_editManager.ApplyEditSet(item);
			}
			return dictionary;
		}

		public void ResetFsm(string sceneName, string fsmKey)
		{
			_editManager?.ResetFsm(fsmKey);
			FsmSaveDataStore.ClearAllSavesForFsm(sceneName, fsmKey);
		}
	}
	[HarmonyPatch(typeof(Fsm), "Preprocess", new Type[] { })]
	internal static class FsmActivatedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Fsm __instance)
		{
			FsmEditManager activeEditManagerForPatches = FsmMasterPlugin.ActiveEditManagerForPatches;
			if (activeEditManagerForPatches == null)
			{
				return;
			}
			PlayMakerFSM fsmComponent = __instance.FsmComponent;
			if (!((Object)(object)fsmComponent == (Object)null))
			{
				string fsmKey = FsmIdentity.GetFsmKey(fsmComponent);
				activeEditManagerForPatches.ReconcileLiveInstance(fsmKey, __instance);
				FsmEditSet activeEditSet = activeEditManagerForPatches.GetActiveEditSet(fsmKey);
				if (activeEditSet != null)
				{
					activeEditManagerForPatches.ApplyEditSet(activeEditSet);
				}
			}
		}
	}
	[HarmonyPatch(typeof(GameManager), "SetLoadedGameData", new Type[]
	{
		typeof(SaveGameData),
		typeof(int)
	})]
	internal static class GameFileLoadedPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			FsmMasterPlugin.ActiveInstanceForPatches?.ShowFirstRunUiIfNeeded();
		}
	}
	internal static class ForceCursorVisiblePatch
	{
		internal static void Prefix(ref bool value)
		{
			if (FsmMasterPlugin.ForceCursorVisible)
			{
				value = true;
			}
		}
	}
	internal static class BuildInfo
	{
		public const string Prefix = "silk";

		public const string Version = "0.3.6";

		public const string ReleaseName = "silk_0.3.6";
	}
	internal interface IFsmConfigValue<T>
	{
		T Value { get; set; }
	}
	internal interface IFsmGraphColorConfig
	{
		IFsmConfigValue<Color>[] StateColors { get; }

		IFsmConfigValue<Color>[] TransitionColors { get; }

		IFsmConfigValue<Color> GlobalTransitionColor { get; }

		IFsmConfigValue<Color> VignetteColor { get; }

		IFsmConfigValue<Color> GlobalPseudoNodeColor { get; }

		IFsmConfigValue<Color> GlobalPseudoNodeOutlineColor { get; }

		IFsmConfigValue<Color> GlobalPseudoNodeTextColor { get; }

		IFsmConfigValue<Color> NodeOutlineColor { get; }

		IFsmConfigValue<Color> TransitionRowBackgroundColor { get; }

		IFsmConfigValue<Color> ActiveStateColor { get; }

		IFsmConfigValue<Color> ActiveTitleBackgroundColor { get; }

		IFsmConfigValue<Color> ActiveTitleTextColor { get; }

		IFsmConfigValue<Color> SelectedStateColor { get; }

		IFsmConfigValue<Color> DisabledOutlineColor { get; }

		IFsmConfigValue<Color> DisabledTitleTextColor { get; }

		IFsmConfigValue<Color> DisabledEventTextColor { get; }

		IFsmConfigValue<Color> DisabledTransitionLineColor { get; }

		IFsmConfigValue<Color> DragTransitionColor { get; }
	}
	internal enum GraphLineStyle
	{
		Thick,
		Thin,
		Straight
	}
	internal enum GraphBoxStyle
	{
		Detailed,
		Standard
	}
	internal interface IFsmGraphPerformanceConfig
	{
		IFsmConfigValue<GraphLineStyle> LineStyle { get; }

		IFsmConfigValue<GraphBoxStyle> BoxStyle { get; }

		IFsmConfigValue<bool> DiagnosticsEnabled { get; }

		int Generation { get; }
	}
	internal interface IFsmHotkey
	{
		bool IsDown();
	}
	internal interface IFsmLog
	{
		void LogInfo(string message);

		void LogWarning(string message);

		void LogError(string message);
	}
	internal interface IFsmPanelLayoutConfig
	{
		IFsmConfigValue<Vector2> Position { get; }

		IFsmConfigValue<Vector2> Size { get; }

		bool HasSavedPosition { get; }

		bool HasSavedSize { get; }
	}
	internal interface IModHost
	{
		IFsmLog Log { get; }

		string StoragePath { get; }

		string Version { get; }
	}
	internal sealed class FsmActiveStateTracker
	{
		private sealed class TrackedFsm
		{
			public Fsm Instance;

			public Action<FsmState> Handler;

			public readonly HashSet<string> EnteredSinceCommit = new HashSet<string>();

			public readonly Dictionary<string, float> FadingStates = new Dictionary<string, float>();
		}

		private const float FadeDurationSeconds = 1f;

		private readonly Dictionary<string, TrackedFsm> _tracked = new Dictionary<string, TrackedFsm>();

		private readonly HashSet<string> _visibleThisFrame = new HashSet<string>();

		public void EnsureTracked(string fsmKey, Fsm instance)
		{
			_visibleThisFrame.Add(fsmKey);
			if (_tracked.TryGetValue(fsmKey, out TrackedFsm value))
			{
				if (value.Instance == instance)
				{
					return;
				}
				Fsm instance2 = value.Instance;
				instance2.StateChanged = (Action<FsmState>)Delegate.Remove(instance2.StateChanged, value.Handler);
				_tracked.Remove(fsmKey);
			}
			TrackedFsm entry = new TrackedFsm
			{
				Instance = instance
			};
			entry.Handler = delegate(FsmState state)
			{
				entry.EnteredSinceCommit.Add(state.Name);
			};
			instance.StateChanged = (Action<FsmState>)Delegate.Combine(instance.StateChanged, entry.Handler);
			_tracked[fsmKey] = entry;
		}

		public void CommitFrame()
		{
			List<string> list = null;
			foreach (KeyValuePair<string, TrackedFsm> item in _tracked)
			{
				string key = item.Key;
				TrackedFsm value = item.Value;
				if ((Object)(object)value.Instance.FsmComponent == (Object)null || !_visibleThisFrame.Contains(key))
				{
					Fsm instance = value.Instance;
					instance.StateChanged = (Action<FsmState>)Delegate.Remove(instance.StateChanged, value.Handler);
					(list ?? (list = new List<string>())).Add(key);
					continue;
				}
				string activeStateName = value.Instance.ActiveStateName;
				foreach (string item2 in value.EnteredSinceCommit)
				{
					if (item2 == activeStateName)
					{
						value.FadingStates.Remove(item2);
					}
					else
					{
						value.FadingStates[item2] = Time.unscaledTime;
					}
				}
				value.EnteredSinceCommit.Clear();
				if (value.FadingStates.Count <= 0)
				{
					continue;
				}
				List<string> list2 = null;
				foreach (KeyValuePair<string, float> fadingState in value.FadingStates)
				{
					if (Time.unscaledTime - fadingState.Value >= 1f)
					{
						(list2 ?? (list2 = new List<string>())).Add(fadingState.Key);
					}
				}
				if (list2 == null)
				{
					continue;
				}
				foreach (string item3 in list2)
				{
					value.FadingStates.Remove(item3);
				}
			}
			if (list != null)
			{
				foreach (string item4 in list)
				{
					_tracked.Remove(item4);
				}
			}
			_visibleThisFrame.Clear();
		}

		public float? GetFadeProgress(string fsmKey, string stateName)
		{
			if (!_tracked.TryGetValue(fsmKey, out TrackedFsm value) || !value.FadingStates.TryGetValue(stateName, out var value2))
			{
				return null;
			}
			return Mathf.Clamp01((Time.unscaledTime - value2) / 1f);
		}

		public bool HasAnyFading(string fsmKey)
		{
			if (_tracked.TryGetValue(fsmKey, out TrackedFsm value))
			{
				return value.FadingStates.Count > 0;
			}
			return false;
		}

		public void UnsubscribeAll()
		{
			foreach (TrackedFsm value in _tracked.Values)
			{
				Fsm instance = value.Instance;
				instance.StateChanged = (Action<FsmState>)Delegate.Remove(instance.StateChanged, value.Handler);
			}
			_tracked.Clear();
			_visibleThisFrame.Clear();
		}
	}
	internal sealed class FsmConsoleLogger
	{
		private readonly IFsmLog _logger;

		public FsmConsoleLogger(IFsmLog logger)
		{
			_logger = logger;
		}

		public void LogSnapshot(FsmSnapshot snapshot)
		{
			_logger.LogInfo($"[FsmMaster] Scene \"{snapshot.SceneName}\": {snapshot.Fsms.Count} live PlayMakerFSM instance(s)");
			foreach (FsmIdentityInfo fsm in snapshot.Fsms)
			{
				if (!((Object)(object)fsm.Component == (Object)null))
				{
					LogFsm(FsmDataCollector.CollectFsmInfo(fsm.Component));
				}
			}
		}

		public void LogFsm(FsmInfo fsm)
		{
			_logger.LogInfo("[FsmMaster]   FSM \"" + fsm.FsmName + "\" on \"" + fsm.GameObjectName + "\" - state \"" + fsm.ActiveStateName + "\"");
			LogFsmDetails(fsm);
		}

		private void LogFsmDetails(FsmInfo fsm)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			_logger.LogInfo($"[FsmMaster]     {fsm.States.Count} state(s)");
			foreach (FsmStateInfo state in fsm.States)
			{
				_logger.LogInfo("[FsmMaster]       State \"" + state.Name + "\"");
				Rect position = state.State.Position;
				_logger.LogInfo(string.Format(CultureInfo.InvariantCulture, "[FsmMaster]         Position=({0:F1}, {1:F1}, {2:F1}, {3:F1}) ColorIndex={4}", ((Rect)(ref position)).x, ((Rect)(ref position)).y, ((Rect)(ref position)).width, ((Rect)(ref position)).height, state.State.ColorIndex));
				LogActions(state.Actions);
				foreach (FsmTransitionInfo transition in state.Transitions)
				{
					_logger.LogInfo("[FsmMaster]         \"" + transition.EventName + "\" -> \"" + transition.ToState + "\"");
				}
			}
			if (fsm.GlobalTransitions.Count > 0)
			{
				_logger.LogInfo($"[FsmMaster]     {fsm.GlobalTransitions.Count} global transition(s)");
				foreach (FsmTransitionInfo globalTransition in fsm.GlobalTransitions)
				{
					_logger.LogInfo("[FsmMaster]       \"" + globalTransition.EventName + "\" -> \"" + globalTransition.ToState + "\"");
				}
			}
			LogFsmVariables(fsm.Fsm.Variables);
		}

		private void LogActions(List<FsmActionInfo> actions)
		{
			_logger.LogInfo($"[FsmMaster]         {actions.Count} action(s)");
			for (int i = 0; i < actions.Count; i++)
			{
				FsmActionInfo fsmActionInfo = actions[i];
				_logger.LogInfo($"[FsmMaster]           [{i}] {fsmActionInfo.ActionType.Name}");
				foreach (FsmActionFieldInfo field in fsmActionInfo.Fields)
				{
					LogActionField(fsmActionInfo.Action, field.FieldName, field.FieldValue);
				}
			}
		}

		private void LogActionField(FsmStateAction action, string fieldName, object? fieldValue)
		{
			FsmArray val = (FsmArray)((fieldValue is FsmArray) ? fieldValue : null);
			if (val == null)
			{
				Array array = fieldValue as Array;
				if (array != null)
				{
					LogActionFieldArray(action, fieldName, array.Length, (int i) => array.GetValue(i));
				}
				else
				{
					_logger.LogInfo("[FsmMaster]             " + fieldName + ": " + FormatActionFieldValue(action, fieldValue));
				}
			}
			else
			{
				LogActionFieldArray(action, WithVariableName(fieldName, ((NamedVariable)val).Name), val.Length, (int i) => val.Values[i]);
			}
		}

		private static string WithVariableName(string fieldName, string variableName)
		{
			if (string.IsNullOrEmpty(variableName))
			{
				return fieldName;
			}
			return fieldName + " (\"" + variableName + "\")";
		}

		private void LogActionFieldArray(FsmStateAction action, string fieldName, int length, Func<int, object?> getElement)
		{
			_logger.LogInfo($"[FsmMaster]             {fieldName}: {length} element(s)");
			for (int i = 0; i < length; i++)
			{
				object fieldValue = getElement(i);
				_logger.LogInfo($"[FsmMaster]               [{i}]: {FormatActionFieldValue(action, fieldValue)}");
			}
		}

		internal static string FormatActionFieldValue(FsmStateAction action, object? fieldValue)
		{
			if (fieldValue != null)
			{
				NamedVariable val = (NamedVariable)((fieldValue is NamedVariable) ? fieldValue : null);
				if (val == null)
				{
					FsmEvent val2 = (FsmEvent)((fieldValue is FsmEvent) ? fieldValue : null);
					if (val2 == null)
					{
						FsmOwnerDefault val3 = (FsmOwnerDefault)((fieldValue is FsmOwnerDefault) ? fieldValue : null);
						if (val3 == null)
						{
							FsmEventTarget val4 = (FsmEventTarget)((fieldValue is FsmEventTarget) ? fieldValue : null);
							if (val4 != null)
							{
								return FormatEventTarget(action.Fsm, val4);
							}
							return fieldValue.ToString();
						}
						return FormatOwnerDefault(action.Fsm, val3);
					}
					return val2.Name;
				}
				string text = val.RawValue?.ToString() ?? "null";
				if (string.IsNullOrEmpty(val.Name))
				{
					return text;
				}
				return "\"" + val.Name + "\": " + text;
			}
			return "null";
		}

		internal static string FormatOwnerDefault(Fsm? fsm, FsmOwnerDefault ownerDefault)
		{
			if (fsm == null)
			{
				return "[uninitialized]";
			}
			GameObject ownerDefaultTarget = fsm.GetOwnerDefaultTarget(ownerDefault);
			if (!((Object)(object)ownerDefaultTarget != (Object)null))
			{
				return "[none]";
			}
			return "[" + ((Object)ownerDefaultTarget).name + "]";
		}

		internal static string FormatEventTarget(Fsm? fsm, FsmEventTarget eventTarget)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			EventTarget target = eventTarget.target;
			switch ((int)target)
			{
			case 0:
				return "EventTarget(Self)";
			case 1:
				return "EventTarget(GameObject): " + FormatOwnerDefault(fsm, eventTarget.gameObject);
			case 2:
			{
				string text2 = eventTarget.fsmName.Value ?? "";
				return "EventTarget(GameObjectFSM): " + FormatOwnerDefault(fsm, eventTarget.gameObject) + "." + text2;
			}
			case 3:
			{
				PlayMakerFSM fsmComponent = eventTarget.fsmComponent;
				string text = (((Object)(object)fsmComponent != (Object)null) ? (((Object)((Component)fsmComponent).gameObject).name + "." + fsmComponent.FsmName) : "none");
				return "EventTarget(FSMComponent): [" + text + "]";
			}
			default:
				return $"EventTarget({eventTarget.target})";
			}
		}

		private void LogFsmVariables(FsmVariables variables)
		{
			_logger.LogInfo("[FsmMaster]     Variables");
			LogVariableArray<FsmFloat>("Float", variables.FloatVariables, (Func<FsmFloat, object>)((FsmFloat v) => v.Value));
			LogVariableArray<FsmInt>("Int", variables.IntVariables, (Func<FsmInt, object>)((FsmInt v) => v.Value));
			LogVariableArray<FsmBool>("Bool", variables.BoolVariables, (Func<FsmBool, object>)((FsmBool v) => v.Value));
			LogVariableArray<FsmString>("String", variables.StringVariables, (Func<FsmString, object>)((FsmString v) => v.Value));
			LogVariableArray<FsmVector2>("Vector2", variables.Vector2Variables, (Func<FsmVector2, object>)((FsmVector2 v) => v.Value));
			LogVariableArray<FsmVector3>("Vector3", variables.Vector3Variables, (Func<FsmVector3, object>)((FsmVector3 v) => v.Value));
			LogVariableArray<FsmRect>("Rect", variables.RectVariables, (Func<FsmRect, object>)((FsmRect v) => v.Value));
			LogVariableArray<FsmQuaternion>("Quaternion", variables.QuaternionVariables, (Func<FsmQuaternion, object>)((FsmQuaternion v) => v.Value));
			LogVariableArray<FsmColor>("Color", variables.ColorVariables, (Func<FsmColor, object>)((FsmColor v) => v.Value));
			LogVariableArray<FsmGameObject>("GameObject", variables.GameObjectVariables, (Func<FsmGameObject, object>)((FsmGameObject v) => v.Value));
			LogVariableArray<FsmObject>("Object", variables.ObjectVariables, (Func<FsmObject, object>)((FsmObject v) => v.Value));
			LogVariableArray<FsmMaterial>("Material", variables.MaterialVariables, (Func<FsmMaterial, object>)((FsmMaterial v) => v.Value));
			LogVariableArray<FsmTexture>("Texture", variables.TextureVariables, (Func<FsmTexture, object>)((FsmTexture v) => v.Value));
			LogVariableArray<FsmEnum>("Enum", variables.EnumVariables, (Func<FsmEnum, object>)((FsmEnum v) => v.Value));
			LogVariableArray<FsmArray>("Array", variables.ArrayVariables, (Func<FsmArray, object>)((FsmArray v) => string.Join(", ", Array.ConvertAll(v.Values, (object x) => x?.ToString() ?? string.Empty))));
		}

		private void LogVariableArray<T>(string typeName, T[] items, Func<T, object> getValue) where T : NamedVariable
		{
			if (items.Length != 0)
			{
				foreach (T val in items)
				{
					_logger.LogInfo($"[FsmMaster]       {typeName} \"{((NamedVariable)val).Name}\": {getValue(val)}");
				}
			}
		}
	}
	internal sealed class FsmSnapshot
	{
		public string SceneName { get; set; } = "";

		public List<FsmIdentityInfo> Fsms { get; set; } = new List<FsmIdentityInfo>();
	}
	internal sealed class FsmIdentityInfo
	{
		public PlayMakerFSM Component { get; set; }

		public string FsmName { get; set; } = "";

		public string GameObjectName { get; set; } = "";
	}
	internal sealed class FsmInfo
	{
		public PlayMakerFSM Component { get; set; }

		public Fsm Fsm { get; set; }

		public string FsmName { get; set; } = "";

		public string GameObjectName { get; set; } = "";

		public string ActiveStateName { get; set; } = "";

		public List<FsmStateInfo> States { get; set; } = new List<FsmStateInfo>();

		public List<FsmTransitionInfo> GlobalTransitions { get; set; } = new List<FsmTransitionInfo>();
	}
	internal sealed class FsmStateInfo
	{
		public FsmState State { get; set; }

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

		public List<FsmActionInfo> Actions { get; set; } = new List<FsmActionInfo>();

		public List<FsmTransitionInfo> Transitions { get; set; } = new List<FsmTransitionInfo>();
	}
	internal sealed class FsmActionInfo
	{
		public FsmStateAction Action { get; set; }

		public Type ActionType { get; set; }

		public List<FsmActionFieldInfo> Fields { get; set; } = new List<FsmActionFieldInfo>();
	}
	internal sealed class FsmActionFieldInfo
	{
		public string FieldName { get; set; } = "";

		public object? FieldValue { get; set; }

		public FieldInfo Field { get; set; }

		public bool IsHidden { get; set; }
	}
	internal sealed class FsmTransitionInfo
	{
		public string EventName { get; set; } = "";

		public string ToState { get; set; } = "";
	}
	internal static class FsmDataCollector
	{
		private static readonly Dictionary<Type, FieldInfo[]> RelevantFieldsByActionType = new Dictionary<Type, FieldInfo[]>();

		public static FsmSnapshot CollectSnapshot(string sceneName, PlayMakerFSM[] components)
		{
			List<FsmIdentityInfo> list = new List<FsmIdentityInfo>(components.Length);
			foreach (PlayMakerFSM val in components)
			{
				list.Add(new FsmIdentityInfo
				{
					Component = val,
					FsmName = val.FsmName,
					GameObjectName = ((Object)((Component)val).gameObject).name
				});
			}
			return new FsmSnapshot
			{
				SceneName = sceneName,
				Fsms = list
			};
		}

		public static FsmInfo CollectFsmInfo(PlayMakerFSM component)
		{
			Fsm fsm = component.Fsm;
			List<FsmStateInfo> list = new List<FsmStateInfo>(fsm.States.Length);
			FsmState[] states = fsm.States;
			foreach (FsmState state in states)
			{
				list.Add(CollectStateInfo(state));
			}
			return new FsmInfo
			{
				Component = component,
				Fsm = fsm,
				FsmName = component.FsmName,
				GameObjectName = ((Object)((Component)component).gameObject).name,
				ActiveStateName = component.ActiveStateName,
				States = list,
				GlobalTransitions = CollectTransitions(fsm.GlobalTransitions)
			};
		}

		private static FsmStateInfo CollectStateInfo(FsmState state)
		{
			return new FsmStateInfo
			{
				State = state,
				Name = state.Name,
				Actions = CollectActions(state.Actions),
				Transitions = CollectTransitions(state.Transitions)
			};
		}

		private static FieldInfo[] GetRelevantFields(Type actionType)
		{
			if (RelevantFieldsByActionType.TryGetValue(actionType, out FieldInfo[] value))
			{
				return value;
			}
			List<FieldInfo> list = new List<FieldInfo>();
			FieldInfo[] fields = actionType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!(fieldInfo.DeclaringType == typeof(FsmStateAction)) && !fieldInfo.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false))
				{
					list.Add(fieldInfo);
				}
			}
			FieldInfo[] array = list.ToArray();
			RelevantFieldsByActionType[actionType] = array;
			return array;
		}

		private static List<FsmActionInfo> CollectActions(FsmStateAction[] actions)
		{
			List<FsmActionInfo> list = new List<FsmActionInfo>(actions.Length);
			foreach (FsmStateAction val in actions)
			{
				Type type = ((object)val).GetType();
				FieldInfo[] relevantFields = GetRelevantFields(type);
				List<FsmActionFieldInfo> list2 = new List<FsmActionFieldInfo>(relevantFields.Length);
				FieldInfo[] array = relevantFields;
				foreach (FieldInfo fieldInfo in array)
				{
					list2.Add(new FsmActionFieldInfo
					{
						FieldName = fieldInfo.Name,
						FieldValue = fieldInfo.GetValue(val),
						Field = fieldInfo,
						IsHidden = !fieldInfo.IsPublic
					});
				}
				list.Add(new FsmActionInfo
				{
					Action = val,
					ActionType = type,
					Fields = list2
				});
			}
			return list;
		}

		private static List<FsmTransitionInfo> CollectTransitions(FsmTransition[] transitions)
		{
			List<FsmTransitionInfo> list = new List<FsmTransitionInfo>(transitions.Length);
			foreach (FsmTransition val in transitions)
			{
				list.Add(new FsmTransitionInfo
				{
					EventName = val.EventName,
					ToState = val.ToState
				});
			}
			return list;
		}
	}
	internal static class FsmIdentity
	{
		private static readonly Regex DuplicateSuffixPattern = new Regex("^(?<base>.+) \\(\\d+\\)$", RegexOptions.Compiled);

		public static string GetObjectBaseName(string gameObjectName)
		{
			Match match = DuplicateSuffixPattern.Match(gameObjectName);
			if (!match.Success)
			{
				return gameObjectName;
			}
			return match.Groups["base"].Value;
		}

		public static string GetFsmKey(string baseObjectName, string fsmName)
		{
			return baseObjectName + "::" + fsmName;
		}

		public static string GetFsmKey(PlayMakerFSM component)
		{
			return GetFsmKey(GetObjectBaseName(((Object)((Component)component).gameObject).name), component.FsmName);
		}

		public static Dictionary<string, List<PlayMakerFSM>> DiscoverFsmGroups(IEnumerable<PlayMakerFSM> components)
		{
			Dictionary<string, List<PlayMakerFSM>> dictionary = new Dictionary<string, List<PlayMakerFSM>>();
			foreach (PlayMakerFSM component in components)
			{
				string fsmKey = GetFsmKey(component);
				if (!dictionary.TryGetValue(fsmKey, out var value))
				{
					value = (dictionary[fsmKey] = new List<PlayMakerFSM>());
				}
				value.Add(component);
			}
			return dictionary;
		}
	}
	internal sealed class FsmPristineSnapshot
	{
		public FsmEditSet OriginalValues { get; } = new FsmEditSet();

		public Dictionary<string, List<int>> NeuteredActionIndices { get; } = new Dictionary<string, List<int>>();

		public List<FsmStateAction> InjectedExitActions { get; } = new List<FsmStateAction>();

		public List<(FsmStateAction Original, FsmStateAction Sequencer)> InstalledSequencers { get; } = new List<(FsmStateAction, FsmStateAction)>();
	}
	internal static class FsmSceneNaming
	{
		internal const string UnknownSceneName = "unknown";

		public static string GetSafeSceneName(Func<string?> getName, IFsmLog? logger = null)
		{
			try
			{
				return getName() ?? string.Empty;
			}
			catch (Exception ex)
			{
				logger?.LogWarning("[FsmMaster] Failed to read scene name for a save/load path; using 'unknown': " + ex.Message);
				return "unknown";
			}
		}
	}
	internal static class FsmSaveDataStore
	{
		[Serializable]
		private sealed class FsmEditSetListWire
		{
			public List<string> EditSets = new List<string>();
		}

		[Serializable]
		private sealed class FsmEditSetWire
		{
			public string FsmKey = "";

			public List<string> VariableOverrides = new List<string>();

			public List<string> ActionFieldOverrides = new List<string>();

			public List<string> DisabledStates = new List<string>();

			public List<string> TransitionRetargets = new List<string>();

			public List<string> SequencerOverrides = new List<string>();
		}

		internal static readonly string DataDirectory = Path.Combine(Application.persistentDataPath, "FsmMasterData");

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

		private const string PairSeparator = "; ";

		private const string KeyValueSeparator = "=";

		private const string PatternSeparator = ", ";

		private static string SanitizeForFileName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char oldChar in invalidFileNameChars)
			{
				value = value.Replace(oldChar, '_');
			}
			return value;
		}

		private static string GetSceneDirectory(string sceneName)
		{
			return Path.Combine(DataDirectory, SanitizeForFileName(sceneName));
		}

		private static string GetFsmDirectory(string sceneName, string fsmKey)
		{
			return Path.Combine(GetSceneDirectory(sceneName), SanitizeForFileName(fsmKey));
		}

		public static string GetFilePath(string sceneName, string fsmKey, string saveName)
		{
			return Path.Combine(GetFsmDirectory(sceneName, fsmKey), SanitizeForFileName(saveName) + ".json");
		}

		public static FsmEditSet? Load(string sceneName, string fsmKey, string saveName)
		{
			string filePath = GetFilePath(sceneName, fsmKey, saveName);
			if (!File.Exists(filePath))
			{
				return null;
			}
			return FromWire(JsonUtility.FromJson<FsmEditSetWire>(File.ReadAllText(filePath)));
		}

		public static List<string> ListSaveNames(string sceneName, string fsmKey)
		{
			List<string> list = new List<string>();
			string fsmDirectory = GetFsmDirectory(sceneName, fsmKey);
			if (!Directory.Exists(fsmDirectory))
			{
				return list;
			}
			string[] files = Directory.GetFiles(fsmDirectory, "*.json");
			foreach (string path in files)
			{
				list.Add(Path.GetFileNameWithoutExtension(path));
			}
			list.Sort(StringComparer.OrdinalIgnoreCase);
			return list;
		}

		public static string Save(string sceneName, string saveName, FsmEditSet edits)
		{
			string fsmDirectory = GetFsmDirectory(sceneName, edits.FsmKey);
			if (!Directory.Exists(fsmDirectory))
			{
				Directory.CreateDirectory(fsmDirectory);
			}
			string text = JsonUtility.ToJson((object)ToWire(edits), true);
			File.WriteAllText(GetFilePath(sceneName, edits.FsmKey, saveName), text);
			return text;
		}

		public static void ClearAllSavesForFsm(string sceneName, string fsmKey)
		{
			string fsmDirectory = GetFsmDirectory(sceneName, fsmKey);
			if (Directory.Exists(fsmDirectory))
			{
				Directory.Delete(fsmDirectory, recursive: true);
			}
			if (LastChosenByScene.TryGetValue(sceneName, out Dictionary<string, string> value))
			{
				value.Remove(fsmKey);
			}
		}

		public static List<FsmEditSet> LoadLastChosenForScene(string sceneName, IEnumerable<string> fsmKeysPresent)
		{
			List<FsmEditSet> list = new List<FsmEditSet>();
			List<string> list2 = ((fsmKeysPresent is List<string> list3) ? list3 : fsmKeysPresent.ToList());
			if (list2.Count == 0 || !LastChosenByScene.TryGetValue(sceneName, out Dictionary<string, string> value))
			{
				return list;
			}
			foreach (string item in list2)
			{
				if (value.TryGetValue(item, out var value2))
				{
					FsmEditSet fsmEditSet = Load(sceneName, item, value2);
					if (fsmEditSet != null)
					{
						list.Add(fsmEditSet);
					}
				}
			}
			return list;
		}

		public static string? GetLastChosenSaveName(string sceneName, string fsmKey)
		{
			if (!LastChosenByScene.TryGetValue(sceneName, out Dictionary<string, string> value) || !value.TryGetValue(fsmKey, out var value2))
			{
				return null;
			}
			return value2;
		}

		public static void SetLastChosenSaveName(string sceneName, string fsmKey, string saveName)
		{
			if (!LastChosenByScene.TryGetValue(sceneName, out Dictionary<string, string> value))
			{
				value = new Dictionary<string, string>();
				LastChosenByScene[sceneName] = value;
			}
			value[fsmKey] = saveName;
		}

		public static string SerializeEditSets(IEnumerable<FsmEditSet> editSets)
		{
			FsmEditSetListWire fsmEditSetListWire = new FsmEditSetListWire();
			foreach (FsmEditSet editSet in editSets)
			{
				fsmEditSetListWire.EditSets.Add(JsonUtility.ToJson((object)ToWire(editSet)));
			}
			return JsonUtility.ToJson((object)fsmEditSetListWire);
		}

		public static List<FsmEditSet> DeserializeEditSets(string json)
		{
			List<FsmEditSet> list = new List<FsmEditSet>();
			FsmEditSetListWire fsmEditSetListWire = JsonUtility.FromJson<FsmEditSetListWire>(json);
			if (fsmEditSetListWire == null)
			{
				return list;
			}
			foreach (string editSet in fsmEditSetListWire.EditSets)
			{
				list.Add(FromWire(JsonUtility.FromJson<FsmEditSetWire>(editSet)));
			}
			return list;
		}

		private static string JoinPairs(params string[] keysAndValues)
		{
			List<string> list = new List<string>(keysAndValues.Length / 2);
			for (int i = 0; i + 1 < keysAndValues.Length; i += 2)
			{
				list.Add(keysAndValues[i] + "=" + keysAndValues[i + 1]);
			}
			return string.Join("; ", list.ToArray());
		}

		private static Dictionary<string, string> SplitPairs(string joined)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string[] array = joined.Split(new string[1] { "; " }, StringSplitOptions.None);
			foreach (string text in array)
			{
				int num = text.IndexOf("=", StringComparison.Ordinal);
				if (num >= 0)
				{
					dictionary[text.Substring(0, num)] = text.Substring(num + 1);
				}
			}
			return dictionary;
		}

		private static FsmEditSetWire ToWire(FsmEditSet edits)
		{
			FsmEditSetWire fsmEditSetWire = new FsmEditSetWire
			{
				FsmKey = edits.FsmKey
			};
			foreach (VariableOverride variableOverride in edits.VariableOverrides)
			{
				fsmEditSetWire.VariableOverrides.Add(JoinPairs("type", variableOverride.VariableType, "name", variableOverride.Name, "array", variableOverride.ArrayIndex.ToString(CultureInfo.InvariantCulture), "value", variableOverride.StringValue));
			}
			foreach (ActionFieldOverride actionFieldOverride in edits.ActionFieldOverrides)
			{
				fsmEditSetWire.ActionFieldOverrides.Add(JoinPairs("state", actionFieldOverride.StateName, "action", actionFieldOverride.ActionIndex.ToString(CultureInfo.InvariantCulture), "type", actionFieldOverride.ExpectedActionTypeName, "field", actionFieldOverride.FieldName, "array", actionFieldOverride.ArrayIndex.ToString(CultureInfo.InvariantCulture), "value", actionFieldOverride.StringValue));
			}
			fsmEditSetWire.DisabledStates.AddRange(edits.DisabledStates);
			foreach (TransitionRetarget transitionRetarget in edits.TransitionRetargets)
			{
				fsmEditSetWire.TransitionRetargets.Add(JoinPairs("state", transitionRetarget.StateName, "event", transitionRetarget.EventName, "newState", transitionRetarget.NewStateName, "newTo", transitionRetarget.NewToState, "newEvent", transitionRetarget.NewEventName));
			}
			foreach (SequencerOverride sequencerOverride in edits.SequencerOverrides)
			{
				fsmEditSetWire.SequencerOverrides.Add(JoinPairs("state", sequencerOverride.StateName, "action", sequencerOverride.ActionIndex.ToString(CultureInfo.InvariantCulture), "repeat", sequencerOverride.RepeatCount.ToString(CultureInfo.InvariantCulture), "pattern", string.Join(", ", sequencerOverride.Pattern.ToArray())));
			}
			return fsmEditSetWire;
		}

		private static FsmEditSet FromWire(FsmEditSetWire? wire)
		{
			FsmEditSet fsmEditSet = new FsmEditSet();
			if (wire == null)
			{
				return fsmEditSet;
			}
			fsmEditSet.FsmKey = wire.FsmKey;
			foreach (string variableOverride in wire.VariableOverrides)
			{
				Dictionary<string, string> dictionary = SplitPairs(variableOverride);
				fsmEditSet.VariableOverrides.Add(new VariableOverride
				{
					VariableType = dictionary["type"],
					Name = dictionary["name"],
					ArrayIndex = (dictionary.TryGetValue("array", out var value) ? int.Parse(value, CultureInfo.InvariantCulture) : (-1)),
					StringValue = dictionary["value"]
				});
			}
			foreach (string actionFieldOverride in wire.ActionFieldOverrides)
			{
				Dictionary<string, string> dictionary2 = SplitPairs(actionFieldOverride);
				fsmEditSet.ActionFieldOverrides.Add(new ActionFieldOverride
				{
					StateName = dictionary2["state"],
					ActionIndex = int.Parse(dictionary2["action"], CultureInfo.InvariantCulture),
					ExpectedActionTypeName = dictionary2["type"],
					FieldName = dictionary2["field"],
					ArrayIndex = (dictionary2.TryGetValue("array", out var value2) ? int.Parse(value2, CultureInfo.InvariantCulture) : (-1)),
					StringValue = dictionary2["value"]
				});
			}
			fsmEditSet.DisabledStates.AddRange(wire.DisabledStates);
			foreach (string transitionRetarget in wire.TransitionRetargets)
			{
				Dictionary<string, string> dictionary3 = SplitPairs(transitionRetarget);
				fsmEditSet.TransitionRetargets.Add(new TransitionRetarget
				{
					StateName = dictionary3["state"],
					EventName = dictionary3["event"],
					NewStateName = dictionary3["newState"],
					NewToState = dictionary3["newTo"],
					NewEventName = (dictionary3.TryGetValue("newEvent", out var value3) ? value3 : "")
				});
			}
			foreach (string sequencerOverride2 in wire.SequencerOverrides)
			{
				Dictionary<string, string> dictionary4 = SplitPairs(sequencerOverride2);
				SequencerOverride sequencerOverride = new SequencerOverride
				{
					StateName = dictionary4["state"],
					ActionIndex = int.Parse(dictionary4["action"], CultureInfo.InvariantCulture),
					RepeatCount = int.Parse(dictionary4["repeat"], CultureInfo.InvariantCulture)
				};
				if (dictionary4.TryGetValue("pattern", out var value4) && value4.Length > 0)
				{
					sequencerOverride.Pattern.AddRange(value4.Split(new string[1] { ", " }, StringSplitOptions.None));
				}
				fsmEditSet.SequencerOverrides.Add(sequencerOverride);
			}
			return fsmEditSet;
		}
	}
	internal sealed class FsmVariableTracker
	{
		private readonly Func<string, List<Fsm>> _getLiveInstances;

		private readonly List<TrackedVariablePath> _tracked = new List<TrackedVariablePath>();

		private readonly List<TrackedVariableValue> _resultBuffer = new List<TrackedVariableValue>();

		public int Version { get; private set; }

		public FsmVariableTracker(Func<string, List<Fsm>> getLiveInstances)
		{
			_getLiveInstances = getLiveInstances;
		}

		public void TrackVariable(string fsmKey, string variableName)
		{
			AddIfAbsent(new TrackedVariablePath(fsmKey, variableName, null, -1, null));
		}

		public void TrackActionField(string fsmKey, string stateName, int actionIndex, string fieldName)
		{
			AddIfAbsent(new TrackedVariablePath(fsmKey, null, stateName, actionIndex, fieldName));
		}

		public void TrackState(string fsmKey, string stateName)
		{
			AddIfAbsent(new TrackedVariablePath(fsmKey, null, stateName, -1, null));
		}

		public void TrackVariableArrayElement(string fsmKey, string variableName, int arrayIndex)
		{
			AddIfAbsent(new TrackedVariablePath(fsmKey, variableName, null, -1, null, arrayIndex));
		}

		public void TrackActionFieldArrayElement(string fsmKey, string stateName, int actionIndex, string fieldName, int arrayIndex)
		{
			AddIfAbsent(new TrackedVariablePath(fsmKey, null, stateName, actionIndex, fieldName, arrayIndex));
		}

		private void AddIfAbsent(TrackedVariablePath path)
		{
			if (!_tracked.Contains(path))
			{
				_tracked.Add(path);
				Version++;
			}
		}

		public void UntrackVariable(string fsmKey, string variableName)
		{
			if (_tracked.Remove(new TrackedVariablePath(fsmKey, variableName, null, -1, null)))
			{
				Version++;
			}
		}

		public void UntrackActionField(string fsmKey, string stateName, int actionIndex, string fieldName)
		{
			if (_tracked.Remove(new TrackedVariablePath(fsmKey, null, stateName, actionIndex, fieldName)))
			{
				Version++;
			}
		}

		public void UntrackState(string fsmKey, string stateName)
		{
			if (_tracked.Remove(new TrackedVariablePath(fsmKey, null, stateName, -1, null)))
			{
				Version++;
			}
		}

		public void UntrackVariableArrayElement(string fsmKey, string variableName, int arrayIndex)
		{
			if (_tracked.Remove(new TrackedVariablePath(fsmKey, variableName, null, -1, null, arrayIndex)))
			{
				Version++;
			}
		}

		public void UntrackActionFieldArrayElement(string fsmKey, string stateName, int actionIndex, string fieldName, int arrayIndex)
		{
			if (_tracked.Remove(new TrackedVariablePath(fsmKey, null, stateName, actionIndex, fieldName, arrayIndex)))
			{
				Version++;
			}
		}

		public bool IsVariableTracked(string fsmKey, string variableName)
		{
			return _tracked.Contains(new TrackedVariablePath(fsmKey, variableName, null, -1, null));
		}

		public bool IsActionFieldTracked(string fsmKey, string stateName, int actionIndex, string fieldName)
		{
			return _tracked.Contains(new TrackedVariablePath(fsmKey, null, stateName, actionIndex, fieldName));
		}

		public bool IsStateTracked(string fsmKey, string stateName)
		{
			return _tracked.Contains(new TrackedVariablePath(fsmKey, null, stateName, -1, null));
		}

		public bool IsVariableArrayElementTracked(string fsmKey, string variableName, int arrayIndex)
		{
			return _tracked.Contains(new TrackedVariablePath(fsmKey, variableName, null, -1, null, arrayIndex));
		}

		public bool IsActionFieldArrayElementTracked(string fsmKey, string stateName, int actionIndex, string fieldName, int arrayIndex)
		{
			return _tracked.Contains(new TrackedVariablePath(fsmKey, null, stateName, actionIndex, fieldName, arrayIndex));
		}

		public List<TrackedVariableValue> GetTracked()
		{
			while (_resultBuffer.Count < _tracked.Count)
			{
				_resultBuffer.Add(new TrackedVariableValue());
			}
			if (_resultBuffer.Count > _tracked.Count)
			{
				_resultBuffer.RemoveRange(_tracked.Count, _resultBuffer.Count - _tracked.Count);
			}
			for (int i = 0; i < _tracked.Count; i++)
			{
				TrackedVariablePath trackedVariablePath = _tracked[i];
				List<Fsm> list = _getLiveInstances(trackedVariablePath.FsmKey);
				Fsm val = ((list.Count > 0) ? list[0] : null);
				TrackedVariableValue trackedVariableValue = _resultBuffer[i];
				trackedVariableValue.FsmKey = trackedVariablePath.FsmKey;
				trackedVariableValue.DisplayLabel = trackedVariablePath.DisplayLabel;
				trackedVariableValue.CurrentValue = ((val == null) ? "<no live instance>" : ResolveCurrentValue(val, trackedVariablePath));
			}
			return _resultBuffer;
		}

		private static string ResolveCurrentValue(Fsm fsm, TrackedVariablePath path)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			int? arrayIndex;
			if (path.VariableName != null)
			{
				NamedVariable val = fsm.Variables.FindVariable(path.VariableName);
				if (val == null)
				{
					return "<not found>";
				}
				arrayIndex = path.ArrayIndex;
				if (arrayIndex.HasValue)
				{
					int valueOrDefault = arrayIndex.GetValueOrDefault();
					FsmArray val2 = (FsmArray)(object)((val is FsmArray) ? val : null);
					if (val2 == null || valueOrDefault >= val2.Length)
					{
						return "<not found>";
					}
					return FsmEditManager.FormatArrayElement(val2.ElementType, val2.Get(valueOrDefault));
				}
				return FormatValue(val.RawValue);
			}
			if (path.ActionIndex < 0 && path.FieldName == null)
			{
				if (fsm.GetState(path.StateName) != null)
				{
					if (!(fsm.ActiveStateName == path.StateName))
					{
						return "Inactive";
					}
					return "Active";
				}
				return "<not found>";
			}
			FsmState state = fsm.GetState(path.StateName);
			if (state == null || path.ActionIndex < 0 || path.ActionIndex >= state.Actions.Length)
			{
				return "<not found>";
			}
			FsmStateAction val3 = state.Actions[path.ActionIndex];
			FieldInfo field = ((object)val3).GetType().GetField(path.FieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				return "<not found>";
			}
			object value = field.GetValue(val3);
			arrayIndex = path.ArrayIndex;
			if (arrayIndex.HasValue)
			{
				int valueOrDefault2 = arrayIndex.GetValueOrDefault();
				if (!(value is Array array) || valueOrDefault2 >= array.Length)
				{
					return "<not found>";
				}
				object value2 = array.GetValue(valueOrDefault2);
				NamedVariable val4 = (NamedVariable)((value2 is NamedVariable) ? value2 : null);
				return FormatValue((val4 != null) ? val4.RawValue : value2);
			}
			NamedVariable val5 = (NamedVariable)((value is NamedVariable) ? value : null);
			return FormatValue((val5 != null) ? val5.RawValue : value);
		}

		private static string FormatValue(object? value)
		{
			return value?.ToString() ?? "null";
		}
	}
	internal sealed class TrackedVariablePath : IEquatable<TrackedVariablePath>
	{
		public string FsmKey { get; }

		public string? VariableName { get; }

		public string? StateName { get; }

		public int ActionIndex { get; }

		public string? FieldName { get; }

		public int? ArrayIndex { get; }

		public string DisplayLabel { get; }

		public TrackedVariablePath(string fsmKey, string? variableName, string? stateName, int actionIndex, string? fieldName, int? arrayIndex = null)
		{
			FsmKey = fsmKey;
			VariableName = variableName;
			StateName = stateName;
			ActionIndex = actionIndex;
			FieldName = fieldName;
			ArrayIndex = arrayIndex;
			string text;
			if (VariableName == null)
			{
				if (FieldName == null)
				{
					text = fsmKey + " / " + stateName + " (state)";
				}
				else if (arrayIndex.HasValue)
				{
					int valueOrDefault = arrayIndex.GetValueOrDefault();
					text = $"{fsmKey} / {stateName}[{actionIndex}].{fieldName}[{valueOrDefault}]";
				}
				else
				{
					text = $"{fsmKey} / {stateName}[{actionIndex}].{fieldName}";
				}
			}
			else if (arrayIndex.HasValue)
			{
				int valueOrDefault2 = arrayIndex.GetValueOrDefault();
				text = $"{fsmKey} / {variableName}[{valueOrDefault2}]";
			}
			else
			{
				text = fsmKey + " / " + variableName;
			}
			DisplayLabel = text;
		}

		public bool Equals(TrackedVariablePath? other)
		{
			if (other != null && FsmKey == other.FsmKey && VariableName == other.VariableName && StateName == other.StateName && ActionIndex == other.ActionIndex && FieldName == other.FieldName)
			{
				return ArrayIndex == other.ArrayIndex;
			}
			return false;
		}

		public override bool Equals(object? obj)
		{
			return Equals(obj as TrackedVariablePath);
		}

		public override int GetHashCode()
		{
			return (((((17 * 31 + FsmKey.GetHashCode()) * 31 + (VariableName?.GetHashCode() ?? 0)) * 31 + (StateName?.GetHashCode() ?? 0)) * 31 + ActionIndex) * 31 + (FieldName?.GetHashCode() ?? 0)) * 31 + (ArrayIndex?.GetHashCode() ?? 0);
		}
	}
	internal sealed class TrackedVariableValue
	{
		public string FsmKey = "";

		public string DisplayLabel = "";

		public string CurrentValue = "";
	}
	internal sealed class SequenceSendEventAction : FsmStateAction
	{
		private readonly FsmEvent[] _sequence;

		private readonly int _repeatCount;

		private readonly FsmStateAction _originalAction;

		private readonly FsmState _state;

		private int _index;

		private int _completedCycles;

		public SequenceSendEventAction(FsmEvent[] sequence, int repeatCount, FsmStateAction originalAction, FsmState state)
		{
			if (sequence.Length == 0)
			{
				throw new ArgumentException("Sequence must contain at least one event.", "sequence");
			}
			_sequence = sequence;
			_repeatCount = repeatCount;
			_originalAction = originalAction;
			_state = state;
		}

		public override void OnEnter()
		{
			if (_repeatCount > 0 && _completedCycles >= _repeatCount)
			{
				RestoreOriginalAction();
				_originalAction.OnEnter();
				return;
			}
			((FsmStateAction)this).Fsm.Event(_sequence[_index]);
			_index++;
			if (_index >= _sequence.Length)
			{
				_index = 0;
				_completedCycles++;
			}
			((FsmStateAction)this).Finish();
		}

		private void RestoreOriginalAction()
		{
			_originalAction.Enabled = true;
			int num = Array.IndexOf(_state.Actions, (FsmStateAction)(object)this);
			if (num >= 0)
			{
				_state.RemoveAction(num);
			}
		}
	}
	internal static class FsmActionSequencer
	{
		public static int IndexRandomEventAction(FsmState state, int rank)
		{
			int num = 0;
			for (int i = 0; i < state.Actions.Length; i++)
			{
				if (((object)state.Actions[i]).GetType().Name.Contains("Random"))
				{
					if (num == rank)
					{
						return i;
					}
					num++;
				}
			}
			return -1;
		}

		public static FsmEvent[] ExtractEventCandidates(FsmStateAction sourceAction, FsmState state)
		{
			FieldInfo fieldInfo = ((object)sourceAction).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public).FirstOrDefault((FieldInfo f) => f.FieldType == typeof(FsmEvent[]));
			if (fieldInfo != null && fieldInfo.GetValue(sourceAction) is FsmEvent[] result)
			{
				return result;
			}
			return state.Transitions.Select((FsmTransition t) => t.FsmEvent).ToArray();
		}

		public static FsmEvent[] ExpandPattern(FsmEvent[] events, int[] repeatCounts)
		{
			List<FsmEvent> list = new List<FsmEvent>();
			for (int i = 0; i < repeatCounts.Length; i++)
			{
				for (int j = 0; j < repeatCounts[i]; j++)
				{
					list.Add(events[i]);
				}
			}
			return list.ToArray();
		}
	}
	internal sealed class FsmEditManager
	{
		private sealed class SendExitEventAction : FsmStateAction
		{
			private readonly FsmEvent _exitEvent;

			public SendExitEventAction(FsmEvent exitEvent)
			{
				_exitEvent = exitEvent;
			}

			public override void OnEnter()
			{
				((FsmStateAction)this).Fsm.Event(_exitEvent);
				((FsmStateAction)this).Finish();
			}
		}

		private static readonly string[] ExitEventPriority = new string[3] { "CANCEL", "FINISHED", "NEXT" };

		private static readonly HashSet<VariableType> SupportedVariableTypes = new HashSet<VariableType>
		{
			(VariableType)0,
			(VariableType)1,
			(VariableType)2,
			(VariableType)4,
			(VariableType)5,
			(VariableType)6,
			(VariableType)8,
			(VariableType)11,
			(VariableType)7,
			(VariableType)14
		};

		private static readonly HashSet<VariableType> SupportedArrayElementTypes = new HashSet<VariableType>
		{
			(VariableType)0,
			(VariableType)1,
			(VariableType)2,
			(VariableType)4
		};

		private readonly IFsmLog _logger;

		private readonly Dictionary<string, List<Fsm>> _liveInstances = new Dictionary<string, List<Fsm>>();

		private readonly Dictionary<string, FsmPristineSnapshot> _pristine = new Dictionary<string, FsmPristineSnapshot>();

		private readonly Dictionary<string, FsmEditSet> _activeEdits = new Dictionary<string, FsmEditSet>();

		private readonly Dictionary<string, Stack<Action>> _undoStacks = new Dictionary<string, Stack<Action>>();

		private bool _isUndoing;

		private readonly HashSet<string> _pendingActivationFsmKeys = new HashSet<string>();

		public int EditGeneration { get; private set; }

		private void BumpEditGeneration()
		{
			EditGeneration++;
		}

		public FsmEditManager(IFsmLog logger)
		{
			_logger = logger;
		}

		public void ReplaceLiveInstances(Dictionary<string, List<Fsm>> instancesByKey)
		{
			_liveInstances.Clear();
			foreach (KeyValuePair<string, List<Fsm>> item in instancesByKey)
			{
				_liveInstances[item.Key] = item.Value;
			}
			PruneStaleSnapshotEntries();
		}

		private void PruneStaleSnapshotEntries()
		{
			foreach (KeyValuePair<string, FsmPristineSnapshot> item in _pristine)
			{
				HashSet<Fsm> alive = new HashSet<Fsm>(GetLiveInstances(item.Key));
				item.Value.InjectedExitActions.RemoveAll((FsmStateAction action) => !alive.Contains(action.State.Fsm));
				item.Value.InstalledSequencers.RemoveAll(((FsmStateAction Original, FsmStateAction Sequencer) pair) => !alive.Contains(pair.Sequencer.State.Fsm));
			}
		}

		public List<Fsm> GetLiveInstances(string fsmKey)
		{
			if (!_liveInstances.TryGetValue(fsmKey, out List<Fsm> value))
			{
				return new List<Fsm>();
			}
			return value;
		}

		public void ReconcileLiveInstance(string fsmKey, Fsm fsm)
		{
			if (!_liveInstances.TryGetValue(fsmKey, out List<Fsm> value))
			{
				value = new List<Fsm>();
				_liveInstances[fsmKey] = value;
			}
			value.RemoveAll((Fsm existing) => existing != fsm && (Object)(object)existing.FsmComponent == (Object)(object)fsm.FsmComponent);
			if (!value.Contains(fsm))
			{
				value.Add(fsm);
			}
		}

		public void PollPendingActivations()
		{
			if (_pendingActivationFsmKeys.Count == 0)
			{
				return;
			}
			string[] array = _pendingActivationFsmKeys.ToArray();
			foreach (string text in array)
			{
				_pendingActivationFsmKeys.Remove(text);
				FsmEditSet activeEditSet = GetActiveEditSet(text);
				if (activeEditSet == null)
				{
					continue;
				}
				Fsm[] array2 = GetLiveInstances(text).ToArray();
				for (int j = 0; j < array2.Length; j++)
				{
					PlayMakerFSM fsmComponent = array2[j].FsmComponent;
					if (fsmComponent != null)
					{
						Fsm fsm = fsmComponent.Fsm;
						if (fsm != null)
						{
							ReconcileLiveInstance(text, fsm);
						}
					}
				}
				ApplyEditSet(activeEditSet);
			}
		}

		public ICollection<string> GetEditedFsmKeys()
		{
			return _activeEdits.Keys;
		}

		public List<FsmEditSet> GetAllActiveEditSets()
		{
			return new List<FsmEditSet>(_activeEdits.Values);
		}

		public FsmEditSet? GetActiveEditSet(string fsmKey)
		{
			if (!_activeEdits.TryGetValue(fsmKey, out FsmEditSet value))
			{
				return null;
			}
			return value;
		}

		private void PruneActiveEditSetIfEmpty(string fsmKey)
		{
			if (_activeEdits.TryGetValue(fsmKey, out FsmEditSet value) && value.IsEmpty)
			{
				_activeEdits.Remove(fsmKey);
			}
		}

		public void PrimeActiveEditSet(FsmEditSet editSet)
		{
			_activeEdits[editSet.FsmKey] = editSet;
		}

		public void ApplyEditSet(FsmEditSet editSet)
		{
			if (!_liveInstances.TryGetValue(editSet.FsmKey, out List<Fsm> value) || value.Count == 0)
			{
				_logger.LogWarning("[FsmMaster] Fsm key '" + editSet.FsmKey + "' is disconnected (no live instances in the current scene); skipping edit set.");
				return;
			}
			VariableOverride[] array = editSet.VariableOverrides.ToArray();
			ActionFieldOverride[] array2 = editSet.ActionFieldOverrides.ToArray();
			string[] array3 = editSet.DisabledStates.ToArray();
			TransitionRetarget[] array4 = editSet.TransitionRetargets.ToArray();
			SequencerOverride[] array5 = editSet.SequencerOverrides.ToArray();
			foreach (Fsm item in value)
			{
				VariableOverride[] array6 = array;
				foreach (VariableOverride ov in array6)
				{
					ApplyVariableOverride(editSet.FsmKey, item, ov);
				}
				ActionFieldOverride[] array7 = array2;
				foreach (ActionFieldOverride ov2 in array7)
				{
					ApplyActionFieldOverride(editSet.FsmKey, item, ov2);
				}
				string[] array8 = array3;
				foreach (string stateName in array8)
				{
					DisableState(editSet.FsmKey, item, stateName);
				}
				TransitionRetarget[] array9 = array4;
				foreach (TransitionRetarget retarget in array9)
				{
					ApplyTransitionRetarget(editSet.FsmKey, item, retarget);
				}
				SequencerOverride[] array10 = array5;
				foreach (SequencerOverride seq in array10)
				{
					InstallSequencer(editSet.FsmKey, item, seq);
				}
			}
			_logger.LogInfo($"[FsmMaster] Applied edit set for fsm key '{editSet.FsmKey}' to {value.Count} live instance(s): " + $"{array.Length} variable, {array2.Length} action-field, {array3.Length} disabled-state, " + $"{array4.Length} transition, {array5.Length} sequencer override(s).");
		}

		public void ResetFsm(string fsmKey)
		{
			if (_pristine.TryGetValue(fsmKey, out FsmPristineSnapshot value))
			{
				_liveInstances.TryGetValue(fsmKey, out List<Fsm> value2);
				RestoreSnapshot(value, value2 ?? new List<Fsm>());
				_pristine.Remove(fsmKey);
				_activeEdits.Remove(fsmKey);
				_undoStacks.Remove(fsmKey);
				BumpEditGeneration();
			}
		}

		public void RevertAllForUnload()
		{
			foreach (KeyValuePair<string, FsmPristineSnapshot> item in _pristine)
			{
				_liveInstances.TryGetValue(item.Key, out List<Fsm> value);
				RestoreSnapshot(item.Value, value ?? new List<Fsm>());
			}
			_pristine.Clear();
			_liveInstances.Clear();
			_activeEdits.Clear();
			_undoStacks.Clear();
		}

		public bool HasUndo(string fsmKey)
		{
			if (_undoStacks.TryGetValue(fsmKey, out Stack<Action> value))
			{
				return value.Count > 0;
			}
			return false;
		}

		public void Undo(string fsmKey)
		{
			if (!_undoStacks.TryGetValue(fsmKey, out Stack<Action> value) || value.Count == 0)
			{
				return;
			}
			Action action = value.Pop();
			_isUndoing = true;
			try
			{
				action();
			}
			finally
			{
				_isUndoing = false;
			}
		}

		private void PushUndo(string fsmKey, Action undo)
		{
			if (!_isUndoing)
			{
				if (!_undoStacks.TryGetValue(fsmKey, out Stack<Action> value))
				{
					value = new Stack<Action>();
					_undoStacks[fsmKey] = value;
				}
				value.Push(undo);
			}
		}

		public void SetVariable(string fsmKey, string variableName, string variableType, string stringValue)
		{
			string previousValue = GetCurrentVariableValue(fsmKey, variableName);
			VariableOverride ov = new VariableOverride
			{
				VariableType = variableType,
				Name = variableName,
				StringValue = stringValue
			};
			foreach (Fsm liveInstance in GetLiveInstances(fsmKey))
			{
				ApplyVariableOverride(fsmKey, liveInstance, ov);
			}
			if (previousValue != null)
			{
				PushUndo(fsmKey, delegate
				{
					SetVariable(fsmKey, variableName, variableType, previousValue);
				});
			}
		}

		public void SetActionField(string fsmKey, string stateName, int actionIndex, string expectedActionTypeName, string fieldName, string stringValue)
		{
			string previousValue = GetCurrentActionFieldValue(fsmKey, stateName, actionIndex, expectedActionTypeName, fieldName);
			ActionFieldOverride ov = new ActionFieldOverride
			{
				StateName = stateName,
				ActionIndex = actionIndex,
				ExpectedActionTypeName = expectedActionTypeName,
				FieldName = fieldName,
				StringValue = stringValue
			};
			foreach (Fsm liveInstance in GetLiveInstances(fsmKey))
			{
				ApplyActionFieldOverride(fsmKey, liveInstance, ov);
			}
			if (previousValue != null)
			{
				PushUndo(fsmKey, delegate
				{
					SetActionField(fsmKey, stateName, actionIndex, expectedActionTypeName, fieldName, previousValue);
				});
			}
		}

		public void SetVariableArrayElement(string fsmKey, string variableName, int arrayIndex, string elementStringValue)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			string previousValue = GetCurrentVariableArrayElementValue(fsmKey, variableName, arrayIndex);
			VariableOverride ov = new VariableOverride
			{
				VariableType = ((object)(VariableType)13/*cast due to .constrained prefix*/).ToString(),
				Name = variableName,
				ArrayIndex = arrayIndex,
				StringValue = elementStringValue
			};
			foreach (Fsm liveInstance in GetLiveInstances(fsmKey))
			{
				ApplyVariableOverride(fsmKey, liveInstance, ov);
			}
			if (previousValue != null)
			{
				PushUndo(fsmKey, delegate
				{
					SetVariableArrayElement(fsmKey, variableName, arrayIndex, previousValue);
				});
			}
		}

		public void SetActionFieldArrayElement(string fsmKey, string stateName, int actionIndex, string expectedActionTypeName, string fieldName, int arrayIndex, string elementStringValue)
		{
			string previousValue = GetCurrentActionFieldArrayElementValue(fsmKey, stateName, actionIndex, expectedActionTypeName, fieldName, arrayIndex);
			ActionFieldOverride ov = new ActionFieldOverride
			{
				StateName = stateName,
				ActionIndex = actionIndex,
				ExpectedActionTypeName = expectedActionTypeName,
				FieldName = fieldName,
				ArrayIndex = arrayIndex,
				StringValue = elementStringValue
			};
			foreach (Fsm liveInstance in GetLiveInstances(fsmKey))
			{
				ApplyActionFieldOverride(fsmKey, liveInstance, ov);
			}
			if (previousValue != null)
			{
				PushUndo(fsmKey, delegate
				{
					SetActionFieldArrayElement(fsmKey, stateName, actionIndex, expectedActionTypeName, fieldName, arrayIndex, previousValue);
				});
			}
		}

		private string? GetCurrentVariableValue(string fsmKey, string variableName)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			foreach (Fsm liveInstance in GetLiveInstances(fsmKey))
			{
				NamedVariable val = liveInstance.Variables.FindVariable(variableName);
				if (val != null && SupportedVariableTypes.Contains(val.VariableType))
				{
					return FormatNamedVariable(val);
				}
			}
			return null;
		}

		private string? GetCurrentVariableArrayElementValue(string fsmKey, string variableName, int arrayIndex)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			foreach (Fsm liveInstance in GetLiveInstances(fsmKey))
			{
				NamedVariable obj = liveInstance.Variables.FindVariable(variableName);
				FsmArray val = (FsmArray)(object)((obj is FsmArray) ? obj : null);
				if (val != null && arrayIndex < val.Length)
				{
					return FormatArrayElement(val.ElementType, val.Get(arrayIndex));
				}
			}
			return null;
		}

		private string? GetCurrentActionFieldValue(string fsmKey, string stateName, int actionIndex, string expectedActionTypeName, string fieldName)
		{
			foreach (Fsm liveInstance in