From 5d173d6fd3a8eaf23a2c34e6fcf2f8becdc80feb Mon Sep 17 00:00:00 2001 From: InvalidArgument3 Date: Sat, 26 Oct 2024 21:24:30 -0500 Subject: [PATCH] cgp unload checks --- .../HeartNetworking/HeartNetwork.cs | 61 ++++--- .../Data/Scripts/ShipPoints/Logger.cs | 161 +++++++----------- .../Data/minified_output.txt | 20 +++ 3 files changed, 115 insertions(+), 127 deletions(-) create mode 100644 ConfigurableGridPoints/Data/minified_output.txt diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/HeartNetworking/HeartNetwork.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/HeartNetworking/HeartNetwork.cs index 54053e3b..d072a675 100644 --- a/ConfigurableGridPoints/Data/Scripts/ShipPoints/HeartNetworking/HeartNetwork.cs +++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/HeartNetworking/HeartNetwork.cs @@ -21,19 +21,26 @@ public class HeartNetwork public ushort NetworkId { get; private set; } public int TotalNetworkLoad { get; private set; } - public void LoadData(ushort networkId) - { - I = this; + public void LoadData(ushort networkId) { + if (I != null) + return; + I = this; NetworkId = networkId; - MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(NetworkId, ReceivedPacket); - foreach (var type in PacketBase.Types) TypeNetworkLoad.Add(type, 0); + TypeNetworkLoad.Clear(); + foreach (var type in PacketBase.Types) + TypeNetworkLoad.Add(type, 0); + + MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(NetworkId, ReceivedPacket); } - public void UnloadData() - { - MyAPIGateway.Multiplayer.UnregisterSecureMessageHandler(NetworkId, ReceivedPacket); + public void UnloadData() { + if (NetworkId > 0) + MyAPIGateway.Multiplayer.UnregisterSecureMessageHandler(NetworkId, ReceivedPacket); + + TypeNetworkLoad?.Clear(); + NetworkId = 0; I = null; } @@ -54,29 +61,37 @@ public void Update() } } - private void ReceivedPacket(ushort channelId, byte[] serialized, ulong senderSteamId, bool isSenderServer) - { - try - { + private void ReceivedPacket(ushort channelId, byte[] serialized, ulong senderSteamId, bool isSenderServer) { + // Add check if mod is unloaded + if (MasterSession.I == null || Log.IsUnloaded) + return; + + try { var packet = MyAPIGateway.Utilities.SerializeFromBinary(serialized); - TypeNetworkLoad[packet.GetType()] += serialized.Length; + if (packet == null) + return; + + if (TypeNetworkLoad.ContainsKey(packet.GetType())) + TypeNetworkLoad[packet.GetType()] += serialized.Length; + HandlePacket(packet, senderSteamId); } - catch (Exception ex) - { - Log.Error(ex); + catch (Exception ex) { + if (!Log.IsUnloaded) + Log.Error(ex); } } - private void HandlePacket(PacketBase packet, ulong senderSteamId) - { - try - { + private void HandlePacket(PacketBase packet, ulong senderSteamId) { + if (packet == null || MasterSession.I == null) + return; + + try { packet.Received(senderSteamId); } - catch (Exception ex) - { - Log.Error(ex); + catch (Exception ex) { + if (!Log.IsUnloaded) + Log.Error(ex); } } diff --git a/ConfigurableGridPoints/Data/Scripts/ShipPoints/Logger.cs b/ConfigurableGridPoints/Data/Scripts/ShipPoints/Logger.cs index 120e997b..4636c9aa 100644 --- a/ConfigurableGridPoints/Data/Scripts/ShipPoints/Logger.cs +++ b/ConfigurableGridPoints/Data/Scripts/ShipPoints/Logger.cs @@ -9,8 +9,7 @@ using VRage.Game.ModAPI; using VRage.Utils; -namespace CGP.ShareTrack -{ +namespace CGP.ShareTrack { /// /// Standalone logger, does not require any setup. /// @@ -20,8 +19,7 @@ namespace CGP.ShareTrack /// Version 1.52 by Digi /// [MySessionComponentDescriptor(MyUpdateOrder.NoUpdate, int.MaxValue)] - public class Log : MySessionComponentBase - { + public class Log : MySessionComponentBase { private const int DefaultTimeInfo = 3000; private const int DefaultTimeError = 10000; @@ -40,17 +38,16 @@ public class Log : MySessionComponentBase private static Log _instance; private static Handler _handler; private static bool _unloaded; + public bool IsUnloaded { get; set; } public static readonly string File = GenerateTimestampedFileName(); - private static string GenerateTimestampedFileName() - { + private static string GenerateTimestampedFileName() { var timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); return $"[{timestamp}]-Sharetrack.log"; } - private class Handler - { + private class Handler { private readonly StringBuilder _sb = new StringBuilder(64); private string _errorPrintText; private int _indent; @@ -68,23 +65,19 @@ private class Handler public ulong WorkshopId { get; private set; } - public string ModName - { + public string ModName { get { return _modName; } - set - { + set { _modName = value; ComputeErrorPrintText(); } } - public void Init(Log sessionComp) - { + public void Init(Log sessionComp) { if (_writer != null) return; // already initialized - if (MyAPIGateway.Utilities == null) - { + if (MyAPIGateway.Utilities == null) { Error("MyAPIGateway.Utilities is NULL !"); return; } @@ -100,8 +93,7 @@ public void Init(Log sessionComp) #region Pre-init messages - if (_preInitMessages != null) - { + if (_preInitMessages != null) { var warning = $"{_modName} WARNING: there are log messages before the mod initialized!"; Info("--- pre-init messages ---"); @@ -155,10 +147,8 @@ public void Init(Log sessionComp) #endregion } - public void Close() - { - if (_writer != null) - { + public void Close() { + if (_writer != null) { Info("Unloaded."); _writer.Flush(); @@ -167,30 +157,25 @@ public void Close() } } - private void ComputeErrorPrintText() - { + private void ComputeErrorPrintText() { _errorPrintText = $"[ {_modName} ERROR, report contents of: %AppData%/SpaceEngineers/Storage/{MyAPIGateway.Utilities.GamePaths.ModScopeName}/{File} ]"; } - public void IncreaseIndent() - { + public void IncreaseIndent() { _indent++; } - public void DecreaseIndent() - { + public void DecreaseIndent() { if (_indent > 0) _indent--; } - public void ResetIndent() - { + public void ResetIndent() { _indent = 0; } - public void Error(string message, string printText = PrintError, int printTime = DefaultTimeError) - { + public void Error(string message, string printText = PrintError, int printTime = DefaultTimeError) { MyLog.Default.WriteLineAndConsole(_modName + " error/exception: " + message); // write to game's log LogMessage(message, "ERROR: "); // write to custom log @@ -199,8 +184,7 @@ public void Error(string message, string printText = PrintError, int printTime = ShowHudMessage(ref _notifyError, message, printText, printTime, MyFontEnum.Red); } - public void Info(string message, string printText = null, int printTime = DefaultTimeInfo) - { + public void Info(string message, string printText = null, int printTime = DefaultTimeInfo) { LogMessage(message); // write to custom log if (printText != null) // printing to HUD is optional @@ -208,26 +192,21 @@ public void Info(string message, string printText = null, int printTime = Defaul } private void ShowHudMessage(ref IMyHudNotification notify, string message, string printText, int printTime, - string font) - { + string font) { if (printText == null) return; - try - { - if (MyAPIGateway.Utilities != null && !MyAPIGateway.Utilities.IsDedicated) - { + try { + if (MyAPIGateway.Utilities != null && !MyAPIGateway.Utilities.IsDedicated) { if (printText == PrintError) printText = _errorPrintText; else if (printText == PrintMsg) printText = $"[ {_modName} ERROR: {message} ]"; - if (notify == null) - { + if (notify == null) { notify = MyAPIGateway.Utilities.CreateNotification(printText, printTime, font); } - else - { + else { notify.Text = printText; notify.AliveTime = printTime; notify.ResetAliveTime(); @@ -236,8 +215,7 @@ private void ShowHudMessage(ref IMyHudNotification notify, string message, strin notify.Show(); } } - catch (Exception e) - { + catch (Exception e) { Info("ERROR: Could not send notification to local client: " + e); MyLog.Default.WriteLineAndConsole(_modName + " logger error/exception: Could not send notification to local client: " + @@ -245,10 +223,8 @@ private void ShowHudMessage(ref IMyHudNotification notify, string message, strin } } - private void LogMessage(string message, string prefix = null) - { - try - { + private void LogMessage(string message, string prefix = null) { + try { _sb.Clear(); _sb.Append(DateTime.Now.ToString("[HH:mm:ss] ")); @@ -263,30 +239,26 @@ private void LogMessage(string message, string prefix = null) _sb.Append(message); - if (_writer == null) - { + if (_writer == null) { if (_preInitMessages == null) _preInitMessages = new List(); _preInitMessages.Add(_sb.ToString()); } - else - { + else { _writer.WriteLine(_sb); _writer.Flush(); } _sb.Clear(); } - catch (Exception e) - { + catch (Exception e) { MyLog.Default.WriteLineAndConsole( $"{_modName} had an error while logging message = '{message}'\nLogger error: {e.Message}\n{e.StackTrace}"); } } - private ulong GetWorkshopId(string modId) - { + private ulong GetWorkshopId(string modId) { // NOTE workaround for MyModContext not having the actual workshop ID number. foreach (var mod in MyAPIGateway.Session.Mods) if (mod.Name == modId) @@ -298,24 +270,22 @@ private ulong GetWorkshopId(string modId) #region Handling of handler - public override void LoadData() - { + public override void LoadData() { _instance = this; EnsureHandlerCreated(); _handler.Init(this); } - protected override void UnloadData() - { + protected override void UnloadData() { + IsUnloaded = true; _instance = null; - - if (_handler != null && _handler.AutoClose) Unload(); + if (_handler != null && _handler.AutoClose) + Unload(); } - private void Unload() - { - try - { + + private void Unload() { + try { if (_unloaded) return; @@ -323,16 +293,14 @@ private void Unload() _handler?.Close(); _handler = null; } - catch (Exception e) - { - MyLog.Default.WriteLine( - $"Error in {ModContext.ModName} ({ModContext.ModId}): {e.Message}\n{e.StackTrace}"); + catch (Exception e) { + MyLog.Default.WriteLine($"Error in {ModContext.ModName} ({ModContext.ModId}): {e.Message}\n{e.StackTrace}"); throw new ModCrashedException(e, ModContext); } } - private static void EnsureHandlerCreated() - { + + private static void EnsureHandlerCreated() { if (_unloaded) throw new Exception("Digi.Log accessed after it was unloaded!"); @@ -348,8 +316,7 @@ private static void EnsureHandlerCreated() /// Manually unload the logger. Works regardless of , but if that property is false then this /// method must be called! /// - public static void Close() - { + public static void Close() { _instance?.Unload(); } @@ -357,15 +324,12 @@ public static void Close() /// Defines if the component self-unloads next tick or after . /// If set to false, you must call manually! /// - public static bool AutoClose - { - get - { + public static bool AutoClose { + get { EnsureHandlerCreated(); return _handler.AutoClose; } - set - { + set { EnsureHandlerCreated(); _handler.AutoClose = value; } @@ -375,15 +339,12 @@ public static bool AutoClose /// Sets/gets the mod name. /// This is optional as the mod name is generated from the folder/workshop name, but those can be weird or long. /// - public static string ModName - { - get - { + public static string ModName { + get { EnsureHandlerCreated(); return _handler.ModName; } - set - { + set { EnsureHandlerCreated(); _handler.ModName = value; } @@ -399,8 +360,7 @@ public static string ModName /// Increases indentation by 4 spaces. /// Each indent adds 4 space characters before each of the future messages. /// - public static void IncreaseIndent() - { + public static void IncreaseIndent() { EnsureHandlerCreated(); _handler.IncreaseIndent(); } @@ -409,8 +369,7 @@ public static void IncreaseIndent() /// Decreases indentation by 4 space characters down to 0 indentation. /// See /// - public static void DecreaseIndent() - { + public static void DecreaseIndent() { EnsureHandlerCreated(); _handler.DecreaseIndent(); } @@ -419,8 +378,7 @@ public static void DecreaseIndent() /// Resets the indentation to 0. /// See /// - public static void ResetIndent() - { + public static void ResetIndent() { EnsureHandlerCreated(); _handler.ResetIndent(); } @@ -436,8 +394,7 @@ public static void ResetIndent() /// /// How long to show the HUD notification for, in miliseconds. public static void Error(Exception exception, string printText = PrintError, - int printTimeMs = DefaultTimeError) - { + int printTimeMs = DefaultTimeError) { EnsureHandlerCreated(); _handler.Error(exception.ToString(), printText, printTimeMs); } @@ -451,8 +408,7 @@ public static void Error(Exception exception, string printText = PrintError, /// message arg, to use the predefined error message, or any other custom string. /// /// How long to show the HUD notification for, in miliseconds. - public static void Error(string message, string printText = PrintError, int printTimeMs = DefaultTimeError) - { + public static void Error(string message, string printText = PrintError, int printTimeMs = DefaultTimeError) { EnsureHandlerCreated(); _handler.Error(message, printText, printTimeMs); } @@ -467,8 +423,7 @@ public static void Error(string message, string printText = PrintError, int prin /// message arg or any other custom string. /// /// How long to show the HUD notification for, in miliseconds. - public static void Info(string message, string printText = null, int printTimeMs = DefaultTimeInfo) - { + public static void Info(string message, string printText = null, int printTimeMs = DefaultTimeInfo) { EnsureHandlerCreated(); _handler.Info(message, printText, printTimeMs); } @@ -479,12 +434,10 @@ public static void Info(string message, string printText = null, int printTimeMs /// The task to check for errors. /// Used in the reports. /// true if errors found, false otherwise. - public static bool TaskHasErrors(Task task, string taskName) - { + public static bool TaskHasErrors(Task task, string taskName) { EnsureHandlerCreated(); - if (task.Exceptions != null && task.Exceptions.Length > 0) - { + if (task.Exceptions != null && task.Exceptions.Length > 0) { foreach (var e in task.Exceptions) Error($"Error in {taskName} thread!\n{e}"); return true; diff --git a/ConfigurableGridPoints/Data/minified_output.txt b/ConfigurableGridPoints/Data/minified_output.txt new file mode 100644 index 00000000..39b48a37 --- /dev/null +++ b/ConfigurableGridPoints/Data/minified_output.txt @@ -0,0 +1,20 @@ +using System;using System.Collections.Generic;using System.Linq;using System.Text;using Sandbox.ModAPI;using CGP.ShareTrack.API;using CGP.ShareTrack.API.CoreSystem;using CGP.ShareTrack.HeartNetworking;using CGP.ShareTrack.HeartNetworking.Custom;using CGP.ShareTrack.ShipTracking;using VRage;using VRage.Game.ModAPI;using VRage.Input;using VRageMath;using BlendTypeEnum=VRageRender.MyBillboard.BlendTypeEnum;namespace CGP.ShareTrack{public class AllGridsList{public static AllGridsList I;public static DictionaryPointValues=new Dictionary();private static readonly DictionaryAllPlayers=new Dictionary();public static HudAPIv2.HUDMessage IntegretyMessage,TimerMessage,Ticketmessage;public static ShipTracker.NametagSettings NametagViewState=ShipTracker.NametagSettings.PlayerName;private readonly Dictionary_bp=new Dictionary();private readonly Dictionary_keyAndActionPairs=new Dictionary{[MyKeys.T]=()=>{I?._hudPointsList?.CycleViewState();},};private readonly List_listPlayers=new List();private readonly Dictionary_m=new Dictionary();private readonly Dictionary_mbp=new Dictionary();private readonly Dictionary_mobp=new Dictionary();private readonly Dictionary_obp=new Dictionary();private readonly Dictionary_pbp=new Dictionary();private readonly Dictionary>_ts=new Dictionary>();private bool _awaitingTrackRequest=true;private Func>_climbingCostFunction;private void ParsePointsDict(object message){try{var dict=message as Dictionary;if(dict!=null){PointValues=new Dictionary();foreach(var kvp in dict){AddFuzzyPointValue(kvp.Key,kvp.Value);}return;}var climbCostFunc=message as Func>;if(climbCostFunc!=null){_climbingCostFunction=climbCostFunc;}}catch(Exception ex){Log.Error(ex);}}private void AddFuzzyPointValue(string key,double value){foreach(var existingKey in PointValues.Keys.ToList()){if(existingKey.StartsWith(key,StringComparison.OrdinalIgnoreCase)){PointValues[existingKey]=value;}}PointValues[key]=value;}private void HudRegistered(){TrackingManager.Init();_hudPointsList=new HudPointsList();IntegretyMessage=new HudAPIv2.HUDMessage(scale:1.15f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(.51,.95),hideHud:false,blend:BlendTypeEnum.PostPP){Visible=true};TimerMessage=new HudAPIv2.HUDMessage(scale:1.2f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(0.35,.99),hideHud:false,shadowing:true,blend:BlendTypeEnum.PostPP){Visible=false,InitialColor=Color.White};Ticketmessage=new HudAPIv2.HUDMessage(scale:1f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(0.51,.99),hideHud:false,shadowing:true,blend:BlendTypeEnum.PostPP){Visible=false,InitialColor=Color.White};}private void HandleKeyInputs(){if(!MyAPIGateway.Input.IsAnyShiftKeyPressed())return;foreach(var pair in _keyAndActionPairs)if(MyAPIGateway.Input.IsNewKeyPressed(pair.Key))pair.Value.Invoke();}private void UpdateTrackingData(){if(MasterSession.I.Ticks%59!=0)return;lock(TrackingManager.I.TrackedGrids){foreach(var shipTracker in TrackingManager.I.TrackedGrids.Values){shipTracker.Update();}}if(IntegretyMessage==null||!MasterSession.I.TextHudApi.Heartbeat)return;var tt=new StringBuilder();_ts.Clear();_m.Clear();_bp.Clear();_mbp.Clear();_pbp.Clear();_obp.Clear();_mobp.Clear();MainTrackerUpdate(_ts,_m,_bp,_mbp,_pbp,_obp,_mobp);TeamBpCalc(tt,_ts,_m,_bp,_mbp,_pbp,_obp,_mobp);if(!IntegretyMessage.Message.Equals(tt)){IntegretyMessage.Message=tt;}IntegretyMessage.Origin=new Vector2D(0.975-IntegretyMessage.GetTextLength().X,IntegretyMessage.Origin.Y);}private void MainTrackerUpdate(Dictionary>ts,Dictionarym,Dictionarybp,Dictionarymbp,Dictionarypbp,Dictionaryobp,Dictionarymobp){foreach(var shipTracker in TrackingManager.I.TrackedGrids.Values){var fn=shipTracker.FactionName.Length>6?shipTracker.FactionName.Substring(0,6):shipTracker.FactionName;var o=shipTracker.OwnerName;var nd=shipTracker.IsFunctional;if(!ts.ContainsKey(fn)){ts.Add(fn,new List());m[fn]=0;bp[fn]=0;mbp[fn]=0;pbp[fn]=0;obp[fn]=0;mobp[fn]=0;}if(nd){m[fn]+=shipTracker.Mass;bp[fn]+=shipTracker.BattlePoints;}else{continue;}mbp[fn]+=shipTracker.RemainingPoints;pbp[fn]+=shipTracker.PowerPoints;obp[fn]+=shipTracker.OffensivePoints;mobp[fn]+=shipTracker.MovementPoints;var wep=0;foreach(var kvp in shipTracker.WeaponCounts){wep+=kvp.Value;}var pwr=FormatPower(Math.Round(shipTracker.TotalPower,1));var ts2=FormatThrust(Math.Round(shipTracker.TotalThrust,2));ts[fn].Add(CreateDisplayString(o,shipTracker,wep,pwr,ts2));}}private string FormatPower(double currentPower){return currentPower>1000?$"{Math.Round(currentPower/1000,1)}GW":$"{currentPower}MW";}private string FormatThrust(double installedThrust){var thrustInMega=Math.Round(installedThrust/1e6,1);return thrustInMega>1e2?$"{Math.Round(thrustInMega/1e3,2)}GN":$"{thrustInMega}MN";}private string CreateDisplayString(string ownerName,ShipTracker tracker,int wep,string power,string thrust){var ownerDisplay=ownerName!=null?ownerName.Substring(0,Math.Min(ownerName.Length,7)):tracker.GridName;var integrityPercent=(int)(tracker.GridIntegrity/tracker.OriginalGridIntegrity*100);var shieldPercent=(int)tracker.CurrentShieldPercent;var shieldColor=shieldPercent<=0?"red":$"{255},{255-tracker.CurrentShieldHeat*2.5f},{255-tracker.CurrentShieldHeat*2.5f}";var weaponColor=wep==0?"red":"Orange";var functionalColor=tracker.IsFunctional?"white":"red";var integrityColor=integrityPercent>=75?"White":integrityPercent>=50?"LightCoral":integrityPercent>=25?"IndianRed":"FireBrick";return$"{ownerDisplay,-8}{integrityPercent,3}% P:{power,3} T:{thrust,3} W:{wep} S:{shieldPercent,3}%";}private static void TeamBpCalc(StringBuilder tt,Dictionary>trackedShip,Dictionarym,Dictionarybp,Dictionarymbp,Dictionarypbp,Dictionaryobp,Dictionarymobp){foreach(var faction in trackedShip.Keys){if(trackedShip[faction]==null||trackedShip[faction].Count==0)continue;var msValue=m[faction]/1e6;var tbi=100f/bp[faction];tt.Append("---- ").Append(faction).Append(" : ").AppendFormat("{0:0.00}M : {1}bp [",msValue,bp[faction]);tt.AppendFormat("{0}%|",(int)(obp[faction]*tbi+0.5f)).AppendFormat("{0}%|",(int)(pbp[faction]*tbi+0.5f)).AppendFormat("{0}%|",(int)(mobp[faction]*tbi+0.5f)).AppendFormat("{0}%]",(int)(mbp[faction]*tbi+0.5f)).AppendLine(" ---------");foreach(var y in trackedShip[faction])tt.AppendLine(y);}}public static IMyPlayer GetOwner(long v){IMyPlayer owner;return AllPlayers.TryGetValue(v,out owner)?owner:null;}public static IMyCubeGrid RaycastGridFromCamera(){var camMat=MyAPIGateway.Session.Camera.WorldMatrix;var hits=new List();MyAPIGateway.Physics.CastRay(camMat.Translation,camMat.Translation+camMat.Forward*500,hits);foreach(var hit in hits){var grid=hit.HitEntity as IMyCubeGrid;if(grid?.Physics!=null)return grid;}return null;}public WcApi WcApi{get;private set;}public ShieldApi ShieldApi{get;private set;}public RtsApi RtsApi{get;private set;}private HudPointsList _hudPointsList;public void Init(){I=this;MasterSession.I.HudRegistered+=HudRegistered;MyAPIGateway.Utilities.ShowMessage("ShareTrack","Aim at a grid and press:"+"\n- Shift+T to show grid stats.");MyAPIGateway.Utilities.RegisterMessageHandler(2546247,ParsePointsDict);if(MyAPIGateway.Utilities.IsDedicated)TrackingManager.Init();WcApi=new WcApi();WcApi?.Load();ShieldApi=new ShieldApi();ShieldApi?.Load();RtsApi=new RtsApi();RtsApi?.Load();}public void Close(){Log.Info("Start PointCheck.UnloadData()");WcApi?.Unload();ShieldApi?.Unload();if(PointValues!=null){PointValues.Clear();AllPlayers.Clear();}MyAPIGateway.Utilities.UnregisterMessageHandler(2546247,ParsePointsDict);I=null;}public void UpdateAfterSimulation(){if(_awaitingTrackRequest&&!MyAPIGateway.Session.IsServer){HeartNetwork.I.SendToServer(new SyncRequestPacket());_awaitingTrackRequest=false;}try{UpdateTrackingData();}catch(Exception e){Log.Error($"Exception in UpdateAfterSimulation TryCatch 01: {e}");}try{if(MasterSession.I.Ticks%61==0){AllPlayers.Clear();MyAPIGateway.Multiplayer.Players.GetPlayers(_listPlayers,delegate(IMyPlayer p){AllPlayers.Add(p.IdentityId,p);return false;});}}catch(Exception e){Log.Error($"Exception in UpdateAfterSimulation TryCatch 02: {e}");}}public void Draw(){if(MyAPIGateway.Utilities.IsDedicated||!MasterSession.I.TextHudApi.Heartbeat)return;try{if(MyAPIGateway.Session?.Camera!=null&&MyAPIGateway.Session.CameraController!=null&&!MyAPIGateway.Gui.ChatEntryVisible&&!MyAPIGateway.Gui.IsCursorVisible&&MyAPIGateway.Gui.GetCurrentScreen==MyTerminalPageEnum.None)HandleKeyInputs();foreach(var tracker in TrackingManager.I.TrackedGrids.Values)tracker.UpdateHud();_hudPointsList?.UpdateDraw();}catch(Exception e){Log.Error($"Exception in Draw: {e}");}}public static void ClimbingCostRename(ref string blockDisplayName,ref float climbingCostMultiplier){if(I._climbingCostFunction==null)return;var results=I._climbingCostFunction.Invoke(blockDisplayName);blockDisplayName=results.Item1;climbingCostMultiplier=results.Item2;}}}using System.Text;using Sandbox.Game.Gui;using Sandbox.ModAPI;using CGP.ShareTrack.API;using VRageMath;using VRageRender;namespace CGP.ShareTrack{internal class BuildingBlockPoints{internal string LastHeldSubtype;private HudAPIv2.HUDMessage _pointsMessage;public BuildingBlockPoints(){MasterSession.I.HudRegistered+=()=>{_pointsMessage=new HudAPIv2.HUDMessage(scale:1f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(-0.969,0.57),blend:MyBillboard.BlendTypeEnum.PostPP);};}private int _ticks;public void Update(){if(_ticks++%10!=0)return;if(LastHeldSubtype!=MyHud.BlockInfo?.DefinitionId.SubtypeName){LastHeldSubtype=MyHud.BlockInfo?.DefinitionId.SubtypeName;UpdateHud(MyHud.BlockInfo);}}private void UpdateHud(MyHudBlockInfo blockInfo){if(_pointsMessage==null)return;double blockPoints;if(blockInfo==null||!AllGridsList.PointValues.TryGetValue(blockInfo.DefinitionId.SubtypeName,out blockPoints)){_pointsMessage.Visible=false;return;}string blockDisplayName=blockInfo.BlockName;float thisClimbingCostMult=0;AllGridsList.ClimbingCostRename(ref blockDisplayName,ref thisClimbingCostMult);_pointsMessage.Message.Clear();_pointsMessage.Message.Append($"{blockDisplayName}:\n{blockPoints}bp");if(thisClimbingCostMult!=0)_pointsMessage.Message.Append($" +{(int)(blockPoints*thisClimbingCostMult)}bp/b");_pointsMessage.Visible=true;}}}using System;using System.Collections.Generic;using System.Linq;using System.Text;using Sandbox.Definitions;using Sandbox.ModAPI;using CGP.ShareTrack.API;using CGP.ShareTrack.API.CoreSystem;using CGP.ShareTrack.ShipTracking;using VRage.Game;using VRage.Game.ModAPI;using VRageMath;using static VRageRender.MyBillboard;namespace CGP.ShareTrack{internal class HudPointsList{private readonly StringBuilder _gunTextBuilder=new StringBuilder();private readonly StringBuilder _speedTextBuilder=new StringBuilder();private ShipTracker _shipTracker=null;private int _currentPage=0;private const int ItemsPerPage=10;private int _pageCounter=0;private const int PageChangeInterval=5;private readonly HudAPIv2.HUDMessage _statMessage=new HudAPIv2.HUDMessage(scale:1f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(-.99,.99),hideHud:false,blend:BlendTypeEnum.PostPP){Visible=false,InitialColor=Color.Orange},_statMessageBattleWeaponCountsist=new HudAPIv2.HUDMessage(scale:1.25f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(-.99,.99),hideHud:false,shadowing:true,blend:BlendTypeEnum.PostPP){Visible=false},_statMessageBattle=new HudAPIv2.HUDMessage(scale:1.25f,font:"BI_SEOutlined",Message:new StringBuilder(""),origin:new Vector2D(-.54,-0.955),hideHud:false,blend:BlendTypeEnum.PostPP){Visible=false};private ViewState _viewState=ViewState.None;private Queue_executionTimes=new Queue();private const int _sampleSize=1;private double _executionTimeSum=0;private static IMyCubeGrid GetFocusedGrid(){var cockpit=MyAPIGateway.Session.ControlledObject?.Entity as IMyCockpit;if(cockpit==null||MyAPIGateway.Session.IsCameraUserControlledSpectator)return AllGridsList.RaycastGridFromCamera();return cockpit.CubeGrid?.Physics!=null?cockpit.CubeGrid:null;}private void ShiftTHandling(){var focusedGrid=GetFocusedGrid();if(focusedGrid!=null){ShiftTCalcs(focusedGrid);}else if(_statMessage.Visible){_shipTracker=null;_statMessage.Message.Clear();_statMessage.Visible=false;}}private void BattleShiftTHandling(){if(_statMessage.Visible){_statMessage.Message.Clear();_statMessage.Visible=false;}var focusedGrid=GetFocusedGrid();if(focusedGrid!=null){BattleShiftTCalcs(focusedGrid);}else if(_statMessageBattle.Visible){_shipTracker=null;_statMessageBattle.Message.Clear();_statMessageBattle.Visible=false;_statMessageBattleWeaponCountsist.Message.Clear();_statMessageBattleWeaponCountsist.Visible=false;}}private void ShiftTCalcs(IMyCubeGrid focusedGrid){if(MasterSession.I.Ticks%59!=0)return;var stopwatch=new System.Diagnostics.Stopwatch();stopwatch.Start();if(_shipTracker?.Grid?.GetGridGroup(GridLinkTypeEnum.Physical)!=focusedGrid.GetGridGroup(GridLinkTypeEnum.Physical)&&!TrackingManager.I.TrackedGrids.TryGetValue(focusedGrid,out _shipTracker)){_shipTracker=new ShipTracker(focusedGrid,false);Log.Info($"ShiftTCalcs Tracked grid {focusedGrid.DisplayName}. Visible: false");}_shipTracker.Update();var totalShieldString="None";if(_shipTracker.MaxShieldHealth>100)totalShieldString=$"{_shipTracker.MaxShieldHealth/100f:F2} M";else if(_shipTracker.MaxShieldHealth>1&&_shipTracker.MaxShieldHealth<100)totalShieldString=$"{_shipTracker.MaxShieldHealth:F0}0 K";var gunTextBuilder=new StringBuilder();foreach(var x in _shipTracker.WeaponCounts.Keys)gunTextBuilder.AppendFormat("{0} x {1}\n",_shipTracker.WeaponCounts[x],x);var gunText=gunTextBuilder.ToString();var blockCountDict=new Dictionary();var fatBlocks=new List();focusedGrid.GetBlocks(fatBlocks,block=>block.FatBlock!=null);foreach(var block in fatBlocks){var fatBlock=block.FatBlock;var blockDef=MyDefinitionManager.Static.GetCubeBlockDefinition(fatBlock.BlockDefinition);if(blockDef!=null){int blockPCU=blockDef.PCU;string blockType=$"{blockDef.DisplayNameText}";if(blockCountDict.ContainsKey(blockType)){blockCountDict[blockType]+=blockPCU;}else{blockCountDict[blockType]=blockPCU;}}}_pageCounter++;if(_pageCounter>=PageChangeInterval){_pageCounter=0;_currentPage++;}var blockList=blockCountDict.ToList();blockList.Sort((x,y)=>string.Compare(x.Key,y.Key,StringComparison.Ordinal));int totalPages=(int)Math.Ceiling((double)blockList.Count/ItemsPerPage);if(totalPages>0){_currentPage=_currentPage%totalPages;}else{_currentPage=0;}var specialBlockTextBuilder=new StringBuilder();int startIndex=_currentPage*ItemsPerPage;int endIndex=Math.Min(startIndex+ItemsPerPage,blockList.Count);for(int i=startIndex;i{0}: {1} total PCU\n",kvp.Key,kvp.Value);}specialBlockTextBuilder.AppendFormat("\nPage {0}/{1}",_currentPage+1,totalPages);var specialBlockText=specialBlockTextBuilder.ToString();var massString=$"{_shipTracker.Mass}";var thrustInKilograms=focusedGrid.GetMaxThrustInDirection(Base6Directions.Direction.Backward)/9.81f;var mass=_shipTracker.Mass;var twr=(float)Math.Round(thrustInKilograms/mass,1);if(_shipTracker.Mass>1000000)massString=$"{Math.Round(_shipTracker.Mass/1000000f,1):F2}m";var twRs=$"{twr:F3}";var thrustString=$"{Math.Round(_shipTracker.TotalThrust,1)}";if(_shipTracker.TotalThrust>1000000)thrustString=$"{Math.Round(_shipTracker.TotalThrust/1000000f,1):F2}M";var playerName=_shipTracker.Owner==null?_shipTracker.GridName:_shipTracker.Owner.DisplayName;var factionName=_shipTracker.Owner==null?"":MyAPIGateway.Session?.Factions?.TryGetPlayerFaction(_shipTracker.OwnerId)?.Name;var speed=focusedGrid.GridSizeEnum==MyCubeSize.Large?MyDefinitionManager.Static.EnvironmentDefinition.LargeShipMaxSpeed:MyDefinitionManager.Static.EnvironmentDefinition.SmallShipMaxSpeed;var reducedAngularSpeed=0f;if(RtsApi!=null&&RtsApi.IsReady){speed=(float)Math.Round(RtsApi.GetMaxSpeed(focusedGrid),2);reducedAngularSpeed=RtsApi.GetReducedAngularSpeed(focusedGrid);}var pwrNotation=_shipTracker.TotalPower>1000?"GW":"MW";var tempPwr=_shipTracker.TotalPower>1000?$"{Math.Round(_shipTracker.TotalPower/1000,1):F1}":Math.Round(_shipTracker.TotalPower,1).ToString();var pwr=tempPwr+pwrNotation;var gyroString=$"{Math.Round(_shipTracker.TotalTorque,1)}";if(_shipTracker.TotalTorque>=1000000){var tempGyro2=Math.Round(_shipTracker.TotalTorque/1000000f,1);gyroString=tempGyro2>1000?$"{Math.Round(tempGyro2/1000,1):F1}G":$"{Math.Round(tempGyro2,1):F1}M";}var sb=new StringBuilder();double lastExecutionTime=_executionTimes.Count>0?_executionTimes.Last():0;sb.AppendLine($"Last Update took: {lastExecutionTime:F2} ms");sb.AppendLine("----Basic Info----");sb.AppendFormat("{0} ",focusedGrid.DisplayName);sb.AppendFormat("Owner: {0} ",playerName);sb.AppendFormat("Faction: {0}\n",factionName);sb.AppendFormat("Mass: {0} kg\n",massString);sb.AppendFormat("Heavy blocks: {0}\n",_shipTracker.HeavyArmorCount);sb.AppendFormat("Total blocks: {0}\n",_shipTracker.BlockCount);sb.AppendFormat("PCU: {0}\n",_shipTracker.PCU);sb.AppendFormat("Size: {0}\n",(focusedGrid.Max+Vector3.Abs(focusedGrid.Min)).ToString());sb.AppendFormat("Max Speed: {0}\n",speed);sb.AppendLine();sb.AppendLine("----Battle Stats----");sb.AppendFormat("Thrust: {0}N\n",thrustString);sb.AppendFormat("Power: {0}\n",pwr);sb.AppendLine();sb.AppendLine("----Armament----");sb.Append(gunText);sb.AppendLine();sb.AppendLine("----Blocks----");sb.AppendLine(specialBlockText);if(!_statMessage.Message.Equals(sb))_statMessage.Message=sb;_statMessage.Visible=true;stopwatch.Stop();UpdateExecutionTimes(stopwatch.Elapsed.TotalMilliseconds);}private void BattleShiftTCalcs(IMyCubeGrid focusedGrid){if(MasterSession.I.Ticks%59!=0)return;ShipTracker tracked;TrackingManager.I.TrackedGrids.TryGetValue(focusedGrid,out tracked);if(tracked==null){tracked=new ShipTracker(focusedGrid,false);Log.Info($"BattleShiftTCalcs Tracked grid {focusedGrid.DisplayName}. Visible: false");}var totalShieldString="None";if(tracked.MaxShieldHealth>100)totalShieldString=$"{tracked.MaxShieldHealth/100f:F2} M";else if(tracked.MaxShieldHealth>1&&tracked.MaxShieldHealth<100)totalShieldString=$"{tracked.MaxShieldHealth:F0}0 K";var maxSpeed=focusedGrid.GridSizeEnum==MyCubeSize.Large?MyDefinitionManager.Static.EnvironmentDefinition.LargeShipMaxSpeed:MyDefinitionManager.Static.EnvironmentDefinition.SmallShipMaxSpeed;var reducedAngularSpeed=0f;var negativeInfluence=0f;if(RtsApi!=null&&RtsApi.IsReady){maxSpeed=(float)Math.Round(RtsApi.GetMaxSpeed(focusedGrid),2);reducedAngularSpeed=RtsApi.GetReducedAngularSpeed(focusedGrid);negativeInfluence=RtsApi.GetNegativeInfluence(focusedGrid);}_speedTextBuilder.Clear();_speedTextBuilder.Append($"\nMax Speed: {maxSpeed:F2} m/s");_speedTextBuilder.Append($"\nReduced Angular Speed: {reducedAngularSpeed:F2} rad/s");_speedTextBuilder.Append($"\nNegative Influence: {negativeInfluence:F2}");_gunTextBuilder.Clear();foreach(var x in tracked.WeaponCounts)_gunTextBuilder.Append($"{x.Value} x {x.Key}\n");var thrustString=$"{Math.Round(tracked.TotalThrust,1)}";if(tracked.TotalThrust>1000000)thrustString=$"{Math.Round(tracked.TotalThrust/1000000f,1):F2}M";var gyroString=$"{Math.Round(tracked.TotalTorque,1)}";double tempGyro2;if(tracked.TotalTorque>=1000000){tempGyro2=Math.Round(tracked.TotalTorque/1000000f,1);if(tempGyro2>1000)gyroString=$"{Math.Round(tempGyro2/1000,1):F1}G";else gyroString=$"{Math.Round(tempGyro2,1):F1}M";}var pwrNotation=tracked.TotalPower>1000?"GW":"MW";var tempPwr=tracked.TotalPower>1000?$"{Math.Round(tracked.TotalPower/1000,1):F1}":Math.Round(tracked.TotalPower,1).ToString();var pwr=tempPwr+pwrNotation;_gunTextBuilder.Append($"\nThrust: {thrustString} N").Append($"\nGyro: {gyroString} N").Append($"\nPower: {pwr}").Append(_speedTextBuilder);_statMessageBattleWeaponCountsist.Message.Length=0;_statMessageBattleWeaponCountsist.Message.Append(_gunTextBuilder);_statMessageBattle.Message.Length=0;_statMessageBattle.Message.Append($"{totalShieldString} ({(int)tracked.CurrentShieldPercent}%)");_statMessageBattle.Visible=true;_statMessageBattleWeaponCountsist.Visible=true;}private void UpdateExecutionTimes(double elapsedTime){if(_executionTimes.Count>=_sampleSize)_executionTimes.Dequeue();_executionTimes.Enqueue(elapsedTime);}private enum ViewState{None,InView,InView2}private WcApi WcApi=>AllGridsList.I.WcApi;private ShieldApi ShApi=>AllGridsList.I.ShieldApi;private RtsApi RtsApi=>AllGridsList.I.RtsApi;private HudAPIv2 TextHudApi=>MasterSession.I.TextHudApi;public void CycleViewState(){_viewState++;if(_viewState>ViewState.InView2){_statMessageBattle.Message.Clear();_statMessageBattleWeaponCountsist.Message.Clear();_statMessageBattle.Visible=false;_statMessageBattleWeaponCountsist.Visible=false;_viewState=ViewState.None;}}public void UpdateDraw(){if(!TextHudApi.Heartbeat)return;switch(_viewState){case ViewState.InView:ShiftTHandling();break;case ViewState.InView2:BattleShiftTHandling();break;}}}}using System;using System.Collections.Generic;using System.IO;using System.Text;using ParallelTasks;using Sandbox.ModAPI;using VRage.Game;using VRage.Game.Components;using VRage.Game.ModAPI;using VRage.Utils;namespace CGP.ShareTrack{[MySessionComponentDescriptor(MyUpdateOrder.NoUpdate,int.MaxValue)]public class Log:MySessionComponentBase{private const int DefaultTimeInfo=3000;private const int DefaultTimeError=10000;public const string PrintError="";public const string PrintMsg="";private static Log _instance;private static Handler _handler;private static bool _unloaded;public static readonly string File=GenerateTimestampedFileName();private static string GenerateTimestampedFileName(){var timestamp=DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");return$"[{timestamp}]-Sharetrack.log";}private class Handler{private readonly StringBuilder _sb=new StringBuilder(64);private string _errorPrintText;private int _indent;private string _modName=string.Empty;private IMyHudNotification _notifyError;private IMyHudNotification _notifyInfo;private List_preInitMessages;private Log _sessionComp;private TextWriter _writer;public bool AutoClose{get;set;}=true;public ulong WorkshopId{get;private set;}public string ModName{get{return _modName;}set{_modName=value;ComputeErrorPrintText();}}public void Init(Log sessionComp){if(_writer!=null)return;if(MyAPIGateway.Utilities==null){Error("MyAPIGateway.Utilities is NULL !");return;}_sessionComp=sessionComp;if(string.IsNullOrWhiteSpace(ModName))ModName=sessionComp.ModContext.ModName;WorkshopId=GetWorkshopId(sessionComp.ModContext.ModId);_writer=MyAPIGateway.Utilities.WriteFileInLocalStorage(File,typeof(Log));if(_preInitMessages!=null){var warning=$"{_modName} WARNING: there are log messages before the mod initialized!";Info("--- pre-init messages ---");foreach(var msg in _preInitMessages)Info(msg,warning);Info("--- end pre-init messages ---");_preInitMessages=null;}_sb.Clear();_sb.Append("Initialized");_sb.Append("\nGameMode=").Append(MyAPIGateway.Session.SessionSettings.GameMode);_sb.Append("\nOnlineMode=").Append(MyAPIGateway.Session.SessionSettings.OnlineMode);_sb.Append("\nServer=").Append(MyAPIGateway.Session.IsServer);_sb.Append("\nDS=").Append(MyAPIGateway.Utilities.IsDedicated);_sb.Append("\nDefined="); +#if STABLE +_sb.Append("STABLE, "); +#endif +#if UNOFFICIAL +_sb.Append("UNOFFICIAL, "); +#endif +#if DEBUG +_sb.Append("DEBUG, "); +#endif +#if BRANCH_STABLE +_sb.Append("BRANCH_STABLE, "); +#endif +#if BRANCH_DEVELOP +_sb.Append("BRANCH_DEVELOP, "); +#endif +#if BRANCH_UNKNOWN +_sb.Append("BRANCH_UNKNOWN, "); +#endif +Info(_sb.ToString());_sb.Clear();}public void Close(){if(_writer!=null){Info("Unloaded.");_writer.Flush();_writer.Close();_writer=null;}}private void ComputeErrorPrintText(){_errorPrintText=$"[ {_modName} ERROR, report contents of: %AppData%/SpaceEngineers/Storage/{MyAPIGateway.Utilities.GamePaths.ModScopeName}/{File} ]";}public void IncreaseIndent(){_indent++;}public void DecreaseIndent(){if(_indent>0)_indent--;}public void ResetIndent(){_indent=0;}public void Error(string message,string printText=PrintError,int printTime=DefaultTimeError){MyLog.Default.WriteLineAndConsole(_modName+" error/exception: "+message);LogMessage(message,"ERROR: ");if(printText!=null)ShowHudMessage(ref _notifyError,message,printText,printTime,MyFontEnum.Red);}public void Info(string message,string printText=null,int printTime=DefaultTimeInfo){LogMessage(message);if(printText!=null)ShowHudMessage(ref _notifyInfo,message,printText,printTime,MyFontEnum.White);}private void ShowHudMessage(ref IMyHudNotification notify,string message,string printText,int printTime,string font){if(printText==null)return;try{if(MyAPIGateway.Utilities!=null&&!MyAPIGateway.Utilities.IsDedicated){if(printText==PrintError)printText=_errorPrintText;else if(printText==PrintMsg)printText=$"[ {_modName} ERROR: {message} ]";if(notify==null){notify=MyAPIGateway.Utilities.CreateNotification(printText,printTime,font);}else{notify.Text=printText;notify.AliveTime=printTime;notify.ResetAliveTime();}notify.Show();}}catch(Exception e){Info("ERROR: Could not send notification to local client: "+e);MyLog.Default.WriteLineAndConsole(_modName+" logger error/exception: Could not send notification to local client: "+e);}}private void LogMessage(string message,string prefix=null){try{_sb.Clear();_sb.Append(DateTime.Now.ToString("[HH:mm:ss] "));if(_writer==null)_sb.Append("(PRE-INIT) ");for(var i=0;i<_indent;i++)_sb.Append(' ',4);if(prefix!=null)_sb.Append(prefix);_sb.Append(message);if(_writer==null){if(_preInitMessages==null)_preInitMessages=new List();_preInitMessages.Add(_sb.ToString());}else{_writer.WriteLine(_sb);_writer.Flush();}_sb.Clear();}catch(Exception e){MyLog.Default.WriteLineAndConsole($"{_modName} had an error while logging message = '{message}'\nLogger error: {e.Message}\n{e.StackTrace}");}}private ulong GetWorkshopId(string modId){foreach(var mod in MyAPIGateway.Session.Mods)if(mod.Name==modId)return mod.PublishedFileId;return 0;}}public override void LoadData(){_instance=this;EnsureHandlerCreated();_handler.Init(this);}protected override void UnloadData(){_instance=null;if(_handler!=null&&_handler.AutoClose)Unload();}private void Unload(){try{if(_unloaded)return;_unloaded=true;_handler?.Close();_handler=null;}catch(Exception e){MyLog.Default.WriteLine($"Error in {ModContext.ModName} ({ModContext.ModId}): {e.Message}\n{e.StackTrace}");throw new ModCrashedException(e,ModContext);}}private static void EnsureHandlerCreated(){if(_unloaded)throw new Exception("Digi.Log accessed after it was unloaded!");if(_handler==null)_handler=new Handler();}public static void Close(){_instance?.Unload();}public static bool AutoClose{get{EnsureHandlerCreated();return _handler.AutoClose;}set{EnsureHandlerCreated();_handler.AutoClose=value;}}public static string ModName{get{EnsureHandlerCreated();return _handler.ModName;}set{EnsureHandlerCreated();_handler.ModName=value;}}public static ulong WorkshopId=>_handler?.WorkshopId??0;public static void IncreaseIndent(){EnsureHandlerCreated();_handler.IncreaseIndent();}public static void DecreaseIndent(){EnsureHandlerCreated();_handler.DecreaseIndent();}public static void ResetIndent(){EnsureHandlerCreated();_handler.ResetIndent();}public static void Error(Exception exception,string printText=PrintError,int printTimeMs=DefaultTimeError){EnsureHandlerCreated();_handler.Error(exception.ToString(),printText,printTimeMs);}public static void Error(string message,string printText=PrintError,int printTimeMs=DefaultTimeError){EnsureHandlerCreated();_handler.Error(message,printText,printTimeMs);}public static void Info(string message,string printText=null,int printTimeMs=DefaultTimeInfo){EnsureHandlerCreated();_handler.Info(message,printText,printTimeMs);}public static bool TaskHasErrors(Task task,string taskName){EnsureHandlerCreated();if(task.Exceptions!=null&&task.Exceptions.Length>0){foreach(var e in task.Exceptions)Error($"Error in {taskName} thread!\n{e}");return true;}return false;}}}using System;using Sandbox.ModAPI;using CGP.ShareTrack.API;using CGP.ShareTrack.HeartNetworking;using CGP.ShareTrack.ShipTracking;using CGP.ShareTrack.TrackerApi;using VRage.Game.Components;using VRageMath;namespace CGP.ShareTrack{[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]internal class MasterSession:MySessionComponentBase{public static readonly Vector2I ModVersion=new Vector2I(3,2);public static MasterSession I;public HudAPIv2 TextHudApi;public Action HudRegistered=()=>{};private readonly AllGridsList _allGridsList=new AllGridsList();private BuildingBlockPoints _buildingBlockPoints;private ApiProvider _apiProvider;public int Ticks{get;private set;}=0;private const int DelayTicks=600;private bool _trackingStarted=false;public override void LoadData(){I=this;try{HeartNetwork.I=new HeartNetwork();HeartNetwork.I.LoadData(42521);_allGridsList.Init();_apiProvider=new ApiProvider();_buildingBlockPoints=new BuildingBlockPoints();TrackingManager.Init();if(!MyAPIGateway.Utilities.IsDedicated)TextHudApi=new HudAPIv2(HudRegistered);}catch(Exception ex){Log.Error(ex);}}protected override void UnloadData(){try{TextHudApi?.Unload();_apiProvider.Unload();_allGridsList.Close();TrackingManager.Close();HeartNetwork.I.UnloadData();}catch(Exception ex){Log.Error(ex);}I=null;}public override void UpdateAfterSimulation(){try{Ticks++;HeartNetwork.I.Update();if(!_trackingStarted){if(Ticks>=DelayTicks){_trackingStarted=true;TrackingManager.I.StartTracking();}}else{TrackingManager.UpdateAfterSimulation();}_allGridsList.UpdateAfterSimulation();}catch(Exception ex){Log.Error(ex);}}public override void Draw(){try{_allGridsList.Draw();_buildingBlockPoints?.Update();}catch(Exception ex){Log.Error(ex);}}public override void HandleInput(){try{}catch(Exception ex){Log.Error(ex);}}}}using System;using System.Collections.Generic;using System.Text;using ProtoBuf;using Sandbox.ModAPI;using VRage;using VRage.Input;using VRage.ModAPI;using VRage.Utils;using VRageMath;using BlendTypeEnum=VRageRender.MyBillboard.BlendTypeEnum;namespace CGP.ShareTrack.API{public class HudAPIv2{public enum TextOrientation:byte{ltr=1,center=2,rtl=3}public const string DefaultFont="white";public const BlendTypeEnum DefaultHUDBlendType=BlendTypeEnum.PostPP;public const BlendTypeEnum DefaultWorldBlendType=BlendTypeEnum.Standard;private const long REGISTRATIONID=573804956;private static HudAPIv2 instance;private Action m_onRegisteredAction;private FuncMessageFactory;private FuncMessageGetter;private ActionMessageSetter;private ActionRemoveMessage;public HudAPIv2(Action onRegisteredAction=null){if(instance!=null)return;instance=this;m_onRegisteredAction=onRegisteredAction;MyAPIGateway.Utilities.RegisterMessageHandler(REGISTRATIONID,RegisterComponents);}public Action OnScreenDimensionsChanged{get;set;}public bool Heartbeat{get;private set;}public void Close(){Unload();}public void Unload(){MyAPIGateway.Utilities.UnregisterMessageHandler(REGISTRATIONID,RegisterComponents);MessageFactory=null;MessageSetter=null;MessageGetter=null;RemoveMessage=null;Heartbeat=false;m_onRegisteredAction=null;if(instance==this)instance=null;}private void RegisterComponents(object obj){if(Heartbeat)return;if(obj is MyTuple,Action,Func,Action>){var Handlers=(MyTuple,Action,Func,Action>)obj;MessageFactory=Handlers.Item1;MessageSetter=Handlers.Item2;MessageGetter=Handlers.Item3;RemoveMessage=Handlers.Item4;Heartbeat=true;if(m_onRegisteredAction!=null)m_onRegisteredAction();APIDialog.GetDialogMethods(MessageGetter);MessageSet(null,(int)RegistrationEnum.OnScreenUpdate,new MyTuple(ScreenChangedHandle));}}private enum RegistrationEnum{OnScreenUpdate=2000}private enum MessageTypes{HUDMessage=0,BillBoardHUDMessage,EntityMessage,SpaceMessage,BillboardTriHUDMessage,MenuItem=20,MenuSubCategory,MenuRootCategory,MenuScreenInput,MenuSliderItem,MenuTextInput,MenuKeybindInput,MenuColorPickerInput,BoxUIContainer=40,BoxUIText,BoxUIImage,UIDefinition=60,UIBehaviourDefinition}public static class APIDialog{private static Func,Action,Action,bool,bool,bool>ColorPickerDialogDelagete;private static Func,StringBuilder,bool>TextDialogDelagete;private static Func,StringBuilder,bool>KeybindDialogDelagete;private static Func,Action,Action,bool>ScreenInputDialogDelagete;private static Func,float,Func,Action,bool>SliderDialogDelagete;internal static void GetDialogMethods(FuncmessageGetter){ColorPickerDialogDelagete=messageGetter.Invoke((int)APIinfo.APIinfoMembers.GetDialog,(int)APIDialogs.ColorPickerDialog)as Func,Action,Action,bool,bool,bool>;TextDialogDelagete=messageGetter.Invoke((int)APIinfo.APIinfoMembers.GetDialog,(int)APIDialogs.TextDialog)as Func,StringBuilder,bool>;KeybindDialogDelagete=messageGetter.Invoke((int)APIinfo.APIinfoMembers.GetDialog,(int)APIDialogs.KeybindDialog)as Func,StringBuilder,bool>;ScreenInputDialogDelagete=messageGetter.Invoke((int)APIinfo.APIinfoMembers.GetDialog,(int)APIDialogs.ScreenInputDialog)as Func,Action,Action,bool>;SliderDialogDelagete=messageGetter.Invoke((int)APIinfo.APIinfoMembers.GetDialog,(int)APIDialogs.SliderDialog)as Func,float,Func,Action,bool>;}public static bool ColorPickerDialog(StringBuilder Title,Color initialColor,ActiononSubmit,ActiononUpdate,Action onCancel,bool showAlpha,bool usehsv=false){return ColorPickerDialogDelagete?.Invoke(Title,initialColor,onSubmit,onUpdate,onCancel,showAlpha,usehsv)??false;}public static bool TextDialog(ActiononSubmit,StringBuilder Title){return TextDialogDelagete?.Invoke(onSubmit,Title)??false;}public static bool KeybindDialog(ActiononSubmit,StringBuilder Title){return KeybindDialogDelagete?.Invoke(onSubmit,Title)??false;}public static bool ScreenInputDialog(StringBuilder title,Vector2D origin,Vector2D size,ActiononSubmit,ActiononUpdate,Action onCancel){return ScreenInputDialogDelagete?.Invoke(title,origin,size,onSubmit,onUpdate,onCancel)??false;}public static bool SliderDialog(StringBuilder title,ActiononSubmit,float initialvalue,FuncSliderPercentToValue,Action onCancel){return SliderDialogDelagete?.Invoke(title,onSubmit,initialvalue,SliderPercentToValue,onCancel)??false;}private enum APIDialogs{ColorPickerDialog=1100,TextDialog,KeybindDialog,ScreenInputDialog,SliderDialog}}public static class APIinfo{public static Vector2D ScreenPositionOnePX=>(Vector2D)instance.MessageGet(null,(int)APIinfoMembers.ScreenPositionOnePX);public static BoxUIDefinition GetBoxUIDefinition(MyStringId definitionName){return new BoxUIDefinition(instance.MessageGet(definitionName,(int)APIinfoMembers.GetBoxUIDefinition));}public static BoxUIBehaviourDef GetBoxUIBehaviour(MyStringId definitionName){return new BoxUIBehaviourDef(instance.MessageGet(definitionName,(int)APIinfoMembers.GetBoxUIBehaviour));}public static FontDefinition GetFontDefinition(MyStringId DefinitionName){var retval=instance.MessageGet(DefinitionName,(int)APIinfoMembers.GetFontDefinition);return new FontDefinition(retval);}public static void GetFonts(Listcollection){instance.MessageGet(collection,(int)APIinfoMembers.GetFonts);}internal enum APIinfoMembers{ScreenPositionOnePX=1000,OnScreenUpdate,GetBoxUIDefinition,GetBoxUIBehaviour,GetFontDefinition,GetFonts,GetDialog}}public class FontDefinition{public object BackingDefinition;public FontDefinition(object BackingObject){BackingDefinition=BackingObject;}public bool ReadOnly{get{return(bool)instance.MessageGet(BackingDefinition,(int)FontDefinitionMembers.ReadOnly);}set{instance.MessageSet(BackingDefinition,(int)FontDefinitionMembers.ReadOnly,value);}}public void DefineFont(int fontbase,int lineheight,int fontsize){var data=new MyTuple(fontbase,lineheight,fontsize);instance.MessageSet(BackingDefinition,(int)FontDefinitionMembers.DefineFont,data);}public void AddCharacter(char character,MyStringId material,int materialtexturesize,string charactercode,int uv1x,int uv1Y,int sizex,int sizey,int aw,int lsb,bool forcewhite=false){var data=new FontCharacterDefinitionData{character=character,MaterialId=material,texturesize=materialtexturesize,charactercode=charactercode,uv1x=uv1x,uv1y=uv1Y,sizex=sizex,sizey=sizey,aw=aw,lsb=lsb,forcewhite=forcewhite};instance.MessageSet(BackingDefinition,(int)FontDefinitionMembers.AddCharacter,MyAPIGateway.Utilities.SerializeToBinary(data));}public void AddKerning(int adjust,char right,char left){var data=new MyTuple(adjust,right,left);instance.MessageSet(BackingDefinition,(int)FontDefinitionMembers.AddKerning,data);}private enum FontDefinitionMembers{AddCharacter=0,DefineFont,AddKerning,ReadOnly}[ProtoContract]public struct FontCharacterDefinitionData{[ProtoMember(1)]public char character;[ProtoMember(2)]public int texturesize;[ProtoMember(3)]public string charactercode;[ProtoMember(4)]public int uv1x;[ProtoMember(5)]public int uv1y;[ProtoMember(6)]public int sizex;[ProtoMember(7)]public int sizey;[ProtoMember(8)]public int aw;[ProtoMember(9)]public int lsb;[ProtoMember(10)]public bool forcewhite;[ProtoMember(11)]public MyStringId MaterialId;}}private void DeleteMessage(object BackingObject){if(BackingObject!=null)RemoveMessage(BackingObject);}private object CreateMessage(MessageTypes type){return MessageFactory((int)type);}private object MessageGet(object BackingObject,int member){return MessageGetter(BackingObject,member);}private void MessageSet(object BackingObject,int member,object value){MessageSetter(BackingObject,member,value);}private void RegisterCheck(){if(instance.Heartbeat==false)throw new InvalidOperationException("HudAPI: Failed to create backing object. Do not instantiate without checking if heartbeat is true.");}private void ScreenChangedHandle(){if(OnScreenDimensionsChanged!=null)OnScreenDimensionsChanged();}public enum Options:byte{None=0x0,HideHud=0x1,Shadowing=0x2,Fixed=0x4,FOVScale=0x8,Pixel=0x10}private enum MessageBaseMembers{Message=0,Visible,TimeToLive,Scale,TextLength,Offset,BlendType,Draw,Flush,SkipLinearRGB}public abstract class MessageBase{internal object BackingObject;public abstract void DeleteMessage();public Vector2D GetTextLength(){return(Vector2D)instance.MessageGet(BackingObject,(int)MessageBaseMembers.TextLength);}public void Draw(){instance.MessageGet(BackingObject,(int)MessageBaseMembers.Draw);}public void Flush(){instance.MessageGet(BackingObject,(int)MessageBaseMembers.Flush);}public StringBuilder Message{get{return(StringBuilder)instance.MessageGet(BackingObject,(int)MessageBaseMembers.Message);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.Message,value);}}public bool Visible{get{return(bool)instance.MessageGet(BackingObject,(int)MessageBaseMembers.Visible);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.Visible,value);}}public int TimeToLive{get{return(int)instance.MessageGet(BackingObject,(int)MessageBaseMembers.TimeToLive);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.TimeToLive,value);}}public double Scale{get{return(double)instance.MessageGet(BackingObject,(int)MessageBaseMembers.Scale);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.Scale,value);}}public Vector2D Offset{get{return(Vector2D)instance.MessageGet(BackingObject,(int)MessageBaseMembers.Offset);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.Offset,value);}}public BlendTypeEnum Blend{get{return(BlendTypeEnum)instance.MessageGet(BackingObject,(int)MessageBaseMembers.BlendType);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.BlendType,value);}}public bool SkipLinearRGB{get{return(bool)instance.MessageGet(BackingObject,(int)MessageBaseMembers.SkipLinearRGB);}set{instance.MessageSet(BackingObject,(int)MessageBaseMembers.SkipLinearRGB,value);}}}public class EntityMessage:MessageBase{public EntityMessage(StringBuilder Message,IMyEntity entity,MatrixD transformMatrix,int timeToLive=-1,double scale=1,TextOrientation orientation=TextOrientation.ltr,Vector2D?offset=null,Vector2D?max=null,string font=DefaultFont){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.EntityMessage);if(BackingObject!=null){if(max.HasValue)Max=max.Value;this.Message=Message;Entity=entity;TransformMatrix=transformMatrix;TimeToLive=timeToLive;Scale=scale;Visible=true;Orientation=orientation;Blend=DefaultWorldBlendType;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Font=font;}}public EntityMessage(StringBuilder Message,IMyEntity entity,Vector3D localPosition,Vector3D forward,Vector3D up,int timeToLive=-1,double scale=1,TextOrientation orientation=TextOrientation.ltr,Vector2D?offset=null,Vector2D?max=null,BlendTypeEnum blend=DefaultWorldBlendType,string font=DefaultFont){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.EntityMessage);if(BackingObject!=null){if(max.HasValue)Max=max.Value;this.Message=Message;Entity=entity;LocalPosition=localPosition;Forward=forward;Up=up;TimeToLive=timeToLive;Scale=scale;Visible=true;Orientation=orientation;Blend=blend;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Font=font;}}public EntityMessage(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.EntityMessage);}public override void DeleteMessage(){instance.DeleteMessage(BackingObject);BackingObject=null;}private enum EntityMembers{Entity=10,LocalPosition,Up,Forward,Orientation,Max,TransformMatrix,Font}public IMyEntity Entity{get{return instance.MessageGet(BackingObject,(int)EntityMembers.Entity)as IMyEntity;}set{instance.MessageSet(BackingObject,(int)EntityMembers.Entity,value);}}public Vector3D LocalPosition{get{return(Vector3D)instance.MessageGet(BackingObject,(int)EntityMembers.LocalPosition);}set{instance.MessageSet(BackingObject,(int)EntityMembers.LocalPosition,value);}}public Vector3D Up{get{return(Vector3D)instance.MessageGet(BackingObject,(int)EntityMembers.Up);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Up,value);}}public Vector3D Forward{get{return(Vector3D)instance.MessageGet(BackingObject,(int)EntityMembers.Forward);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Forward,value);}}public TextOrientation Orientation{get{return(TextOrientation)instance.MessageGet(BackingObject,(int)EntityMembers.Orientation);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Orientation,(byte)value);}}public Vector2D Max{get{return(Vector2D)instance.MessageGet(BackingObject,(int)EntityMembers.Max);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Max,value);}}public MatrixD TransformMatrix{get{return(MatrixD)instance.MessageGet(BackingObject,(int)EntityMembers.TransformMatrix);}set{instance.MessageSet(BackingObject,(int)EntityMembers.TransformMatrix,value);}}public string Font{get{return(string)instance.MessageGet(BackingObject,(int)EntityMembers.Font);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Font,value);}}}public class HUDMessage:MessageBase{public HUDMessage(StringBuilder Message,Vector2D origin,Vector2D?offset=null,int timeToLive=-1,double scale=1.0d,bool hideHud=true,bool shadowing=false,Color?shadowColor=null,BlendTypeEnum blend=DefaultHUDBlendType,string font=DefaultFont){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.HUDMessage);if(BackingObject!=null){TimeToLive=timeToLive;Origin=origin;Options=Options.None;if(hideHud)Options|=Options.HideHud;if(shadowing)Options|=Options.Shadowing;var blackshadow=Color.Black;if(shadowColor.HasValue)shadowColor=shadowColor.Value;Scale=scale;this.Message=Message;Blend=blend;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Font=font;}}public HUDMessage(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.HUDMessage);}public override void DeleteMessage(){instance.DeleteMessage(BackingObject);BackingObject=null;}private enum EntityMembers{Origin=10,Options,ShadowColor,Font,InitalColor}public Vector2D Origin{get{return(Vector2D)instance.MessageGet(BackingObject,(int)EntityMembers.Origin);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Origin,value);}}public Options Options{get{return(Options)instance.MessageGet(BackingObject,(int)EntityMembers.Options);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Options,(byte)value);}}public Color ShadowColor{get{return(Color)instance.MessageGet(BackingObject,(int)EntityMembers.ShadowColor);}set{instance.MessageSet(BackingObject,(int)EntityMembers.ShadowColor,value);}}public string Font{get{return(string)instance.MessageGet(BackingObject,(int)EntityMembers.Font);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Font,value);}}public Color InitialColor{get{return(Color)instance.MessageGet(BackingObject,(int)EntityMembers.InitalColor);}set{instance.MessageSet(BackingObject,(int)EntityMembers.InitalColor,value);}}}public class BillBoardHUDMessage:MessageBase{public BillBoardHUDMessage(MyStringId Material,Vector2D origin,Color billBoardColor,Vector2D?offset=null,int timeToLive=-1,double scale=1d,float width=1f,float height=1f,float rotation=0,bool hideHud=true,bool shadowing=true,BlendTypeEnum blend=DefaultHUDBlendType){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BillBoardHUDMessage);if(BackingObject!=null){TimeToLive=timeToLive;Origin=origin;Options=Options.None;if(hideHud)Options|=Options.HideHud;if(shadowing)Options|=Options.Shadowing;BillBoardColor=billBoardColor;Scale=scale;this.Material=Material;Rotation=rotation;Blend=blend;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Width=width;Height=height;}}public BillBoardHUDMessage(MyStringId Material,Vector2D origin,Color billBoardColor,Vector2 uvOffset,Vector2 uvSize,float textureSize,Vector2D?offset=null,int timeToLive=-1,double scale=1d,float width=1f,float height=1f,float rotation=0,bool hideHud=true,bool shadowing=true,BlendTypeEnum blend=DefaultHUDBlendType){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BillBoardHUDMessage);if(BackingObject!=null){uvEnabled=true;this.uvOffset=uvOffset;this.uvSize=uvSize;TextureSize=textureSize;TimeToLive=timeToLive;Origin=origin;Options=Options.None;if(hideHud)Options|=Options.HideHud;if(shadowing)Options|=Options.Shadowing;BillBoardColor=billBoardColor;Scale=scale;this.Material=Material;Rotation=rotation;Blend=blend;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Width=width;Height=height;}}public BillBoardHUDMessage(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BillBoardHUDMessage);}public override void DeleteMessage(){instance.DeleteMessage(BackingObject);BackingObject=null;}private enum EntityMembers{Origin=10,Options,BillBoardColor,Material,Rotation,Width,Height,uvOffset,uvSize,TextureSize,uvEnabled}public Vector2D Origin{get{return(Vector2D)instance.MessageGet(BackingObject,(int)EntityMembers.Origin);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Origin,value);}}public MyStringId Material{get{return(MyStringId)instance.MessageGet(BackingObject,(int)EntityMembers.Material);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Material,value);}}public Options Options{get{return(Options)instance.MessageGet(BackingObject,(int)EntityMembers.Options);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Options,(byte)value);}}public Color BillBoardColor{get{return(Color)instance.MessageGet(BackingObject,(int)EntityMembers.BillBoardColor);}set{instance.MessageSet(BackingObject,(int)EntityMembers.BillBoardColor,value);}}public float Rotation{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.Rotation);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Rotation,value);}}public float Width{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.Width);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Width,value);}}public float Height{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.Height);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Height,value);}}public Vector2 uvOffset{get{return(Vector2)instance.MessageGet(BackingObject,(int)EntityMembers.uvOffset);}set{instance.MessageSet(BackingObject,(int)EntityMembers.uvOffset,value);}}public Vector2 uvSize{get{return(Vector2)instance.MessageGet(BackingObject,(int)EntityMembers.uvSize);}set{instance.MessageSet(BackingObject,(int)EntityMembers.uvSize,value);}}public float TextureSize{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.TextureSize);}set{instance.MessageSet(BackingObject,(int)EntityMembers.TextureSize,value);}}public bool uvEnabled{get{return(bool)instance.MessageGet(BackingObject,(int)EntityMembers.uvEnabled);}set{instance.MessageSet(BackingObject,(int)EntityMembers.uvEnabled,value);}}}public class BillBoardTriHUDMessage:MessageBase{public BillBoardTriHUDMessage(MyStringId Material,Vector2D origin,Color billBoardColor,Vector2 p0,Vector2 p1,Vector2 p2,Vector2D?offset=null,int timeToLive=-1,double scale=1d,float width=1f,float height=1f,float rotation=0,bool hideHud=true,bool shadowing=true,BlendTypeEnum blend=DefaultHUDBlendType){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BillboardTriHUDMessage);if(BackingObject!=null){TimeToLive=timeToLive;Origin=origin;Options=Options.None;if(hideHud)Options|=Options.HideHud;if(shadowing)Options|=Options.Shadowing;BillBoardColor=billBoardColor;Scale=scale;this.Material=Material;Rotation=rotation;Blend=blend;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Width=width;Height=height;P0=p0;P1=p1;P2=p2;}}public BillBoardTriHUDMessage(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BillboardTriHUDMessage);}public override void DeleteMessage(){instance.DeleteMessage(BackingObject);BackingObject=null;}private enum EntityMembers{Message=0,Origin=10,Options,BillBoardColor,Material,Rotation,Width,Height,p0,p1,p2}public Vector2D Origin{get{return(Vector2D)instance.MessageGet(BackingObject,(int)EntityMembers.Origin);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Origin,value);}}public MyStringId Material{get{return(MyStringId)instance.MessageGet(BackingObject,(int)EntityMembers.Material);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Material,value);}}public Options Options{get{return(Options)instance.MessageGet(BackingObject,(int)EntityMembers.Options);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Options,(byte)value);}}public Color BillBoardColor{get{return(Color)instance.MessageGet(BackingObject,(int)EntityMembers.BillBoardColor);}set{instance.MessageSet(BackingObject,(int)EntityMembers.BillBoardColor,value);}}public float Rotation{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.Rotation);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Rotation,value);}}public float Width{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.Width);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Width,value);}}public float Height{get{return(float)instance.MessageGet(BackingObject,(int)EntityMembers.Height);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Height,value);}}public Vector2 P0{get{return(Vector2)instance.MessageGet(BackingObject,(int)EntityMembers.p0);}set{instance.MessageSet(BackingObject,(int)EntityMembers.p0,value);}}public Vector2 P1{get{return(Vector2)instance.MessageGet(BackingObject,(int)EntityMembers.p1);}set{instance.MessageSet(BackingObject,(int)EntityMembers.p1,value);}}public Vector2 P2{get{return(Vector2)instance.MessageGet(BackingObject,(int)EntityMembers.p2);}set{instance.MessageSet(BackingObject,(int)EntityMembers.p2,value);}}}public class SpaceMessage:MessageBase{public SpaceMessage(StringBuilder Message,Vector3D worldPosition,Vector3D up,Vector3D left,double scale=1,Vector2D?offset=null,int timeToLive=-1,TextOrientation txtOrientation=TextOrientation.ltr,BlendTypeEnum blend=DefaultWorldBlendType,string font=DefaultFont){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.SpaceMessage);if(BackingObject!=null){TimeToLive=timeToLive;Scale=scale;WorldPosition=worldPosition;Up=up;Left=left;TxtOrientation=txtOrientation;this.Message=Message;Blend=blend;if(offset.HasValue)Offset=offset.Value;else Offset=Vector2D.Zero;Font=font;}}public SpaceMessage(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.SpaceMessage);}public override void DeleteMessage(){instance.DeleteMessage(BackingObject);BackingObject=null;}private enum EntityMembers{WorldPosition=10,Up,Left,TxtOrientation,Font}public Vector3D WorldPosition{get{return(Vector3D)instance.MessageGet(BackingObject,(int)EntityMembers.WorldPosition);}set{instance.MessageSet(BackingObject,(int)EntityMembers.WorldPosition,value);}}public Vector3D Up{get{return(Vector3D)instance.MessageGet(BackingObject,(int)EntityMembers.Up);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Up,value);}}public Vector3D Left{get{return(Vector3D)instance.MessageGet(BackingObject,(int)EntityMembers.Left);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Left,value);}}public string Font{get{return(string)instance.MessageGet(BackingObject,(int)EntityMembers.Font);}set{instance.MessageSet(BackingObject,(int)EntityMembers.Font,value);}}public TextOrientation TxtOrientation{get{return(TextOrientation)instance.MessageGet(BackingObject,(int)EntityMembers.TxtOrientation);}set{instance.MessageSet(BackingObject,(int)EntityMembers.TxtOrientation,(byte)value);}}}public abstract class MenuItemBase{internal object BackingObject;public string Text{get{return(string)instance.MessageGet(BackingObject,(int)MenuItemBaseMembers.Text);}set{instance.MessageSet(BackingObject,(int)MenuItemBaseMembers.Text,value);}}public bool Interactable{get{return(bool)instance.MessageGet(BackingObject,(int)MenuItemBaseMembers.Interactable);}set{instance.MessageSet(BackingObject,(int)MenuItemBaseMembers.Interactable,value);}}private enum MenuItemBaseMembers{Text=0,Interactable}}public class MenuItem:MenuItemBase{public MenuItem(string Text,MenuCategoryBase parent,Action onClick=null,bool interactable=true){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuItem);this.Text=Text;Parent=parent;OnClick=onClick;Interactable=interactable;}public Action OnClick{get{return(Action)instance.MessageGet(BackingObject,(int)MenuItemMembers.OnClickAction);}set{instance.MessageSet(BackingObject,(int)MenuItemMembers.OnClickAction,value);}}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuItemMembers.Parent,value.BackingObject);}}private enum MenuItemMembers{OnClickAction=100,Parent}}public abstract class MenuCategoryBase:MenuItemBase{public string Header{get{return(string)instance.MessageGet(BackingObject,(int)MenuBaseCategoryMembers.Header);}set{instance.MessageSet(BackingObject,(int)MenuBaseCategoryMembers.Header,value);}}private enum MenuBaseCategoryMembers{Header=100}}public class MenuRootCategory:MenuCategoryBase{public enum MenuFlag{None=0,PlayerMenu=1,AdminMenu=2}public MenuRootCategory(string Text,MenuFlag attachedMenu=MenuFlag.None,string headerText="Default Header"){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuRootCategory);this.Text=Text;Header=headerText;Menu=attachedMenu;}public MenuFlag Menu{get{return(MenuFlag)instance.MessageGet(BackingObject,(int)MenuRootCategoryMembers.MenuFlag);}set{instance.MessageSet(BackingObject,(int)MenuRootCategoryMembers.MenuFlag,(int)value);}}private enum MenuRootCategoryMembers{MenuFlag=200}}public class MenuSubCategory:MenuCategoryBase{public MenuSubCategory(string Text,MenuCategoryBase parent,string headerText="Default Header"){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuSubCategory);this.Text=Text;Header=headerText;Parent=parent;}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuSubCategoryMembers.Parent,value.BackingObject);}}private enum MenuSubCategoryMembers{Parent=200}}public class MenuColorPickerInput:MenuItemBase{public MenuColorPickerInput(string Text,MenuCategoryBase parent,Color initialColor,string inputDialogTitle="Enter text value",ActiononSubmit=null,ActiononUpdate=null,Action onCancel=null,bool showAlpha=true,bool useHsv=false){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuColorPickerInput);this.Text=Text;InputDialogTitle=inputDialogTitle;OnSubmitAction=onSubmit;Parent=parent;InitialColor=initialColor;OnUpdateAction=onUpdate;OnCancelAction=onCancel;ShowAlpha=showAlpha;UseHSV=useHsv;}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.Parent,value.BackingObject);}}public string InputDialogTitle{get{return(string)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.InputDialogTitle);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.InputDialogTitle,value);}}public ActionOnSubmitAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.OnSubmitAction);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.OnSubmitAction,value);}}public ActionOnUpdateAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.OnUpdateAction);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.OnUpdateAction,value);}}public Action OnCancelAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.OnCancelAction);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.OnCancelAction,value);}}public Color InitialColor{get{return(Color)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.InitialColor);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.InitialColor,value);}}public bool ShowAlpha{get{return(bool)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.ShowAlpha);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.ShowAlpha,value);}}public bool UseHSV{get{return(bool)instance.MessageGet(BackingObject,(int)MenuColorPickerInputMembers.UseHSV);}set{instance.MessageSet(BackingObject,(int)MenuColorPickerInputMembers.UseHSV,value);}}private enum MenuColorPickerInputMembers{OnSubmitAction=100,Parent,InputDialogTitle,OnUpdateAction,OnCancelAction,InitialColor,ShowAlpha,UseHSV}}public class MenuTextInput:MenuItemBase{public MenuTextInput(string Text,MenuCategoryBase parent,string inputDialogTitle="Enter text value",ActiononSubmit=null){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuTextInput);this.Text=Text;InputDialogTitle=inputDialogTitle;OnSubmitAction=onSubmit;Parent=parent;}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuTextInputMembers.Parent,value.BackingObject);}}public string InputDialogTitle{get{return(string)instance.MessageGet(BackingObject,(int)MenuTextInputMembers.InputDialogTitle);}set{instance.MessageSet(BackingObject,(int)MenuTextInputMembers.InputDialogTitle,value);}}public ActionOnSubmitAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuTextInputMembers.OnSubmitAction);}set{instance.MessageSet(BackingObject,(int)MenuTextInputMembers.OnSubmitAction,value);}}private enum MenuTextInputMembers{OnSubmitAction=100,Parent,InputDialogTitle}}public class MenuKeybindInput:MenuItemBase{public MenuKeybindInput(string Text,MenuCategoryBase parent,string inputDialogTitle="Keybind - Press any key",ActiononSubmit=null){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuKeybindInput);this.Text=Text;InputDialogTitle=inputDialogTitle;OnSubmitAction=onSubmit;Parent=parent;}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuKeybindInputMembers.Parent,value.BackingObject);}}public string InputDialogTitle{get{return(string)instance.MessageGet(BackingObject,(int)MenuKeybindInputMembers.InputDialogTitle);}set{instance.MessageSet(BackingObject,(int)MenuKeybindInputMembers.InputDialogTitle,value);}}public ActionOnSubmitAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuKeybindInputMembers.OnSubmitAction);}set{instance.MessageSet(BackingObject,(int)MenuKeybindInputMembers.OnSubmitAction,value);}}private enum MenuKeybindInputMembers{OnSubmitAction=100,Parent,InputDialogTitle}}public class MenuScreenInput:MenuItemBase{public MenuScreenInput(string Text,MenuCategoryBase parent,Vector2D origin,Vector2D size,string inputDialogTitle="Move this element",ActiononSubmit=null,Actionupdate=null,Action cancel=null,Action onSelect=null){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuScreenInput);this.Text=Text;InputDialogTitle=inputDialogTitle;OnSubmitAction=onSubmit;UpdateAction=update;Origin=origin;Size=size;OnCancel=cancel;OnSelect=onSelect;Parent=parent;}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.Parent,value.BackingObject);}}public string InputDialogTitle{get{return(string)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.InputDialogTitle);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.InputDialogTitle,value);}}public Action OnCancel{get{return(Action)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.Cancel);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.Cancel,value);}}public Vector2D Origin{get{return(Vector2D)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.Origin);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.Origin,value);}}public Vector2D Size{get{return(Vector2D)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.Size);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.Size,value);}}public ActionOnSubmitAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.OnSubmitAction);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.OnSubmitAction,value);}}public ActionUpdateAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.OnUpdateAction);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.OnUpdateAction,value);}}public Action OnSelect{get{return(Action)instance.MessageGet(BackingObject,(int)MenuScreenInputMembers.OnSelect);}set{instance.MessageSet(BackingObject,(int)MenuScreenInputMembers.OnSelect,value);}}private enum MenuScreenInputMembers{OnSubmitAction=100,Parent,InputDialogTitle,Origin,Size,OnUpdateAction,Cancel,OnSelect}}public class MenuSliderInput:MenuItemBase{public MenuSliderInput(string Text,MenuCategoryBase parent,float initialPercent,string inputDialogTitle="Adjust Slider to modify value",ActiononSubmitAction=null,FuncsliderPercentToValue=null,Action onCancel=null){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.MenuSliderItem);this.Text=Text;InputDialogTitle=inputDialogTitle;OnSubmitAction=onSubmitAction;SliderPercentToValue=sliderPercentToValue;InitialPercent=initialPercent;OnCancel=onCancel;Parent=parent;}public MenuCategoryBase Parent{set{instance.MessageSet(BackingObject,(int)MenuSliderItemMembers.Parent,value.BackingObject);}}public string InputDialogTitle{get{return(string)instance.MessageGet(BackingObject,(int)MenuSliderItemMembers.InputDialogTitle);}set{instance.MessageSet(BackingObject,(int)MenuSliderItemMembers.InputDialogTitle,value);}}public float InitialPercent{get{return(float)instance.MessageGet(BackingObject,(int)MenuSliderItemMembers.InitialPercent);}set{instance.MessageSet(BackingObject,(int)MenuSliderItemMembers.InitialPercent,value);}}public ActionOnSubmitAction{get{return(Action)instance.MessageGet(BackingObject,(int)MenuSliderItemMembers.OnSubmitAction);}set{instance.MessageSet(BackingObject,(int)MenuSliderItemMembers.OnSubmitAction,value);}}public Action OnCancel{get{return(Action)instance.MessageGet(BackingObject,(int)MenuSliderItemMembers.OnCancel);}set{instance.MessageSet(BackingObject,(int)MenuSliderItemMembers.OnCancel,value);}}public FuncSliderPercentToValue{get{return(Func)instance.MessageGet(BackingObject,(int)MenuSliderItemMembers.SliderPercentToValue);}set{instance.MessageSet(BackingObject,(int)MenuSliderItemMembers.SliderPercentToValue,value);}}private enum MenuSliderItemMembers{OnSubmitAction=100,Parent,InputDialogTitle,InitialPercent,SliderPercentToValue,OnCancel}}public class BoxUIDefinition{public object BackingDefinition;public BoxUIDefinition(){BackingDefinition=instance.CreateMessage(MessageTypes.UIDefinition);}public BoxUIDefinition(MyStringId Material,int imagesize,int topwidthpx,int leftwidthpx,int bottomwidthpx,int rightwidthpx,int margin=0,int padding=0){BackingDefinition=instance.CreateMessage(MessageTypes.UIDefinition);var data=new BoxUIDefinitionData{Material=Material,imagesize=imagesize,topwidthpx=topwidthpx,leftwidthpx=leftwidthpx,bottomwidthpx=bottomwidthpx,rightwidthpx=rightwidthpx,margin=margin,padding=padding};BoxUIDef=data;}public BoxUIDefinition(object BackingObject){BackingDefinition=BackingObject;}public BoxUIDefinitionData BoxUIDef{set{instance.MessageSet(BackingDefinition,(int)BoxUIDefinitionMembers.Definition,MyAPIGateway.Utilities.SerializeToBinary(value));}}public Vector2I Min=>(Vector2I)instance.MessageGet(BackingDefinition,(int)BoxUIDefinitionMembers.Min);[ProtoContract]public struct BoxUIDefinitionData{[ProtoMember(1)]public MyStringId Material;[ProtoMember(2)]public int imagesize;[ProtoMember(3)]public int topwidthpx;[ProtoMember(4)]public int leftwidthpx;[ProtoMember(5)]public int bottomwidthpx;[ProtoMember(6)]public int rightwidthpx;[ProtoMember(7)]public int margin;[ProtoMember(8)]public int padding;}private enum BoxUIDefinitionMembers{Definition=0,Min}}public class BoxUIBehaviourDef{public object BackingDefinition;public BoxUIBehaviourDef(){BackingDefinition=instance.CreateMessage(MessageTypes.UIBehaviourDefinition);}public BoxUIBehaviourDef(object BackingObject){BackingDefinition=BackingObject;}}public abstract class BoxUIBase{internal object BackingObject;internal BoxUIBase m_Parent;public Vector2I Origin{get{return(Vector2I)instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.Origin);}set{instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Origin,value);}}public int Width{get{return(int)instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.Width);}set{instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Width,value);}}public int Height{get{return(int)instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.Height);}set{instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Height,value);}}public Color BackgroundColor{get{return(Color)instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.BackgroundColor);}set{instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.BackgroundColor,value);}}public bool Visible{get{return(bool)instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.Visible);}set{instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Visible,value);}}public object DefinitionObject{get{return instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.Definition);}set{if(value is BoxUIDefinition){instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Definition,(value as BoxUIDefinition).BackingDefinition);return;}instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Definition,value);}}public object BehaviourObject{get{return instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.Behaviour);}set{if(value is BoxUIBehaviourDef){instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Behaviour,(value as BoxUIDefinition).BackingDefinition);return;}instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Behaviour,value);}}public bool HideHud{get{return(bool)instance.MessageGet(BackingObject,(int)BoxUIBaseMembers.HideHud);}set{instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.HideHud,value);}}public BoxUIBase Parent{get{return m_Parent;}set{m_Parent=value;instance.MessageSet(BackingObject,(int)BoxUIBaseMembers.Parent,m_Parent.BackingObject);}}public void SetDefinition(BoxUIDefinition def){DefinitionObject=def.BackingDefinition;}public void SetBehaviour(BoxUIBehaviourDef def){BehaviourObject=def.BackingDefinition;}private enum BoxUIBaseMembers{Origin=0,BackgroundColor,Width,Height,Definition,Behaviour,Visible,Parent,HideHud}}public class BoxUIContainer:BoxUIBase{public BoxUIContainer(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BoxUIContainer);}}public class BoxUIText:BoxUIBase{public BoxUIText(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BoxUIText);}public void SetTextContent(HUDMessage Message){instance.MessageSet(BackingObject,(int)BoxUITextMembers.SetTextContent,Message.BackingObject);}private enum BoxUITextMembers{SetTextContent=100}}public class BoxUIImage:BoxUIBase{public BoxUIImage(){instance.RegisterCheck();BackingObject=instance.CreateMessage(MessageTypes.BoxUIImage);}public void SetImageContent(BillBoardHUDMessage Message){instance.MessageSet(BackingObject,(int)BoxUIImageMembers.SetImageContent,Message.BackingObject);}private enum BoxUIImageMembers{SetImageContent=100}}}}using System;using System.Collections.Generic;using Sandbox.ModAPI;using VRage.Game.ModAPI;namespace CGP.ShareTrack.API{public class RtsApi{private const long ChannelId=2772681332;private Func_GetAcceleration;private Func_GetAccelerationByDirection;private Func_GetBoost;private Func_GetCruiseSpeed;private Func_GetMaxSpeed;private Func_GetNegativeInfluence;private Func_GetReducedAngularSpeed;private bool isRegistered;private Action ReadyCallback;public bool IsReady{get;private set;}public void Load(Action readyCallback=null){if(isRegistered)throw new Exception($"{GetType().Name}.Load() should not be called multiple times!");isRegistered=true;ReadyCallback=readyCallback;MyAPIGateway.Utilities.RegisterMessageHandler(ChannelId,HandleMessage);MyAPIGateway.Utilities.SendModMessage(ChannelId,"ApiEndpointRequest");}public void Unload(){MyAPIGateway.Utilities.UnregisterMessageHandler(ChannelId,HandleMessage);IsReady=false;isRegistered=false;}private void HandleMessage(object obj){if(obj is string)return;var dict=obj as IReadOnlyDictionary;if(dict==null)return;AssignMethod(dict,"GetCruiseSpeed",ref _GetCruiseSpeed);AssignMethod(dict,"GetMaxSpeed",ref _GetMaxSpeed);AssignMethod(dict,"GetBoost",ref _GetBoost);AssignMethod(dict,"GetAcceleration",ref _GetAcceleration);AssignMethod(dict,"GetAccelerationByDirection",ref _GetAccelerationByDirection);AssignMethod(dict,"GetNegativeInfluence",ref _GetNegativeInfluence);AssignMethod(dict,"GetReducedAngularSpeed",ref _GetReducedAngularSpeed);IsReady=true;ReadyCallback?.Invoke();}private void AssignMethod(IReadOnlyDictionarydelegates,string name,ref T field)where T:class{if(delegates==null){field=null;return;}Delegate del;if(!delegates.TryGetValue(name,out del))throw new Exception($"{GetType().Name} :: Couldn't find {name} delegate of type {typeof(T)}");field=del as T;if(field==null)throw new Exception($"{GetType().Name} :: Delegate {name} is not type {typeof(T)}, instead it's: {del.GetType()}");}public float GetCruiseSpeed(IMyCubeGrid grid){return _GetCruiseSpeed.Invoke(grid);}public float GetMaxSpeed(IMyCubeGrid grid){return _GetMaxSpeed.Invoke(grid);}public float[]GetBoost(IMyCubeGrid grid){return _GetBoost.Invoke(grid);}public float[]GetAcceleration(IMyCubeGrid grid){return _GetAcceleration.Invoke(grid);}public float[]GetAccelerationByDirection(IMyCubeGrid grid){return _GetAccelerationByDirection.Invoke(grid);}public float GetNegativeInfluence(IMyCubeGrid grid){return _GetNegativeInfluence.Invoke(grid);}public float GetReducedAngularSpeed(IMyCubeGrid grid){return _GetReducedAngularSpeed.Invoke(grid);}}}using System;using System.Collections.Generic;using System.Collections.Immutable;using Sandbox.ModAPI;using VRage;using VRage.Game.Entity;using VRage.Game.ModAPI;using VRage.ModAPI;using VRageMath;namespace CGP.ShareTrack.API{public class ShieldApi{private const long Channel=1365616918;private Action_addAtacker;private bool _apiInit;private Func_entityBypass;private Func_getCharge;private Func_getChargeRate;private Func_getClosestShield;private Func_getClosestShieldPoint;private Func_getDistanceToShield;private Func>_getFaceInfo;private Func>_getFaceInfoAndPenChance;private Func>_getFacesFast;private Action>>_getLastAttackers;private Func_getMaxCharge;private Func_getMaxHpCap;private Func>_getModulationInfo;private Func_getPowerCap;private Func_getPowerUsed;private Func_getShieldBlock;private Func_getShieldHeat;private Func>_getShieldInfo;private Func_getShieldPercent;private Func_gridHasShield;private Func_gridShieldOnline;private Func_hpToChargeRatio;private Func,RayD,bool,bool,long,float,MyTuple>_intersectEntToShieldFast;private Func_isBlockProtected;private Func_isFortified;private bool _isRegistered;private Func_isShieldBlock;private Func_isShieldUp;private Func_lineAttackShield;private Func_lineIntersectShield;private Func_matchEntToShieldFast;private Func,MyTuple,MyTuple>?>_matchEntToShieldFastDetails;private Func,MyTuple>?>_matchEntToShieldFastExt;private Action_overLoad;private Func_pointAttackShield;private Func_pointAttackShieldCon;private Func_pointAttackShieldExt;private Func_pointAttackShieldHeat;private Func_pointInShield;private Func_protectedByShield;private Func_rayAttackShield;private Func_rayIntersectShield;private Action_setCharge;private Action_setShieldHeat;private Func_shieldStatus;public bool IsReady{get;private set;}public bool Compromised{get;private set;}private void HandleMessage(object o){if(_apiInit)return;var dict=o as IReadOnlyDictionary;var message=o as string;if(message!=null&&message=="Compromised")Compromised=true;if(dict==null||dict is ImmutableDictionary)return;var builder=ImmutableDictionary.CreateBuilder();foreach(var pair in dict)builder.Add(pair.Key,pair.Value);MyAPIGateway.Utilities.SendModMessage(Channel,builder.ToImmutable());ApiLoad(dict);IsReady=true;}public bool Load(){if(!_isRegistered){_isRegistered=true;MyAPIGateway.Utilities.RegisterMessageHandler(Channel,HandleMessage);}if(!IsReady)MyAPIGateway.Utilities.SendModMessage(Channel,"ApiEndpointRequest");return IsReady;}public void Unload(){if(_isRegistered){_isRegistered=false;MyAPIGateway.Utilities.UnregisterMessageHandler(Channel,HandleMessage);}IsReady=false;}public void ApiLoad(IReadOnlyDictionarydelegates){_apiInit=true;_rayAttackShield=(Func)delegates["RayAttackShield"];_lineAttackShield=(Func)delegates["LineAttackShield"];_intersectEntToShieldFast=(Func,RayD,bool,bool,long,float,MyTuple>)delegates["IntersectEntToShieldFast"];_pointAttackShield=(Func)delegates["PointAttackShield"];_pointAttackShieldExt=(Func)delegates["PointAttackShieldExt"];_pointAttackShieldCon=(Func)delegates["PointAttackShieldCon"];_pointAttackShieldHeat=(Func)delegates["PointAttackShieldHeat"];_setShieldHeat=(Action)delegates["SetShieldHeat"];_overLoad=(Action)delegates["OverLoadShield"];_setCharge=(Action)delegates["SetCharge"];_rayIntersectShield=(Func)delegates["RayIntersectShield"];_lineIntersectShield=(Func)delegates["LineIntersectShield"];_pointInShield=(Func)delegates["PointInShield"];_getShieldPercent=(Func)delegates["GetShieldPercent"];_getShieldHeat=(Func)delegates["GetShieldHeat"];_getChargeRate=(Func)delegates["GetChargeRate"];_hpToChargeRatio=(Func)delegates["HpToChargeRatio"];_getMaxCharge=(Func)delegates["GetMaxCharge"];_getCharge=(Func)delegates["GetCharge"];_getPowerUsed=(Func)delegates["GetPowerUsed"];_getPowerCap=(Func)delegates["GetPowerCap"];_getMaxHpCap=(Func)delegates["GetMaxHpCap"];_isShieldUp=(Func)delegates["IsShieldUp"];_shieldStatus=(Func)delegates["ShieldStatus"];_entityBypass=(Func)delegates["EntityBypass"];_gridHasShield=(Func)delegates["GridHasShield"];_gridShieldOnline=(Func)delegates["GridShieldOnline"];_protectedByShield=(Func)delegates["ProtectedByShield"];_getShieldBlock=(Func)delegates["GetShieldBlock"];_matchEntToShieldFast=(Func)delegates["MatchEntToShieldFast"];_matchEntToShieldFastExt=(Func,MyTuple>?>)delegates["MatchEntToShieldFastExt"];_matchEntToShieldFastDetails=(Func,MyTuple,MyTuple>?>)delegates["MatchEntToShieldFastDetails"];_isShieldBlock=(Func)delegates["IsShieldBlock"];_getClosestShield=(Func)delegates["GetClosestShield"];_getDistanceToShield=(Func)delegates["GetDistanceToShield"];_getClosestShieldPoint=(Func)delegates["GetClosestShieldPoint"];_getShieldInfo=(Func>)delegates["GetShieldInfo"];_getModulationInfo=(Func>)delegates["GetModulationInfo"];_getFaceInfo=(Func>)delegates["GetFaceInfo"];_getFaceInfoAndPenChance=(Func>)delegates["GetFaceInfoAndPenChance"];_addAtacker=(Action)delegates["AddAttacker"];_isBlockProtected=(Func)delegates["IsBlockProtected"];_getFacesFast=(Func>)delegates["GetFacesFast"];_getLastAttackers=(Action>>)delegates["GetLastAttackers"];_isFortified=(Func)delegates["IsFortified"];}public Vector3D?RayAttackShield(IMyTerminalBlock block,RayD ray,long attackerId,float damage,bool energy,bool drawParticle){return _rayAttackShield?.Invoke(block,ray,attackerId,damage,energy,drawParticle)??null;}public Vector3D?LineAttackShield(IMyTerminalBlock block,LineD line,long attackerId,float damage,bool energy,bool drawParticle){return _lineAttackShield?.Invoke(block,line,attackerId,damage,energy,drawParticle)??null;}public MyTupleIntersectEntToShieldFast(Listentities,RayD ray,bool onlyIfOnline,bool enemyOnly,long requesterId,float maxRange){return _intersectEntToShieldFast?.Invoke(entities,ray,onlyIfOnline,enemyOnly,requesterId,maxRange)??new MyTuple(false,float.MaxValue);}public bool PointAttackShield(IMyTerminalBlock block,Vector3D pos,long attackerId,float damage,bool energy,bool drawParticle,bool posMustBeInside=false){return _pointAttackShield?.Invoke(block,pos,attackerId,damage,energy,drawParticle,posMustBeInside)??false;}public float?PointAttackShieldExt(IMyTerminalBlock block,Vector3D pos,long attackerId,float damage,bool energy,bool drawParticle,bool posMustBeInside=false){return _pointAttackShieldExt?.Invoke(block,pos,attackerId,damage,energy,drawParticle,posMustBeInside)??null;}public float?PointAttackShieldCon(IMyTerminalBlock block,Vector3D pos,long attackerId,float damage,float optionalDamage,bool energy,bool drawParticle,bool posMustBeInside=false){return _pointAttackShieldCon?.Invoke(block,pos,attackerId,damage,optionalDamage,energy,drawParticle,posMustBeInside)??null;}public float?PointAttackShieldHeat(IMyTerminalBlock block,Vector3D pos,long attackerId,float damage,float optionalDamage,bool energy,bool drawParticle,bool posMustBeInside=false,float heatScaler=1){return _pointAttackShieldHeat?.Invoke(block,pos,attackerId,damage,optionalDamage,energy,drawParticle,posMustBeInside,heatScaler)??null;}public void SetShieldHeat(IMyTerminalBlock block,int value){_setShieldHeat?.Invoke(block,value);}public void OverLoadShield(IMyTerminalBlock block){_overLoad?.Invoke(block);}public void SetCharge(IMyTerminalBlock block,float value){_setCharge.Invoke(block,value);}public Vector3D?RayIntersectShield(IMyTerminalBlock block,RayD ray){return _rayIntersectShield?.Invoke(block,ray)??null;}public Vector3D?LineIntersectShield(IMyTerminalBlock block,LineD line){return _lineIntersectShield?.Invoke(block,line)??null;}public bool PointInShield(IMyTerminalBlock block,Vector3D pos){return _pointInShield?.Invoke(block,pos)??false;}public float GetShieldPercent(IMyTerminalBlock block){return _getShieldPercent?.Invoke(block)??-1;}public int GetShieldHeat(IMyTerminalBlock block){return _getShieldHeat?.Invoke(block)??-1;}public float GetChargeRate(IMyTerminalBlock block){return _getChargeRate?.Invoke(block)??-1;}public float HpToChargeRatio(IMyTerminalBlock block){return _hpToChargeRatio?.Invoke(block)??-1;}public float GetMaxCharge(IMyTerminalBlock block){return _getMaxCharge?.Invoke(block)??-1;}public float GetCharge(IMyTerminalBlock block){return _getCharge?.Invoke(block)??-1;}public float GetPowerUsed(IMyTerminalBlock block){return _getPowerUsed?.Invoke(block)??-1;}public float GetPowerCap(IMyTerminalBlock block){return _getPowerCap?.Invoke(block)??-1;}public float GetMaxHpCap(IMyTerminalBlock block){return _getMaxHpCap?.Invoke(block)??-1;}public bool IsShieldUp(IMyTerminalBlock block){return _isShieldUp?.Invoke(block)??false;}public string ShieldStatus(IMyTerminalBlock block){return _shieldStatus?.Invoke(block)??string.Empty;}public bool EntityBypass(IMyTerminalBlock block,IMyEntity entity,bool remove=false){return _entityBypass?.Invoke(block,entity,remove)??false;}public bool GridHasShield(IMyCubeGrid grid){return _gridHasShield?.Invoke(grid)??false;}public bool GridShieldOnline(IMyCubeGrid grid){return _gridShieldOnline?.Invoke(grid)??false;}public bool ProtectedByShield(IMyEntity entity){return _protectedByShield?.Invoke(entity)??false;}public IMyTerminalBlock GetShieldBlock(IMyEntity entity){return _getShieldBlock?.Invoke(entity)??null;}public IMyTerminalBlock MatchEntToShieldFast(IMyEntity entity,bool onlyIfOnline){return _matchEntToShieldFast?.Invoke(entity,onlyIfOnline)??null;}public MyTuple,MyTuple>?MatchEntToShieldFastExt(MyEntity entity,bool onlyIfOnline){return _matchEntToShieldFastExt?.Invoke(entity,onlyIfOnline)??null;}public MyTuple,MyTuple,MyTuple>?MatchEntToShieldFastDetails(MyEntity entity,bool onlyIfOnline){return _matchEntToShieldFastDetails?.Invoke(entity,onlyIfOnline)??null;}public bool IsShieldBlock(IMyTerminalBlock block){return _isShieldBlock?.Invoke(block)??false;}public IMyTerminalBlock GetClosestShield(Vector3D pos){return _getClosestShield?.Invoke(pos)??null;}public double GetDistanceToShield(IMyTerminalBlock block,Vector3D pos){return _getDistanceToShield?.Invoke(block,pos)??-1;}public Vector3D?GetClosestShieldPoint(IMyTerminalBlock block,Vector3D pos){return _getClosestShieldPoint?.Invoke(block,pos)??null;}public MyTupleGetShieldInfo(MyEntity entity){return _getShieldInfo?.Invoke(entity)??new MyTuple();}public MyTupleGetModulationInfo(MyEntity entity){return _getModulationInfo?.Invoke(entity)??new MyTuple();}public MyTupleGetFaceInfo(IMyTerminalBlock block,Vector3D pos,bool posMustBeInside=false){return _getFaceInfo?.Invoke(block,pos,posMustBeInside)??new MyTuple();}public MyTupleTAPI_GetFaceInfoAndPenChance(IMyTerminalBlock block,Vector3D pos,bool posMustBeInside=false){return _getFaceInfoAndPenChance?.Invoke(block,pos,posMustBeInside)??new MyTuple();}public void AddAttacker(long attacker){_addAtacker?.Invoke(attacker);}public bool IsBlockProtected(IMySlimBlock block){return _isBlockProtected?.Invoke(block)??false;}public MyTupleGetFacesFast(MyEntity entity){return _getFacesFast?.Invoke(entity)??new MyTuple();}public void GetLastAttackers(MyEntity entity,ICollection>collection){_getLastAttackers?.Invoke(entity,collection);}public bool IsFortified(IMyTerminalBlock block){return _isFortified?.Invoke(block)??false;}}}using System;using System.Collections.Generic;using Sandbox.ModAPI;using VRage;using VRage.Collections;using VRage.Game;using VRage.Game.Entity;using VRage.Game.ModAPI;using VRageMath;namespace CGP.ShareTrack.API.CoreSystem{public partial class WcApi{public enum ChangeMode{Add,Release,Lock}public enum EventTriggers{Reloading,Firing,Tracking,Overheated,TurnOn,TurnOff,BurstReload,NoMagsToLoad,PreFire,EmptyOnGameLoad,StopFiring,StopTracking,LockDelay,Init,Homing,TargetAligned,WhileOn,TargetRanged100,TargetRanged75,TargetRanged50,TargetRanged25}public enum ShootState{EventStart,EventEnd,Preceding,Canceled}private const long Channel=67549756549;public readonly ListWeaponDefinitions=new List();private Action>_addProjectileMonitor;private bool _apiInit;private Func_canShootTarget;private Func_currentPowerConsumption;private Action_disableRequiredPower;private Action_fireWeaponOnce;private Func_forceReload;private Func_getActiveAmmo;private Func_getAiFocus;private Action>>>>_getAllNpcSafeWeaponMagazines;private Action>_getAllWeaponDefinitions;private Action>>>>_getAllWeaponMagazines;private Func_getConstructEffectiveDps;private Action>_getCoreArmors;private Action>_getCorePhantoms;private Action>_getCoreRifles;private Action>_getCoreStaticLaunchers;private Action>_getCoreTurrets;private Action>_getCoreWeapons;private Func_getHeatLevel;private Func>_getMagazineMap;private Func_getMaxPower;private Func_getMaxWeaponRange;private Action>>_getMuzzleInfo;private Action>_getNpcSafeWeapons;private Action>_getObstructions;private Func_getOptimalDps;private Func_getPlayerController;private Func_getPredictedTargetPos;private Func>_getProjectilesLockedOn;private Action>_getProjectilesLockedOnPos;private Func>_getProjectileState;private Func_getShotsFired;private Action>>_getSortedThreats;private Func,int,bool>_getTurretTargetTypes;private Func_getWeaponAzimuthMatrix;private bool _getWeaponDefinitions;private Func_getWeaponElevationMatrix;private Func>_getWeaponScope;private Func>_getWeaponTarget;private Func_hasAi;private Func_hasCoreWeapon;private Func,bool>_hudHandler;private Func>_isInRange;private bool _isRegistered;private Func_isTargetAligned;private Func>_isTargetAlignedExtended;private Func_isTargetValid;private Func_isWeaponReadyToFire;private Func_isWeaponShooting;private Action>_monitorEvents;private Action _readyCallback;private Action>>>>>_registerDamageEvent;private Func_releaseAiFocus;private Action>_removeProjectileMonitor;private Action_setActiveAmmo;private Func_setAiFocus;private Action_setBlockTrackingRange;private Func_setMagazine;private Action>_setProjectileState;private Action,int>_setTurretTargetTypes;private Action_setWeaponTarget;private Func,bool>_shootHandler;private Func_shootRequest;private Func,bool>_targetFocusHandler;private Action_toggleWeaponFire;private Func_toggoleInfiniteResources;private Action>_unmonitorEvents;public bool IsReady{get;private set;}public void SetWeaponTarget(MyEntity weapon,MyEntity target,int weaponId=0){_setWeaponTarget?.Invoke(weapon,target,weaponId);}public void FireWeaponOnce(MyEntity weapon,bool allWeapons=true,int weaponId=0){_fireWeaponOnce?.Invoke(weapon,allWeapons,weaponId);}public void ToggleWeaponFire(MyEntity weapon,bool on,bool allWeapons,int weaponId=0){_toggleWeaponFire?.Invoke(weapon,on,allWeapons,weaponId);}public bool IsWeaponReadyToFire(MyEntity weapon,int weaponId=0,bool anyWeaponReady=true,bool shootReady=false){return _isWeaponReadyToFire?.Invoke(weapon,weaponId,anyWeaponReady,shootReady)??false;}public float GetMaxWeaponRange(MyEntity weapon,int weaponId){return _getMaxWeaponRange?.Invoke(weapon,weaponId)??0f;}public bool GetTurretTargetTypes(MyEntity weapon,IListcollection,int weaponId=0){return _getTurretTargetTypes?.Invoke(weapon,collection,weaponId)??false;}public void SetTurretTargetTypes(MyEntity weapon,IListcollection,int weaponId=0){_setTurretTargetTypes?.Invoke(weapon,collection,weaponId);}public void SetBlockTrackingRange(MyEntity weapon,float range){_setBlockTrackingRange?.Invoke(weapon,range);}public bool IsTargetAligned(MyEntity weapon,MyEntity targetEnt,int weaponId){return _isTargetAligned?.Invoke(weapon,targetEnt,weaponId)??false;}public MyTupleIsTargetAlignedExtended(MyEntity weapon,MyEntity targetEnt,int weaponId){return _isTargetAlignedExtended?.Invoke(weapon,targetEnt,weaponId)??new MyTuple();}public bool CanShootTarget(MyEntity weapon,MyEntity targetEnt,int weaponId){return _canShootTarget?.Invoke(weapon,targetEnt,weaponId)??false;}public Vector3D?GetPredictedTargetPosition(MyEntity weapon,MyEntity targetEnt,int weaponId){return _getPredictedTargetPos?.Invoke(weapon,targetEnt,weaponId)??null;}public float GetHeatLevel(MyEntity weapon){return _getHeatLevel?.Invoke(weapon)??0f;}public float GetCurrentPower(MyEntity weapon){return _currentPowerConsumption?.Invoke(weapon)??0f;}public void DisableRequiredPower(MyEntity weapon){_disableRequiredPower?.Invoke(weapon);}public bool HasCoreWeapon(MyEntity weapon){return _hasCoreWeapon?.Invoke(weapon)??false;}public string GetActiveAmmo(MyEntity weapon,int weaponId){return _getActiveAmmo?.Invoke(weapon,weaponId)??null;}public void SetActiveAmmo(MyEntity weapon,int weaponId,string ammoType){_setActiveAmmo?.Invoke(weapon,weaponId,ammoType);}public long GetPlayerController(MyEntity weapon){return _getPlayerController?.Invoke(weapon)??-1;}public Matrix GetWeaponAzimuthMatrix(MyEntity weapon,int weaponId){return _getWeaponAzimuthMatrix?.Invoke(weapon,weaponId)??Matrix.Zero;}public Matrix GetWeaponElevationMatrix(MyEntity weapon,int weaponId){return _getWeaponElevationMatrix?.Invoke(weapon,weaponId)??Matrix.Zero;}public bool IsTargetValid(MyEntity weapon,MyEntity target,bool onlyThreats,bool checkRelations){return _isTargetValid?.Invoke(weapon,target,onlyThreats,checkRelations)??false;}public void GetAllWeaponDefinitions(IListcollection){_getAllWeaponDefinitions?.Invoke(collection);}public void GetAllCoreWeapons(ICollectioncollection){_getCoreWeapons?.Invoke(collection);}public void GetNpcSafeWeapons(ICollectioncollection){_getNpcSafeWeapons?.Invoke(collection);}public void GetAllCoreStaticLaunchers(ICollectioncollection){_getCoreStaticLaunchers?.Invoke(collection);}public void GetAllWeaponMagazines(IDictionary>>>collection){_getAllWeaponMagazines?.Invoke(collection);}public void GetAllNpcSafeWeaponMagazines(IDictionary>>>collection){_getAllNpcSafeWeaponMagazines?.Invoke(collection);}public void GetAllCoreTurrets(ICollectioncollection){_getCoreTurrets?.Invoke(collection);}public void GetAllCorePhantoms(ICollectioncollection){_getCorePhantoms?.Invoke(collection);}public void GetAllCoreRifles(ICollectioncollection){_getCoreRifles?.Invoke(collection);}public void GetAllCoreArmors(IListcollection){_getCoreArmors?.Invoke(collection);}public MyTupleGetProjectilesLockedOn(MyEntity victim){return _getProjectilesLockedOn?.Invoke(victim)??new MyTuple();}public void GetProjectilesLockedOnPos(MyEntity victim,ICollectioncollection){_getProjectilesLockedOnPos?.Invoke(victim,collection);}public void GetSortedThreats(MyEntity shooter,ICollection>collection){_getSortedThreats?.Invoke(shooter,collection);}public void GetObstructions(MyEntity shooter,ICollectioncollection){_getObstructions?.Invoke(shooter,collection);}public MyEntity GetAiFocus(MyEntity shooter,int priority=0){return _getAiFocus?.Invoke(shooter,priority);}public bool SetAiFocus(MyEntity shooter,MyEntity target,int priority=0){return _setAiFocus?.Invoke(shooter,target,priority)??false;}public bool ReleaseAiFocus(MyEntity shooter,long playerId){return _releaseAiFocus?.Invoke(shooter,playerId)??false;}public MyTupleGetWeaponTarget(MyEntity weapon,int weaponId=0){return _getWeaponTarget?.Invoke(weapon,weaponId)??new MyTuple();}public float GetMaxPower(MyDefinitionId weaponDef){return _getMaxPower?.Invoke(weaponDef)??0f;}public bool HasAi(MyEntity entity){return _hasAi?.Invoke(entity)??false;}public float GetOptimalDps(MyEntity entity){return _getOptimalDps?.Invoke(entity)??0f;}public MyTupleGetProjectileState(ulong projectileId){return _getProjectileState?.Invoke(projectileId)??new MyTuple();}public float GetConstructEffectiveDps(MyEntity entity){return _getConstructEffectiveDps?.Invoke(entity)??0f;}public MyTupleGetWeaponScope(MyEntity weapon,int weaponId){return _getWeaponScope?.Invoke(weapon,weaponId)??new MyTuple();}public void AddProjectileCallback(MyEntity entity,int weaponId,Actionaction){_addProjectileMonitor?.Invoke(entity,weaponId,action);}public void RemoveProjectileCallback(MyEntity entity,int weaponId,Actionaction){_removeProjectileMonitor?.Invoke(entity,weaponId,action);}public MyTupleIsInRange(MyEntity entity){return _isInRange?.Invoke(entity)??new MyTuple();}public void SetProjectileState(ulong projectileId,MyTuplevalues){_setProjectileState?.Invoke(projectileId,values);}internal bool IsWeaponShooting(MyEntity weaponBlock,int weaponId){return _isWeaponShooting?.Invoke(weaponBlock,weaponId)??false;}internal int GetShotsFired(MyEntity weaponBlock,int weaponId){return _getShotsFired?.Invoke(weaponBlock,weaponId)??-1;}internal void GetMuzzleInfo(MyEntity weaponBlock,int weaponId,List>output){_getMuzzleInfo?.Invoke(weaponBlock,weaponId,output);}public bool ToggleInfiniteResources(MyEntity entity){return _toggoleInfiniteResources?.Invoke(entity)??false;}public void MonitorEvents(MyEntity entity,int partId,Actionaction){_monitorEvents?.Invoke(entity,partId,action);}public void UnMonitorEvents(MyEntity entity,int partId,Actionaction){_unmonitorEvents?.Invoke(entity,partId,action);}public void RegisterDamageEvent(long modId,int type,Action>>>>callback){_registerDamageEvent?.Invoke(modId,type,callback);}public void TargetFocushandler(long handledEntityId,bool unregister){_targetFocusHandler(handledEntityId,unregister,TargetFocusCallback);}private bool TargetFocusCallback(MyEntity target,IMyCharacter requestingCharacter,long handledEntityId,int modeCode){var mode=(ChangeMode)modeCode;return true;}public void Hudhandler(long handledEntityId,bool unregister){_hudHandler?.Invoke(handledEntityId,unregister,HudCallback);}private bool HudCallback(IMyCharacter requestingCharacter,long handledEntityId,int modeCode){var mode=(HudMode)modeCode;return true;}public bool ShootRequest(MyEntity weaponEntity,object target,int weaponId=0,double additionalDeviateShotAngle=0){return _shootRequest?.Invoke(weaponEntity,target,weaponId,additionalDeviateShotAngle)??false;}public void ShootRequestHandler(long handledEntityId,bool unregister,Funccallback){_shootHandler?.Invoke(handledEntityId,unregister,callback);}private bool ShootCallBack(Vector3D scopePos,Vector3D scopeDirection,int requestState,bool hasLos,object target,int currentAmmo,int remainingMags,int requestStage){var stage=(EventTriggers)requestStage;var state=(ShootState)requestState;var targetAsEntity=target as MyEntity;var targetAsProjectileId=target as ulong???0;var targetAsPosition=target as Vector3D???Vector3D.Zero;return true;}public MyTupleGetMagazineMap(MyEntity weapon,int weaponId){return _getMagazineMap?.Invoke(weapon,weaponId)??new MyTuple();}public bool SetMagazine(MyEntity weapon,int weaponId,MyDefinitionId id,bool forceReload){return _setMagazine?.Invoke(weapon,weaponId,id,forceReload)??false;}public bool ForceReload(MyEntity weapon,int weaponId){return _forceReload?.Invoke(weapon,weaponId)??false;}public void Load(Action readyCallback=null,bool getWeaponDefinitions=false){if(_isRegistered)throw new Exception($"{GetType().Name}.Load() should not be called multiple times!");_readyCallback=readyCallback;_getWeaponDefinitions=getWeaponDefinitions;_isRegistered=true;MyAPIGateway.Utilities.RegisterMessageHandler(Channel,HandleMessage);MyAPIGateway.Utilities.SendModMessage(Channel,"ApiEndpointRequest");}public void Unload(){MyAPIGateway.Utilities.UnregisterMessageHandler(Channel,HandleMessage);ApiAssign(null);_isRegistered=false;_apiInit=false;IsReady=false;}private void HandleMessage(object obj){if(_apiInit||obj is string)return;var dict=obj as IReadOnlyDictionary;if(dict==null)return;ApiAssign(dict,_getWeaponDefinitions);IsReady=true;_readyCallback?.Invoke();}public void ApiAssign(IReadOnlyDictionarydelegates,bool getWeaponDefinitions=false){_apiInit=delegates!=null;AssignMethod(delegates,"GetAllWeaponDefinitions",ref _getAllWeaponDefinitions);AssignMethod(delegates,"GetCoreWeapons",ref _getCoreWeapons);AssignMethod(delegates,"GetNpcSafeWeapons",ref _getNpcSafeWeapons);AssignMethod(delegates,"GetAllWeaponMagazines",ref _getAllWeaponMagazines);AssignMethod(delegates,"GetAllNpcSafeWeaponMagazines",ref _getAllNpcSafeWeaponMagazines);AssignMethod(delegates,"GetCoreStaticLaunchers",ref _getCoreStaticLaunchers);AssignMethod(delegates,"GetCoreTurrets",ref _getCoreTurrets);AssignMethod(delegates,"GetCorePhantoms",ref _getCorePhantoms);AssignMethod(delegates,"GetCoreRifles",ref _getCoreRifles);AssignMethod(delegates,"GetCoreArmors",ref _getCoreArmors);AssignMethod(delegates,"GetBlockWeaponMap",ref _getBlockWeaponMap);AssignMethod(delegates,"GetSortedThreatsBase",ref _getSortedThreats);AssignMethod(delegates,"GetObstructionsBase",ref _getObstructions);AssignMethod(delegates,"GetMaxPower",ref _getMaxPower);AssignMethod(delegates,"GetProjectilesLockedOnBase",ref _getProjectilesLockedOn);AssignMethod(delegates,"GetProjectilesLockedOnPos",ref _getProjectilesLockedOnPos);AssignMethod(delegates,"GetAiFocusBase",ref _getAiFocus);AssignMethod(delegates,"SetAiFocusBase",ref _setAiFocus);AssignMethod(delegates,"ReleaseAiFocusBase",ref _releaseAiFocus);AssignMethod(delegates,"HasGridAiBase",ref _hasAi);AssignMethod(delegates,"GetOptimalDpsBase",ref _getOptimalDps);AssignMethod(delegates,"GetConstructEffectiveDpsBase",ref _getConstructEffectiveDps);AssignMethod(delegates,"IsInRangeBase",ref _isInRange);AssignMethod(delegates,"GetProjectileState",ref _getProjectileState);AssignMethod(delegates,"SetProjectileState",ref _setProjectileState);AssignMethod(delegates,"AddMonitorProjectile",ref _addProjectileMonitor);AssignMethod(delegates,"RemoveMonitorProjectile",ref _removeProjectileMonitor);AssignMethod(delegates,"TargetFocusHandler",ref _targetFocusHandler);AssignMethod(delegates,"HudHandler",ref _hudHandler);AssignMethod(delegates,"ShootHandler",ref _shootHandler);AssignMethod(delegates,"ShootRequest",ref _shootRequest);AssignMethod(delegates,"GetWeaponTargetBase",ref _getWeaponTarget);AssignMethod(delegates,"SetWeaponTargetBase",ref _setWeaponTarget);AssignMethod(delegates,"FireWeaponOnceBase",ref _fireWeaponOnce);AssignMethod(delegates,"ToggleWeaponFireBase",ref _toggleWeaponFire);AssignMethod(delegates,"IsWeaponReadyToFireBase",ref _isWeaponReadyToFire);AssignMethod(delegates,"GetMaxWeaponRangeBase",ref _getMaxWeaponRange);AssignMethod(delegates,"GetTurretTargetTypesBase",ref _getTurretTargetTypes);AssignMethod(delegates,"SetTurretTargetTypesBase",ref _setTurretTargetTypes);AssignMethod(delegates,"SetBlockTrackingRangeBase",ref _setBlockTrackingRange);AssignMethod(delegates,"IsTargetAlignedBase",ref _isTargetAligned);AssignMethod(delegates,"IsTargetAlignedExtendedBase",ref _isTargetAlignedExtended);AssignMethod(delegates,"CanShootTargetBase",ref _canShootTarget);AssignMethod(delegates,"GetPredictedTargetPositionBase",ref _getPredictedTargetPos);AssignMethod(delegates,"GetHeatLevelBase",ref _getHeatLevel);AssignMethod(delegates,"GetCurrentPowerBase",ref _currentPowerConsumption);AssignMethod(delegates,"DisableRequiredPowerBase",ref _disableRequiredPower);AssignMethod(delegates,"HasCoreWeaponBase",ref _hasCoreWeapon);AssignMethod(delegates,"GetActiveAmmoBase",ref _getActiveAmmo);AssignMethod(delegates,"SetActiveAmmoBase",ref _setActiveAmmo);AssignMethod(delegates,"GetPlayerControllerBase",ref _getPlayerController);AssignMethod(delegates,"GetWeaponAzimuthMatrixBase",ref _getWeaponAzimuthMatrix);AssignMethod(delegates,"GetWeaponElevationMatrixBase",ref _getWeaponElevationMatrix);AssignMethod(delegates,"IsTargetValidBase",ref _isTargetValid);AssignMethod(delegates,"GetWeaponScopeBase",ref _getWeaponScope);AssignMethod(delegates,"GetTargetAssessment",ref _getTargetAssessment);AssignMethod(delegates,"SetTriggerState",ref _setTriggerState);AssignMethod(delegates,"AddMagazines",ref _addMagazines);AssignMethod(delegates,"SetAmmo",ref _setAmmo);AssignMethod(delegates,"ClosePhantom",ref _closePhantom);AssignMethod(delegates,"SpawnPhantom",ref _spawnPhantom);AssignMethod(delegates,"SetFocusTarget",ref _setPhantomFocusTarget);AssignMethod(delegates,"IsWeaponShootingBase",ref _isWeaponShooting);AssignMethod(delegates,"GetShotsFiredBase",ref _getShotsFired);AssignMethod(delegates,"GetMuzzleInfoBase",ref _getMuzzleInfo);AssignMethod(delegates,"ToggleInfiniteAmmoBase",ref _toggoleInfiniteResources);AssignMethod(delegates,"RegisterEventMonitor",ref _monitorEvents);AssignMethod(delegates,"UnRegisterEventMonitor",ref _unmonitorEvents);AssignMethod(delegates,"GetMagazineMap",ref _getMagazineMap);AssignMethod(delegates,"SetMagazine",ref _setMagazine);AssignMethod(delegates,"ForceReload",ref _forceReload);AssignMethod(delegates,"DamageHandler",ref _registerDamageEvent);if(getWeaponDefinitions){var byteArrays=new List();GetAllWeaponDefinitions(byteArrays);foreach(var byteArray in byteArrays)WeaponDefinitions.Add(MyAPIGateway.Utilities.SerializeFromBinary(byteArray));}}private void AssignMethod(IReadOnlyDictionarydelegates,string name,ref T field)where T:class{if(delegates==null){field=null;return;}Delegate del;if(!delegates.TryGetValue(name,out del))throw new Exception($"{GetType().Name} :: Couldn't find {name} delegate of type {typeof(T)}");field=del as T;if(field==null)throw new Exception($"{GetType().Name} :: Delegate {name} is not type {typeof(T)}, instead it's: {del.GetType()}");}internal enum HudMode{Selector,Reload,TargetInfo,Lead,Drone,PainterMarks}public class DamageHandlerHelper{public enum EventType{Unregister,SystemWideDamageEvents}private readonly List_convertedObjects=new List();private readonly Stack>_hitPool=new Stack>(256);private readonly WcApi _wcApi;public DamageHandlerHelper(WcApi wcApi){_wcApi=wcApi;}public void YourCallBackFunction(Listlist){}public void RegisterForDamage(long modId,EventType type){_wcApi.RegisterDamageEvent(modId,(int)type,DefaultCallBack);}private void DefaultCallBack(ListReader>>>listReader){YourCallBackFunction(ProcessEvents(listReader));CleanUpEvents();}private ListProcessEvents(ListReader>>>projectiles){foreach(var p in projectiles){var hits=_hitPool.Count>0?_hitPool.Pop():new List();foreach(var hitObj in p.Item6)hits.Add(new ProjectileDamageEvent.ProHit{HitPosition=hitObj.Item1,ObjectHit=hitObj.Item2,Damage=hitObj.Item3});_convertedObjects.Add(new ProjectileDamageEvent{ProId=p.Item1,PlayerId=p.Item2,WeaponId=p.Item3,WeaponEntity=p.Item4,WeaponParent=p.Item5,ObjectsHit=hits});}return _convertedObjects;}private void CleanUpEvents(){foreach(var p in _convertedObjects){p.ObjectsHit.Clear();_hitPool.Push(p.ObjectsHit);}_convertedObjects.Clear();}public struct ProjectileDamageEvent{public ulong ProId;public long PlayerId;public int WeaponId;public MyEntity WeaponEntity;public MyEntity WeaponParent;public ListObjectsHit;public struct ProHit{public Vector3D HitPosition;public object ObjectHit;public float Damage;}}}}}using System;using System.Collections.Generic;using Sandbox.ModAPI;namespace CGP.ShareTrack.API.CoreSystem{public partial class WcApi{private Func,bool>_getBlockWeaponMap;public bool GetBlockWeaponMap(IMyTerminalBlock weaponBlock,IDictionarycollection){return _getBlockWeaponMap?.Invoke(weaponBlock,collection)??false;}}}using System.Collections.Generic;using ProtoBuf;using VRageMath;namespace CGP.ShareTrack.API.CoreSystem{public static class WcApiDef{[ProtoContract]public class ContainerDefinition{[ProtoMember(2)]internal ArmorDefinition[]ArmorDefs;[ProtoMember(4)]internal SupportDefinition[]SupportDefs;[ProtoMember(3)]internal UpgradeDefinition[]UpgradeDefs;[ProtoMember(1)]internal WeaponDefinition[]WeaponDefs;}[ProtoContract]public class ConsumeableDef{[ProtoMember(5)]internal float EnergyCost;[ProtoMember(4)]internal bool Hybrid;[ProtoMember(2)]internal string InventoryItem;[ProtoMember(1)]internal string ItemName;[ProtoMember(3)]internal int ItemsNeeded;[ProtoMember(6)]internal float Strength;}[ProtoContract]public class UpgradeDefinition{[ProtoMember(3)]internal WeaponDefinition.AnimationDef Animations;[ProtoMember(1)]internal ModelAssignmentsDef Assignments;[ProtoMember(5)]internal ConsumeableDef[]Consumable;[ProtoMember(2)]internal HardPointDef HardPoint;[ProtoMember(4)]internal string ModPath;[ProtoContract]public struct ModelAssignmentsDef{[ProtoMember(1)]internal MountPointDef[]MountPoints;[ProtoContract]public struct MountPointDef{[ProtoMember(1)]internal string SubtypeId;[ProtoMember(2)]internal float DurabilityMod;[ProtoMember(3)]internal string IconName;}}[ProtoContract]public struct HardPointDef{[ProtoMember(1)]internal string PartName;[ProtoMember(2)]internal HardwareDef HardWare;[ProtoMember(3)]internal UiDef Ui;[ProtoMember(4)]internal OtherDef Other;[ProtoContract]public struct UiDef{[ProtoMember(1)]internal bool StrengthModifier;}[ProtoContract]public struct HardwareDef{public enum HardwareType{Default}[ProtoMember(1)]internal float InventorySize;[ProtoMember(2)]internal HardwareType Type;[ProtoMember(3)]internal int BlockDistance;}[ProtoContract]public struct OtherDef{[ProtoMember(1)]internal int ConstructPartCap;[ProtoMember(2)]internal int EnergyPriority;[ProtoMember(3)]internal bool Debug;[ProtoMember(4)]internal double RestrictionRadius;[ProtoMember(5)]internal bool CheckInflatedBox;[ProtoMember(6)]internal bool CheckForAnySupport;[ProtoMember(7)]internal bool StayCharged;}}}[ProtoContract]public class SupportDefinition{[ProtoMember(3)]internal WeaponDefinition.AnimationDef Animations;[ProtoMember(1)]internal ModelAssignmentsDef Assignments;[ProtoMember(5)]internal ConsumeableDef[]Consumable;[ProtoMember(6)]internal SupportEffect Effect;[ProtoMember(2)]internal HardPointDef HardPoint;[ProtoMember(4)]internal string ModPath;[ProtoContract]public struct ModelAssignmentsDef{[ProtoMember(1)]internal MountPointDef[]MountPoints;[ProtoContract]public struct MountPointDef{[ProtoMember(1)]internal string SubtypeId;[ProtoMember(2)]internal float DurabilityMod;[ProtoMember(3)]internal string IconName;}}[ProtoContract]public struct HardPointDef{[ProtoMember(1)]internal string PartName;[ProtoMember(2)]internal HardwareDef HardWare;[ProtoMember(3)]internal UiDef Ui;[ProtoMember(4)]internal OtherDef Other;[ProtoContract]public struct UiDef{[ProtoMember(1)]internal bool ProtectionControl;}[ProtoContract]public struct HardwareDef{[ProtoMember(1)]internal float InventorySize;}[ProtoContract]public struct OtherDef{[ProtoMember(1)]internal int ConstructPartCap;[ProtoMember(2)]internal int EnergyPriority;[ProtoMember(3)]internal bool Debug;[ProtoMember(4)]internal double RestrictionRadius;[ProtoMember(5)]internal bool CheckInflatedBox;[ProtoMember(6)]internal bool CheckForAnySupport;[ProtoMember(7)]internal bool StayCharged;}}[ProtoContract]public struct SupportEffect{public enum AffectedBlocks{Armor,ArmorPlus,PlusFunctional,All}public enum Protections{KineticProt,EnergeticProt,GenericProt,Regenerate,Structural}[ProtoMember(1)]internal Protections Protection;[ProtoMember(2)]internal AffectedBlocks Affected;[ProtoMember(3)]internal int BlockRange;[ProtoMember(4)]internal int MaxPoints;[ProtoMember(5)]internal int PointsPerCharge;[ProtoMember(6)]internal int UsablePerSecond;[ProtoMember(7)]internal int UsablePerMinute;[ProtoMember(8)]internal float Overflow;[ProtoMember(9)]internal float Effectiveness;[ProtoMember(10)]internal float ProtectionMin;[ProtoMember(11)]internal float ProtectionMax;}}[ProtoContract]public class ArmorDefinition{[ProtoMember(4)]internal double EnergeticResistance;[ProtoMember(2)]internal ArmorType Kind;[ProtoMember(3)]internal double KineticResistance;[ProtoMember(1)]internal string[]SubtypeIds;internal enum ArmorType{Light,Heavy,NonArmor}}[ProtoContract]public class WeaponDefinition{[ProtoMember(5)]internal AmmoDef[]Ammos;[ProtoMember(3)]internal AnimationDef Animations;[ProtoMember(1)]internal ModelAssignmentsDef Assignments;[ProtoMember(4)]internal HardPointDef HardPoint;[ProtoMember(6)]internal string ModPath;[ProtoMember(2)]internal TargetingDef Targeting;[ProtoMember(7)]internal DictionaryUpgrades;[ProtoContract]public struct ModelAssignmentsDef{[ProtoMember(1)]internal MountPointDef[]MountPoints;[ProtoMember(2)]internal string[]Muzzles;[ProtoMember(3)]internal string Ejector;[ProtoMember(4)]internal string Scope;[ProtoContract]public struct MountPointDef{[ProtoMember(1)]internal string SubtypeId;[ProtoMember(2)]internal string SpinPartId;[ProtoMember(3)]internal string MuzzlePartId;[ProtoMember(4)]internal string AzimuthPartId;[ProtoMember(5)]internal string ElevationPartId;[ProtoMember(6)]internal float DurabilityMod;[ProtoMember(7)]internal string IconName;}}[ProtoContract]public struct TargetingDef{public enum Threat{Projectiles,Characters,Grids,Neutrals,Meteors,Other,ScanNeutralGrid,ScanFriendlyGrid,ScanFriendlyCharacter,ScanRoid,ScanPlanet,ScanEnemyCharacter,ScanEnemyGrid,ScanNeutralCharacter,ScanUnOwnedGrid,ScanOwnersGrid}public enum BlockTypes{Any,Offense,Utility,Power,Production,Thrust,Jumping,Steering}[ProtoMember(1)]internal int TopTargets;[ProtoMember(2)]internal int TopBlocks;[ProtoMember(3)]internal double StopTrackingSpeed;[ProtoMember(4)]internal float MinimumDiameter;[ProtoMember(5)]internal float MaximumDiameter;[ProtoMember(6)]internal bool ClosestFirst;[ProtoMember(7)]internal BlockTypes[]SubSystems;[ProtoMember(8)]internal Threat[]Threats;[ProtoMember(9)]internal float MaxTargetDistance;[ProtoMember(10)]internal float MinTargetDistance;[ProtoMember(11)]internal bool IgnoreDumbProjectiles;[ProtoMember(12)]internal bool LockedSmartOnly;[ProtoMember(13)]internal bool UniqueTargetPerWeapon;[ProtoMember(14)]internal int MaxTrackingTime;[ProtoMember(15)]internal bool ShootBlanks;[ProtoMember(19)]internal CommunicationDef Communications;[ProtoMember(20)]internal bool FocusOnly;[ProtoMember(21)]internal bool EvictUniqueTargets;[ProtoMember(22)]internal int CycleTargets;[ProtoMember(23)]internal int CycleBlocks;[ProtoContract]public struct CommunicationDef{public enum Comms{NoComms,BroadCast,Relay,Jamming,RelayAndBroadCast}public enum SecurityMode{Public,Private,Secure}[ProtoMember(1)]internal bool StoreTargets;[ProtoMember(2)]internal int StorageLimit;[ProtoMember(3)]internal string StorageLocation;[ProtoMember(4)]internal Comms Mode;[ProtoMember(5)]internal SecurityMode Security;[ProtoMember(6)]internal string BroadCastChannel;[ProtoMember(7)]internal double BroadCastRange;[ProtoMember(8)]internal double JammingStrength;[ProtoMember(9)]internal string RelayChannel;[ProtoMember(10)]internal double RelayRange;[ProtoMember(11)]internal bool TargetPersists;[ProtoMember(12)]internal bool StoreLimitPerBlock;[ProtoMember(13)]internal int MaxConnections;}}[ProtoContract]public struct AnimationDef{[ProtoMember(1)]internal PartAnimationSetDef[]AnimationSets;[ProtoMember(2)]internal PartEmissive[]Emissives;[ProtoMember(3)]internal string[]HeatingEmissiveParts;[ProtoMember(4)]internal DictionaryEventParticles;[ProtoContract(IgnoreListHandling=true)]public struct PartAnimationSetDef{public enum EventTriggers{Reloading,Firing,Tracking,Overheated,TurnOn,TurnOff,BurstReload,NoMagsToLoad,PreFire,EmptyOnGameLoad,StopFiring,StopTracking,LockDelay}public enum ResetConditions{None,Home,Off,On,Reloaded}[ProtoMember(1)]internal string[]SubpartId;[ProtoMember(2)]internal string BarrelId;[ProtoMember(3)]internal uint StartupFireDelay;[ProtoMember(4)]internal DictionaryAnimationDelays;[ProtoMember(5)]internal EventTriggers[]Reverse;[ProtoMember(6)]internal EventTriggers[]Loop;[ProtoMember(7)]internal DictionaryEventMoveSets;[ProtoMember(8)]internal EventTriggers[]TriggerOnce;[ProtoMember(9)]internal EventTriggers[]ResetEmissives;[ProtoMember(10)]internal ResetConditions Resets;}[ProtoContract]public struct PartEmissive{[ProtoMember(1)]internal string EmissiveName;[ProtoMember(2)]internal string[]EmissivePartNames;[ProtoMember(3)]internal bool CycleEmissivesParts;[ProtoMember(4)]internal bool LeavePreviousOn;[ProtoMember(5)]internal Vector4[]Colors;[ProtoMember(6)]internal float[]IntensityRange;}[ProtoContract]public struct EventParticle{[ProtoMember(1)]internal string[]EmptyNames;[ProtoMember(2)]internal string[]MuzzleNames;[ProtoMember(3)]internal ParticleDef Particle;[ProtoMember(4)]internal uint StartDelay;[ProtoMember(5)]internal uint LoopDelay;[ProtoMember(6)]internal bool ForceStop;}[ProtoContract]internal struct RelMove{public enum MoveType{Linear,ExpoDecay,ExpoGrowth,Delay,Show,Hide}[ProtoMember(1)]internal MoveType MovementType;[ProtoMember(2)]internal XYZ[]LinearPoints;[ProtoMember(3)]internal XYZ Rotation;[ProtoMember(4)]internal XYZ RotAroundCenter;[ProtoMember(5)]internal uint TicksToMove;[ProtoMember(6)]internal string CenterEmpty;[ProtoMember(7)]internal bool Fade;[ProtoMember(8)]internal string EmissiveName;[ProtoContract]internal struct XYZ{[ProtoMember(1)]internal double x;[ProtoMember(2)]internal double y;[ProtoMember(3)]internal double z;}}}[ProtoContract]public struct UpgradeValues{[ProtoMember(1)]internal string[]Ammo;[ProtoMember(2)]internal Dependency[]Dependencies;[ProtoMember(3)]internal int RateOfFireMod;[ProtoMember(4)]internal int BarrelsPerShotMod;[ProtoMember(5)]internal int ReloadMod;[ProtoMember(6)]internal int MaxHeatMod;[ProtoMember(7)]internal int HeatSinkRateMod;[ProtoMember(8)]internal int ShotsInBurstMod;[ProtoMember(9)]internal int DelayAfterBurstMod;[ProtoMember(10)]internal int AmmoPriority;[ProtoContract]public struct Dependency{internal string SubtypeId;internal int Quanity;}}[ProtoContract]public struct HardPointDef{public enum Prediction{Off,Basic,Accurate,Advanced}[ProtoMember(1)]internal string PartName;[ProtoMember(2)]internal int DelayCeaseFire;[ProtoMember(3)]internal float DeviateShotAngle;[ProtoMember(4)]internal double AimingTolerance;[ProtoMember(5)]internal Prediction AimLeadingPrediction;[ProtoMember(6)]internal LoadingDef Loading;[ProtoMember(7)]internal AiDef Ai;[ProtoMember(8)]internal HardwareDef HardWare;[ProtoMember(9)]internal UiDef Ui;[ProtoMember(10)]internal HardPointAudioDef Audio;[ProtoMember(11)]internal HardPointParticleDef Graphics;[ProtoMember(12)]internal OtherDef Other;[ProtoMember(13)]internal bool AddToleranceToTracking;[ProtoMember(14)]internal bool CanShootSubmerged;[ProtoMember(15)]internal bool NpcSafe;[ProtoMember(16)]internal bool ScanTrackOnly;[ProtoContract]public struct LoadingDef{[ProtoMember(1)]internal int ReloadTime;[ProtoMember(2)]internal int RateOfFire;[ProtoMember(3)]internal int BarrelsPerShot;[ProtoMember(4)]internal int SkipBarrels;[ProtoMember(5)]internal int TrajectilesPerBarrel;[ProtoMember(6)]internal int HeatPerShot;[ProtoMember(7)]internal int MaxHeat;[ProtoMember(8)]internal int HeatSinkRate;[ProtoMember(9)]internal float Cooldown;[ProtoMember(10)]internal int DelayUntilFire;[ProtoMember(11)]internal int ShotsInBurst;[ProtoMember(12)]internal int DelayAfterBurst;[ProtoMember(13)]internal bool DegradeRof;[ProtoMember(14)]internal int BarrelSpinRate;[ProtoMember(15)]internal bool FireFull;[ProtoMember(16)]internal bool GiveUpAfter;[ProtoMember(17)]internal bool DeterministicSpin;[ProtoMember(18)]internal bool SpinFree;[ProtoMember(19)]internal bool StayCharged;[ProtoMember(20)]internal int MagsToLoad;[ProtoMember(21)]internal int MaxActiveProjectiles;[ProtoMember(22)]internal int MaxReloads;[ProtoMember(23)]internal bool GoHomeToReload;[ProtoMember(24)]internal bool DropTargetUntilLoaded;}[ProtoContract]public struct UiDef{[ProtoMember(1)]internal bool RateOfFire;[ProtoMember(2)]internal bool DamageModifier;[ProtoMember(3)]internal bool ToggleGuidance;[ProtoMember(4)]internal bool EnableOverload;[ProtoMember(5)]internal bool AlternateUi;[ProtoMember(6)]internal bool DisableStatus;}[ProtoContract]public struct AiDef{[ProtoMember(1)]internal bool TrackTargets;[ProtoMember(2)]internal bool TurretAttached;[ProtoMember(3)]internal bool TurretController;[ProtoMember(4)]internal bool PrimaryTracking;[ProtoMember(5)]internal bool LockOnFocus;[ProtoMember(6)]internal bool SuppressFire;[ProtoMember(7)]internal bool OverrideLeads;[ProtoMember(8)]internal int DefaultLeadGroup;[ProtoMember(9)]internal bool TargetGridCenter;}[ProtoContract]public struct HardwareDef{public enum HardwareType{BlockWeapon=0,HandWeapon=1,Phantom=6}[ProtoMember(1)]internal float RotateRate;[ProtoMember(2)]internal float ElevateRate;[ProtoMember(3)]internal Vector3D Offset;[ProtoMember(4)]internal bool FixedOffset;[ProtoMember(5)]internal int MaxAzimuth;[ProtoMember(6)]internal int MinAzimuth;[ProtoMember(7)]internal int MaxElevation;[ProtoMember(8)]internal int MinElevation;[ProtoMember(9)]internal float InventorySize;[ProtoMember(10)]internal HardwareType Type;[ProtoMember(11)]internal int HomeAzimuth;[ProtoMember(12)]internal int HomeElevation;[ProtoMember(13)]internal CriticalDef CriticalReaction;[ProtoMember(14)]internal float IdlePower;[ProtoContract]public struct CriticalDef{[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal int DefaultArmedTimer;[ProtoMember(3)]internal bool PreArmed;[ProtoMember(4)]internal bool TerminalControls;[ProtoMember(5)]internal string AmmoRound;}}[ProtoContract]public struct HardPointAudioDef{[ProtoMember(1)]internal string ReloadSound;[ProtoMember(2)]internal string NoAmmoSound;[ProtoMember(3)]internal string HardPointRotationSound;[ProtoMember(4)]internal string BarrelRotationSound;[ProtoMember(5)]internal string FiringSound;[ProtoMember(6)]internal bool FiringSoundPerShot;[ProtoMember(7)]internal string PreFiringSound;[ProtoMember(8)]internal uint FireSoundEndDelay;[ProtoMember(9)]internal bool FireSoundNoBurst;}[ProtoContract]public struct OtherDef{[ProtoMember(1)]internal int ConstructPartCap;[ProtoMember(2)]internal int EnergyPriority;[ProtoMember(3)]internal int RotateBarrelAxis;[ProtoMember(4)]internal bool MuzzleCheck;[ProtoMember(5)]internal bool Debug;[ProtoMember(6)]internal double RestrictionRadius;[ProtoMember(7)]internal bool CheckInflatedBox;[ProtoMember(8)]internal bool CheckForAnyWeapon;[ProtoMember(9)]internal bool DisableLosCheck;[ProtoMember(10)]internal bool NoVoxelLosCheck;}[ProtoContract]public struct HardPointParticleDef{[ProtoMember(1)]internal ParticleDef Effect1;[ProtoMember(2)]internal ParticleDef Effect2;}}[ProtoContract]public class AmmoDef{[ProtoMember(17)]internal AmmoAudioDef AmmoAudio;[ProtoMember(16)]internal GraphicDef AmmoGraphics;[ProtoMember(1)]internal string AmmoMagazine;[ProtoMember(2)]internal string AmmoRound;[ProtoMember(13)]internal AreaDamageDef AreaEffect;[ProtoMember(24)]internal AreaOfDamageDef AreaOfDamage;[ProtoMember(8)]internal float BackKickForce;[ProtoMember(5)]internal float BaseDamage;[ProtoMember(14)]internal BeamDef Beams;[ProtoMember(9)]internal DamageScaleDef DamageScales;[ProtoMember(21)]internal float DecayPerShot;[ProtoMember(22)]internal EjectionDef Ejection;[ProtoMember(4)]internal float EnergyCost;[ProtoMember(20)]internal int EnergyMagazineSize;[ProtoMember(25)]internal EwarDef Ewar;[ProtoMember(15)]internal FragmentDef Fragment;[ProtoMember(18)]internal bool HardPointUsable;[ProtoMember(7)]internal float Health;[ProtoMember(28)]internal double HeatModifier;[ProtoMember(3)]internal bool HybridRound;[ProtoMember(26)]internal bool IgnoreVoxels;[ProtoMember(23)]internal bool IgnoreWater;[ProtoMember(6)]internal float Mass;[ProtoMember(31)]internal bool NoGridOrArmorScaling;[ProtoMember(29)]internal bool NpcSafe;[ProtoMember(11)]internal ObjectsHitDef ObjectsHit;[ProtoMember(19)]internal PatternDef Pattern;[ProtoMember(10)]internal ShapeDef Shape;[ProtoMember(30)]internal SynchronizeDef Sync;[ProtoMember(27)]internal bool Synchronize;[ProtoMember(12)]internal TrajectoryDef Trajectory;[ProtoContract]public struct SynchronizeDef{[ProtoMember(1)]internal bool Full;[ProtoMember(2)]internal bool PointDefense;[ProtoMember(3)]internal bool OnHitDeath;}[ProtoContract]public struct DamageScaleDef{[ProtoMember(1)]internal float MaxIntegrity;[ProtoMember(2)]internal bool DamageVoxels;[ProtoMember(3)]internal float Characters;[ProtoMember(4)]internal bool SelfDamage;[ProtoMember(5)]internal GridSizeDef Grids;[ProtoMember(6)]internal ArmorDef Armor;[ProtoMember(7)]internal CustomScalesDef Custom;[ProtoMember(8)]internal ShieldDef Shields;[ProtoMember(9)]internal FallOffDef FallOff;[ProtoMember(10)]internal double HealthHitModifier;[ProtoMember(11)]internal double VoxelHitModifier;[ProtoMember(12)]internal DamageTypes DamageType;[ProtoMember(13)]internal DeformDef Deform;[ProtoContract]public struct FallOffDef{[ProtoMember(1)]internal float Distance;[ProtoMember(2)]internal float MinMultipler;}[ProtoContract]public struct GridSizeDef{[ProtoMember(1)]internal float Large;[ProtoMember(2)]internal float Small;}[ProtoContract]public struct ArmorDef{[ProtoMember(1)]internal float Armor;[ProtoMember(2)]internal float Heavy;[ProtoMember(3)]internal float Light;[ProtoMember(4)]internal float NonArmor;}[ProtoContract]public struct CustomScalesDef{internal enum SkipMode{NoSkip,Inclusive,Exclusive}[ProtoMember(1)]internal CustomBlocksDef[]Types;[ProtoMember(2)]internal bool IgnoreAllOthers;[ProtoMember(3)]internal SkipMode SkipOthers;}[ProtoContract]public struct DamageTypes{internal enum Damage{Energy,Kinetic}[ProtoMember(1)]internal Damage Base;[ProtoMember(2)]internal Damage AreaEffect;[ProtoMember(3)]internal Damage Detonation;[ProtoMember(4)]internal Damage Shield;}[ProtoContract]public struct ShieldDef{internal enum ShieldType{Default,Heal,Bypass,EmpRetired}[ProtoMember(1)]internal float Modifier;[ProtoMember(2)]internal ShieldType Type;[ProtoMember(3)]internal float BypassModifier;}[ProtoContract]public struct DeformDef{internal enum DeformTypes{HitBlock,AllDamagedBlocks,NoDeform}[ProtoMember(1)]internal DeformTypes DeformType;[ProtoMember(2)]internal int DeformDelay;}}[ProtoContract]public struct ShapeDef{public enum Shapes{LineShape,SphereShape}[ProtoMember(1)]internal Shapes Shape;[ProtoMember(2)]internal double Diameter;}[ProtoContract]public struct ObjectsHitDef{[ProtoMember(1)]internal int MaxObjectsHit;[ProtoMember(2)]internal bool CountBlocks;}[ProtoContract]public struct CustomBlocksDef{[ProtoMember(1)]internal string SubTypeId;[ProtoMember(2)]internal float Modifier;}[ProtoContract]public struct GraphicDef{[ProtoMember(1)]internal bool ShieldHitDraw;[ProtoMember(2)]internal float VisualProbability;[ProtoMember(3)]internal string ModelName;[ProtoMember(4)]internal AmmoParticleDef Particles;[ProtoMember(5)]internal LineDef Lines;[ProtoMember(6)]internal DecalDef Decals;[ProtoContract]public struct AmmoParticleDef{[ProtoMember(1)]internal ParticleDef Ammo;[ProtoMember(2)]internal ParticleDef Hit;[ProtoMember(3)]internal ParticleDef Eject;}[ProtoContract]public struct LineDef{internal enum Texture{Normal,Cycle,Chaos,Wave}public enum FactionColor{DontUse,Foreground,Background}[ProtoMember(1)]internal TracerBaseDef Tracer;[ProtoMember(2)]internal string TracerMaterial;[ProtoMember(3)]internal Randomize ColorVariance;[ProtoMember(4)]internal Randomize WidthVariance;[ProtoMember(5)]internal TrailDef Trail;[ProtoMember(6)]internal OffsetEffectDef OffsetEffect;[ProtoMember(7)]internal bool DropParentVelocity;[ProtoContract]public struct OffsetEffectDef{[ProtoMember(1)]internal double MaxOffset;[ProtoMember(2)]internal double MinLength;[ProtoMember(3)]internal double MaxLength;}[ProtoContract]public struct TracerBaseDef{[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal float Length;[ProtoMember(3)]internal float Width;[ProtoMember(4)]internal Vector4 Color;[ProtoMember(5)]internal uint VisualFadeStart;[ProtoMember(6)]internal uint VisualFadeEnd;[ProtoMember(7)]internal SegmentDef Segmentation;[ProtoMember(8)]internal string[]Textures;[ProtoMember(9)]internal Texture TextureMode;[ProtoMember(10)]internal bool AlwaysDraw;[ProtoMember(11)]internal FactionColor FactionColor;[ProtoContract]public struct SegmentDef{[ProtoMember(1)]internal string Material;[ProtoMember(2)]internal double SegmentLength;[ProtoMember(3)]internal double SegmentGap;[ProtoMember(4)]internal double Speed;[ProtoMember(5)]internal Vector4 Color;[ProtoMember(6)]internal double WidthMultiplier;[ProtoMember(7)]internal bool Reverse;[ProtoMember(8)]internal bool UseLineVariance;[ProtoMember(9)]internal Randomize ColorVariance;[ProtoMember(10)]internal Randomize WidthVariance;[ProtoMember(11)]internal string[]Textures;[ProtoMember(12)]internal bool Enable;[ProtoMember(13)]internal FactionColor FactionColor;}}[ProtoContract]public struct TrailDef{[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal string Material;[ProtoMember(3)]internal int DecayTime;[ProtoMember(4)]internal Vector4 Color;[ProtoMember(5)]internal bool Back;[ProtoMember(6)]internal float CustomWidth;[ProtoMember(7)]internal bool UseWidthVariance;[ProtoMember(8)]internal bool UseColorFade;[ProtoMember(9)]internal string[]Textures;[ProtoMember(10)]internal Texture TextureMode;[ProtoMember(11)]internal bool AlwaysDraw;[ProtoMember(12)]internal FactionColor FactionColor;}}[ProtoContract]public struct DecalDef{[ProtoMember(1)]internal int MaxAge;[ProtoMember(2)]internal TextureMapDef[]Map;[ProtoContract]public struct TextureMapDef{[ProtoMember(1)]internal string HitMaterial;[ProtoMember(2)]internal string DecalMaterial;}}}[ProtoContract]public struct BeamDef{[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal bool ConvergeBeams;[ProtoMember(3)]internal bool VirtualBeams;[ProtoMember(4)]internal bool RotateRealBeam;[ProtoMember(5)]internal bool OneParticle;[ProtoMember(6)]internal bool FakeVoxelHits;}[ProtoContract]public struct FragmentDef{[ProtoMember(1)]internal string AmmoRound;[ProtoMember(2)]internal int Fragments;[ProtoMember(3)]internal float Radial;[ProtoMember(4)]internal float BackwardDegrees;[ProtoMember(5)]internal float Degrees;[ProtoMember(6)]internal bool Reverse;[ProtoMember(7)]internal bool IgnoreArming;[ProtoMember(8)]internal bool DropVelocity;[ProtoMember(9)]internal float Offset;[ProtoMember(10)]internal int MaxChildren;[ProtoMember(11)]internal TimedSpawnDef TimedSpawns;[ProtoMember(12)]internal bool FireSound;[ProtoMember(13)]internal Vector3D AdvOffset;[ProtoMember(14)]internal bool ArmWhenHit;[ProtoContract]public struct TimedSpawnDef{public enum PointTypes{Direct,Lead,Predict}[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal int Interval;[ProtoMember(3)]internal int StartTime;[ProtoMember(4)]internal int MaxSpawns;[ProtoMember(5)]internal double Proximity;[ProtoMember(6)]internal bool ParentDies;[ProtoMember(7)]internal bool PointAtTarget;[ProtoMember(8)]internal int GroupSize;[ProtoMember(9)]internal int GroupDelay;[ProtoMember(10)]internal PointTypes PointType;}}[ProtoContract]public struct PatternDef{public enum PatternModes{Never,Weapon,Fragment,Both}[ProtoMember(1)]internal string[]Patterns;[ProtoMember(2)]internal bool Enable;[ProtoMember(3)]internal float TriggerChance;[ProtoMember(4)]internal bool SkipParent;[ProtoMember(5)]internal bool Random;[ProtoMember(6)]internal int RandomMin;[ProtoMember(7)]internal int RandomMax;[ProtoMember(8)]internal int PatternSteps;[ProtoMember(9)]internal PatternModes Mode;}[ProtoContract]public struct EjectionDef{public enum SpawnType{Item,Particle}[ProtoMember(1)]internal float Speed;[ProtoMember(2)]internal float SpawnChance;[ProtoMember(3)]internal SpawnType Type;[ProtoMember(4)]internal ComponentDef CompDef;[ProtoContract]public struct ComponentDef{[ProtoMember(1)]internal string ItemName;[ProtoMember(2)]internal int ItemLifeTime;[ProtoMember(3)]internal int Delay;}}[ProtoContract]public struct AreaOfDamageDef{public enum Falloff{Legacy,NoFalloff,Linear,Curve,InvCurve,Squeeze,Pooled,Exponential}public enum AoeShape{Round,Diamond}[ProtoMember(1)]internal ByBlockHitDef ByBlockHit;[ProtoMember(2)]internal EndOfLifeDef EndOfLife;[ProtoContract]public struct ByBlockHitDef{[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal double Radius;[ProtoMember(3)]internal float Damage;[ProtoMember(4)]internal float Depth;[ProtoMember(5)]internal float MaxAbsorb;[ProtoMember(6)]internal Falloff Falloff;[ProtoMember(7)]internal AoeShape Shape;}[ProtoContract]public struct EndOfLifeDef{[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal double Radius;[ProtoMember(3)]internal float Damage;[ProtoMember(4)]internal float Depth;[ProtoMember(5)]internal float MaxAbsorb;[ProtoMember(6)]internal Falloff Falloff;[ProtoMember(7)]internal bool ArmOnlyOnHit;[ProtoMember(8)]internal int MinArmingTime;[ProtoMember(9)]internal bool NoVisuals;[ProtoMember(10)]internal bool NoSound;[ProtoMember(11)]internal float ParticleScale;[ProtoMember(12)]internal string CustomParticle;[ProtoMember(13)]internal string CustomSound;[ProtoMember(14)]internal AoeShape Shape;}}[ProtoContract]public struct EwarDef{public enum EwarType{AntiSmart,JumpNull,EnergySink,Anchor,Emp,Offense,Nav,Dot,Push,Pull,Tractor}public enum EwarMode{Effect,Field}[ProtoMember(1)]internal bool Enable;[ProtoMember(2)]internal EwarType Type;[ProtoMember(3)]internal EwarMode Mode;[ProtoMember(4)]internal float Strength;[ProtoMember(5)]internal double Radius;[ProtoMember(6)]internal int Duration;[ProtoMember(7)]internal bool StackDuration;[ProtoMember(8)]internal bool Depletable;[ProtoMember(9)]internal int MaxStacks;[ProtoMember(10)]internal bool NoHitParticle;[ProtoMember(11)]internal PushPullDef Force;[ProtoMember(12)]internal FieldDef Field;[ProtoContract]public struct FieldDef{[ProtoMember(1)]internal int Interval;[ProtoMember(2)]internal int PulseChance;[ProtoMember(3)]internal int GrowTime;[ProtoMember(4)]internal bool HideModel;[ProtoMember(5)]internal bool ShowParticle;[ProtoMember(6)]internal double TriggerRange;[ProtoMember(7)]internal ParticleDef Particle;}[ProtoContract]public struct PushPullDef{public enum Force{ProjectileLastPosition,ProjectileOrigin,HitPosition,TargetCenter,TargetCenterOfMass}[ProtoMember(1)]internal Force ForceFrom;[ProtoMember(2)]internal Force ForceTo;[ProtoMember(3)]internal Force Position;[ProtoMember(4)]internal bool DisableRelativeMass;[ProtoMember(5)]internal double TractorRange;[ProtoMember(6)]internal bool ShooterFeelsForce;}}[ProtoContract]public struct AreaDamageDef{public enum AreaEffectType{Disabled,Explosive,Radiant,AntiSmart,JumpNullField,EnergySinkField,AnchorField,EmpField,OffenseField,NavField,DotField,PushField,PullField,TractorField}[ProtoMember(1)]internal double AreaEffectRadius;[ProtoMember(2)]internal float AreaEffectDamage;[ProtoMember(3)]internal AreaEffectType AreaEffect;[ProtoMember(4)]internal PulseDef Pulse;[ProtoMember(5)]internal DetonateDef Detonation;[ProtoMember(6)]internal ExplosionDef Explosions;[ProtoMember(7)]internal EwarFieldsDef EwarFields;[ProtoMember(8)]internal AreaInfluence Base;[ProtoContract]public struct AreaInfluence{[ProtoMember(1)]internal double Radius;[ProtoMember(2)]internal float EffectStrength;}[ProtoContract]public struct PulseDef{[ProtoMember(1)]internal int Interval;[ProtoMember(2)]internal int PulseChance;[ProtoMember(3)]internal int GrowTime;[ProtoMember(4)]internal bool HideModel;[ProtoMember(5)]internal bool ShowParticle;[ProtoMember(6)]internal ParticleDef Particle;}[ProtoContract]public struct EwarFieldsDef{[ProtoMember(1)]internal int Duration;[ProtoMember(2)]internal bool StackDuration;[ProtoMember(3)]internal bool Depletable;[ProtoMember(4)]internal double TriggerRange;[ProtoMember(5)]internal int MaxStacks;[ProtoMember(6)]internal PushPullDef Force;[ProtoMember(7)]internal bool DisableParticleEffect;[ProtoContract]public struct PushPullDef{public enum Force{ProjectileLastPosition,ProjectileOrigin,HitPosition,TargetCenter,TargetCenterOfMass}[ProtoMember(1)]internal Force ForceFrom;[ProtoMember(2)]internal Force ForceTo;[ProtoMember(3)]internal Force Position;[ProtoMember(4)]internal bool DisableRelativeMass;[ProtoMember(5)]internal double TractorRange;[ProtoMember(6)]internal bool ShooterFeelsForce;}}[ProtoContract]public struct DetonateDef{[ProtoMember(1)]internal bool DetonateOnEnd;[ProtoMember(2)]internal bool ArmOnlyOnHit;[ProtoMember(3)]internal float DetonationRadius;[ProtoMember(4)]internal float DetonationDamage;[ProtoMember(5)]internal int MinArmingTime;}[ProtoContract]public struct ExplosionDef{[ProtoMember(1)]internal bool NoVisuals;[ProtoMember(2)]internal bool NoSound;[ProtoMember(3)]internal float Scale;[ProtoMember(4)]internal string CustomParticle;[ProtoMember(5)]internal string CustomSound;[ProtoMember(6)]internal bool NoShrapnel;[ProtoMember(7)]internal bool NoDeformation;}}[ProtoContract]public struct AmmoAudioDef{[ProtoMember(1)]internal string TravelSound;[ProtoMember(2)]internal string HitSound;[ProtoMember(3)]internal float HitPlayChance;[ProtoMember(4)]internal bool HitPlayShield;[ProtoMember(5)]internal string VoxelHitSound;[ProtoMember(6)]internal string PlayerHitSound;[ProtoMember(7)]internal string FloatingHitSound;[ProtoMember(8)]internal string ShieldHitSound;[ProtoMember(9)]internal string ShotSound;}[ProtoContract]public struct TrajectoryDef{internal enum GuidanceType{None,Remote,TravelTo,Smart,DetectTravelTo,DetectSmart,DetectFixed,DroneAdvanced}[ProtoMember(1)]internal float MaxTrajectory;[ProtoMember(2)]internal float AccelPerSec;[ProtoMember(3)]internal float DesiredSpeed;[ProtoMember(4)]internal float TargetLossDegree;[ProtoMember(5)]internal int TargetLossTime;[ProtoMember(6)]internal int MaxLifeTime;[ProtoMember(7)]internal int DeaccelTime;[ProtoMember(8)]internal Randomize SpeedVariance;[ProtoMember(9)]internal Randomize RangeVariance;[ProtoMember(10)]internal GuidanceType Guidance;[ProtoMember(11)]internal SmartsDef Smarts;[ProtoMember(12)]internal MinesDef Mines;[ProtoMember(13)]internal float GravityMultiplier;[ProtoMember(14)]internal uint MaxTrajectoryTime;[ProtoMember(15)]internal ApproachDef[]Approaches;[ProtoMember(16)]internal double TotalAcceleration;[ProtoContract]public struct SmartsDef{[ProtoMember(1)]internal double Inaccuracy;[ProtoMember(2)]internal double Aggressiveness;[ProtoMember(3)]internal double MaxLateralThrust;[ProtoMember(4)]internal double TrackingDelay;[ProtoMember(5)]internal int MaxChaseTime;[ProtoMember(6)]internal bool OverideTarget;[ProtoMember(7)]internal int MaxTargets;[ProtoMember(8)]internal bool NoTargetExpire;[ProtoMember(9)]internal bool Roam;[ProtoMember(10)]internal bool KeepAliveAfterTargetLoss;[ProtoMember(11)]internal float OffsetRatio;[ProtoMember(12)]internal int OffsetTime;[ProtoMember(13)]internal bool CheckFutureIntersection;[ProtoMember(14)]internal double NavAcceleration;[ProtoMember(15)]internal bool AccelClearance;[ProtoMember(16)]internal double SteeringLimit;[ProtoMember(17)]internal bool FocusOnly;[ProtoMember(18)]internal double OffsetMinRange;[ProtoMember(19)]internal bool FocusEviction;[ProtoMember(20)]internal double ScanRange;[ProtoMember(21)]internal bool NoSteering;[ProtoMember(22)]internal double FutureIntersectionRange;[ProtoMember(23)]internal double MinTurnSpeed;[ProtoMember(24)]internal bool NoTargetApproach;[ProtoMember(25)]internal bool AltNavigation;}[ProtoContract]public struct ApproachDef{public enum ReInitCondition{Wait,MoveToPrevious,MoveToNext,ForceRestart}public enum Conditions{Ignore,Spawn,DistanceFromPositionC,Lifetime,DesiredElevation,MinTravelRequired,MaxTravelRequired,Deadtime,DistanceToPositionC,NextTimedSpawn,RelativeLifetime,RelativeDeadtime,SinceTimedSpawn,RelativeSpawns,EnemyTargetLoss,RelativeHealthLost,HealthRemaining,DistanceFromPositionB,DistanceToPositionB,DistanceFromTarget,DistanceToTarget,DistanceFromEndTrajectory,DistanceToEndTrajectory}public enum UpRelativeTo{UpRelativeToBlock,UpRelativeToGravity,UpTargetDirection,UpTargetVelocity,UpStoredStartDontUse,UpStoredEndDontUse,UpStoredStartPosition,UpStoredEndPosition,UpStoredStartLocalPosition,UpStoredEndLocalPosition,UpRelativeToShooter,UpOriginDirection,UpElevationDirection}public enum FwdRelativeTo{ForwardElevationDirection,ForwardRelativeToBlock,ForwardRelativeToGravity,ForwardTargetDirection,ForwardTargetVelocity,ForwardStoredStartDontUse,ForwardStoredEndDontUse,ForwardStoredStartPosition,ForwardStoredEndPosition,ForwardStoredStartLocalPosition,ForwardStoredEndLocalPosition,ForwardRelativeToShooter,ForwardOriginDirection}public enum RelativeTo{Origin,Shooter,Target,Surface,MidPoint,PositionA,Nothing,StoredStartDontUse,StoredEndDontUse,StoredStartPosition,StoredEndPosition,StoredStartLocalPosition,StoredEndLocalPosition}public enum ConditionOperators{StartEnd_And,StartEnd_Or,StartAnd_EndOr,StartOr_EndAnd}public enum StageEvents{DoNothing,EndProjectile,EndProjectileOnRestart,StoreDontUse,StorePositionDontUse,Refund,StorePositionA,StorePositionB,StorePositionC}[ProtoContract]public struct WeightedIdListDef{[ProtoMember(1)]public int ApproachId;[ProtoMember(2)]public Randomize Weight;[ProtoMember(3)]public double End1WeightMod;[ProtoMember(4)]public double End2WeightMod;[ProtoMember(5)]public int MaxRuns;[ProtoMember(6)]public double End3WeightMod;}[ProtoMember(1)]internal ReInitCondition RestartCondition;[ProtoMember(2)]internal Conditions StartCondition1;[ProtoMember(3)]internal Conditions EndCondition1;[ProtoMember(4)]internal UpRelativeTo Up;[ProtoMember(5)]internal RelativeTo PositionB;[ProtoMember(6)]internal double AngleOffset;[ProtoMember(7)]internal double Start1Value;[ProtoMember(8)]internal double End1Value;[ProtoMember(9)]internal double LeadDistance;[ProtoMember(10)]internal double DesiredElevation;[ProtoMember(11)]internal double AccelMulti;[ProtoMember(12)]internal double SpeedCapMulti;[ProtoMember(13)]internal bool AdjustPositionC;[ProtoMember(14)]internal bool CanExpireOnceStarted;[ProtoMember(15)]internal ParticleDef AlternateParticle;[ProtoMember(16)]internal string AlternateSound;[ProtoMember(17)]internal string AlternateModel;[ProtoMember(18)]internal int OnRestartRevertTo;[ProtoMember(19)]internal ParticleDef StartParticle;[ProtoMember(20)]internal bool AdjustPositionB;[ProtoMember(21)]internal bool AdjustUp;[ProtoMember(22)]internal bool PushLeadByTravelDistance;[ProtoMember(23)]internal double TrackingDistance;[ProtoMember(24)]internal Conditions StartCondition2;[ProtoMember(25)]internal double Start2Value;[ProtoMember(26)]internal Conditions EndCondition2;[ProtoMember(27)]internal double End2Value;[ProtoMember(28)]internal RelativeTo Elevation;[ProtoMember(29)]internal double ElevationTolerance;[ProtoMember(30)]internal ConditionOperators Operators;[ProtoMember(31)]internal StageEvents StartEvent;[ProtoMember(32)]internal StageEvents EndEvent;[ProtoMember(33)]internal double TotalAccelMulti;[ProtoMember(34)]internal double DeAccelMulti;[ProtoMember(35)]internal bool Orbit;[ProtoMember(36)]internal double OrbitRadius;[ProtoMember(37)]internal int OffsetTime;[ProtoMember(38)]internal double OffsetMinRadius;[ProtoMember(39)]internal bool NoTimedSpawns;[ProtoMember(40)]internal double OffsetMaxRadius;[ProtoMember(41)]internal bool ForceRestart;[ProtoMember(42)]internal RelativeTo PositionC;[ProtoMember(43)]internal bool DisableAvoidance;[ProtoMember(44)]internal int StoredStartId;[ProtoMember(45)]internal int StoredEndId;[ProtoMember(46)]internal WeightedIdListDef[]RestartList;[ProtoMember(47)]internal RelativeTo StoredStartType;[ProtoMember(48)]internal RelativeTo StoredEndType;[ProtoMember(49)]internal bool LeadRotateElevatePositionB;[ProtoMember(50)]internal bool LeadRotateElevatePositionC;[ProtoMember(51)]internal bool NoElevationLead;[ProtoMember(52)]internal bool IgnoreAntiSmart;[ProtoMember(53)]internal double HeatRefund;[ProtoMember(54)]internal Randomize AngleVariance;[ProtoMember(55)]internal bool ReloadRefund;[ProtoMember(56)]internal int ModelRotateTime;[ProtoMember(57)]internal FwdRelativeTo Forward;[ProtoMember(58)]internal bool AdjustForward;[ProtoMember(59)]internal bool ToggleIngoreVoxels;[ProtoMember(60)]internal bool SelfAvoidance;[ProtoMember(61)]internal bool TargetAvoidance;[ProtoMember(62)]internal bool SelfPhasing;[ProtoMember(63)]internal bool TrajectoryRelativeToB;[ProtoMember(64)]internal Conditions EndCondition3;[ProtoMember(65)]internal double End3Value;[ProtoMember(66)]internal bool SwapNavigationType;[ProtoMember(67)]internal bool ElevationRelativeToC;}[ProtoContract]public struct MinesDef{[ProtoMember(1)]internal double DetectRadius;[ProtoMember(2)]internal double DeCloakRadius;[ProtoMember(3)]internal int FieldTime;[ProtoMember(4)]internal bool Cloak;[ProtoMember(5)]internal bool Persist;}}[ProtoContract]public struct Randomize{[ProtoMember(1)]internal float Start;[ProtoMember(2)]internal float End;}}[ProtoContract]public struct ParticleOptionDef{[ProtoMember(1)]internal float Scale;[ProtoMember(2)]internal float MaxDistance;[ProtoMember(3)]internal float MaxDuration;[ProtoMember(4)]internal bool Loop;[ProtoMember(5)]internal bool Restart;[ProtoMember(6)]internal float HitPlayChance;}[ProtoContract]public struct ParticleDef{[ProtoMember(1)]internal string Name;[ProtoMember(2)]internal Vector4 Color;[ProtoMember(3)]internal Vector3D Offset;[ProtoMember(4)]internal ParticleOptionDef Extras;[ProtoMember(5)]internal bool ApplyToShield;[ProtoMember(6)]internal bool DisableCameraCulling;}}}}using System;using VRage;using VRage.Game.Entity;using VRageMath;namespace CGP.ShareTrack.API.CoreSystem{public partial class WcApi{public enum TriggerActions{TriggerOff,TriggerOn,TriggerOnce}private Action_addMagazines;private Func_closePhantom;private Func>_getTargetAssessment;private Action_setAmmo;private Func_setPhantomFocusTarget;private Action_setTriggerState;private Func_spawnPhantom;internal void GetTargetAssessment(MyEntity phantom,MyEntity target,int weapon=0,bool mustBeInrange=false,bool checkTargetOrb=false){_getTargetAssessment?.Invoke(phantom,target,weapon,mustBeInrange,checkTargetOrb);}internal void SetTriggerState(MyEntity phantom,TriggerActions trigger){_setTriggerState?.Invoke(phantom,(int)trigger);}internal void AddMagazines(MyEntity phantom,int weapon,long quanity){_addMagazines?.Invoke(phantom,weapon,quanity);}internal void SetAmmo(MyEntity phantom,int weapon,string ammoName){_setAmmo?.Invoke(phantom,weapon,ammoName);}internal bool ClosePhantom(MyEntity phantom){return _closePhantom?.Invoke(phantom)??false;}internal MyEntity SpawnPhantom(string phantomType,uint maxAge=0,bool closeWhenOutOfAmmo=false,long defaultReloads=long.MaxValue,string ammoOverideName=null,TriggerActions trigger=TriggerActions.TriggerOff,float?modelScale=null,MyEntity parnet=null,bool addToPrunning=false,bool shadows=false,long identityId=0,bool sync=false){return _spawnPhantom?.Invoke(phantomType,maxAge,closeWhenOutOfAmmo,defaultReloads,ammoOverideName,(int)trigger,modelScale,parnet,addToPrunning,shadows,identityId,sync)??null;}internal bool SetPhantomFocusTarget(MyEntity phantom,MyEntity target,int focusId){return _setPhantomFocusTarget?.Invoke(phantom,target,focusId)??false;}}}using System;using System.Collections.Generic;using System.Linq;using Sandbox.ModAPI;using VRage.Game.ModAPI;namespace CGP.ShareTrack.HeartNetworking{public class HeartNetwork{public static HeartNetwork I;private int _networkLoadUpdate;public int NetworkLoadTicks=240;private readonly ListTempPlayers=new List();public DictionaryTypeNetworkLoad=new Dictionary();public ushort NetworkId{get;private set;}public int TotalNetworkLoad{get;private set;}public void LoadData(ushort networkId){I=this;NetworkId=networkId;MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(NetworkId,ReceivedPacket);foreach(var type in PacketBase.Types)TypeNetworkLoad.Add(type,0);}public void UnloadData(){MyAPIGateway.Multiplayer.UnregisterSecureMessageHandler(NetworkId,ReceivedPacket);I=null;}public void Update(){_networkLoadUpdate--;if(_networkLoadUpdate<=0){_networkLoadUpdate=NetworkLoadTicks;TotalNetworkLoad=0;foreach(var networkLoadArray in TypeNetworkLoad.Keys.ToArray()){TotalNetworkLoad+=TypeNetworkLoad[networkLoadArray];TypeNetworkLoad[networkLoadArray]=0;}TotalNetworkLoad/=NetworkLoadTicks/60;}}private void ReceivedPacket(ushort channelId,byte[]serialized,ulong senderSteamId,bool isSenderServer){try{var packet=MyAPIGateway.Utilities.SerializeFromBinary(serialized);TypeNetworkLoad[packet.GetType()]+=serialized.Length;HandlePacket(packet,senderSteamId);}catch(Exception ex){Log.Error(ex);}}private void HandlePacket(PacketBase packet,ulong senderSteamId){try{packet.Received(senderSteamId);}catch(Exception ex){Log.Error(ex);}}public KeyValuePairHighestNetworkLoad(){Type highest=null;foreach(var networkLoadArray in TypeNetworkLoad)if(highest==null||networkLoadArray.Value>TypeNetworkLoad[highest])highest=networkLoadArray.Key;return new KeyValuePair(highest,TypeNetworkLoad[highest]);}public void SendToPlayer(PacketBase packet,ulong playerSteamId,byte[]serialized=null){RelayToClient(packet,playerSteamId,MyAPIGateway.Session?.Player?.SteamUserId??0,serialized);}public void SendToEveryone(PacketBase packet,byte[]serialized=null){RelayToClients(packet,MyAPIGateway.Session?.Player?.SteamUserId??0,serialized);}public void SendToServer(PacketBase packet,byte[]serialized=null){RelayToServer(packet,MyAPIGateway.Session?.Player?.SteamUserId??0,serialized);}private void RelayToClients(PacketBase packet,ulong senderSteamId=0,byte[]serialized=null){if(!MyAPIGateway.Multiplayer.IsServer)return;TempPlayers.Clear();MyAPIGateway.Players.GetPlayers(TempPlayers);foreach(var p in TempPlayers){if(p.SteamUserId==MyAPIGateway.Multiplayer.ServerId||p.SteamUserId==senderSteamId)continue;if(serialized==null)serialized=MyAPIGateway.Utilities.SerializeToBinary(packet);MyAPIGateway.Multiplayer.SendMessageTo(NetworkId,serialized,p.SteamUserId);}TempPlayers.Clear();}private void RelayToClient(PacketBase packet,ulong playerSteamId,ulong senderSteamId,byte[]serialized=null){if(playerSteamId==MyAPIGateway.Multiplayer.ServerId||playerSteamId==senderSteamId)return;if(serialized==null)serialized=MyAPIGateway.Utilities.SerializeToBinary(packet);MyAPIGateway.Multiplayer.SendMessageTo(NetworkId,serialized,playerSteamId);}private void RelayToServer(PacketBase packet,ulong senderSteamId=0,byte[]serialized=null){if(senderSteamId==MyAPIGateway.Multiplayer.ServerId)return;if(serialized==null)serialized=MyAPIGateway.Utilities.SerializeToBinary(packet);MyAPIGateway.Multiplayer.SendMessageToServer(NetworkId,serialized);}}}using System;using ProtoBuf;using CGP.ShareTrack.HeartNetworking.Custom;namespace CGP.ShareTrack.HeartNetworking{[ProtoInclude(91,typeof(TrackingSyncPacket))][ProtoInclude(92,typeof(SyncRequestPacket))][ProtoContract(UseProtoMembersOnly=true)]public abstract class PacketBase{public static Type[]Types={typeof(PacketBase),typeof(TrackingSyncPacket),typeof(SyncRequestPacket),};public abstract void Received(ulong SenderSteamId);}}using System;using ProtoBuf;using Sandbox.ModAPI;using CGP.ShareTrack.ShipTracking;namespace CGP.ShareTrack.HeartNetworking.Custom{[ProtoContract]internal class SyncRequestPacket:PacketBase{public override void Received(ulong SenderSteamId){if(!MyAPIGateway.Session.IsServer)return;if(AllGridsList.I==null)throw new Exception("Null PointCheck instance!");if(TrackingManager.I==null)throw new Exception("Null TrackingManager instance!");Log.Info("Received join-sync request from "+SenderSteamId);TrackingManager.I.ServerDoSync();}}}using System;using ProtoBuf;using Sandbox.ModAPI;using CGP.ShareTrack.ShipTracking;namespace CGP.ShareTrack.HeartNetworking.Custom{[ProtoContract]internal class TrackingSyncPacket:PacketBase{[ProtoMember(22)]public bool?IsAddingReference;[ProtoMember(21)]public long[]TrackedGrids;public TrackingSyncPacket(){}public TrackingSyncPacket(long[]trackedGrids){TrackedGrids=trackedGrids;}public TrackingSyncPacket(long referenceGrid,bool isAddingReference){TrackedGrids=new[]{referenceGrid};IsAddingReference=isAddingReference;}public override void Received(ulong SenderSteamId){if(TrackingManager.I==null){Log.Info("TrackingManager is null!");return;}if(TrackedGrids==null){Log.Info("Null TrackedGrids!");TrackedGrids=Array.Empty();}if(IsAddingReference==null)TrackingManager.I.BulkTrackGrids(TrackedGrids);else if((bool)IsAddingReference)TrackingManager.I.TrackGrid(TrackedGrids[0],MyAPIGateway.Session.IsServer);else TrackingManager.I.UntrackGrid(TrackedGrids[0],MyAPIGateway.Session.IsServer);Log.Info("Receive track request! "+(IsAddingReference==null));}}}using System;using System.Collections.Generic;using System.Linq;using Sandbox.Definitions;using Sandbox.Game.Entities;using Sandbox.Game.Weapons;using Sandbox.ModAPI;using CGP.ShareTrack.API;using CGP.ShareTrack.API.CoreSystem;using VRage.Game.Entity;using VRage.Game.ModAPI;namespace CGP.ShareTrack.ShipTracking{internal class GridStats{private readonly HashSet_fatBlocks=new HashSet();private readonly HashSet_slimBlocks;private ShieldApi ShieldApi=>AllGridsList.I.ShieldApi;private WcApi WcApi=>AllGridsList.I.WcApi;public bool NeedsUpdate{get;private set;}=true;public bool IsPrimaryGrid=false;public GridStats(IMyCubeGrid grid){if(grid==null){Log.Error("GridStats constructor called with null grid");throw new ArgumentNullException(nameof(grid));}Grid=grid;var allSlimBlocks=new List();Grid.GetBlocks(allSlimBlocks);_slimBlocks=allSlimBlocks.ToHashSet();foreach(var block in _slimBlocks){if(block?.FatBlock!=null){_fatBlocks.Add(block.FatBlock);GridIntegrity+=block.Integrity;}}OriginalGridIntegrity=GridIntegrity;Grid.OnBlockAdded+=OnBlockAdd;Grid.OnBlockRemoved+=OnBlockRemove;Update();}public void Close(){Grid.OnBlockAdded-=OnBlockAdd;Grid.OnBlockRemoved-=OnBlockRemove;_slimBlocks.Clear();_fatBlocks.Clear();}public void UpdateAfterSim(){UpdateCounter++;if(Grid!=null){int updateCount=(int)(Grid.EntityId%UpdateInterval);if(UpdateCounter%UpdateInterval==updateCount){float tempGridInteg=0;foreach(var block in _slimBlocks){if(block.FatBlock!=null){tempGridInteg+=block.Integrity;}}GridIntegrity=tempGridInteg;}}if(UpdateCounter>=int.MaxValue-UpdateInterval){UpdateCounter=0;}}public void Update(){if(!NeedsUpdate)return;BattlePoints=0;OffensivePoints=0;PowerPoints=0;MovementPoints=0;PointDefensePoints=0;CockpitCount=0;foreach(var block in _fatBlocks)CalculateCost(block);UpdateGlobalStats();UpdateWeaponStats();NeedsUpdate=false;}public readonly IMyCubeGrid Grid;public int BlockCount{get;private set;}public int HeavyArmorCount{get;private set;}public int CockpitCount{get;private set;}public int PCU{get;private set;}public readonly DictionaryBlockCounts=new Dictionary();public readonly DictionarySpecialBlockCounts=new Dictionary();public float TotalThrust{get;private set;}public float TotalTorque{get;private set;}public float GridIntegrity{get;private set;}public float OriginalGridIntegrity{get;private set;}public double BattlePoints{get;private set;}public double OffensivePoints{get;private set;}public double PowerPoints{get;private set;}public double MovementPoints{get;private set;}public double PointDefensePoints{get;private set;}public readonly DictionaryWeaponCounts=new Dictionary();private void OnBlockAdd(IMySlimBlock block){if(block==null)return;_slimBlocks.Add(block);if(block.FatBlock!=null)_fatBlocks.Add(block.FatBlock);NeedsUpdate=true;}private void OnBlockRemove(IMySlimBlock block){if(block==null)return;_slimBlocks.Remove(block);if(block.FatBlock!=null)_fatBlocks.Remove(block.FatBlock);NeedsUpdate=true;}private int UpdateCounter=0;private int UpdateInterval=100;private void UpdateGlobalStats(){BlockCounts.Clear();SpecialBlockCounts.Clear();TotalThrust=0;TotalTorque=0;foreach(var block in _fatBlocks){if(block is IMyCockpit&&block.IsFunctional)CockpitCount++;if(block is IMyThrust&&block.IsFunctional){TotalThrust+=((IMyThrust)block).MaxEffectiveThrust;}else if(block is IMyGyro&&block.IsFunctional){TotalTorque+=((MyGyroDefinition)MyDefinitionManager.Static.GetDefinition((block as IMyGyro).BlockDefinition)).ForceMagnitude*(block as IMyGyro).GyroStrengthMultiplier;}if(!(block is IMyConveyorSorter)||!WcApi.HasCoreWeapon((MyEntity)block)){var blockDisplayName=block.DefinitionDisplayNameText;if(blockDisplayName.Contains("Armor")&&!blockDisplayName.StartsWith("Armor Laser"))continue;if(!AllGridsList.PointValues.ContainsKey(block.BlockDefinition.SubtypeName))continue;float ignored=0;AllGridsList.ClimbingCostRename(ref blockDisplayName,ref ignored);ShipTracker.SpecialBlockRename(ref blockDisplayName,block);if(!SpecialBlockCounts.ContainsKey(blockDisplayName))SpecialBlockCounts.Add(blockDisplayName,0);SpecialBlockCounts[blockDisplayName]++;}}BlockCount=((MyCubeGrid)Grid).BlocksCount;PCU=((MyCubeGrid)Grid).BlocksPCU;HeavyArmorCount=0;foreach(var slimBlock in _slimBlocks){if(slimBlock.FatBlock!=null)continue;if(slimBlock.BlockDefinition.Id.SubtypeName.Contains("Heavy"))HeavyArmorCount++;}}private void UpdateWeaponStats(){WeaponCounts.Clear();foreach(var block in _fatBlocks){double weaponPoints;var weaponDisplayName=block.DefinitionDisplayNameText;if(AllGridsList.PointValues.TryGetValue(block.BlockDefinition.SubtypeName,out weaponPoints)&&WcApi.HasCoreWeapon((MyEntity)block)){float thisClimbingCostMult=0;AllGridsList.ClimbingCostRename(ref weaponDisplayName,ref thisClimbingCostMult);AddWeaponCount(weaponDisplayName);continue;}var gunObject=block as IMyGunObject;if(gunObject!=null&&block is IMyCubeBlock){AddWeaponCount(weaponDisplayName);}}}private string GetWeaponDisplayName(IMyCubeBlock block,IMyGunObjectgunObject){if(block is IMyLargeTurretBase)return$"{block.DefinitionDisplayNameText} Turret";else return block.DefinitionDisplayNameText;}private void AddWeaponCount(string weaponDisplayName){if(!WeaponCounts.ContainsKey(weaponDisplayName))WeaponCounts.Add(weaponDisplayName,0);WeaponCounts[weaponDisplayName]++;}private void CalculateCost(IMyCubeBlock block){double blockPoints=0;foreach(var kvp in AllGridsList.PointValues){if(block.BlockDefinition.SubtypeName.StartsWith(kvp.Key,StringComparison.OrdinalIgnoreCase)){blockPoints=kvp.Value;break;}}if(blockPoints==0)return;var blockDisplayName=block.DefinitionDisplayNameText;float climbingCostMultiplier=0;AllGridsList.ClimbingCostRename(ref blockDisplayName,ref climbingCostMultiplier);if(!BlockCounts.ContainsKey(blockDisplayName))BlockCounts.Add(blockDisplayName,0);var thisSpecialBlocksCount=BlockCounts[blockDisplayName]++;if(climbingCostMultiplier>0)blockPoints+=(blockPoints*thisSpecialBlocksCount*climbingCostMultiplier);if(block is IMyThrust||block is IMyGyro)MovementPoints+=blockPoints;if(block is IMyPowerProducer)PowerPoints+=blockPoints;if(WcApi.HasCoreWeapon((MyEntity)block)){var validTargetTypes=new List();WcApi.GetTurretTargetTypes((MyEntity)block,validTargetTypes);if(validTargetTypes.Contains("Projectiles"))PointDefensePoints+=blockPoints;else OffensivePoints+=blockPoints;}BattlePoints+=blockPoints;}}}using System;using System.Collections.Generic;using System.Linq;using System.Text;using Sandbox.Game.Entities;using Sandbox.Game.EntityComponents;using Sandbox.ModAPI;using CGP.ShareTrack.API;using VRage.Game;using VRage.Game.Entity;using VRage.Game.ModAPI;using VRage.ModAPI;using VRageMath;using BlendTypeEnum=VRageRender.MyBillboard.BlendTypeEnum;namespace CGP.ShareTrack.ShipTracking{public class ShipTracker{[Flags]public enum NametagSettings{None=0,PlayerName=1,GridName=2}private readonly Dictionary_gridStats=new Dictionary();private HudAPIv2.HUDMessage _nametag;private ShipTracker(){}public ShipTracker(IMyCubeGrid grid,bool showOnHud=true){TransferToGrid(grid,showOnHud);Update();if(!showOnHud||MyAPIGateway.Utilities.IsDedicated)return;_nametag=new HudAPIv2.HUDMessage(new StringBuilder("Initializing..."),Vector2D.Zero,font:"BI_SEOutlined",blend:BlendTypeEnum.PostPP,hideHud:false,shadowing:true);UpdateHud();}private void TransferToGrid(IMyCubeGrid newGrid,bool showOnHud=true){Log.Info($"TransferToGrid called for grid {newGrid?.DisplayName??"null"}");if(newGrid==null){Log.Error("TransferToGrid called with null newGrid");return;}if(Grid!=null){Grid.OnClose-=OnClose;Grid.OnGridSplit-=OnGridSplit;var oldGridGroup=Grid.GetGridGroup(GridLinkTypeEnum.Physical);if(oldGridGroup!=null){oldGridGroup.OnGridAdded-=OnGridAdd;oldGridGroup.OnGridRemoved-=OnGridRemove;}foreach(var gridStat in _gridStats){if(gridStat.Key!=newGrid)gridStat.Value.Close();}_gridStats.Clear();TrackingManager.I.TrackedGrids.Remove(Grid);}Grid=newGrid;var allAttachedGrids=new List();var newGridGroup=Grid.GetGridGroup(GridLinkTypeEnum.Physical);if(newGridGroup!=null){newGridGroup.GetGrids(allAttachedGrids);}else{Log.Error($"Grid {Grid.DisplayName} has no physical grid group");allAttachedGrids.Add(Grid);}OriginalGridIntegrity=0;foreach(var attachedGrid in allAttachedGrids){if(attachedGrid!=null){try{var stats=new GridStats(attachedGrid);_gridStats.Add(attachedGrid,stats);OriginalGridIntegrity+=stats.OriginalGridIntegrity;if(((MyCubeGrid)attachedGrid).BlocksCount>((MyCubeGrid)Grid).BlocksCount)Grid=attachedGrid;}catch(Exception ex){Log.Error($"Error processing attached grid {attachedGrid.DisplayName}: {ex}");}}}Grid.OnClose+=OnClose;Grid.OnGridSplit+=OnGridSplit;var gridGroup=Grid.GetGridGroup(GridLinkTypeEnum.Physical);if(gridGroup!=null){gridGroup.OnGridAdded+=OnGridAdd;gridGroup.OnGridRemoved+=OnGridRemove;}if(!TrackingManager.I.TrackedGrids.ContainsKey(Grid)&&showOnHud)TrackingManager.I.TrackedGrids.Add(Grid,this);Log.Info($"TransferToGrid completed for grid {Grid.DisplayName}");}private ShieldApi ShieldApi=>AllGridsList.I.ShieldApi;public IMyCubeGrid Grid{get;private set;}public IMyPlayer Owner=>MyAPIGateway.Players.GetPlayerControllingEntity(Grid)??AllGridsList.GetOwner(OwnerId);public long OwnerId=>Grid?.BigOwners.Count>0?Grid?.BigOwners[0]??-1:-1;public string GridName=>Grid?.DisplayName;public float Mass=>((MyCubeGrid)Grid).GetCurrentMass();public Vector3 Position=>Grid.Physics.CenterOfMassWorld;public IMyFaction OwnerFaction=>MyAPIGateway.Session?.Factions?.TryGetPlayerFaction(OwnerId);public string FactionName=>OwnerFaction?.Name??"None";public Vector3 FactionColor=>ColorMaskToRgb(OwnerFaction?.CustomColor??Vector3.Zero);public string OwnerName=>Owner?.DisplayName??GridName;public void OnClose(IMyEntity e){if(Grid!=null){Grid.OnClose-=OnClose;var gridGroup=Grid.GetGridGroup(GridLinkTypeEnum.Physical);if(gridGroup!=null){gridGroup.OnGridAdded-=OnGridAdd;gridGroup.OnGridRemoved-=OnGridRemove;}}TrackingManager.I.TrackedGrids.Remove(Grid);DisposeHud();}public void OnGridSplit(IMyCubeGrid originalGrid,IMyCubeGrid newGrid){int originalCockpitsCount=originalGrid.GetFatBlocks().Count();int newCockpitsCount=newGrid.GetFatBlocks().Count();if(newCockpitsCount>originalCockpitsCount){TransferToGrid(newGrid);return;}if(newCockpitsCount((MyCubeGrid)originalGrid).BlocksCount){TransferToGrid(newGrid);}}public void Update(){if(Grid?.Physics==null)return;var shieldController=ShieldApi.GetShieldBlock(Grid);if(shieldController==null)OriginalMaxShieldHealth=-1;if(OriginalMaxShieldHealth==-1&&!ShieldApi.IsFortified(shieldController))OriginalMaxShieldHealth=MaxShieldHealth;foreach(var gridStat in _gridStats.Values){gridStat.IsPrimaryGrid=gridStat.Grid==Grid;gridStat.Update();}bool bufferIsFunctional=IsFunctional;IsFunctional=TotalPower>0&&TotalTorque>0&&CockpitCount>0;if(bufferIsFunctional!=IsFunctional){TrackingManager.I.OnShipAliveChanged?.Invoke(Grid,IsFunctional);}}public void UpdateAfterSim(){foreach(var gridStat in _gridStats.Values){gridStat.UpdateAfterSim();}}private void OnGridAdd(IMyGridGroupData groupData,IMyCubeGrid grid,IMyGridGroupData previousGroupData){if(_gridStats.ContainsKey(grid))return;var stats=new GridStats(grid);_gridStats.Add(grid,stats);OriginalGridIntegrity+=stats.OriginalGridIntegrity;}private void OnGridRemove(IMyGridGroupData groupData,IMyCubeGrid grid,IMyGridGroupData newGroupData){if(!_gridStats.ContainsKey(grid)||grid==Grid)return;OriginalGridIntegrity-=_gridStats[grid].OriginalGridIntegrity;_gridStats[grid].Close();_gridStats.Remove(grid);}public static void SpecialBlockRename(ref string blockDisplayName,IMyCubeBlock block){var subtype=block.BlockDefinition.SubtypeName;var groupings=new Dictionary{{"Suspension","Wheel Suspension"},{"Wing_","Wing"},{"DieselEngine","Engine"},};foreach(var group in groupings){if(subtype.StartsWith(group.Key,StringComparison.OrdinalIgnoreCase)||blockDisplayName.StartsWith(group.Key,StringComparison.OrdinalIgnoreCase)){blockDisplayName=group.Value;return;}}if(block is IMyGasTank)blockDisplayName="HydrogenTank";else if(block is IMyLightingBlock&&!(block is IMyReflectorLight))blockDisplayName="Light";else if(block is IMyConveyor||block is IMyConveyorTube)blockDisplayName="Conveyor";else if(block is IMyMotorStator&&subtype=="SubgridBase")blockDisplayName="Invincible Subgrid";else if(block is IMyUpgradeModule){switch(subtype){case"LargeEnhancer":blockDisplayName="Shield Enhancer";break;case"EmitterL":case"EmitterLA":blockDisplayName="Shield Emitter";break;case"LargeShieldModulator":blockDisplayName="Shield Modulator";break;case"DSControlLarge":case"DSControlTable":blockDisplayName="Shield Controller";break;case"AQD_LG_GyroBooster":blockDisplayName="Gyro Booster";break;case"AQD_LG_GyroUpgrade":blockDisplayName="Large Gyro Booster";break;}}else if(block is IMyReactor){switch(subtype){case"LargeBlockLargeGenerator":case"LargeBlockLargeGeneratorWarfare2":blockDisplayName="Large Reactor";break;case"LargeBlockSmallGenerator":case"LargeBlockSmallGeneratorWarfare2":blockDisplayName="Small Reactor";break;}}else if(block is IMyGyro){switch(subtype){case"LargeBlockGyro":blockDisplayName="Small Gyro";break;case"AQD_LG_LargeGyro":blockDisplayName="Large Gyro";break;}}else if(block is IMyCameraBlock){switch(subtype){case"MA_Buster_Camera":blockDisplayName="Buster Camera";break;case"LargeCameraBlock":blockDisplayName="Camera";break;}}}private static Vector3 ColorMaskToRgb(Vector3 colorMask){return MyColorPickerConstants.HSVOffsetToHSV(colorMask).HSVtoColor();}public void UpdateHud(){if(_nametag==null||MyAPIGateway.Utilities.IsDedicated)return;try{var camera=MyAPIGateway.Session.Camera;const int distanceThreshold=20000;const int maxAngle=60;Vector3D gridPosition=Position;var targetHudPos=camera.WorldToScreen(ref gridPosition);var newOrigin=new Vector2D(targetHudPos.X,targetHudPos.Y);_nametag.InitialColor=new Color(FactionColor);var fov=camera.FieldOfViewAngle;var angle=GetAngleBetweenDegree(gridPosition-camera.WorldMatrix.Translation,camera.WorldMatrix.Forward);var stealthed=((uint)Grid.Flags&0x1000000)>0;var visible=!(newOrigin.X>1||newOrigin.X<-1||newOrigin.Y>1||newOrigin.Y<-1)&&angle<=fov&&!stealthed;var distance=Vector3D.Distance(camera.WorldMatrix.Translation,gridPosition);_nametag.Scale=1-MathHelper.Clamp(distance/distanceThreshold,0,1)+30/Math.Max(maxAngle,angle*angle*angle);_nametag.Origin=new Vector2D(targetHudPos.X,targetHudPos.Y+MathHelper.Clamp(-0.000125*distance+0.25,0.05,0.25));_nametag.Visible=visible&&AllGridsList.NametagViewState!=NametagSettings.None;_nametag.Message.Clear();var nameTagText="";if((AllGridsList.NametagViewState&NametagSettings.PlayerName)>0)nameTagText+=OwnerName;if((AllGridsList.NametagViewState&NametagSettings.GridName)>0)nameTagText+="\n"+GridName;if(!IsFunctional)nameTagText+=":[Dead]";_nametag.Message.Append(nameTagText.TrimStart('\n'));_nametag.Offset=-_nametag.GetTextLength()/2;}catch(Exception ex){Log.Error(ex);}}private double GetAngleBetweenDegree(Vector3D vectorA,Vector3D vectorB){vectorA.Normalize();vectorB.Normalize();return Math.Acos(MathHelper.Clamp(vectorA.Dot(vectorB),-1,1))*(180.0/Math.PI);}public void DisposeHud(){if(_nametag!=null){_nametag.Visible=false;_nametag.Message.Clear();_nametag.DeleteMessage();}_nametag=null;}public bool IsFunctional=false;public int BlockCount{get{var total=0;foreach(var stats in _gridStats.Values)total+=stats.BlockCount;return total;}}public float GridIntegrity{get{float total=0;foreach(var stats in _gridStats.Values)total+=stats.GridIntegrity;return total;}}public float OriginalGridIntegrity;public int HeavyArmorCount{get{var total=0;foreach(var stats in _gridStats.Values)total+=stats.HeavyArmorCount;return total;}}public int CockpitCount{get{var total=0;foreach(var stats in _gridStats.Values)total+=stats.CockpitCount;return total;}}public int PCU{get{var total=0;foreach(var stats in _gridStats.Values)total+=stats.PCU;return total;}}public float TotalThrust{get{float total=0;foreach(var stats in _gridStats.Values)total+=stats.TotalThrust;return total;}}public float TotalTorque{get{float total=0;foreach(var stats in _gridStats.Values)total+=stats.TotalTorque;return total;}}public float TotalPower=>Grid?.ResourceDistributor?.MaxAvailableResourceByType(MyResourceDistributorComponent.ElectricityId)??0;public DictionarySpecialBlockCounts{get{var blockCounts=new Dictionary();foreach(var stats in _gridStats.Values)foreach(var kvp in stats.SpecialBlockCounts){if(!blockCounts.ContainsKey(kvp.Key))blockCounts.Add(kvp.Key,0);blockCounts[kvp.Key]+=kvp.Value;}return blockCounts;}}public double BattlePoints{get{double total=0;foreach(var stats in _gridStats.Values)total+=stats.BattlePoints;return total;}}public double OffensivePoints{get{double total=0;foreach(var stats in _gridStats.Values)total+=stats.OffensivePoints;return total;}}public float OffensivePointsRatio=>BattlePoints==0?0:(float)OffensivePoints/(float)BattlePoints;public double PowerPoints{get{double total=0;foreach(var stats in _gridStats.Values)total+=stats.PowerPoints;return total;}}public float PowerPointsRatio=>BattlePoints==0?0:(float)PowerPoints/(float)BattlePoints;public double MovementPoints{get{double total=0;foreach(var stats in _gridStats.Values)total+=stats.MovementPoints;return total;}}public float MovementPointsRatio=>BattlePoints==0?0:(float)MovementPoints/(float)BattlePoints;public double PointDefensePoints{get{double total=0;foreach(var stats in _gridStats.Values)total+=stats.PointDefensePoints;return total;}}public float PointDefensePointsRatio=>BattlePoints==0?0:(float)PointDefensePoints/(float)BattlePoints;public double RemainingPoints=>BattlePoints-OffensivePoints-PowerPoints-MovementPoints-PointDefensePoints;public double RemainingPointsRatio=>BattlePoints==0?0:RemainingPoints/BattlePoints;public float OriginalMaxShieldHealth=-1;public float MaxShieldHealth{get{var shieldController=ShieldApi.GetShieldBlock(Grid);if(shieldController==null)return-1;return ShieldApi.GetMaxHpCap(shieldController);}}public float CurrentShieldPercent{get{var shieldController=ShieldApi.GetShieldBlock(Grid);if(shieldController==null)return-1;return ShieldApi.GetShieldPercent(shieldController);}}public float CurrentShieldHeat{get{var shieldController=ShieldApi.GetShieldBlock(Grid);if(shieldController==null)return-1;return ShieldApi.GetShieldHeat(shieldController);}}public DictionaryWeaponCounts{get{var blockCounts=new Dictionary();foreach(var stats in _gridStats.Values)foreach(var kvp in stats.WeaponCounts){if(!blockCounts.ContainsKey(kvp.Key))blockCounts.Add(kvp.Key,0);blockCounts[kvp.Key]+=kvp.Value;}return blockCounts;}}public float DamagePerSecond=>Math.Abs(AllGridsList.I.WcApi.GetConstructEffectiveDps((MyEntity)Grid));}}using System;using System.Collections.Generic;using System.Linq;using Sandbox.Game.Entities;using Sandbox.ModAPI;using CGP.ShareTrack.HeartNetworking;using CGP.ShareTrack.HeartNetworking.Custom;using VRage.Game.ModAPI;using VRage.ModAPI;namespace CGP.ShareTrack.ShipTracking{internal class TrackingManager{public static TrackingManager I;private static readonly string[]AutoTrackSubtypes={""};private readonly HashSet_queuedGridTracks=new HashSet();public HashSetAllGrids=new HashSet();public DictionaryTrackedGrids=new Dictionary();public ActionOnShipTracked;public ActionOnShipAliveChanged;private bool _isTracking=false;private TrackingManager(){}public void StartTracking(){}private void ProcessEntity(IMyEntity entity){var grid=entity as IMyCubeGrid;if(grid?.Physics==null)return;AllGrids.Add(grid);grid.GetBlocks(null,block=>{CheckAutotrack(block);return false;});if(_queuedGridTracks.Contains(grid.EntityId)){_queuedGridTracks.Remove(grid.EntityId);if(!TrackedGrids.ContainsKey(grid)){TrackGrid(grid,false);}}}private void Update(){if(!_isTracking)return;foreach(var tracker in TrackedGrids.Values){tracker.UpdateAfterSim();}}private void Unload(){AllGrids.Clear();foreach(var tracker in TrackedGrids.Values)tracker.DisposeHud();TrackedGrids.Clear();MyAPIGateway.Entities.OnEntityAdd-=OnEntityAdd;MyAPIGateway.Entities.OnEntityRemove-=OnEntityRemove;}private void OnEntityAdd(IMyEntity entity){if(!_isTracking)return;ProcessEntity(entity);}private void OnEntityRemove(IMyEntity entity){if(!(entity is IMyCubeGrid)||entity.Physics==null)return;var grid=(IMyCubeGrid)entity;AllGrids.Remove(grid);if(TrackedGrids.ContainsKey(grid)){TrackedGrids[grid].DisposeHud();TrackedGrids.Remove(grid);}_queuedGridTracks.Remove(grid.EntityId);}private long[]GetGridIds(){var gridIds=new List();foreach(var grid in TrackedGrids.Keys)gridIds.Add(grid.EntityId);return gridIds.ToArray();}private void CheckAutotrack(IMySlimBlock block){if(block==null){Log.Error("CheckAutotrack called with null block");return;}if(block.FatBlock==null||!AutoTrackSubtypes.Contains(block.BlockDefinition.Id.SubtypeName))return;if(block.CubeGrid==null){Log.Error($"Block {block.BlockDefinition.Id.SubtypeName} has null CubeGrid");return;}TrackGrid(block.CubeGrid,false);}public static void Init(){I=new TrackingManager();}public static void UpdateAfterSimulation(){I?.Update();}public static void Close(){I?.Unload();I=null;}public void BulkTrackGrids(long[]gridIds){if(!_isTracking){Log.Info($"Queuing bulk track request with {gridIds.Length} items!");_queuedGridTracks.UnionWith(gridIds);return;}Log.Info($"Processing bulk track request with {gridIds.Length} items!");var gridIds_List=new List(gridIds);foreach(var grid in TrackedGrids.Keys.ToArray()){if(gridIds.Contains(grid.EntityId)){gridIds_List.Remove(grid.EntityId);continue;}UntrackGrid(grid,false);}foreach(var gridId in gridIds_List)TrackGrid(gridId,false);}public void TrackGrid(IMyCubeGrid grid,bool share=true){}public void TrackGrid(long gridId,bool share=true){if(!_isTracking){_queuedGridTracks.Add(gridId);return;}var grid=MyAPIGateway.Entities.GetEntityById(gridId)as IMyCubeGrid;if(grid==null){_queuedGridTracks.Add(gridId);return;}TrackGrid(grid,share);}public void UntrackGrid(IMyCubeGrid grid,bool share=true){var allAttachedGrids=new List();grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(allAttachedGrids);foreach(var attachedGrid in allAttachedGrids.Where(attachedGrid=>TrackedGrids.ContainsKey(attachedGrid))){TrackedGrids[attachedGrid].DisposeHud();TrackedGrids.Remove(attachedGrid);OnShipTracked?.Invoke(attachedGrid,false);}if(!share)return;if(MyAPIGateway.Session.IsServer){ServerDoSync();}else{var packet=new TrackingSyncPacket(grid.EntityId,false);HeartNetwork.I.SendToServer(packet);}}public void UntrackGrid(long gridId,bool share=true){var grid=MyAPIGateway.Entities.GetEntityById(gridId)as IMyCubeGrid;_queuedGridTracks.Remove(gridId);if(grid!=null)UntrackGrid(grid,share);}public bool IsGridTracked(IMyCubeGrid grid){var allAttachedGrids=new List();grid.GetGridGroup(GridLinkTypeEnum.Physical).GetGrids(allAttachedGrids);foreach(var attachedGrid in allAttachedGrids.Where(attachedGrid=>TrackedGrids.ContainsKey(attachedGrid)))return true;return false;}public void ServerDoSync(){var packet=new TrackingSyncPacket(GetGridIds());HeartNetwork.I.SendToEveryone(packet);}public long[]GetQueuedGridTracks(){return _queuedGridTracks.ToArray();}}}using System;using System.Collections.Generic;using System.Linq;using CGP.ShareTrack.ShipTracking;using VRage.Game.ModAPI;namespace CGP.ShareTrack.TrackerApi{internal class ApiMethods{internal readonly DictionaryModApiMethods;internal ApiMethods(){ModApiMethods=new Dictionary{["GetTrackedGrids"]=new Func(GetTrackedGrids),["IsGridAlive"]=new Func(IsGridAlive),["RegisterOnTrack"]=new Action>(RegisterOnTrack),["UnregisterOnTrack"]=new Action>(UnregisterOnTrack),["RegisterOnAliveChanged"]=new Action>(RegisterOnAliveChanged),["UnregisterOnAliveChanged"]=new Action>(UnregisterOnAliveChanged),["AreTrackedGridsLoaded"]=new Func(AreTrackedGridsLoaded),["GetGridPoints"]=new Func(GetGridPoints),["TrackGrid"]=new Action(TrackGrid),["UnTrackGrid"]=new Action(UnTrackGrid),};}private IMyCubeGrid[]GetTrackedGrids(){return TrackingManager.I?.TrackedGrids.Keys.ToArray();}private bool IsGridAlive(IMyCubeGrid grid){return TrackingManager.I?.TrackedGrids.GetValueOrDefault(grid,null)?.IsFunctional??false;}private void RegisterOnTrack(Actionaction){if(TrackingManager.I!=null)TrackingManager.I.OnShipTracked+=action;}private void UnregisterOnTrack(Actionaction){if(TrackingManager.I!=null)TrackingManager.I.OnShipTracked-=action;}private void RegisterOnAliveChanged(Actionaction){if(TrackingManager.I!=null)TrackingManager.I.OnShipAliveChanged+=action;}private void UnregisterOnAliveChanged(Actionaction){if(TrackingManager.I!=null)TrackingManager.I.OnShipAliveChanged-=action;}private bool AreTrackedGridsLoaded(){if(TrackingManager.I==null)return false;return TrackingManager.I.GetQueuedGridTracks().Length==0;}private double GetGridPoints(IMyCubeGrid grid){if(TrackingManager.I==null||!TrackingManager.I.TrackedGrids.ContainsKey(grid))return-1;return TrackingManager.I.TrackedGrids[grid].BattlePoints;}private void TrackGrid(IMyCubeGrid grid,bool share){}private void UnTrackGrid(IMyCubeGrid grid,bool share){}}}using System;using System.Collections.Generic;using Sandbox.ModAPI;using VRage;using VRageMath;namespace CGP.ShareTrack.TrackerApi{internal class ApiProvider{private const long Channel=3033234540;private readonly IReadOnlyDictionary_apiDefinitions;private readonly MyTuple>_endpointTuple;public ApiProvider(){_apiDefinitions=new ApiMethods().ModApiMethods;_endpointTuple=new MyTuple>(MasterSession.ModVersion,_apiDefinitions);MyAPIGateway.Utilities.RegisterMessageHandler(Channel,HandleMessage);IsReady=true;try{MyAPIGateway.Utilities.SendModMessage(Channel,_endpointTuple);}catch(Exception ex){Log.Info($"Exception in Api Load: {ex}");}Log.Info($"ShareTrackAPI v{MasterSession.ModVersion.Y} initialized.");}public bool IsReady{get;private set;}private void HandleMessage(object o){if(o as string=="ApiEndpointRequest"){MyAPIGateway.Utilities.SendModMessage(Channel,_endpointTuple);Log.Info("ShareTrackAPI sent definitions.");}}public void Unload(){MyAPIGateway.Utilities.UnregisterMessageHandler(Channel,HandleMessage);IsReady=false;MyAPIGateway.Utilities.SendModMessage(Channel,new MyTuple>(MasterSession.ModVersion,null));Log.Info("ShareTrackAPI unloaded.");}}}using System;using System.Collections.Generic;using Sandbox.ModAPI;using VRage;using VRage.Game.ModAPI;using VRage.Utils;using VRageMath;namespace CGP.ShareTrack.TrackerApi{public class ShareTrackApi{public const int ApiVersion=3;public Action OnReady;public int FrameworkVersion{get;private set;}=-1;public bool IsReady{get;private set;}public void Init(IMyModContext modContext,Action onLoad=null){if(_isRegistered)throw new Exception($"{GetType().Name}.Load() should not be called multiple times!");_modContext=modContext;OnReady=onLoad;_isRegistered=true;MyAPIGateway.Utilities.RegisterMessageHandler(ApiChannel,HandleMessage);MyAPIGateway.Utilities.SendModMessage(ApiChannel,"ApiEndpointRequest");MyLog.Default.WriteLineAndConsole($"{_modContext.ModName}: ShareTrackAPI listening for API methods...");}public void UnloadData(){MyAPIGateway.Utilities.UnregisterMessageHandler(ApiChannel,HandleMessage);if(_apiInit)ApiAssign();_isRegistered=false;_apiInit=false;IsReady=false;OnReady=null;MyLog.Default.WriteLineAndConsole($"{_modContext.ModName}: ShareTrackAPI unloaded.");}public IMyCubeGrid[]GetTrackedGrids(){return _getTrackedGrids?.Invoke();}public bool IsGridAlive(IMyCubeGrid grid){return _isGridAlive?.Invoke(grid)??false;}public void RegisterOnTrack(Actionaction){_registerOnTrack?.Invoke(action);}public void UnregisterOnTrack(Actionaction){_unRegisterOnTrack?.Invoke(action);}public void RegisterOnAliveChanged(Actionaction){_registerOnAliveChanged?.Invoke(action);}public void UnregisterOnAliveChanged(Actionaction){_unregisterOnAliveChanged?.Invoke(action);}public bool AreTrackedGridsLoaded(){return _areTrackedGridsLoaded?.Invoke()??false;}public int GetGridPoints(IMyCubeGrid grid){return _getGridPoints?.Invoke(grid)??-1;}public void TrackGrid(IMyCubeGrid grid,bool share=true){_trackGrid?.Invoke(grid,share);}public void UnTrackGrid(IMyCubeGrid grid,bool share=true){_unTrackGrid?.Invoke(grid,share);}private Func_getTrackedGrids;private Func_isGridAlive;private Action>_registerOnTrack;private Action>_unRegisterOnTrack;private Action>_registerOnAliveChanged;private Action>_unregisterOnAliveChanged;private Func_areTrackedGridsLoaded;private Func_getGridPoints;private Action_trackGrid;private Action_unTrackGrid;private bool _isRegistered;private bool _apiInit;private const long ApiChannel=3033234540;private IReadOnlyDictionary_methodMap;private IMyModContext _modContext;public bool ApiAssign(){_apiInit=_methodMap!=null;SetApiMethod("GetTrackedGrids",ref _getTrackedGrids);SetApiMethod("IsGridAlive",ref _isGridAlive);SetApiMethod("RegisterOnTrack",ref _registerOnTrack);SetApiMethod("UnregisterOnTrack",ref _unRegisterOnTrack);SetApiMethod("RegisterOnAliveChanged",ref _registerOnAliveChanged);SetApiMethod("UnregisterOnAliveChanged",ref _unregisterOnAliveChanged);SetApiMethod("AreTrackedGridsLoaded",ref _areTrackedGridsLoaded);SetApiMethod("GetGridPoints",ref _getGridPoints);SetApiMethod("TrackGrid",ref _trackGrid);SetApiMethod("UnTrackGrid",ref _unTrackGrid);if(_methodMap==null){UnloadData();return false;}_methodMap=null;OnReady?.Invoke();return true;}private void SetApiMethod(string name,ref T method)where T:class{if(_methodMap==null){method=null;return;}if(!_methodMap.ContainsKey(name))throw new Exception("Method Map does not contain method "+name);var del=_methodMap[name];if(del.GetType()!=typeof(T))throw new Exception($"Method {name} type mismatch! [MapMethod: {del.GetType().Name} | ApiMethod: {typeof(T).Name}]");method=_methodMap[name]as T;}private void HandleMessage(object obj){try{if(_apiInit||obj is string||obj==null)return;var tuple=(MyTuple>)obj;var receivedVersion=tuple.Item1;var dict=tuple.Item2;if(dict==null){MyLog.Default.WriteLineAndConsole($"{_modContext.ModName}: ShareTrackAPI ERR: Received null dictionary!");return;}if(receivedVersion.Y!=ApiVersion)Log.Info($"Expected API version ({ApiVersion}) differs from received API version {receivedVersion}; errors may occur.");_methodMap=dict;if(!ApiAssign())return;FrameworkVersion=receivedVersion.X;IsReady=true;Log.Info($"ShareTrackApi v{ApiVersion} loaded!");}catch(Exception ex){MyLog.Default.WriteLineAndConsole($"{_modContext.ModName}: Exception in ShareTrackAPI! "+ex);MyAPIGateway.Utilities.ShowMessage(_modContext.ModName,"Exception in ShareTrackAPI!\n"+ex);}}}}