-
Notifications
You must be signed in to change notification settings - Fork 123
Terminal Properties and Actions
Note: Terminal actions and properties are orders of magnitude slower than their equivalent C# members. As such it is highly recommended you use proper C# code and not terminal actions and properties, for less overhead, whereever this is possible.
In addition to the normal C# properties, fields and methods, Space Engineers introduces a couple of unique concepts to the programmable block: The Terminal Properties and Actions. These are usually - but not entirely exclusively - connected directly to user interface components shown in the block's terminal. They are not accessed via normal interfaces, but via specialized methods available for any block. However note that it is highly recommended that you do your best to use the proper C# code wherever possible, since these will always be the most performant and least bug prone to use - not to mention that if you use Visual Studio, these will show up in the intellisense popup, as opposed to the terminal properties and actions which will not. At the time of writing this tutorial, not all Terminal items have gotten their proper C# interface access, in which case you will have to resort to the Terminal access.
In short when trying to do something on a block but you don't know where to look:
- Find the block's interface (
IMyMotorStator
, etc) and see if it has the thing you require (API index). - If not, check the terminal properties list
- If not, check the terminal actions list
- If still not, ask in #programmable-block channel in Keen's discord server.
Terminal properties are ways to access the values of the user interface components (also known as terminal controls).
Unfortunately not all of the terminal controls can be controlled by the Programmable Block, for example button and list-box. They might however have toolbar action counterparts.
You can get the value of a terminal property by calling the method GetValue<T>
. This is a generic method, so you need to specify the type of the value you wish to retrieve yourself.
IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName("Suspension 3x3");
float propulsionOverride = block.GetValue<float>("Propulsion override");
Here I'm retrieving the Propulsion Override slider's value from a suspension block.
Note that I did not cast the block to a suspension interface, that is not necessary to use these terminal properties and actions.
However if the block you retrieve does not have the property specified, your script will crash with a NullReferenceException
.
Similarly, you can set the value of a terminal property by calling the method SetValue<T>
.
IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName("Suspension 3x3");
block.SetValue<float>("Propulsion override", 0.5f);
This code will set suspension's Propulsion Override slider to 0.5 which is the internal value that results in 50%.
You can see the internal value format for sliders in-game by using ctrl+click on the slider. Other controls are a bit more complicated and would require peeking at the game code with a decompiler.
You can also check if a property exists by using block.GetProperty("PropId")
which returns null if it doesn't exist.
Then if you also want to use it, you can skip retrieving it again by using this returned object like so:
IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName("Suspension 3x3");
ITerminalProperty prop = block.GetProperty("Propulsion override");
if(prop != null)
{
ITerminalProperty<float> propFloat = prop.As<float>();
if(propFloat.GetValue(block) < 0.9f)
{
propFloat.SetValue(block, 0.9f);
}
}
For IDs see below on how to find them yourself or the list of vanilla ones.
Terminal actions are the same actions you see when dragging a block from the block area to a toolbar in a sensor, timer block, button panel etc.
Only actions that can be added to Button Panel's toolbar can also be used by the Programmable Block. For example the Jump action on a Jump Drive cannot.
You invoke a terminal action by calling the method ApplyAction
on a filled reference to a block:
IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName("Interior Door");
block.ApplyAction("Open_On");
This particular action will open the door retrieved. Note again that if the block you retrieve does not have the action specified, your script will crash with a NullReferenceException
.
You can however check if the action exists by using block.GetActionWithName("ActionId")
which returns null if not found.
Then you can also use that given object to trigger it too.
IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName("Interior Door");
ITerminalAction action = block.GetActionWithName("Open");
if(action != null)
{
action.Apply(block);
}
Which opens or closes the door, as this action is the toggle one.
Additionally you can retrieve the text information that shows on the toolbar slot for this action by using the above to get the action then call action.WriteValue()
, as shown:
IMyTerminalBlock block = GridTerminalSystem.GetBlockWithName("Interior Door");
ITerminalAction action = block.GetActionWithName("Open");
if(action != null)
{
var sb = new StringBuilder();
action.WriteValue(block, sb);
Echo($"Status: {sb}");
}
Generated from the vanilla game: List Of Terminal Properties And Actions.
You can also find the usable terminal properties and actions with code in the Programmable Block.
This is also very useful to interact with terminal controls or actions added by mods.
The following example lists out the IDs and value types of all the terminal properties in the block.
List<ITerminalProperty> properties = new List<ITerminalProperty>();
block.GetProperties(properties);
foreach (var property in properties)
{
Echo($"{property.Id}: {property.TypeName}");
}
The following example lists out the IDs and display text of all the actions in the block.
List<ITerminalAction> actions = new List<ITerminalAction>();
block.GetActions(actions);
foreach (var action in actions)
{
Echo($"{action.Id}: {action.Name}");
}
Do you have questions, comments, suggestions for improvements? Is there something I can do better? Did I make a mistake? Please add an issue here, and prefix your issue title with Wiki. Thank you, your help will be very appreciated!