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(); 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 _heldUnits = new HashSet(); public static event Action 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(); 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(); 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(); 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(); 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(); 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(); 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.i != (Object)null) { SceneSingleton.i.UnselectAll(); SceneSingleton.i.DeselectAllIcons(); } if ((Object)(object)SceneSingleton.i != (Object)null) { if ((Object)(object)SceneSingleton.i.aircraft != (Object)null) { SceneSingleton.i.DeselectAll(true); } else if (AccessTools.Field(typeof(CombatHUD), "targetList")?.GetValue(SceneSingleton.i) is IList list) { list.Clear(); } } if ((Object)(object)SceneSingleton.i != (Object)null) { SceneSingleton.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(); } Instance._targetUnit = unit; Instance._isOpen = true; List 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()); GUILayout.Label(text.ToUpper(), _headerStyle, Array.Empty()); GUILayout.Space(4f); List 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(); 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(); 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(); 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.i != (Object)null && SceneSingleton.i.mapIcons != null) { Vector3 mousePosition = Input.mousePosition; float num = 3600f; Unit val = null; List mapIcons = SceneSingleton.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(); 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 _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(__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 _registeredCommands; private static readonly List> _orderFilters; public static event Action OnCommandExecuted; public static event Action OnHoldPositionChanged; public static event Action OnCustomOrderStateChanged; static CommandFrameworkAPI() { _registeredCommands = new List(); _orderFilters = new List>(); 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 GetVisibleCommandsForUnit(Unit unit) { List list = new List(); 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 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 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 CustomData { get; } = new Dictionary(); public UnitOrderState(Unit unit) { Unit = unit; } public T GetData(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 _states = new Dictionary(); public static event Action OnUnitStateCreated; public static event Action 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 list = new List(); foreach (KeyValuePair 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(); } } }