Decompiled source of CommandFramework v0.3.1

CommandFramework.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using CommandFramework.API;
using CommandFramework.Commands;
using CommandFramework.Patches;
using CommandFramework.UI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NuclearOption.MissionEditorScripts;
using UnityEngine;
using UnityEngine.EventSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CommandFramework
{
	[BepInPlugin("com.nuclearoption.commandframework", "Command Framework", "0.3.1")]
	[BepInProcess("NuclearOption.exe")]
	public class CommandFrameworkPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.nuclearoption.commandframework";

		public const string PluginName = "Command Framework";

		public const string PluginVersion = "0.3.1";

		private Harmony _harmony;

		public static CommandFrameworkPlugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Command Framework v0.3.1 initializing...");
			try
			{
				_harmony = new Harmony("com.nuclearoption.commandframework");
				_harmony.PatchAll(typeof(CommandFrameworkPlugin).Assembly);
				Log.LogInfo((object)"Command Framework successfully applied Harmony patches!");
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("Failed to apply Harmony patches for {0}: {1}", "Command Framework", arg));
			}
			CommandFrameworkAPI.RegisterCommand(new HoldPositionCommandAction());
			GameObject val = new GameObject("CommandFramework_UI");
			val.AddComponent<ContextMenuUI>();
			Object.DontDestroyOnLoad((Object)(object)val);
			Log.LogInfo((object)"Command Framework ready! API and Context Menu initialized.");
		}

		private void OnDestroy()
		{
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}

		public static void LogInfo(string message)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}

		public static void LogWarning(string message)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)message);
			}
		}

		public static void LogError(string message)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)message);
			}
		}
	}
	public static class HoldPositionManager
	{
		private static readonly HashSet<Unit> _heldUnits = new HashSet<Unit>();

		public static event Action<Unit, bool> OnHoldPositionChanged;

		public static bool IsHoldingPosition(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return false;
			}
			PruneDeadUnits();
			return _heldUnits.Contains(unit);
		}

		public static bool ToggleHoldPosition(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return false;
			}
			bool flag = !IsHoldingPosition(unit);
			SetHoldPosition(unit, flag);
			return flag;
		}

		public static void SetHoldPosition(Unit unit, bool hold)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)unit == (Object)null)
			{
				return;
			}
			UnitOrderState orCreateState = UnitStateManager.GetOrCreateState(unit);
			orCreateState.IsHoldPosition = hold;
			if (hold)
			{
				_heldUnits.Add(unit);
				if (string.IsNullOrEmpty(orCreateState.CustomStateKey))
				{
					orCreateState.CustomStateKey = "HoldPosition";
					orCreateState.CustomStateLabel = "HOLD POSITION";
					orCreateState.CustomStateColor = new Color(1f, 0.65f, 0.15f);
				}
				ApplyHold(unit);
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Unit '" + unit.NetworkunitName + "' set to HOLD POSITION (Stop).");
			}
			else
			{
				_heldUnits.Remove(unit);
				if (orCreateState.CustomStateKey == "HoldPosition")
				{
					orCreateState.CustomStateKey = null;
					orCreateState.CustomStateLabel = null;
					orCreateState.CustomStateColor = null;
				}
				ApplyResume(unit);
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Unit '" + unit.NetworkunitName + "' RESUMED and NUDGED back to active AI operations.");
			}
			HoldPositionManager.OnHoldPositionChanged?.Invoke(unit, hold);
		}

		private static void ApplyHold(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return;
			}
			GroundVehicle val = (GroundVehicle)(object)((unit is GroundVehicle) ? unit : null);
			if (val != null)
			{
				val.SetHoldPosition(true);
				val.StopImmediately();
				return;
			}
			Ship val2 = (Ship)(object)((unit is Ship) ? unit : null);
			if (val2 != null)
			{
				val2.SetHoldPosition(true);
				ShipAI component = ((Component)val2).GetComponent<ShipAI>();
				if ((Object)(object)component != (Object)null)
				{
					AccessTools.Method(typeof(ShipAI), "StartHoldPosition", (Type[])null, (Type[])null)?.Invoke(component, null);
				}
			}
		}

		private static void ApplyResume(Unit unit)
		{
			if (!((Object)(object)unit == (Object)null))
			{
				NudgeAI(unit);
			}
		}

		public static void NudgeAI(Unit unit)
		{
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)unit == (Object)null || unit.disabled)
			{
				return;
			}
			try
			{
				GroundVehicle val = (GroundVehicle)(object)((unit is GroundVehicle) ? unit : null);
				if (val != null)
				{
					val.SetHoldPosition(false);
					AccessTools.Field(typeof(GroundVehicle), "anchored")?.SetValue(val, false);
					AccessTools.Field(typeof(GroundVehicle), "resetStationary")?.SetValue(val, true);
					AccessTools.Field(typeof(GroundVehicle), "commandedDestination")?.SetValue(val, false);
					MobileArtilleryAI component = ((Component)val).GetComponent<MobileArtilleryAI>();
					if ((Object)(object)component != (Object)null)
					{
						AccessTools.Method(typeof(MobileArtilleryAI), "TargetSearch", (Type[])null, (Type[])null)?.Invoke(component, null);
						CommandFrameworkPlugin.LogInfo("[CommandFramework] Nudged MobileArtilleryAI for '" + ((Unit)val).NetworkunitName + "'.");
						return;
					}
					RearmVehicleAI component2 = ((Component)val).GetComponent<RearmVehicleAI>();
					if ((Object)(object)component2 != (Object)null)
					{
						AccessTools.Method(typeof(RearmVehicleAI), "LeaveDepot", (Type[])null, (Type[])null)?.Invoke(component2, null);
						CommandFrameworkPlugin.LogInfo("[CommandFramework] Nudged RearmVehicleAI for '" + ((Unit)val).NetworkunitName + "'.");
						return;
					}
					if (AccessTools.Field(typeof(GroundVehicle), "savedWaypoints")?.GetValue(val) is IList { Count: >0 } list)
					{
						object obj = list[0];
						FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), "position");
						if (fieldInfo != null)
						{
							GlobalPosition val2 = (GlobalPosition)fieldInfo.GetValue(obj);
							UnitCommand component3 = ((Component)val).GetComponent<UnitCommand>();
							if (component3 != null)
							{
								component3.SetDestination(val2, false);
							}
							CommandFrameworkPlugin.LogInfo("[CommandFramework] Nudged '" + ((Unit)val).NetworkunitName + "' towards saved waypoint.");
							return;
						}
					}
					GlobalPosition val3 = GlobalPositionExtensions.GlobalPosition(((Component)val).transform) + ((Component)val).transform.forward * 800f;
					UnitCommand component4 = ((Component)val).GetComponent<UnitCommand>();
					if (component4 != null)
					{
						component4.SetDestination(val3, false);
					}
					val.ReturnToRoad((GlobalPosition?)null);
					CommandFrameworkPlugin.LogInfo("[CommandFramework] Nudged GroundVehicle '" + ((Unit)val).NetworkunitName + "' forward on road network.");
					return;
				}
				Ship val4 = (Ship)(object)((unit is Ship) ? unit : null);
				if (val4 == null)
				{
					return;
				}
				val4.SetHoldPosition(false);
				ShipAI component5 = ((Component)val4).GetComponent<ShipAI>();
				if ((Object)(object)component5 != (Object)null)
				{
					FieldInfo fieldInfo2 = AccessTools.Field(typeof(ShipAI), "state");
					if (fieldInfo2 != null)
					{
						fieldInfo2.SetValue(component5, Enum.ToObject(fieldInfo2.FieldType, 0));
					}
					AccessTools.Field(typeof(ShipAI), "commandedDestination")?.SetValue(component5, false);
					AccessTools.Method(typeof(ShipAI), "ChooseTarget", (Type[])null, (Type[])null)?.Invoke(component5, null);
					object? obj2 = AccessTools.Field(typeof(ShipAI), "inputs")?.GetValue(component5);
					ShipInputs val5 = (ShipInputs)((obj2 is ShipInputs) ? obj2 : null);
					if (val5 != null)
					{
						val5.throttle = 1f;
					}
					CommandFrameworkPlugin.LogInfo("[CommandFramework] Nudged ShipAI for '" + ((Unit)val4).NetworkunitName + "' and restored state to Moving.");
				}
			}
			catch (Exception arg)
			{
				CommandFrameworkPlugin.LogError($"[CommandFramework] Error during AI Nudge for '{unit.NetworkunitName}': {arg}");
			}
		}

		public static void PruneDeadUnits()
		{
			if (_heldUnits.Count != 0)
			{
				_heldUnits.RemoveWhere((Unit u) => (Object)(object)u == (Object)null || u.disabled);
			}
		}

		public static void ClearAll()
		{
			_heldUnits.Clear();
		}
	}
}
namespace CommandFramework.UI
{
	public class ContextMenuUI : MonoBehaviour
	{
		private bool _isOpen;

		private Unit _targetUnit;

		private Rect _menuRect;

		private GUIStyle _boxStyle;

		private GUIStyle _headerStyle;

		private GUIStyle _buttonMinimalStopStyle;

		private GUIStyle _buttonMinimalResumeStyle;

		private GUIStyle _buttonCustomStyle;

		private Texture2D _bgBorderTexture;

		private Texture2D _btnStopTexture;

		private Texture2D _btnResumeTexture;

		private Texture2D _btnHoverTexture;

		private bool _stylesInitialized;

		public static ContextMenuUI Instance { get; private set; }

		public static bool IsOpen => (Object)(object)Instance != (Object)null && Instance._isOpen;

		public static Unit CurrentUnit => Instance?._targetUnit;

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		private void Update()
		{
			if (_isOpen && Input.GetKeyDown((KeyCode)27))
			{
				Close();
				return;
			}
			if (Input.GetMouseButtonDown(0))
			{
				TryHandleLeftClick();
			}
			if (Input.GetMouseButtonDown(1))
			{
				TryWorldRightClick();
			}
			if (_isOpen && ((Object)(object)_targetUnit == (Object)null || _targetUnit.disabled))
			{
				Close();
			}
		}

		private void TryHandleLeftClick()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (_isOpen)
			{
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y);
				if (((Rect)(ref _menuRect)).Contains(val))
				{
					return;
				}
			}
			if (!RightClickSuppressor.TryGetUnitUnderCursor(out var _))
			{
				TryDeselectEmptySpace();
			}
		}

		private void TryDeselectEmptySpace()
		{
			if (_isOpen)
			{
				Close();
			}
			try
			{
				if ((Object)(object)SceneSingleton<DynamicMap>.i != (Object)null)
				{
					SceneSingleton<DynamicMap>.i.UnselectAll();
					SceneSingleton<DynamicMap>.i.DeselectAllIcons();
				}
				if ((Object)(object)SceneSingleton<CombatHUD>.i != (Object)null)
				{
					if ((Object)(object)SceneSingleton<CombatHUD>.i.aircraft != (Object)null)
					{
						SceneSingleton<CombatHUD>.i.DeselectAll(true);
					}
					else if (AccessTools.Field(typeof(CombatHUD), "targetList")?.GetValue(SceneSingleton<CombatHUD>.i) is IList list)
					{
						list.Clear();
					}
				}
				if ((Object)(object)SceneSingleton<UnitSelection>.i != (Object)null)
				{
					SceneSingleton<UnitSelection>.i.ClearSelection();
				}
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Deselected units/targets cleanly via empty space left-click.");
			}
			catch (Exception arg)
			{
				CommandFrameworkPlugin.LogError($"[CommandFramework] Error during deselection: {arg}");
			}
		}

		private void TryWorldRightClick()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (_isOpen)
			{
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y);
				if (((Rect)(ref _menuRect)).Contains(val))
				{
					return;
				}
			}
			if (RightClickSuppressor.TryGetUnitUnderCursor(out var unit))
			{
				RightClickSuppressor.SuppressThisFrame();
				OpenForUnit(unit, Vector2.op_Implicit(Input.mousePosition));
			}
			else if (_isOpen)
			{
				Close();
			}
		}

		public static void OpenForUnit(Unit unit, Vector2 screenPos)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if (!((Object)(object)unit == (Object)null) && !unit.disabled)
			{
				if ((Object)(object)Instance == (Object)null)
				{
					GameObject val = new GameObject("CommandFramework_UI");
					val.AddComponent<ContextMenuUI>();
				}
				Instance._targetUnit = unit;
				Instance._isOpen = true;
				List<IUnitCommandAction> visibleCommandsForUnit = CommandFrameworkAPI.GetVisibleCommandsForUnit(unit);
				float num = 44f + (float)visibleCommandsForUnit.Count * 28f;
				float num2 = Mathf.Clamp(screenPos.x, 10f, (float)Screen.width - 190f);
				float num3 = Mathf.Clamp((float)Screen.height - screenPos.y, 10f, (float)Screen.height - num - 20f);
				Instance._menuRect = new Rect(num2, num3, 180f, num);
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Opened Minimal Menu for '" + unit.NetworkunitName + "'.");
			}
		}

		public static void Close()
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Instance._isOpen = false;
				Instance._targetUnit = null;
			}
		}

		private void InitStyles()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_013d: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: 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_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Expected O, but got Unknown
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: 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_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Expected O, but got Unknown
			if (!_stylesInitialized)
			{
				Color val = default(Color);
				((Color)(ref val))..ctor(0.06f, 0.88f, 0.5f, 1f);
				Color fill = default(Color);
				((Color)(ref fill))..ctor(0.02f, 0.04f, 0.06f, 0.96f);
				_bgBorderTexture = MakeBorderedTexture(64, 64, fill, val, 2);
				_btnStopTexture = MakeBorderedTexture(32, 32, new Color(0.06f, 0.88f, 0.5f, 0.08f), new Color(0.06f, 0.88f, 0.5f, 0.4f), 1);
				_btnResumeTexture = MakeBorderedTexture(32, 32, new Color(1f, 0.65f, 0.15f, 0.12f), new Color(1f, 0.65f, 0.15f, 0.5f), 1);
				_btnHoverTexture = MakeBorderedTexture(32, 32, new Color(0.06f, 0.88f, 0.5f, 0.25f), val, 1);
				GUIStyle val2 = new GUIStyle(GUI.skin.box);
				val2.normal.background = _bgBorderTexture;
				val2.padding = new RectOffset(8, 8, 6, 6);
				_boxStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11,
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = val;
				val3.alignment = (TextAnchor)4;
				_headerStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 11,
					fontStyle = (FontStyle)1
				};
				val4.normal.background = _btnStopTexture;
				val4.normal.textColor = new Color(0.9f, 0.98f, 0.94f);
				val4.hover.background = _btnHoverTexture;
				val4.hover.textColor = Color.white;
				val4.alignment = (TextAnchor)4;
				_buttonMinimalStopStyle = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 11,
					fontStyle = (FontStyle)1
				};
				val5.normal.background = _btnResumeTexture;
				val5.normal.textColor = new Color(1f, 0.75f, 0.25f);
				val5.hover.background = MakeBorderedTexture(32, 32, new Color(1f, 0.65f, 0.15f, 0.3f), new Color(1f, 0.75f, 0.25f), 1);
				val5.hover.textColor = Color.white;
				val5.alignment = (TextAnchor)4;
				_buttonMinimalResumeStyle = val5;
				GUIStyle val6 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 10,
					fontStyle = (FontStyle)1
				};
				val6.normal.background = _btnStopTexture;
				val6.normal.textColor = new Color(0.8f, 0.95f, 1f);
				val6.hover.background = _btnHoverTexture;
				val6.hover.textColor = Color.white;
				val6.alignment = (TextAnchor)4;
				_buttonCustomStyle = val6;
				_stylesInitialized = true;
			}
		}

		private void OnGUI()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (_isOpen && !((Object)(object)_targetUnit == (Object)null))
			{
				InitStyles();
				if ((int)Event.current.type == 0 && !((Rect)(ref _menuRect)).Contains(Event.current.mousePosition))
				{
					Close();
				}
				else
				{
					GUI.Window(98234, _menuRect, new WindowFunction(DrawMenuContent), "", _boxStyle);
				}
			}
		}

		private void DrawMenuContent(int windowID)
		{
			if ((Object)(object)_targetUnit == (Object)null)
			{
				return;
			}
			string text = ((!string.IsNullOrEmpty(_targetUnit.NetworkunitName)) ? _targetUnit.NetworkunitName : ((Object)_targetUnit).name);
			bool flag = HoldPositionManager.IsHoldingPosition(_targetUnit);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label(text.ToUpper(), _headerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(4f);
			List<IUnitCommandAction> visibleCommandsForUnit = CommandFrameworkAPI.GetVisibleCommandsForUnit(_targetUnit);
			foreach (IUnitCommandAction item in visibleCommandsForUnit)
			{
				GUIStyle val = _buttonCustomStyle;
				if (item.Id == "core.hold_position")
				{
					val = (flag ? _buttonMinimalResumeStyle : _buttonMinimalStopStyle);
				}
				string text2 = ((!(item.Id == "core.hold_position")) ? item.GetDisplayName(_targetUnit) : (flag ? "▶ RESUME" : "⏹ STOP"));
				GUI.enabled = item.IsEnabled(_targetUnit);
				if (GUILayout.Button(text2, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
				{
					CommandFrameworkAPI.ExecuteCommand(item, _targetUnit);
				}
				GUI.enabled = true;
				GUILayout.Space(3f);
			}
			GUILayout.EndVertical();
		}

		private static Texture2D MakeBorderedTexture(int width, int height, Color fill, Color border, int borderWidth)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					bool flag = j < borderWidth || j >= width - borderWidth || i < borderWidth || i >= height - borderWidth;
					array[i * width + j] = (flag ? border : fill);
				}
			}
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(array);
			val.Apply();
			return val;
		}
	}
}
namespace CommandFramework.Patches
{
	[HarmonyPatch]
	public static class CommandInterceptPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(UnitCommand), "ServerSetDestination")]
		public static bool UnitCommand_ServerSetDestination_Prefix(UnitCommand __instance, GlobalPosition waypoint, object player)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			Unit component = ((Component)__instance).GetComponent<Unit>();
			if ((Object)(object)component != (Object)null && !CommandFrameworkAPI.IsDestinationAllowed(component, waypoint))
			{
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Blocked destination update for '" + component.NetworkunitName + "'.");
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GroundVehicle), "Vehicle_OnObjectiveStarted")]
		public static bool GroundVehicle_Vehicle_OnObjectiveStarted_Prefix(GroundVehicle __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)null && !CommandFrameworkAPI.IsDestinationAllowed((Unit)(object)__instance, default(GlobalPosition)))
			{
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Blocked Objective waypoint for GroundVehicle '" + ((Unit)__instance).NetworkunitName + "'.");
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Ship), "Ship_OnObjectiveStarted")]
		public static bool Ship_Ship_OnObjectiveStarted_Prefix(Ship __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)null && !CommandFrameworkAPI.IsDestinationAllowed((Unit)(object)__instance, default(GlobalPosition)))
			{
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Blocked Objective waypoint for Ship '" + ((Unit)__instance).NetworkunitName + "'.");
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MobileArtilleryAI), "DestinationSearch")]
		public static bool MobileArtilleryAI_DestinationSearch_Prefix(MobileArtilleryAI __instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)null)
			{
				Unit component = ((Component)__instance).GetComponent<Unit>();
				if ((Object)(object)component != (Object)null && !CommandFrameworkAPI.IsDestinationAllowed(component, default(GlobalPosition)))
				{
					return false;
				}
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ShipAI), "SetDestination")]
		public static bool ShipAI_SetDestination_Prefix(ShipAI __instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)null)
			{
				Unit component = ((Component)__instance).GetComponent<Unit>();
				if ((Object)(object)component != (Object)null && !CommandFrameworkAPI.IsDestinationAllowed(component, default(GlobalPosition)))
				{
					return false;
				}
			}
			return true;
		}
	}
	public static class RightClickSuppressor
	{
		public static int SuppressFrame = -1;

		public static bool IsSuppressed => SuppressFrame == Time.frameCount;

		public static void SuppressThisFrame()
		{
			SuppressFrame = Time.frameCount;
		}

		public static bool TryGetUnitUnderCursor(out Unit unit)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			unit = null;
			if (DynamicMap.mapMaximized && (Object)(object)SceneSingleton<DynamicMap>.i != (Object)null && SceneSingleton<DynamicMap>.i.mapIcons != null)
			{
				Vector3 mousePosition = Input.mousePosition;
				float num = 3600f;
				Unit val = null;
				List<MapIcon> mapIcons = SceneSingleton<DynamicMap>.i.mapIcons;
				for (int i = 0; i < mapIcons.Count; i++)
				{
					MapIcon val2 = mapIcons[i];
					UnitMapIcon val3 = (UnitMapIcon)(object)((val2 is UnitMapIcon) ? val2 : null);
					if (val3 != null && ((Component)val2).gameObject.activeInHierarchy && (Object)(object)val3.unit != (Object)null && !val3.unit.disabled)
					{
						Vector3 position = ((Component)val2).transform.position;
						float num2 = (mousePosition.x - position.x) * (mousePosition.x - position.x) + (mousePosition.y - position.y) * (mousePosition.y - position.y);
						if (num2 < num)
						{
							num = num2;
							val = val3.unit;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					unit = val;
					return true;
				}
				return false;
			}
			if (!DynamicMap.mapMaximized)
			{
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)null)
				{
					Ray val4 = main.ScreenPointToRay(Input.mousePosition);
					RaycastHit val5 = default(RaycastHit);
					if (Physics.Raycast(val4, ref val5, 25000f))
					{
						Unit componentInParent = ((Component)((RaycastHit)(ref val5)).collider).GetComponentInParent<Unit>();
						if ((Object)(object)componentInParent != (Object)null && !componentInParent.disabled)
						{
							unit = componentInParent;
							return true;
						}
					}
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(MapIcon), "UnityEngine.EventSystems.IPointerClickHandler.OnPointerClick")]
	public static class MapIcon_RightClick_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(MapIcon __instance, PointerEventData eventData)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || eventData == null)
			{
				return true;
			}
			if ((int)eventData.button == 1)
			{
				UnitMapIcon val = (UnitMapIcon)(object)((__instance is UnitMapIcon) ? __instance : null);
				if (val != null && (Object)(object)val.unit != (Object)null)
				{
					RightClickSuppressor.SuppressThisFrame();
					ContextMenuUI.OpenForUnit(val.unit, Vector2.op_Implicit(Input.mousePosition));
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(DynamicMap), "MapControls")]
	public static class DynamicMap_MapControls_SuppressMove_Patch
	{
		private static List<MapIcon> _stashedIcons;

		[HarmonyPrefix]
		public static void Prefix(DynamicMap __instance)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)null) && Input.GetMouseButtonDown(1) && RightClickSuppressor.TryGetUnitUnderCursor(out var unit))
			{
				RightClickSuppressor.SuppressThisFrame();
				ContextMenuUI.OpenForUnit(unit, Vector2.op_Implicit(Input.mousePosition));
				if (__instance.selectedIcons != null && __instance.selectedIcons.Count > 0)
				{
					_stashedIcons = new List<MapIcon>(__instance.selectedIcons);
					__instance.selectedIcons.Clear();
				}
			}
		}

		[HarmonyPostfix]
		public static void Postfix(DynamicMap __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && _stashedIcons != null)
			{
				if (__instance.selectedIcons != null)
				{
					__instance.selectedIcons.AddRange(_stashedIcons);
				}
				_stashedIcons = null;
			}
		}
	}
	[HarmonyPatch(typeof(UnitCommand), "SetDestination")]
	public static class UnitCommand_SetDestination_Suppress_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(UnitCommand __instance, GlobalPosition waypoint, bool playerCommand)
		{
			if (playerCommand && RightClickSuppressor.IsSuppressed)
			{
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Blocked waypoint/destination creation from unit context right-click.");
				return false;
			}
			return true;
		}
	}
}
namespace CommandFramework.Commands
{
	public class HoldPositionCommandAction : IUnitCommandAction
	{
		public string Id => "core.hold_position";

		public int Priority => 10;

		public string GetDisplayName(Unit unit)
		{
			return HoldPositionManager.IsHoldingPosition(unit) ? "▶ RESUME" : "⏹ STOP";
		}

		public bool IsVisible(Unit unit)
		{
			return (Object)(object)unit != (Object)null && !unit.disabled && (unit is GroundVehicle || unit is Ship);
		}

		public bool IsEnabled(Unit unit)
		{
			return (Object)(object)unit != (Object)null && !unit.disabled;
		}

		public Color? GetButtonColor(Unit unit)
		{
			//IL_0039: 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 (HoldPositionManager.IsHoldingPosition(unit))
			{
				return new Color(1f, 0.65f, 0.15f);
			}
			return new Color(0.06f, 0.88f, 0.5f);
		}

		public void Execute(Unit unit)
		{
			if (!((Object)(object)unit == (Object)null) && !unit.disabled)
			{
				HoldPositionManager.ToggleHoldPosition(unit);
			}
		}
	}
}
namespace CommandFramework.API
{
	public static class CommandFrameworkAPI
	{
		private static readonly List<IUnitCommandAction> _registeredCommands;

		private static readonly List<Func<Unit, GlobalPosition, bool>> _orderFilters;

		public static event Action<Unit, IUnitCommandAction> OnCommandExecuted;

		public static event Action<Unit, bool> OnHoldPositionChanged;

		public static event Action<Unit, string> OnCustomOrderStateChanged;

		static CommandFrameworkAPI()
		{
			_registeredCommands = new List<IUnitCommandAction>();
			_orderFilters = new List<Func<Unit, GlobalPosition, bool>>();
			HoldPositionManager.OnHoldPositionChanged += delegate(Unit unit, bool isHolding)
			{
				CommandFrameworkAPI.OnHoldPositionChanged?.Invoke(unit, isHolding);
			};
			UnitStateManager.OnCustomStateChanged += delegate(Unit unit, string stateKey)
			{
				CommandFrameworkAPI.OnCustomOrderStateChanged?.Invoke(unit, stateKey);
			};
		}

		public static void RegisterCommand(IUnitCommandAction action)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (_registeredCommands.Exists((IUnitCommandAction c) => c.Id == action.Id))
			{
				CommandFrameworkPlugin.LogWarning("[CommandFrameworkAPI] Command with ID '" + action.Id + "' is already registered. Overwriting.");
				_registeredCommands.RemoveAll((IUnitCommandAction c) => c.Id == action.Id);
			}
			_registeredCommands.Add(action);
			_registeredCommands.Sort((IUnitCommandAction a, IUnitCommandAction b) => a.Priority.CompareTo(b.Priority));
			CommandFrameworkPlugin.LogInfo($"[CommandFrameworkAPI] Registered command '{action.Id}' (Priority {action.Priority}).");
		}

		public static bool UnregisterCommand(string commandId)
		{
			int num = _registeredCommands.RemoveAll((IUnitCommandAction c) => c.Id == commandId);
			return num > 0;
		}

		public static List<IUnitCommandAction> GetVisibleCommandsForUnit(Unit unit)
		{
			List<IUnitCommandAction> list = new List<IUnitCommandAction>();
			if ((Object)(object)unit == (Object)null)
			{
				return list;
			}
			foreach (IUnitCommandAction registeredCommand in _registeredCommands)
			{
				try
				{
					if (registeredCommand.IsVisible(unit))
					{
						list.Add(registeredCommand);
					}
				}
				catch (Exception arg)
				{
					CommandFrameworkPlugin.LogError($"[CommandFrameworkAPI] Error checking visibility for command '{registeredCommand.Id}': {arg}");
				}
			}
			return list;
		}

		public static void ExecuteCommand(IUnitCommandAction action, Unit unit)
		{
			if (action == null || (Object)(object)unit == (Object)null)
			{
				return;
			}
			try
			{
				action.Execute(unit);
				CommandFrameworkAPI.OnCommandExecuted?.Invoke(unit, action);
				CommandFrameworkPlugin.LogInfo("[CommandFrameworkAPI] Executed command '" + action.Id + "' on '" + unit.NetworkunitName + "'.");
			}
			catch (Exception arg)
			{
				CommandFrameworkPlugin.LogError($"[CommandFrameworkAPI] Error executing command '{action.Id}': {arg}");
			}
		}

		public static UnitOrderState GetOrderState(Unit unit)
		{
			return UnitStateManager.GetOrCreateState(unit);
		}

		public static void SetCustomOrderState(Unit unit, string stateKey, string stateLabel = null, Color? stateColor = null)
		{
			UnitStateManager.SetCustomState(unit, stateKey, stateLabel, stateColor);
		}

		public static void ClearCustomOrderState(Unit unit)
		{
			UnitStateManager.ClearCustomState(unit);
		}

		public static void SetHoldPosition(Unit unit, bool hold)
		{
			HoldPositionManager.SetHoldPosition(unit, hold);
		}

		public static bool IsHoldingPosition(Unit unit)
		{
			return HoldPositionManager.IsHoldingPosition(unit);
		}

		public static void NudgeAI(Unit unit)
		{
			HoldPositionManager.NudgeAI(unit);
		}

		public static void RegisterOrderFilter(Func<Unit, GlobalPosition, bool> filter)
		{
			if (filter != null && !_orderFilters.Contains(filter))
			{
				_orderFilters.Add(filter);
			}
		}

		public static bool IsDestinationAllowed(Unit unit, GlobalPosition targetPosition)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)unit == (Object)null)
			{
				return true;
			}
			if (HoldPositionManager.IsHoldingPosition(unit))
			{
				return false;
			}
			foreach (Func<Unit, GlobalPosition, bool> orderFilter in _orderFilters)
			{
				try
				{
					if (!orderFilter(unit, targetPosition))
					{
						return false;
					}
				}
				catch (Exception arg)
				{
					CommandFrameworkPlugin.LogError($"[CommandFrameworkAPI] Error in OrderFilter: {arg}");
				}
			}
			return true;
		}
	}
	public interface IUnitCommandAction
	{
		string Id { get; }

		int Priority { get; }

		string GetDisplayName(Unit unit);

		bool IsVisible(Unit unit);

		bool IsEnabled(Unit unit);

		Color? GetButtonColor(Unit unit);

		void Execute(Unit unit);
	}
	public class UnitOrderState
	{
		public Unit Unit { get; }

		public bool IsHoldPosition { get; set; }

		public string CustomStateKey { get; set; } = null;

		public string CustomStateLabel { get; set; } = null;

		public Color? CustomStateColor { get; set; } = null;

		public Dictionary<string, object> CustomData { get; } = new Dictionary<string, object>();

		public UnitOrderState(Unit unit)
		{
			Unit = unit;
		}

		public T GetData<T>(string key, T defaultValue = default(T))
		{
			if (CustomData.TryGetValue(key, out var value) && value is T result)
			{
				return result;
			}
			return defaultValue;
		}

		public void SetData(string key, object value)
		{
			CustomData[key] = value;
		}

		public bool HasData(string key)
		{
			return CustomData.ContainsKey(key);
		}

		public bool RemoveData(string key)
		{
			return CustomData.Remove(key);
		}
	}
	public static class UnitStateManager
	{
		private static readonly Dictionary<Unit, UnitOrderState> _states = new Dictionary<Unit, UnitOrderState>();

		public static event Action<Unit, UnitOrderState> OnUnitStateCreated;

		public static event Action<Unit, string> OnCustomStateChanged;

		public static UnitOrderState GetOrCreateState(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return null;
			}
			PruneDeadUnits();
			if (!_states.TryGetValue(unit, out var value))
			{
				value = new UnitOrderState(unit);
				_states[unit] = value;
				UnitStateManager.OnUnitStateCreated?.Invoke(unit, value);
			}
			return value;
		}

		public static bool TryGetState(Unit unit, out UnitOrderState state)
		{
			if ((Object)(object)unit == (Object)null)
			{
				state = null;
				return false;
			}
			return _states.TryGetValue(unit, out state);
		}

		public static void SetCustomState(Unit unit, string stateKey, string stateLabel = null, Color? stateColor = null)
		{
			if (!((Object)(object)unit == (Object)null))
			{
				UnitOrderState orCreateState = GetOrCreateState(unit);
				orCreateState.CustomStateKey = stateKey;
				orCreateState.CustomStateLabel = stateLabel ?? stateKey;
				orCreateState.CustomStateColor = stateColor;
				UnitStateManager.OnCustomStateChanged?.Invoke(unit, stateKey);
				CommandFrameworkPlugin.LogInfo("[CommandFramework] Custom state '" + stateKey + "' set on unit '" + unit.NetworkunitName + "'.");
			}
		}

		public static void ClearCustomState(Unit unit)
		{
			if (!((Object)(object)unit == (Object)null) && _states.TryGetValue(unit, out var value))
			{
				value.CustomStateKey = null;
				value.CustomStateLabel = null;
				value.CustomStateColor = null;
				UnitStateManager.OnCustomStateChanged?.Invoke(unit, null);
			}
		}

		public static void PruneDeadUnits()
		{
			if (_states.Count == 0)
			{
				return;
			}
			List<Unit> list = new List<Unit>();
			foreach (KeyValuePair<Unit, UnitOrderState> state in _states)
			{
				if ((Object)(object)state.Key == (Object)null || state.Key.disabled)
				{
					list.Add(state.Key);
				}
			}
			foreach (Unit item in list)
			{
				_states.Remove(item);
			}
		}

		public static void ClearAll()
		{
			_states.Clear();
		}
	}
}