Skip to content

The Modular API

Aristeas edited this page May 22, 2024 · 17 revisions

The Modular Assemblies Definition API (DefinitionApi from here on) is the beating heart of the framework. All communication between client mods and Modular Assemblies goes through it, and it offers several useful functions to ensure your custom assemblies work properly.

Installation

While the DefinitionApi is best used in the Client Mod Template, it can also be used standalone in your mods. The template provides a simple project structure for using Modular Assemblies as the focus of your mod and will automatically handle loading your definitions, whereas the standalone DefinitionApi gives you more flexibility in using the framework exactly how your mod demands.

Follow the steps below to add the DefinitionApi to your mod:

  1. Copy the latest API version into your mod's ./Data/Scripts/ subfolder.
  1. Create a new instance of the DefinitionApi in one of your classes:
[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]
internal class SessionLogic : MySessionComponentBase
{
    public ModularDefinitionApi ModularApi = new ModularDefinitionApi();

    public override void LoadData()
    {

    }
}
  1. Initialize the API and check if it's ready.
[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]
internal class SessionLogic : MySessionComponentBase
{
    public ModularDefinitionApi ModularApi = new ModularDefinitionApi();

    public override void LoadData()
    {
        ModularApi.Init(ModContext); // ModContext is available to all session and gamelogic components.
    }

    public override void UpdateAfterSimulation()
    {
        if (!ModularApi.IsReady)
            return;

        // do stuff
    }
}
  1. Use Modular Assemblies to your heart's content.

Updating

To update your version of the DefinitionApi, copy the entire latest API version into your existing DefinitionApi.cs file and check for broken references.


API Reference

All public methods are explained in the DefinitionApi's included documentation, but this reference will provide more details and give examples.
In examples, defApi represents an instance of the DefinitionApi. "Modular_Fusion" represents the name of a definition.

API Meta

Object Description Example

void Init(IMyModContext modContext, Action onLoad = null)

Prepares the DefinitionApi for use - this *must* be called before using the API.
Include your mod context and an optional action to be triggered whenever the API fully loads (equivalent to OnReady).
DefinitionApi defApi = new DefinitionApi();
defApi.Init(this.ModContext);

int ApiVersion

The integer DefinitionApi version included in your mod.
The latest API can always be [obtained from here.](https://github.com/StarCoreSE/Modular-Assemblies/blob/main/Data/Scripts/AssemblyScripts/Definitions/DefinitionApi.cs)
ShowNotification($"DefinitionApi {defApi.ApiVersion} loaded.");

int FrameworkVersion

The integer Modular Assemblies Framework version currently loaded.
ShowNotification($"Framework v{defApi.FrameworkVersion} detected.");

bool IsReady

Boolean value representing whether or not the DefinitionApi is ready for use.
public override void UpdateAfterSimulation()
{
    if (!defApi.IsReady)
	  return;
    // do stuff with the API
}

Global Methods

Object Description Example

bool IsDebug()

Returns true if debug mode is enabled.
if (defApi.IsDebug())
{
    // do stuff
}

void Log(string text)

Writes a line to the Modular Assemblies log. %AppData%\Space Engineers\Storage\ModularAssemblies.log
Note that all log entries will include your mod's name for ease of debugging.
defApi.Log("Hello World!");

void AddChatCommand(string command, string helpText, Action<string[]> onTrigger)

Registers a chat command. Help page is tied into "!md help"
The Command parameter is the string that triggers the command. A command that looks like "!md test arg1" would have "test" as its command. Commands are case insensitive.
The HelpText parameter is displayed whenever "!md help" is run.
The OnTrigger action is run whenever the chat command is entered. It has the following parameters:
- string[] Arguments: Space-separated array representing the command input. Includes the command (i.e. "!md test arg1" would return { "test", "arg1" })
// The below command is triggered with "!md mycommand"
defApi.AddChatCommand("mycommand", "Does something great.", (args) => ShowMessage("", "/stop"));

void RemoveChatCommand(string command)

De-registers a chat command. Case-insensitive.
// The command won't be triggered anymore.
defApi.RemoveChatCommand("mycommand");

Global Assembly Methods

Object Description Example

IMyCubeBlock[] GetAllParts()

Returns an array of all blocks in the world with AssemblyParts.
foreach (IMyCubeBlock block in defApi.GetAllParts())
{
    // Do stuff
}

int[] GetAllAssemblies()

Returns an array of all PhysicalAssembly ids in the world.
ShowNotification($"{defApi.GetAllAssemblies().Count} assemblies registered.");

Per-Assembly Methods

Object Description Example

IMyCubeBlock[] GetMemberParts(int assemblyId)

Returns an array of all member blocks in a given assembly.
void RenameBlocksInAssembly(int assemblyId)
{
	foreach (IMyCubeBlock block in defApi.GetMemberParts(assemblyId))
	{
		block.DisplayNameText += $" [ASM {assemblyId}]";
	}
}

IMyCubeBlock GetBasePart(int assemblyId)

Returns the base part of a given assembly. If no base part is defined or the assembly does not exist, returns null.
long GetAssemblyOwner(int assemblyId)
{
    IMyCubeBlock baseBlock = defApi.GetBasePart(assemblyId);
    return baseBlock.OwnerId;
}

IMyCubeGrid GetAssemblyGrid(int assemblyId)

Returns the grid a given assembly is built on, or null if the assembly is not found.
defApi.GetAssemblyGrid(anAssemblyId)?.SetPosition(Vector3D.Zero);

void AddOnAssemblyClose(Action<int> action)

Registers an Action triggered on assembly removal. The action is run with the Assembly's ID as an argument.
defApi.AddOnAssemblyClose(AssemblyClosed);

// elsewhere
// This method will be triggered when an assembly is closed.
void AssemblyClosed(int assemblyId)
{
	ShowNotification($"Assembly {assemblyId} closed.");
}

void RemoveOnAssemblyClose(Action<int> action)

Removes an Action triggered on assembly removal.
defApi.RemoveOnAssemblyClose(AssemblyClosed);

// elsewhere
// This won't be triggered anymore.
void AssemblyClosed(int assemblyId)
{
	ShowNotification($"Assembly {assemblyId} closed.");
}

void RecreateAssembly(int assemblyId)

Removes all blocks from the assembly and queues them for a connection check.
This will typically result in an identical assembly.
if (buttonPressed)
{
	defApi.RecreateAssembly(anAssemblyId);
}

T GetAssemblyProperty<T>(int assemblyId, string propertyName)

Returns a given property of an assembly, or the default value of T if it could not be found.
T must be a byte array, string, bool, or number.
See SetAssemblyProperty for a description of Assembly Properties.
float maxHeat = defApi.GetAssemblyProperty<float>(anAssemblyId, "MaxHeat");

void SetAssemblyProperty<T>(int assemblyId, string propertyName, T value)

Sets a global property of a single assembly. Properties are saved to the assembly, and are accessible by all client mods.
T must be a byte array, string, bool, or number.
If a property is set to null, its entry is removed.
defApi.SetAssemblyProperty(anAssemblyId, "MaxHeat", 100);

string[] ListAssemblyProperties(int assemblyId)

Lists all set properties of an assembly.
string[] allPropertyNames = defApi.ListAssemblyProperties(anAssemblyId);

Per-Part Methods

Object Description Example

IMyCubeBlock[] GetConnectedBlocks(IMyCubeBlock partBlockId, string definition, bool useCached = true)

Returns an array of parts connected to a given block. Use the `definition` parameter to select which definition name to check.
Note - setting useCached to false will slightly improve performance, but can be unreliable when multithreading.
IMyCubeBlock[] neighborBlocks = defApi.GetConnectedBlocks(baseBlock, "Modular_Fusion");

int GetContainingAssembly(IMyCubeBlock blockPart, string definition)

Returns the ID of the assembly containing a given part, or -1 if no assembly was found. Use the `definition` parameter to select which definition name to check.
if (defApi.GetContainingAssembly(aBlock, "Modular_Fusion") != -1)
{
	ShowNotification("The block is in an assembly!");
}

void RecreateConnections(IMyCubeBlock blockPart, string definition)

Removes a part from its assembly and queues it for a connection check.
This can split assemblies temporarily, and often results in no net change.
if (defApi.GetContainingAssembly(aBlock, "Modular_Fusion") == -1)
{
	ShowNotification("The block is not in an assembly!");
	defApi.RecreateConnections(aBlock, "Modular_Fusion");
}

Definition Methods

Object Description Example

string[] RegisterDefinitions(DefinitionDefs.DefinitionContainer definitionContainer)

Registers a set of definitions with Modular Assemblies Framework. Returns an array of newly created definition names.
Note - this also registers actions within the definitions.
[Read more about definitions here.](https://github.com/StarCoreSE/Modular-Assemblies/wiki/The-Modular-Definition)
DefinitionContainer StoredDef = ModularDefinition.GetBaseDefinitions();
ModularDefinition.ModularApi.RegisterDefinitions(StoredDef);

bool UnregisterDefinition(string definitionName)

Unregisters a definition and removes all assemblies/parts referencing it. Returns true if the definition exists, and false if it does not.
[Read more about definitions here.](https://github.com/StarCoreSE/Modular-Assemblies/wiki/The-Modular-Definition)
defApi.UnregisterDefinition("Modular_Fusion");

string[] GetAllDefinitions()

Returns a list of all registered definition names.
foreach (string defName in defApi.GetAllDefinitions())
{
	ShowMessage("", "Found definition " + defName);
}

void RegisterOnPartAdd(string definitionName, Action<int, IMyCubeBlock, bool> action)

Registers an action to be triggered when a part is added.
The action is triggered with the following arguments:
- int PhysicalAssemblyId: The unique ID of the assembly containing this block.
- IMyCubeBlock newBlock: The freshly placed block.
- bool IsBaseBlock: If a base block is defined, this value will be true for that subtype.
defApi.RegisterOnPartAdd("Modular_Fusion", OnPartAdd);

// later

void OnPartAdd(int physicalAssemblyId, IMyCubeBlock newBlock, bool isBaseBlock)
{
    // do stuff
}

void RegisterOnPartRemove(string definitionName, Action<int, IMyCubeBlock, bool> action)

Registers an action to be triggered when a part is removed.
The action is triggered with the following arguments:
- int PhysicalAssemblyId: The unique ID of the assembly containing this block.
- IMyCubeBlock newBlock: The freshly removed block.
- bool IsBaseBlock: If a base block is defined, this value will be true for that subtype.
defApi.RegisterOnPartRemove("Modular_Fusion", OnPartRemove);

// later

void OnPartRemove(int physicalAssemblyId, IMyCubeBlock newBlock, bool isBaseBlock)
{
    // do stuff
}

void RegisterOnPartDestroy(string definitionName, Action<int, IMyCubeBlock, bool> action)

Registers an action to be triggered when a part is destroyed. Triggered immediately after OnPartRemove if a block was destroyed.
The action is triggered with the following arguments:
- int PhysicalAssemblyId: The unique ID of the assembly containing this block.
- IMyCubeBlock newBlock: The freshly destroyed block.
- bool IsBaseBlock: If a base block is defined, this value will be true for that subtype.
defApi.RegisterOnPartDestroy("Modular_Fusion", OnPartDestroy);

// later

void OnPartDestroy(int physicalAssemblyId, IMyCubeBlock newBlock, bool isBaseBlock)
{
    // do stuff
}

void UnregisterOnPartAdd(string definitionName, Action<int, IMyCubeBlock, bool> action)

Unregisters an action to be triggered when a part is placed. The action will not be called anymore if it was previously registered.
defApi.UnregisterOnPartAdd("Modular_Fusion", OnPartAdd);

// later
// This function won't get called anymore.
void OnPartAdd(int physicalAssemblyId, IMyCubeBlock newBlock, bool isBaseBlock)
{
    // do stuff
}

void UnregisterOnPartRemove(string definitionName, Action<int, IMyCubeBlock, bool> action)

Unregisters an action to be triggered when a part is removed. The action will not be called anymore if it was previously registered.
defApi.UnregisterOnPartRemove("Modular_Fusion", OnPartRemove);

// later
// This function won't get called anymore.
void OnPartRemove(int physicalAssemblyId, IMyCubeBlock newBlock, bool isBaseBlock)
{
    // do stuff
}

void UnregisterOnPartDestroy(string definitionName, Action<int, IMyCubeBlock, bool> action)

Unregisters an action to be triggered when a part is destroyed. The action will not be called anymore if it was previously registered.
defApi.UnregisterOnPartDestroy("Modular_Fusion", OnPartDestroy);

// later
// This function won't get called anymore.
void OnPartDestroy(int physicalAssemblyId, IMyCubeBlock newBlock, bool isBaseBlock)
{
    // do stuff
}