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();
}
}
}