using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using HarmonyLib; using NuclearOption.Chat; using NuclearOption.Networking; using NuclearOption.SavedMission.ObjectiveV2; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GlassPanel")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.8.0.0")] [assembly: AssemblyInformationalVersion("1.8.0+71ddbeaf6d5dc173f4b567b92a2464a23ce7d1c1")] [assembly: AssemblyProduct("NO Glass Panel")] [assembly: AssemblyTitle("GlassPanel")] [assembly: AssemblyVersion("1.8.0.0")] namespace GlassPanel; internal static class ChatBridge { private struct Line { public string who; public string msg; } private static readonly List _lines = new List(); private static readonly object _lock = new object(); private const int MAX = 40; public static void Add(string who, string msg) { if (string.IsNullOrEmpty(msg)) { return; } lock (_lock) { _lines.Add(new Line { who = (who ?? ""), msg = msg }); if (_lines.Count > 40) { _lines.RemoveAt(0); } } } public static string BuildJson() { lock (_lock) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < _lines.Count; i++) { if (i > 0) { stringBuilder.Append(','); } stringBuilder.Append("{\"who\":\"").Append(Esc(_lines[i].who)).Append("\",\"msg\":\"") .Append(Esc(_lines[i].msg)) .Append("\"}"); } return stringBuilder.ToString(); } } private static string Esc(string s) { if (s != null) { return s.Replace("\\", "\\\\").Replace("\"", "\\\""); } return ""; } public static void Send(string text, bool allChat) { try { if (!string.IsNullOrEmpty(text) && ChatManager.CanSend(text, false, false)) { ChatManager.SendChatMessage(text, allChat); } } catch { } } } [HarmonyPatch(typeof(ChatManager), "UserCode_TargetReceiveMessage_1307761090")] internal static class Patch_ReceiveMessage { private static void Postfix(string message, Player player, bool allChat) { string who = "?"; try { if ((Object)(object)player != (Object)null) { who = player.PlayerName; } } catch { } ChatBridge.Add(who, message); } } [HarmonyPatch(typeof(ChatManager), "UserCode_RpcServerMessage_1244201393")] internal static class Patch_ServerMessage { private static void Postfix(string message) { ChatBridge.Add("SERVER", message); } } [HarmonyPatch(typeof(WeaponIndicator), "Show")] internal static class Patch_HideWeaponIndicator { private static void Prefix(ref bool arg) { if (Plugin.HideWeaponHMD) { arg = false; } } } internal class MiniServer { private const string WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; private readonly int _port; private readonly byte[] _pageBytes; private readonly List _clients = new List(); private readonly object _lock = new object(); private Socket _listen; private Thread _acceptThread; private volatile bool _running; public Action OnMessage; public int ClientCount { get { lock (_lock) { return _clients.Count; } } } public MiniServer(int port, string pageHtml) { _port = port; _pageBytes = Encoding.UTF8.GetBytes(pageHtml ?? ""); } public void Start() { try { _running = true; _listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _listen.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true); _listen.Bind(new IPEndPoint(IPAddress.Any, _port)); _listen.Listen(16); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("MiniServer LISTENING on " + _listen.LocalEndPoint)); } _acceptThread = new Thread(AcceptLoop) { IsBackground = true, Name = "GlassPanel-accept" }; _acceptThread.Start(); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)("MiniServer bind FAILED: " + ex)); } } } public void Stop() { _running = false; try { _listen?.Close(); } catch { } lock (_lock) { foreach (Socket client in _clients) { try { client.Close(); } catch { } } _clients.Clear(); } } private void AcceptLoop() { while (_running) { Socket socket = null; try { socket = _listen.Accept(); } catch { if (!_running) { break; } Thread.Sleep(50); continue; } try { Handle(socket); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("client handle error: " + ex.Message)); } try { socket.Close(); } catch { } } } } private void Handle(Socket sock) { string text; using (NetworkStream stream = new NetworkStream(sock, ownsSocket: false)) { text = ReadHeaders(stream); } if (text == null) { sock.Close(); } else if (text.IndexOf("upgrade: websocket", StringComparison.OrdinalIgnoreCase) >= 0) { string text2 = ExtractHeader(text, "sec-websocket-key"); if (text2 == null) { sock.Close(); return; } string text3; using (SHA1 sHA = SHA1.Create()) { text3 = Convert.ToBase64String(sHA.ComputeHash(Encoding.UTF8.GetBytes(text2 + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))); } string s = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + text3 + "\r\n\r\n"; sock.Send(Encoding.ASCII.GetBytes(s)); lock (_lock) { _clients.Add(sock); } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("panel connected (" + ClientCount + " total)")); } Thread thread = new Thread((ThreadStart)delegate { ReadLoop(sock); }); thread.IsBackground = true; thread.Name = "GlassPanel-read"; thread.Start(); } else { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("HTTP/1.1 200 OK\r\n"); stringBuilder.Append("Content-Type: text/html; charset=utf-8\r\n"); stringBuilder.Append("Content-Length: ").Append(_pageBytes.Length).Append("\r\n"); stringBuilder.Append("Cache-Control: no-cache\r\nConnection: close\r\n\r\n"); sock.Send(Encoding.ASCII.GetBytes(stringBuilder.ToString())); sock.Send(_pageBytes); sock.Close(); } } private static string ReadHeaders(NetworkStream stream) { byte[] array = new byte[4096]; StringBuilder stringBuilder = new StringBuilder(); stream.ReadTimeout = 5000; while (stringBuilder.Length < 16384) { int num; try { num = stream.Read(array, 0, array.Length); } catch { return null; } if (num <= 0) { break; } stringBuilder.Append(Encoding.ASCII.GetString(array, 0, num)); if (stringBuilder.ToString().IndexOf("\r\n\r\n", StringComparison.Ordinal) >= 0) { break; } } if (stringBuilder.Length != 0) { return stringBuilder.ToString(); } return null; } private static string ExtractHeader(string request, string name) { string[] array = request.Split(new string[1] { "\r\n" }, StringSplitOptions.None); foreach (string text in array) { int num = text.IndexOf(':'); if (num > 0 && text.Substring(0, num).Trim().Equals(name, StringComparison.OrdinalIgnoreCase)) { return text.Substring(num + 1).Trim(); } } return null; } public void Broadcast(string message) { byte[] buffer = EncodeTextFrame(message); lock (_lock) { for (int num = _clients.Count - 1; num >= 0; num--) { Socket socket = _clients[num]; try { socket.Send(buffer); } catch { try { socket.Close(); } catch { } _clients.RemoveAt(num); } } } } private void ReadLoop(Socket sock) { try { NetworkStream networkStream = new NetworkStream(sock, ownsSocket: false); while (_running && sock.Connected) { int num = networkStream.ReadByte(); if (num < 0) { break; } int num2 = networkStream.ReadByte(); if (num2 < 0) { break; } int num3 = num & 0xF; bool flag = (num2 & 0x80) != 0; long num4 = num2 & 0x7F; switch (num4) { case 126L: num4 = (ReadN(networkStream) << 8) | ReadN(networkStream); break; case 127L: { num4 = 0L; for (int i = 0; i < 8; i++) { num4 = (num4 << 8) | ReadN(networkStream); } break; } } if (num4 < 0 || num4 > 65536) { break; } byte[] array = new byte[4]; if (flag) { ReadFull(networkStream, array, 4); } byte[] array2 = new byte[num4]; ReadFull(networkStream, array2, (int)num4); if (flag) { for (int j = 0; j < num4; j++) { array2[j] ^= array[j & 3]; } } switch (num3) { case 1: if (OnMessage != null) { OnMessage(Encoding.UTF8.GetString(array2)); } break; case 8: return; } } } catch { } finally { lock (_lock) { _clients.Remove(sock); } try { sock.Close(); } catch { } } } private static int ReadN(NetworkStream ns) { int num = ns.ReadByte(); if (num < 0) { throw new IOException(); } return num; } private static void ReadFull(NetworkStream ns, byte[] buf, int count) { int num; for (int i = 0; i < count; i += num) { num = ns.Read(buf, i, count - i); if (num <= 0) { throw new IOException(); } } } private static byte[] EncodeTextFrame(string message) { byte[] bytes = Encoding.UTF8.GetBytes(message); int num = bytes.Length; byte[] array = ((num < 126) ? new byte[2] { 129, (byte)num } : ((num > 65535) ? new byte[10] { 129, 127, 0, 0, 0, 0, (byte)(num >> 24), (byte)(num >> 16), (byte)(num >> 8), (byte)(num & 0xFF) } : new byte[4] { 129, 126, (byte)(num >> 8), (byte)(num & 0xFF) })); byte[] array2 = new byte[array.Length + num]; Array.Copy(array, array2, array.Length); Array.Copy(bytes, 0, array2, array.Length, num); return array2; } } [BepInPlugin("ai.fireballz.noglasspanel", "NO Glass Panel", "1.8.1")] [BepInProcess("NuclearOption.exe")] public class Plugin : BaseUnityPlugin { public const string GUID = "ai.fireballz.noglasspanel"; internal static ManualLogSource Log; internal static bool HideWeaponHMD; private MiniServer _server; private TelemetryReader _reader; private float _accum; private float _interval = 1f / 30f; private readonly Queue _inbox = new Queue(); private readonly object _inboxLock = new object(); private Aircraft _subAircraft; private Action _radarHandler; private void Awake() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; GameObject managerObject = Chainloader.ManagerObject; if ((Object)(object)managerObject != (Object)null) { ((Object)managerObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)managerObject); } int value = ((BaseUnityPlugin)this).Config.Bind("Server", "Port", 8787, "TCP port serving the panel page (HTTP) and the live feed (WebSocket) on the same port.").Value; float value2 = ((BaseUnityPlugin)this).Config.Bind("Server", "UpdateHz", 30f, "Telemetry frames per second pushed to connected panels.").Value; _interval = 1f / Mathf.Max(1f, value2); HideWeaponHMD = ((BaseUnityPlugin)this).Config.Bind("HMD", "HideWeaponAmmo", false, "Hide the weapon/ammo indicator on the in-game HMD (it lives on the panel instead).").Value; _reader = new TelemetryReader(); _server = new MiniServer(value, LoadPanelHtml()); _server.OnMessage = OnPanelMessage; _server.Start(); try { new Harmony("ai.fireballz.noglasspanel").PatchAll(); } catch (Exception ex) { Log.LogWarning((object)("chat receive patch skipped: " + ex.Message)); } Log.LogInfo((object)$"Glass Panel up. On the laptop, open http://:{value}"); } private void Update() { if (_server == null) { return; } lock (_inboxLock) { while (_inbox.Count > 0) { HandlePanelMessage(_inbox.Dequeue()); } } EnsureRadarSub(); _accum += Time.unscaledDeltaTime; if (_accum < _interval) { return; } _accum = 0f; if (_server.ClientCount != 0) { string text = _reader.BuildFrame(); if (text != null) { _server.Broadcast(text); } } } private void OnDestroy() { _server?.Stop(); } private void OnPanelMessage(string msg) { lock (_inboxLock) { if (_inbox.Count < 32) { _inbox.Enqueue(msg); } } } private void EnsureRadarSub() { try { Aircraft val = default(Aircraft); GameManager.GetLocalAircraft(ref val); if (val == _subAircraft) { return; } if ((Object)(object)_subAircraft != (Object)null && _radarHandler != null) { _subAircraft.onRadarWarning -= _radarHandler; } _subAircraft = val; if (!((Object)(object)val != (Object)null)) { return; } if (_radarHandler == null) { _radarHandler = delegate(OnRadarWarning w) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) RadarWarnTracker.Mark(w.radar); }; } val.onRadarWarning += _radarHandler; } catch { } } private static void HandlePanelMessage(string json) { if (json == null) { return; } if (json.IndexOf("\"cmd\"", StringComparison.Ordinal) >= 0) { HandleCommand(json); } else { if (json.IndexOf("\"chat\"", StringComparison.Ordinal) < 0) { return; } bool allChat = json.IndexOf("\"all\":true", StringComparison.Ordinal) >= 0; int num = json.IndexOf("\"text\":\"", StringComparison.Ordinal); if (num >= 0) { num += 8; int num2 = json.LastIndexOf('"'); if (num2 > num) { ChatBridge.Send(json.Substring(num, num2 - num).Replace("\\\"", "\"").Replace("\\\\", "\\"), allChat); } } } } private static void HandleCommand(string json) { string text = Extract(json, "\"a\":\""); Aircraft val = default(Aircraft); if (text == null || !GameManager.GetLocalAircraft(ref val) || (Object)(object)val == (Object)null) { return; } try { switch (text) { case "gear": val.SetGear(!val.gearDeployed); break; case "wpn+": if ((Object)(object)val.weaponManager != (Object)null) { val.weaponManager.NextWeaponStation(); } break; case "wpn-": if ((Object)(object)val.weaponManager != (Object)null) { val.weaponManager.PreviousWeaponStation(); } break; case "cm": if (val.countermeasureManager != null) { val.countermeasureManager.PopFlares(); } break; } } catch { } } private static string Extract(string json, string marker) { int num = json.IndexOf(marker, StringComparison.Ordinal); if (num < 0) { return null; } num += marker.Length; int num2 = json.IndexOf('"', num); if (num2 <= num) { return null; } return json.Substring(num, num2 - num); } private static string LoadPanelHtml() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("GlassPanel.index.html"); if (stream == null) { return "

panel resource missing from mod build

"; } using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd(); } } internal static class RadarWarnTracker { private static readonly Dictionary _hits = new Dictionary(); private static readonly object _lock = new object(); private const float TTL = 4f; public static void Mark(Radar r) { if ((Object)(object)r == (Object)null) { return; } lock (_lock) { _hits[r] = Time.time; } } public static List Active() { List list = new List(); lock (_lock) { float time = Time.time; List list2 = null; foreach (KeyValuePair hit in _hits) { if ((Object)(object)hit.Key == (Object)null || time - hit.Value > 4f) { (list2 ?? (list2 = new List())).Add(hit.Key); } else { list.Add(hit.Key); } } if (list2 != null) { foreach (Radar item in list2) { _hits.Remove(item); } } } return list; } } internal class TelemetryReader { private const float MS_TO_KN = 1.943844f; private const float M_TO_FT = 3.28084f; private const float MS_TO_FTMIN = 196.8504f; private const float RAD_TO_DEG = 57.29578f; public string BuildFrame() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) Aircraft val = default(Aircraft); if (!GameManager.GetLocalAircraft(ref val) || (Object)(object)val == (Object)null) { return null; } Transform transform = ((Component)val).transform; Vector3 val2 = (((Object)(object)val.cockpit != (Object)null && (Object)(object)val.cockpit.rb != (Object)null) ? val.cockpit.rb.velocity : Vector3.zero); float speed = ((Unit)val).speed; float x = transform.eulerAngles.x; float z = transform.eulerAngles.z; float v = ((x > 180f) ? (360f - x) : (0f - x)); float v2 = ((z > 180f) ? (360f - z) : (0f - z)); float y = transform.eulerAngles.y; float v3 = 0f; if ((Object)(object)val.cockpit != (Object)null) { Vector3 val3 = ((Component)val.cockpit).transform.InverseTransformDirection(val2); v3 = Mathf.Atan2(val3.y, val3.z) * -57.29578f; } ControlInputs inputs = val.GetInputs(); float num = GlobalPositionExtensions.GlobalY(transform.position); float num2 = Mathf.Pow(Mathf.Max(0.05f, 1f - 2.25577E-05f * Mathf.Max(0f, num)), 4.2561f); List list = new List(28); list.Add(Num("tas", speed * 1.943844f)); list.Add(Num("ias", speed * Mathf.Sqrt(num2) * 1.943844f)); list.Add(Num("mach", speed / 340f)); list.Add(Num("alt", GlobalPositionExtensions.GlobalY(transform.position) * 3.28084f)); list.Add(Num("agl", Mathf.Max(0f, ((Unit)val).radarAlt) * 3.28084f)); list.Add(Num("vs", val2.y * 196.8504f)); list.Add(Num("hdg", y)); list.Add(Num("pitch", v)); list.Add(Num("roll", v2)); list.Add(Num("aoa", v3)); list.Add(Num("g", val.gForce)); list.Add(Num("engine", EngineThrustKN(val))); list.Add(Num("throttle", inputs.throttle)); list.Add(Bool("gear", val.gearDeployed)); list.Add(Num("fuelKg", val.GetFuelQuantity())); list.Add("\"inputs\":{" + Num("pitch", inputs.pitch) + "," + Num("roll", inputs.roll) + "," + Num("yaw", inputs.yaw) + "," + Num("throttle", inputs.throttle) + "}"); list.Add("\"weapons\":[" + BuildLoadout(val, out var selIndex) + "]"); list.Add(Int("weaponIndex", selIndex)); int flares = 0; int chaff = 0; int flaresMax = 0; int chaffMax = 0; ReadCountermeasures(val, ref flares, ref chaff, ref flaresMax, ref chaffMax); list.Add(Int("flares", flares)); list.Add(Int("chaff", chaff)); list.Add(Int("flaresMax", (flaresMax <= 0) ? 1 : flaresMax)); list.Add(Int("chaffMax", (chaffMax <= 0) ? 1 : chaffMax)); list.Add("\"contacts\":[" + BuildContacts(val) + "]"); list.Add("\"rwr\":[" + BuildRWR(val) + "]"); list.Add(BuildDamage(val)); list.Add("\"chat\":[" + ChatBridge.BuildJson() + "]"); list.Add("\"datalink\":[" + BuildDatalink(val) + "]"); list.Add(BuildNav(val)); list.Add("\"objectives\":[" + BuildObjectives() + "]"); return "{" + string.Join(",", list.ToArray()) + "}"; } private static float EngineThrustKN(Aircraft ac) { try { float num = 0f; if (ac.engines != null) { foreach (IEngine engine in ac.engines) { if (engine != null) { num += engine.GetThrust(); } } } return num / 1000f; } catch { return 0f; } } private static string BuildLoadout(Aircraft ac, out int selIndex) { selIndex = 0; try { List weaponStations = ((Unit)ac).weaponStations; if (weaponStations == null) { return BuildSelectedWeapon(ac); } WeaponStation val = (((Object)(object)ac.weaponManager != (Object)null) ? ac.weaponManager.currentWeaponStation : null); List list = new List(); foreach (WeaponStation item in weaponStations) { if (item != null && !((Object)(object)item.WeaponInfo == (Object)null)) { string text = ((!string.IsNullOrEmpty(item.WeaponInfo.weaponName)) ? item.WeaponInfo.weaponName : item.WeaponInfo.shortName); if (val != null && item == val) { selIndex = list.Count; } list.Add("{" + Str("name", text ?? "-") + "," + Int("ammo", item.Ammo) + "," + Str("unit", "") + "}"); } } return (list.Count > 0) ? string.Join(",", list.ToArray()) : BuildSelectedWeapon(ac); } catch { selIndex = 0; return BuildSelectedWeapon(ac); } } private static string BuildSelectedWeapon(Aircraft ac) { WeaponManager weaponManager = ac.weaponManager; WeaponStation val = (((Object)(object)weaponManager != (Object)null) ? weaponManager.currentWeaponStation : null); if (val == null || (Object)(object)val.WeaponInfo == (Object)null) { return ""; } string text = ((!string.IsNullOrEmpty(val.WeaponInfo.weaponName)) ? val.WeaponInfo.weaponName : val.WeaponInfo.shortName); return "{" + Str("name", text ?? "-") + "," + Int("ammo", val.Ammo) + "," + Str("unit", "RDS") + "}"; } private static void ReadCountermeasures(Aircraft ac, ref int flares, ref int chaff, ref int flaresMax, ref int chaffMax) { try { CountermeasureManager countermeasureManager = ac.countermeasureManager; if (countermeasureManager == null || !(typeof(CountermeasureManager).GetField("countermeasureStations", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(countermeasureManager) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { if (item != null) { Type type = item.GetType(); int num = (int)(type.GetField("ammo")?.GetValue(item) ?? ((object)0)); int num2 = (int)(type.GetField("maxAmmo")?.GetValue(item) ?? ((object)0)); if (type.GetField("threatTypes")?.GetValue(item) is List list && list.Exists((string x) => x?.ToLower().Contains("radar") ?? false)) { chaff += num; chaffMax += num2; } else { flares += num; flaresMax += num2; } } } } catch { } } private static string BuildContacts(Aircraft ac) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) try { WeaponManager weaponManager = ac.weaponManager; List list = (((Object)(object)weaponManager != (Object)null) ? weaponManager.GetTargetList() : null); if (list == null) { return ""; } List list2 = new List(); int num = 0; foreach (Unit item in list) { if (!((Object)(object)item == (Object)null) && num < 12) { num++; Vector3 val = ((Component)item).transform.position - ((Component)ac).transform.position; float magnitude = ((Vector3)(ref val)).magnitude; float v = (Mathf.Atan2(val.x, val.z) * 57.29578f + 360f) % 360f; list2.Add("{" + Num("brg", v) + "," + Num("rng", magnitude) + "," + Str("type", "H") + "}"); } } return string.Join(",", list2.ToArray()); } catch { return ""; } } private static string BuildRWR(Aircraft ac) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) try { List list = new List(); MissileWarning missileWarningSystem = ac.GetMissileWarningSystem(); if ((Object)(object)missileWarningSystem != (Object)null && missileWarningSystem.knownMissiles != null) { foreach (Missile knownMissile in missileWarningSystem.knownMissiles) { if (!((Object)(object)knownMissile == (Object)null)) { Vector3 val = ((Component)knownMissile).transform.position - ((Component)ac).transform.position; float v = (Mathf.Atan2(val.x, val.z) * 57.29578f + 360f) % 360f; list.Add("{" + Num("brg", v) + "," + Str("band", "M") + "," + Int("lock", 2) + "}"); } } } foreach (Radar item in RadarWarnTracker.Active()) { if (!((Object)(object)item == (Object)null)) { Vector3 val2 = ((Component)item).transform.position - ((Component)ac).transform.position; float v2 = (Mathf.Atan2(val2.x, val2.z) * 57.29578f + 360f) % 360f; list.Add("{" + Num("brg", v2) + "," + Str("band", "R") + "," + Int("lock", 1) + "}"); } } return string.Join(",", list.ToArray()); } catch { return ""; } } private static string BuildDatalink(Aircraft ac) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) try { FactionHQ networkHQ = ((Unit)ac).NetworkHQ; if ((Object)(object)networkHQ == (Object)null || networkHQ.trackingDatabase == null) { return ""; } Faction faction = networkHQ.faction; List list = new List(); int num = 0; Unit val = default(Unit); foreach (KeyValuePair item in networkHQ.trackingDatabase) { if (num < 40) { TrackingInfo value = item.Value; if (value != null && value.TryGetUnit(ref val) && !((Object)(object)val == (Object)null) && (object)val != ac) { Vector3 val2 = ((Component)val).transform.position - ((Component)ac).transform.position; float magnitude = ((Vector3)(ref val2)).magnitude; float v = (Mathf.Atan2(val2.x, val2.z) * 57.29578f + 360f) % 360f; Faction val3 = (((Object)(object)val.NetworkHQ != (Object)null) ? val.NetworkHQ.faction : null); string v2 = (((Object)(object)faction != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)faction == (Object)(object)val3) ? "F" : "H"); list.Add("{" + Num("brg", v) + "," + Num("rng", magnitude) + "," + Str("type", v2) + "}"); num++; } continue; } break; } return string.Join(",", list.ToArray()); } catch { return ""; } } private static string BuildDamage(Aircraft ac) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) float v = 1f; float v2 = 1f; float v3 = 1f; float v4 = 1f; float v5 = 1f; float v6 = 1f; string v7 = ""; string v8 = ""; try { if (ac.partDamageTracker != null) { v = 1f - ac.partDamageTracker.GetDetachedRatio(); } if ((Object)(object)ac.definition != (Object)null) { v7 = ((UnitDefinition)ac.definition).unitName ?? ""; v8 = ((UnitDefinition)ac.definition).code ?? ""; } foreach (UnitPart allPart in ((Unit)ac).GetAllParts()) { if (!((Object)(object)allPart == (Object)null) && allPart.IsDetached()) { Vector3 localPosition = ((Component)allPart).transform.localPosition; if (localPosition.x < -0.8f) { v3 = 0f; } else if (localPosition.x > 0.8f) { v4 = 0f; } else if (localPosition.z > 1f) { v2 = 0f; } else if (localPosition.z < -1f) { v5 = 0f; } else { v6 = 0.3f; } } } } catch { } return "\"damage\":{" + Num("hull", v) + "," + Str("name", v7) + "," + Str("code", v8) + ",\"sections\":{" + Num("nose", v2) + "," + Num("lwing", v3) + "," + Num("rwing", v4) + "," + Num("tail", v5) + "," + Num("engine", v6) + "}}"; } private static string BuildNav(Aircraft ac) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) try { FactionHQ networkHQ = ((Unit)ac).NetworkHQ; Airbase val = default(Airbase); if ((Object)(object)networkHQ != (Object)null && networkHQ.TryGetNearestAirbase(((Component)ac).transform.position, ref val, default(RunwayQuery)) && (Object)(object)val != (Object)null && (Object)(object)val.center != (Object)null) { Vector3 val2 = val.center.position - ((Component)ac).transform.position; float magnitude = ((Vector3)(ref val2)).magnitude; float v = (Mathf.Atan2(val2.x, val2.z) * 57.29578f + 360f) % 360f; string networknetworkUniqueName = val.NetworknetworkUniqueName; return "\"nav\":{" + Str("name", string.IsNullOrEmpty(networknetworkUniqueName) ? "BASE" : networknetworkUniqueName) + "," + Num("brg", v) + "," + Num("rng", magnitude) + "}"; } } catch { } return "\"nav\":null"; } private static string BuildObjectives() { try { MissionObjectives objectives = MissionManager.Objectives; if (objectives == null || objectives.AllObjectives == null) { return ""; } List list = new List(); foreach (Objective allObjective in objectives.AllObjectives) { if (allObjective == null) { continue; } string text = null; try { text = allObjective.ToUIString(false); } catch { } if (string.IsNullOrEmpty(text)) { try { text = ((object)allObjective).ToString(); } catch { } } string v = ""; try { v = ((object)Unsafe.As(ref allObjective.Status)/*cast due to .constrained prefix*/).ToString(); } catch { } float v2 = 0f; try { v2 = allObjective.CompletePercent; } catch { } list.Add("{" + Str("text", text ?? "") + "," + Str("status", v) + "," + Num("pct", v2) + "}"); } return string.Join(",", list.ToArray()); } catch { return ""; } } private static string Num(string k, float v) { if (float.IsNaN(v) || float.IsInfinity(v)) { v = 0f; } return "\"" + k + "\":" + v.ToString("0.###", CultureInfo.InvariantCulture); } private static string Int(string k, int v) { return "\"" + k + "\":" + v.ToString(CultureInfo.InvariantCulture); } private static string Bool(string k, bool v) { return "\"" + k + "\":" + (v ? "true" : "false"); } private static string Str(string k, string v) { return "\"" + k + "\":\"" + Esc(v) + "\""; } private static string Esc(string s) { if (s != null) { return s.Replace("\\", "\\\\").Replace("\"", "\\\""); } return ""; } }