1. This forum is obsolete and read-only. Feel free to contact us at support.keenswh.com

[Guide] Programmable Block - Hello, Galaxy! (Beacon)

Discussion in 'Programming Guides and Tools' started by Textor, Jan 1, 2015.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Textor

    Textor Junior Engineer

    Messages:
    775
    Hey All,

    Here is a quick "Hello, World" script. Bolded words are found in the glossary at the bottom.

    For the new programmers out there, the traditional first script you'll make is a "Hello, World" script, since it is very simple and lets you start getting used to the syntax of things.

    So, first, what you will need:

    1. I recommend Creative Mode for this-- you're learning, why bother messing with all that resource gathering?
    2. Create a station platform (really, you can make ANY type of ship you want, but this is simple... no motion or drifting to worry about).
    3. You'll need the following components present: Beacon, Power Source, Programmable Block, Button Panel

    Set up the button panel to point to the programmable block with action "Run"
    Set up the beacon to be named "Beacon" (if it isn't already).

    Ok, now to the actual programming bit:

    Go to the programmable block and click "edit"

    You'll notice that Keen has been kind enough to fill out your void Main() method already. void Main() is the entry point to the code.

    Go to line 2 (the '{' ) and press "enter" to get a new line. You should now be on a blank line between { and }. Your code should now look like:

    Code:
    void Main()
    {
    
    }
    
    Press TAB once. you should now be indented. Indentation is very important for readability. It isn't strictly necessary-- the code will execute without it, but it makes it a lot easier to follow what is going on when you properly indent.

    You'll want to put in the following line:

    Code:
    IMyBeacon beacon = GridTerminalSystem.GetBlockWithName("Beacon") as IMyBeacon; //Variable definition.
    
    So what does this line do?

    Code:
    IMyBeacon beacon
    This tells the system that you want to define a variable named "Beacon" of type IMyBeacon. You may see other people define this as "var" but I feel that for readability's sake, IMyBeacon is a bit more appropriate -- you know exactly what you intend the variable to be right from the start.

    Code:
    = GridTerminalSystem
    
    This is a Keen-defined class. It lets you access blocks on the same "grid" (same ship/station) as the programmable block.

    Code:
    GridTerminalSystem.GetBlockWithName("Beacon")
    
    The '.' indicates that you are accessing a method or property contained within a class. In this case, you want to access the "GetBlockWithName" method that is part of "GridTerminalSystem".

    GetBlockWithName takes a parameter. This parameter is a string. So we put "Beacon" into the parentheses so the method knows what to do. Quotation marks tell the system that everything within the quotation marks are a string. You cannot use GetBlockWithName(beacon) because that would pass the IMyBeacon variable into the method, which would case an error (IMyBeacon is not a string type.)

    Code:
    as IMyBeacon;
    
    GetBlockWithName returns a block that isn't a beacon. This might be a bit confusing, but it goes back to the types used by variables. "as" tells the code to cast the variable type into another type of variable. In this case, it is telling the system to convert the "IMyTerminalBlock" given to us to a "IMyBeacon"

    The semicolon (';') tells the system that you are done here -- end the instruction, and move on to the next instruction.

    But wait, there's one more piece to that line!

    Code:
    //variable definition.
    
    This doesn't have a semicolon, and what are those weird slashes in front!?

    This is a comment. Comments in code like this aren't strictly necessary, but it is a good habit to get into. Comments let you as a programmer tell other people reading the code (or even a reminder to yourself) what something is doing. This is telling us that the line we just had was a variable definition. Comments are defined by two slashes in front OR blocked using /* and */.

    // only works on ONE LINE. It works from the start of the two slashes to the end of the line.

    /* */ only works BETWEEN THEMSELVES. You can use this to comment out part of a line, or ENTIRE BLOCKS OF CODE. Why is this important? You may hear people tell you to "comment out..." something. This lets you comment out large amounts of code (make it ignored by the system) for debugging purposes or to set it aside for later-- it isn't finished being worked on, it breaks the ability for the script to work, and you want things to keep operating while you work on this section of the code.

    Finally, we get to the last line. You'll notice that in my code, I put an extra line between the two. This isn't necessary, just makes it a little more readable (I like to separate actions I take from variable definitions.)

    Add the following line to your code, on a new line (either just below the beacon definition or spaced out with a blank line or two.) Don't forget to use TAB to indent!

    Code:
    beacon.SetCustomName("Hello, Galaxy!");//sets the beacon's name to Hello, Galaxy!
    
    So, this is pretty easy to figure out:

    Code:
    .SetCustomName("Hello, Galaxy!");
    
    You have a IMyBeacon variable named beacon. This beacon has a pre-defined method called "SetCustomName" which takes a single parameter: a name. So, we tell the system to set it to "Hello, Galaxy!" (without the quotes, of course) for us.

    So, click "Check Code" down at the bottom. This is very important to always do. Why? Because it tells you if there are any problems. Did you forget a semicolon somewhere? Are you doing something that just isn't allowed? The check code button tells you! If you simply save and exit, the code may not work at all, and you'll be wondering why.

    Go ahead and "Remember and Exit" your code.

    And that's the code. So how do we run it?

    Well, there are two ways that we've set up. Let's do it through button-- press that button I asked you to set up earlier. What happened to the beacon? It now says, "Hello, Galaxy!"

    Pressing the button additional times won't do anything, since the beacon doesn't have the name "beacon" anymore. You can rename the original beacon, or you can build another beacon and name it "beacon" to do it again.

    The other way to execute the code is to get into the control panel and press "run" beneath "edit" on the programmable block. But that's not as fun as pressing a button with your engineer, is it?

    Full Code:

    Code:
    void Main()
    {
        IMyBeacon beacon = GridTerminalSystem.GetBlockWithName("Beacon") as IMyBeacon;//variable definition.
     
        beacon.SetCustomName("Hello, Galaxy!");//sets name to "Hello, Galaxy!"
    }
    
    Glossary
    • void Main() - This is required in every C# program, and the internal block scripting is no exception.
    • Method - A set of instructions that can be reused in your code so that you don't have to keep typing it in over and over again.
    • Entry Point - This is where the script begins executing. Why is that important? Because you can have things before void Main(). The script doesn't execute from line 1 down, it executes starting at void Main(). void Main() will always be the entry point.
    • Variable - A word that contains data. This word is "typed" which means that it contains a specific type of data. It is always defined as: type variablename = value; Variables are case sensitive and can contain mixed case. Variables can contain numbers, but cannot start with a number. You should always name your variables descriptively. I could name a variable 'a', but that doesn't mean as much as naming a variable 'beacon' which doesn't mean as much as naming a variable 'imbBeaconToBeRenamed'. Use a naming scheme you like, but just remember that you and other people likely need to be able to figure out what things do if variables are too vague, which can cause headaches later.
    • Parameter - A variable that is passed into a method. This will be expanded upon more when I do a tutorial demonstrating methods.
    • String - A variable type that contains text data. "Hello, Galaxy!" is a string. "This is a string." is also a string. "This is not a string." is also a string (and a liar, to boot.) So is "asdfkasdjladafljkadlfjasdfhjasdhflsdajflja" though I don't know when you'd actually want to set a string to that.
    • Cast - This term refers to converting a variable from one type to another. For now, know that it is necessary to do this, but I'll have another tutorial to explain casting at much greater length.
    • ; (semicolon) - This tells the system that you are done with a line of code. Useful, in that you can break up long lines into multiple lines without having to do anything special, as long as it is terminated with a semicolon.
    • instruction - A single action that a system is told to do. int i = 0; is instructing the system to make a variable named i that contains whole numbers, and set its value to '0'. beacon.SetCustomName("Hello, Galaxy!"); is instructing the system to set a beacon's name to "Hello, Galaxy!"
    • Comment - As explained above, a comment is a section of the code that is ignored by the system. You do not have to end it with a semicolon, you do not have to follow any syntax conventions, you can write a novel in this area. The system skips right over it, as if it is invisible. The comments aren't for the system. Comments are for you. Use them! Remind yourself and anyone looking at your code of your glorious genius solution to something! Good documentation makes life easier, so comment to your heart's content!
    Please feel free to ask questions in the comments!
     
    Last edited by a moderator: Jan 1, 2015
  2. Skeloton

    Skeloton Master Engineer

    Messages:
    4,069
  3. Thedevistator

    Thedevistator Senior Engineer

    Messages:
    1,942
    I like it I hope to see more guides like this.
     
  4. Locko1997

    Locko1997 Trainee Engineer

    Messages:
    17
    Ah, i can see my errors now. Since i'have never done more than E2 in garrysmod ( Yeah, it's like the programmable block. but it's sorta of c++ % & html ). I was trying to do the hello world as a nub programmer on this. My error was trying to get the beacon as type, which would give me array's of beacon if i had more than one. So i tryied to do this:

    Code:
    int[] = beacon
    beacon = GridTerminalSystem.GetBlockOfType<IMyBeacon>
    
    
    
    And i always got errors :3
     
  5. Skeloton

    Skeloton Master Engineer

    Messages:
    4,069
    You know...Ive gotten an idea. Now it most likely wont work. I'll back with an edit to see how it goes.
     
  6. Arcturus

    Arcturus Senior Engineer

    Messages:
    1,649
    If you use GetBlockWithName then Set the name, you can't use GetBlockWithName again on the same block.

    Here is my suggestion which sets all antennas to the same message:

    Code:
    void Main()
    {
     
    var blocks = new List<IMyTerminalBlock>(); 
    GridTerminalSystem.GetBlocksOfType<IMyRadioAntenna>(blocks); 
     
    for ( int i = 0; i <blocks.Count; i++) 
    { 
      var antenna = (IMyRadioAntenna)blocks[i]; 
      antenna.SetCustomName("Hello World") ;
    } 
    }
    
     
  7. a2457

    a2457 Senior Engineer

    Messages:
    1,366
    stunning at least :D

    Code:
    GridTerminalSystem.GetBlockWithName("Beacon")
    The '.' indicates that you are accessing a method or property contained within a class. In this case, you want to access the "GetBlockWithName" method that is part of "GridTerminalSystem".



    if that part is confusing, think of it like this.
    GridTerminalSystem would be a folder on your computer.
    and you want to access stuff inside GetBlockWithName folder.
    instead of the \ mark, the dot '.' is used.


    the reason for the CapitalLettersIs to make it more readable.

    gridterminalsystem looks farm more clumsy then GridTerminalSystem
    You will get used to it.

    the comments, well... comment everything. makes is easy to debug, and helps to remember what You are doing.
     
  8. Textor

    Textor Junior Engineer

    Messages:
    775
    Guide was designed with beginners in mind. Getting all blocks of type rather than a single block was for simplicity's sake, so people learn things a little at a time. Hence the limitation in using it again.

    Plus, even if I selected the same block again using a more advanced method, what would the result of setting a beacon named "Hello, Galaxy!" to the name "Hello, Galaxy!" accomplish?
     
  9. THE_VB

    THE_VB Junior Engineer

    Messages:
    511
    So you know what is going to be good?
    To put the source of code(variables etc) near the glossary, so people would use this topic as basic wiki.
     
  10. Tilted

    Tilted Trainee Engineer

    Messages:
    10
    This was helpful
     
  11. Locko1997

    Locko1997 Trainee Engineer

    Messages:
    17
    Code:
    Random rnd = new Random();
     
    void Main()
    {
     
        var blocks = new List<IMyTerminalBlock>(); 
        GridTerminalSystem.GetBlocksOfType<IMyBeacon>(blocks); 
     
        var beacon = (IMyBeacon)blocks[0]; // instead than using for loop as aracturus said, i just make so the first beacon will only say this.
        
        if ( rnd.Next(100) < 50 )
            beacon.SetCustomName("Hello, Galaxy!");
        else
           beacon.SetCustomName("Bye, Galaxy!");
        
     
    }
    
    
    I made this, it's basically glueing stuff together since im still learning :3
    It has a 50% probability of say hello galaxy or bye galaxy on each iteration.
     
    Last edited by a moderator: Jan 1, 2015
  12. Kuu Lightwing

    Kuu Lightwing Senior Engineer

    Messages:
    1,503
    You, sir, deserve a cookie and a hug.
    I'll be looking for more guides from you :)
     
  13. Textor

    Textor Junior Engineer

    Messages:
    775
     
  14. TheQuixote

    TheQuixote Apprentice Engineer

    Messages:
    119
    Clever solution for having no output console

    Here's another example that takes that idea a little further.

    Code:
    IMyBeacon outputConsole; // var for the beacon to be used as an output console
    
    void Main() 
    { 
        for (int i = 0; i < GridTerminalSystem.Blocks.Count; i++) 
        {     
            if(GridTerminalSystem.Blocks[i] is IMyBeacon) 
            {    
                outputConsole = GridTerminalSystem.Blocks[i] as IMyBeacon;
            } 
        }
    
        ClearConsole ();
    
        for (int i=0; i <GridTerminalSystem.Blocks.Count; i++ )
        {
            if ( !GridTerminalSystem.Blocks[i].CustomName.Contains ( "Start" ) )//Excludes the beacon being used as the console
            {
                Trace ( GridTerminalSystem.Blocks[i].CustomName );
            }
        }
    }
    
    void ClearConsole ()
    {
        if ( outputConsole != null )
        {
               outputConsole.SetCustomName ( "Start" );
        }
    }
    
    void Trace ( String sMessage )
    {
        if ( outputConsole != null )
        {
            outputConsole.SetCustomName ( outputConsole.CustomName + "\r" + sMessage );
        }
    }
    
     
  15. Dajk

    Dajk Trainee Engineer

    Messages:
    6
    Very nice guide. I like the traditional teaching by example method.
     
  16. nogare321

    nogare321 Trainee Engineer

    Messages:
    64
    Thanks! This is very helpful for a beginning C# programmer. It seems very different to Matlab...
     
  17. aaraujo

    aaraujo Trainee Engineer

    Messages:
    8
    I would just change one thing in your code: in ClearConsole, you set the beacon's name to "Start", but in the loop you test if the name of the block "Contains" "Start". I would change that to

    Code:
    if ( !GridTerminalSystem.Blocks[i].CustomName.Equals ( "Start" ) )
    
    to avoid excluding blocks from the list that might have "Start" somewhere in their name (i.e. "Start of Conveyor", "Starting Ship", etc.)
     
  18. Johnny Depth

    Johnny Depth Apprentice Engineer

    Messages:
    198
    How would the code look if I wanted the name of the beacon to change every 5 seconds? From Hello Galaxy, to Goodbye Galaxy.. just changing back n forth every 5 seconds
     
  19. REDHAWK

    REDHAWK Trainee Engineer

    Messages:
    45
    i goit a few questions:

    1: if u are on an online server. can u go into an enemie ship and program their programmable block?

    2: is it possiblie to make a code that makes the turrets on the ship destroying its own ship or attack friendlies (wich means my enemies but the turrets friendlies)



    3: if this is possiblie ... how would i go forth to make something like this?
     
  20. Textor

    Textor Junior Engineer

    Messages:
    775
    1. If you are on a server, you cannot go to an enemy ship and reprogram their programmable block. You don't have ownership, so you have no rights to do that. If you hack the block (grind it down, rebuild it) you can take ownership, but then the block has no rights to control other blocks on the grid that you haven't hacked.

    2. See above.

    3. It isn't possible.
     
  21. BluePhoenix8406

    BluePhoenix8406 Trainee Engineer

    Messages:
    2
    I know this coding style has been seen before but I wanted to post this as an example of renaming multiple Antennas and Beacons with examples of both commenting styles. Note: I used Notepad++ to code this as my Visual Studio 2010 has issues with one of the referances for Space Engineers

    /*
    Program: Rename Antennas and Beacons
    Programmer: BluePhoenix8406
    Date: 01/09/2015
    */

    void Main()
    {

    RenameAntennas(); // Calls Antenna Modual
    RenameBeacons(); // Calls Beacon Modual

    } // End void Main()

    void RenameAntennas()
    {

    // List to contain antenna blocks

    List<IMyBeaconBlock> antennaBlocks = new List<IMyRadioAntennaBlock>();
    GridTerminalSystem.GetBlocksOfType<IMyRadioAntennaBlock>(antennaBlocks);

    // Get all antenna blocks

    int antennaCount = antennaBlocks.Count

    // Loop through the antenna and antenna beacons

    for(int i = 0; i < beaconCount; i++;)
    {
    // Variable Definitions
    var antenna = IMyRadioAntennaBlock(i); // Finds all antennas
    Antenna.SetCustonName("Test"); // Renames all antennas

    } // End For

    } // End void RenameAntennas()

    void RenameBeacons()
    {

    // List to contain beacon blocks

    List<IMyBeaconBlock> beaconBlocks = new List<IMyBeaconBlock>();
    GridTerminalSystem.GetBlocksOfType<IMyBeaconBlock>(beaconBlocks);

    // Get all beacon blocks

    int beaconCount = beaconBlocks.Count

    // Loop through the beacons and rename beacons

    for(int i = 0; i < beaconCount; i++;)
    {
    // Variable Definitions
    var beacon = IMyBeaconBlock(i); // Finds all beacons
    beacon.SetCustonName("Test"); // Renames all beacons

    } // End For

    } // End void RenameBeacons()
     
  22. Corrimus

    Corrimus Trainee Engineer

    Messages:
    1
    I've looked around a bit and havent found where to see that blocks names are for the code, for example Antenna is apparantly "radio antenna" to be used as IMyRadioAntenna, but how do i find THAT name.
    Just starting to learn this using your very good youtube guides and a online C# learning thing with MS visual C# studio 2010, but to use blocks in the game i need to know their "actual" name, or am i being confused again?

    Regards,
    Corrimus
     
  23. Textor

    Textor Junior Engineer

    Messages:
    775
    It's located in the official documentation. You can see either the help file in the space engineers directory, or the official guide on steam:
    https://steamcommunity.com/sharedfiles/filedetails/?id=360966557
     
    Last edited by a moderator: Mar 19, 2015
  24. return 0;

    return 0; Trainee Engineer

    Messages:
    1
    Hey Textor,

    Really good job on these instructions man. I just barely started learning c++ and c# about a month ago. So I'm still trying to remember what does what. I liked the glossary type set up you did at the end for all of the keywords and terms too. Keep up the good work. And if they ever make a programming SE for dummies, you should definitely be the author for it.

    return 0;
     
  25. Beyogi

    Beyogi Trainee Engineer

    Messages:
    56
    So I've got a question. This here really helped me to get an idea how ingame scripting worked in space engineers and I tried to do a little airlock script of my own (open one door, close two others)

    Code:
    public void Main(string argument) {
    
    IMyDoor DoorBase = GridTerminalSystem.GetBlockWithName ("Sliding Door - Base") as IMyDoor;
    //Variable definiton for base door
    IMyDoor DoorMine = GridTerminalSystem.GetBlockWithName ("Sliding Door - Mine") as IMyDoor;
    //Variable definition for mine door
    IMyDoor DoorHangar = GridTerminalSystem.GetBlockWithName ("Sliding Door - Hangar") as IMyDoor;
    
    
    ITerminalAction Offnen = DoorBase.GetActionWithName ("Open_On") as ITerminalAction;
    ITerminalAction Schließen1 = DoorMine.GetActionWithName ("Open_Off") as ITerminalAction;
    ITerminalAction Schließen2 = DoorHangar.GetActionWithName ("Open_Off") as ITerminalAction;
    //As far as I can tell this is necessary to define the actions I want to use first.
    
    Offnen.Apply(DoorBase);
    Schließen1.Apply(DoorMine);
    Schließen2.Apply(DoorHangar);
    //Application of the actions I previously defined.
    
    }
    I wonder if I need to define each action for the object I want to apply it to or if I can skip part of the code above/simplify things.

    I tried to just go
    Code:
    Open_On.Apply(DoorBase);
    Open_Off.Apply(DoorMine);
    Open_Off.Apply(DoorHangar);
    , but that doesn't seem to compile for some reason.

    It feels a bit strange to me that I need to create a new variable for an already defined action I just want to apply.
     
  26. d4rky1989

    d4rky1989 Apprentice Engineer

    Messages:
    332
    You can directly apply actions. Like myBlock.ApplyAction("Open_Off")
     
    • Like Like x 1
  27. Beyogi

    Beyogi Trainee Engineer

    Messages:
    56
    Thank you. What I did so far seemed incredibly clunky.
     
  28. NeonWhite

    NeonWhite Trainee Engineer

    Messages:
    2
    I'm designing a smart drill, where vertical pistons lie on an advanced rotor, a conveyor is at the tip of the vertical pistons, and horizontal pistons extend from the conveyor. The program starts the drills and the rotor, taking the initial angle of the rotor. It then stores the initial angle in a beacon as its message, much like this "Hello Galaxy" program does.

    Since programmable blocks are not allowed to wait, I split the program into two discreet parts,
    1) The script gets all needed variables and stores them and
    2) The second programmable block accesses and evaluates if the drill is done.
    My basic question is, how do I access the public text of SetCustomName() and parse it as a double or a float? Doesn't matter which one.
     
  29. Malware

    Malware Master Engineer

    Messages:
    9,867
    @NeonWhite This tutorial is very outdated. See here for basics and go to Keen's discord, #programming-in-game channel, for lots of helpful people.
     
Thread Status:
This last post in this thread was made more than 31 days old.