diff --git a/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/API/StealthAPI.cs b/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/API/StealthAPI.cs
new file mode 100644
index 000000000..8f62cc6da
--- /dev/null
+++ b/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/API/StealthAPI.cs
@@ -0,0 +1,119 @@
+using Sandbox.ModAPI;
+using System;
+using System.Collections.Generic;
+using VRage.Game.ModAPI;
+
+namespace StealthSystem
+{
+ internal class StealthAPI
+ {
+ /// Returns true if drive status was toggled successfully.
+ /// Ignore power requirements and overheat.
+ public bool ToggleStealth(IMyTerminalBlock drive, bool force) => _toggleStealth?.Invoke(drive, force) ?? false;
+
+ /// Returns status of drive. 0 = Ready, 1 = Active, 2 = Cooldown, 3 = Not enough power, 4 = Offline
+ public int GetStatus(IMyTerminalBlock drive) => _getStatus?.Invoke(drive) ?? 4;
+
+ /// Returns remaining duration of stealth/cooldown.
+ public int GetDuration(IMyTerminalBlock drive) => _getDuration?.Invoke(drive) ?? 0;
+
+ /// Retuns active stealth drive on grid if one exists, otherwise returns null.
+ public IMyTerminalBlock GetMainDrive(IMyCubeGrid grid) => _getMainDrive?.Invoke(grid);
+
+ /// Collection to populate with heat sinks on grid.
+ public void GetHeatSinks(IMyCubeGrid grid, ICollection sinks) => _getHeatSinks?.Invoke(grid, sinks);
+
+
+
+ private const long CHANNEL = 2172757427;
+ private bool _isRegistered;
+ private bool _apiInit;
+ private Action _readyCallback;
+
+ private Func _toggleStealth;
+ private Func _getStatus;
+ private Func _getDuration;
+ private Func _getMainDrive;
+ private Action> _getHeatSinks;
+
+ public bool IsReady { get; private set; }
+
+
+ ///
+ /// Ask CoreSystems to send the API methods.
+ /// Throws an exception if it gets called more than once per session without .
+ ///
+ /// Method to be called when CoreSystems replies.
+ public void Load(Action readyCallback = null)
+ {
+ if (_isRegistered)
+ throw new Exception($"{GetType().Name}.Load() should not be called multiple times!");
+
+ _readyCallback = readyCallback;
+ _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
+ ) // the sent "ApiEndpointRequest" will also be received here, explicitly ignoring that
+ return;
+
+ var dict = obj as IReadOnlyDictionary;
+
+ if (dict == null)
+ return;
+
+ ApiAssign(dict);
+
+ IsReady = true;
+ _readyCallback?.Invoke();
+ }
+
+ public void ApiAssign(IReadOnlyDictionary delegates)
+ {
+ _apiInit = (delegates != null);
+ /// base methods
+ AssignMethod(delegates, "ToggleStealth", ref _toggleStealth);
+ AssignMethod(delegates, "GetStatus", ref _getStatus);
+ AssignMethod(delegates, "GetDuration", ref _getDuration);
+ AssignMethod(delegates, "GetMainDrive", ref _getMainDrive);
+ AssignMethod(delegates, "GetHeatSinks", ref _getHeatSinks);
+ }
+
+ private void AssignMethod(IReadOnlyDictionary delegates, 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()}");
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/MasterSession.cs b/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/MasterSession.cs
index 9d1c78f61..19d6edb72 100644
--- a/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/MasterSession.cs
+++ b/Gamemode Mods/Starcore_Sharetrack/Data/Scripts/ShipPoints/MasterSession.cs
@@ -4,6 +4,7 @@
using StarCore.ShareTrack.HeartNetworking;
using StarCore.ShareTrack.ShipTracking;
using StarCore.ShareTrack.TrackerApi;
+using StealthSystem;
using VRage.Game.Components;
using VRageMath;
@@ -20,6 +21,7 @@ internal class MasterSession : MySessionComponentBase
public static MasterSession I;
public static SharetrackConfig Config;
+ public StealthAPI StealthApi = new StealthAPI();
public HudAPIv2 TextHudApi;
public Action HudRegistered = () => { };
@@ -46,6 +48,8 @@ public override void LoadData()
_buildingBlockPoints = new BuildingBlockPoints();
TrackingManager.Init(); // Initialize TrackingManager, but don't start tracking yet
+ StealthApi.Load();
+
if (!MyAPIGateway.Utilities.IsDedicated)
// Initialize the sphere entities
// Initialize the text_api with the HUDRegistered callback