-
Notifications
You must be signed in to change notification settings - Fork 123
The Grid Terminal System
The Grid Terminal System is where you will be able to access your ship's devices. It provides access to all blocks on the same grid the programmable block is on, as well as any grids connected via rotors, pistons or connectors (not landing gears) - as long as the blocks have the same ownership as the running programmable block.
You access it via the property GridTerminalSystem
, which belongs to the script's base class, MyGridProgram
. This means that it will be available to all methods and properties in your script - but it is not directly available in any subclasses. More on this later.
The easiest way to see what the Grid Terminal System has to offer, is to create your script project in Visual Studio. Find your Main method
public void Main()
{
// Start typing in here
}
and where the comment indicates above, start typing Grid (mind the casing). Visual Studio will respond by showing you this:
This is called "intellisense". It shows you what is available to you at the current location. In this case, it is showing you GridTerminalSystem, which is the property we want. Press tab
or enter
and the IDE will fill in the rest for you. This method is available to you for any accessible type, variable, field or property, not just the GridTerminalSystem. This means that if you for instance define a variable with the type of a block you want, you can use this technique to see what this block can do and what it can provide in terms of information - to a certain degree. There's also (unfortunately) something called Terminal Properties and Terminal Actions which makes this more complicated than it has to be.
Now continue by adding a .
at the end. This is what is important. Now it should show you this:
These are the methods available to you in the grid terminal system. All of them are ways to retrieve blocks from your grids in various ways.
-
GetBlocks
Gets all the available blocks the Grid Terminal System has access to. Requires a target list of the baseIMyTerminalBlock
type.List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>(); void Main() { // Fill a list with all blocks in the system GridTerminalSystem.GetBlocks(blocks); }
-
GetBlocksOfType
Allows you to retrieve a list of blocks of a specific type, optionally filtered by a given collect predicate.List<IMyInteriorLight> lights = new List<IMyInteriorLight>(); void Main() { // Fill a list with all interior lights in the system GridTerminalSystem.GetBlocksOfType(lights); }
// Create a list containing all interior lights in the system, but store them // in a generic list containing blocks of the IMyTerminalBlock type List<IMyTerminalBlock> lights = new List<IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType<IMyInteriorLight>(lights);
List<IMyInteriorLight> lights = new List<IMyInteriorLight>(); void Main() { // Fill a list with all interior lights that are currently on GridTerminalSystem.GetBlocksOfType(lights, light => light.Enabled); }
-
SearchBlocksOfName
Searches through all the blocks, returning those whose name contains the entered name. Meaning, a block named "Mynoch" would be returned if you search for "no". Also provides the ability to use a collect predicate, just likeGetBlocksOfType
. Unfortunately, this method can only accept a target list of the baseIMyTerminalBlock
type.Note: This method is rather inefficiently implemented. You can do everything this method can do, in a better way, simply using the filter of GetBlocksOfType.
List<IMyTerminalBlock> lights = new List<IMyTerminalBlock>(); void Main() { // Fill a list with all lights in the system whose name contains the text "no" GridTerminalSystem.SearchBlocksOfName("no", lights, light => light is IMyInteriorLight); }
-
GetBlockWithName
Allows you to retrieve a single block having a specific name. Note that the name must be exact, case sensitive and including any spacing.// Find a block of a specific name, then check if it's a timer block. If it is, store it in the // timer variable, otherwise store null there. IMyTimerBlock timer = GridTerminalSystem.GetBlockWithName("Timer Block") as IMyTimerBlock;
-
GetBlockWithId
Allows you to retrieve a block by itsEntityId
. This is a unique id given to a block by the game, and will remain the same even if you rename the block. -
GetBlockGroups
Fetches a list of block groups, optionally filtered by a given collect predicate.List<IMyBlockGroup> groups = new List<IMyBlockGroup>(); void Main() { // Fill a list with all the block groups in the system GridTerminalSystem.GetBlockGroups(groups); }
List<IMyBlockGroup> groups = new List<IMyBlockGroup>(); void Main() { // Fill a list with all the block groups whose name contains the text "no" GridTerminalSystem.GetBlockGroups(groups, group => group.Name.Contains("no")); }
-
GetBlockGroupWithName
Returns a block group by its name. Note that the name must be exact, case sensitive and including any spacing.// Retrieve the block group named "Interesting Blocks" IMyBlockGroup group; group = GridTerminalSystem.GetBlockGroupWithName("Interesting Blocks");
By default, the grid terminal system just grabs everything it has access to, whether it's a part of your ship or not. From version 1.188 you will have access to a new block method called IsSameConstructAs
. This method will check if the two compared blocks belong to the same mechanical group, which means any set of grids connected by rotors and pistons. This mechanical group is called a construct and is usually what your ship, vehicle or station is made out from.
Be aware that you cannot distinguish between grids that are merged with a merge block, since the very purpose of that block is to permanently merge two grids into one.
List<IMyTerminalBlock> blocks = new List<IMyTerminalBlock>();
void Main()
{
// Fill a list with all blocks in the current construct (ship, vehicle or station),
// ignoring anything that might be docked to it. "Me" is the Program's reference to
// the programmable block this script is running in.
GridTerminalSystem.GetBlocksOfType(blocks, block => block.IsSameConstructAs(Me));
}
As your scripts increase in complexity, it's inevitable that you'll want to split your code into classes. Once you do this you will quickly realize that you lose access to the content of your program inside these classes. This is because the program itself is just another class. This very fact, however, provides you with a solution to this problem.
public class SomeUsefulSubclass
{
Program _program;
public SomeUsefulSubclass(Program program)
{
_program = program;
}
public void SomeUsefulMethod()
{
var block = _program.GridTerminalSystem.GetBlockWithName("That Block I Want");
// Do useful stuff with that block
}
}
SomeUsefulSubclass _subclass;
public Program()
{
_subclass = new SomeUsefulSubclass(this);
}
public void Main() {
_subclass.SomeUsefulMethod();
}
In this example we are leveraging the very fact that your script is just a class like any other, a class which is always named Program
. We are passing the main Program instance (this
in any of the methods or properties in your main script - not in your subclasses) into our subclass via its constructor. We choose to pass the program itself rather than just the GridTerminalSystem
because it will provide access to the other scripting facilities like the Echo, Storage and the Runtime as well as the GridTerminalSystem.
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!