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

A Basic Guide to C# for new programmers in space engineers

Discussion in 'Programming Guides and Tools' started by Sinbad, Jan 3, 2016.

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

    Sinbad Senior Engineer

    Messages:
    2,788
    This is intended as a basic C# primer, with a focus on Space engineers (SE) programming (which is C# with a limited function library). I'll provide a dictionary of terms used when talking about C#. I will try to explain the overall concept and structure of the language as well as provide information on syntax, how to read the documentation and tips on bug fixing.

    One of the most often cited difficulties that new programmers face is that it seems that programming tutorials seem to be written for people who already know how to program. Often basic terminology and concepts are glossed over or never mentioned at all before a block of code is thrown at you. Im going try to help with that a little.

    But first, how to use the programming block (PB)? The simplest way is to click on 'edit' and type your code into the editor, then click 'check code' button, which will check for most errors. Then click on the 'remember and exit' button to save your code and go back to the system menu. From here you can run your script by clicking the run button, or adding the PB to an action bar slot in a timer, sensor, air vent or toolbar with the run option.

    What is C#?
    C# (pronounced See-Sharp) is a high level Explicit Object Orientated programming language. High level means that the words that you type when writing in it are closer to natural English than they are to what a computer can understand. Which means they must be compiled by a special program to translate the words you type into words the computer understands. Explicit means that you need to explicitly tell the computer what you want it to do, you can’t let it make up its own mind or assume it will understand the implied meaning. Object Orientated describes the way the language organises data, more on that later.
    C# is the language many operating systems (including windows) is written in, and forms the basis of many other languages. It is old, but still under development and frequent use so is far from obsolete.

    The biggest thing to wrap your head around is the Object Orientated (OO) part. The old way of doing things was to lay out a program from beginning to end in a linear fashion. The computer read the code like most people read a book, from beginning to end. Some old languages allowed you to use 'Go To' to jump from one section to another, but it was very easy to get lost doing this after you jumped since you had to tell the computer exactly where to jump back to. That means that you couldn’t write a section of code, jump into it from anywhere in your program and then easily find your way back.
    Object orientated (OO) languages fix this. They do it by letting you write a sub-program that you can run from inside your main program. These sub programs are called 'methods'.
    C# comes with a set of built in libraries of methods, called Functions. These are short little programs that can do a lot of work for you, and all you need to do is call them by name and give them the information they need.
    For example you could do this

    If the number is greater than 10, make the number be 10. If the number is less than one, make the number be one. Otherwise, keep the number the same.

    But with the built in Functions, there is one that does that for you,

    Code:
    Clamp(1,10)
    Clamp is the name of the function. Inside the brackets are the options for that function. This is the information it needs to do its job. In this case, the lowest allowed number, then the highest. Functions can really make life easy.
    But now I'm starting to use a lot of words to mean things that they don’t normally mean, so here is a lit of terms with explanations of their meanings when used to talk about C#. There is a lot info in here, please read through it as these terms will be used frequently later.

    Variable: this is a 'space' in the computer memory. Think of it like a box to put things in. Variables need to be assigned a type.
    Variable Type: this tells a variable 'box' what shape to be.

    • If it is for holding letters it will be called a 'string' variable (because it will hold a string of characters).These can be of any length. You could store this entire primer in one string variable. String values are always typed with double quotation marks (" ") around them.
    • If it is holding whole numbers (with no decimal) then it can be called an Int (short for Integer, which means 'a whole number'). They can be positive or negative and can be worth a little over 2 Billion.
    • If it is a number with a decimal, it can be called a 'float' (or 'single') which is a 'floating point single precision number'. That's a fancy way of saying it is a 32 bit (really, quite large) number whose decimal point can be anywhere in it. If you need more accuracy, or need very large numbers, you can call it a 'Double", which is the same as a float, but is a 64 bit number. That’s a lot of decimal places. There is another type specifically for decimals, but is rarely used.
    • If it is just going to be a true or false value, you can call it a 'bool' (short for Boolean logic). These are stored as True or False only. More on Boolean logic later.

    Variable name: this is the label you put on the front of the box so you can find it quickly and easily. It can be as short (i) or as long (TheNumberOfTimesThisBlockOfCodeHasRun) as you like. It can contain underscores (_) but no spaces. It can contain numbers, as long as they are not the first character (InB4U is ok, 2Cool4U isn't). The only other symbol that can be used is the at (@) if placed as the first character of the name. The at allows you to use words that are reserved by C# for specific meanings. This allows you to use words like @float as a variable name without the computer confusing it with a variable type. Names are case sensitive, 'Thisbox' is a different variable to 'thisbox'. Variable names are used instead of the numbers when typed into code. So instead of writing 1+3, you can write A+B. Think of it like algebra, but with all sorts of names, like This+That-SomeThingElse. That means wherever you can use a number, you can use a variable name instead, as long as that variable is one of the number types.

    Variable Declaration: this is the magic formula we type in to make a variable exist. It goes like this:

    Variable Type Variable Name

    That’s it. If I wanted an integer variable named MyNumber I would write this;

    Code:
    int MyNumber;
    The semicolon ( ; ) is used like a period. It tells the computer where the end of the sentence (called a statement) is. This statement will 'Declare' to the computer that when I type MyNumber it should expect to find a whole number in the box. In fact, this statement creates the box. Think of it as ‘declaring’ that the box exists.
    Assign a Variable: this is the act of assigning a value to a variable. You do it like this:

    Code:
    MyNumber = 42;
    So you first use the variable name. Then an equal sign (which is the variable assignment operator). Then tell it what number it is. The variable on the left will be made to equal the value on the right. It is almost that simple.

    Cast: This is a term used to describe attaching a label to a box. So when you declare a variable, you are also casting the variable as a specific type. The neat thing is that you can change the variable type this way. There are a few different ways you can do it. Let’s say you want to change an integer into a float (let it have a decimal). There are a few ways you can do is this:
    Code:
    float MyNumberAsASingle = Convert.ToSingle(MyNumber);
    This is actually a function, more on functions later.
    Code:
    float MyNumberAsASingle = MyNumber as float;
    This uses the 'as' operator, more on operators later.
    Code:
    float MyNumberAsAfloat = (float)MyNumber;
    This is an explicit cast, and has a list of allowed conversions.
    Notice that all of these first declare a new variable, then assign the value of the old variable to it, cast as the new variables type.

    Return: this is a term used to say 'but what does it equal?'. If I wrote
    Code:
    float MyNumber = 42f;
    Then anytime I do this;

    Code:
    float NewNumber = MyNumber+3;
    The computer will use the value of MyNumber instead of the name, so this turns into 42+3. So MyNumber by itself Returns its value. The equation MyNumber+3 Returns the value of MyNumber plus 3. Remember that the '=' assigns a variable. It is saying what is on the left now equals what's on the right. It is not a logical comparison, more on those later.

    Objects: now that you know about variables, which can hold one piece of information. It is time to tell you about the real power of OO languages. An Object is a very special type of variable (not really, but it won't hurt right now to think of it as one). That can hold more than one piece of information. These pieces are called properties. For example, in SE a rotor can be cast as an object: IMyMotorStator (i didn't make that up, that's the actual type). It has lots of properties attached to it, like Angle, Velocity and Torque. You can access these properties by sticking them onto the end of the object name. So let’s declare a rotor object:

    Code:
    IMyMotorStator ThisRotor;
    That declares an Object type variable of IMyMotorStator type. All Objects with this type will automatically have access to the same set of properties. They will all have Angle, Velocity and Torque without you needing to tell them they do. Now, if you do this:

    Code:
    float Angle = ThisRotor.Angle;
    You can declare a new variable named angle, and assign the value stored as the angle property of ThisRotor. ThisRotor.Angle acts like a variable here in that naming it is the same as typing in the number it contains.
    This might need some more explanation. Remember that ThisRotor is the name we gave the Object cast as IMyMotorStator. That type of object contains properties, which are variables of fixed name and type attached automatically to the object. The ‘dot' between the object name and the property just tells the computer to look in that object for the property, rather than any other place. See what I mean about having to be explicit?

    Object Extension Methods: Objects can also have little miniature scripts in them. These are all named, and can be used just by naming them. Most need more information provided to them, but not all. You can easily identify a method by the fact its name will be followed by a set of parenthesis (). If the method needs more information to do its job, you put that information inside the parenthesis. For example, a fairly common extension method is SetValueFloat(). Lots of objects have this extension method. What it does is it sets a property of the object to a specific value, as long as that property is a float type. It needs the name of the property, as well as what value to set it to. You can do this:

    Code:
    ThisRotor.SetValueFloat("Velocity", 10f);
    Like the properties of this object, its extension methods are also accessed with the ‘dot’. The information inside the parenthesis is the name of the property that you want to set. Because the property name is actually a string it has to be set inside double quotation marks. A comma is used to separate it from the value you want it set to. The 'f' on the end is your way of telling the computer that the number 10 is a float, rather than an integer or a double. If you don’t use the 'f', the computer will assume it is a double. Not using the f is an implicit cast to double, and can get you in trouble if you merely forgot the 'f' and didn’t mean to try to cast it as a double).

    Class Inheritance: Extension methods are inherited from the object's parent class. A tiger is a mammal. Mammals have fur, so tigers have fur too. Mammal is the parent class, tiger is the object. In the case of the rotor, SetValueFloat() is inherited from the TerminalPropertyExtentions class. Most block object types belong to this class. An object can inherit from multiple classes. A tiger is a mammal, it is also a vertebrate but not all vertebrates are mammals. So the tiger will inherit 'spine' properties and extension methods from the 'vertebrate' class, and it will inherit 'fur' from the mammal class. A trout will inherit the 'vertebrate' class as well but it belongs to the 'scaly fish' class rather than the mammal class, so has scales instead of fur.

    Object Type Methods: these are the powerful methods attached to an object type. They are quite large mini scripts that do some complicated things. They work the same way as Object Extension Methods but often require a bit more information, and may return more than one value. The IMyRemoteControl class has a few of these.
    User Defined Methods, or just Methods: These are mini scripts you write yourself. It is handy because you can use them to do complex things that you need to do often without having to type out that complex thing a bunch of times. I’ll cover more on those in a later tutorial including how to create them.

    Operator: this is a small bit of the language that does a specific thing. We have already seen the 'as' operator used in casting, as well as the assignment operator (=). There are a bunch of them. Most of the words that actually get the work done are operators. One we have discussed is the Member Access Operator which looks like a period or ‘dot’. It lets you access a member of an object class, properties, methods and extension methods are members of the class they belong to. There is also the '( )' function invocation or method invocation. Which tells the computer the word before is a function or method. When used before a variable it can explicitly change the cast of the returned value. There are lots more, but it is enough to know that they always mean the same thing, wherever they are used and using them is as much a rule of syntax as it is programming.

    Syntax: this is a general term meaning 'the order of terms' or something like that. Basically it means that in English, you say 'the green cat'. In other languages you say 'the cat green'. You can break those three words down into a numerical declarative 'the' meaning 'there is one', an object 'cat' which names the class of object there is one of and a descriptor 'green' which applies to the object. These elements are expected in a specific order and don't make sense when mixed up. 'Cat Green The' doesn’t make sense, even though all the words are spelled correctly and are in fact words in the language. Programming languages work the same way. Each name, cast, and operator is expected to be placed in a specific order and changing the order can change the meaning significantly. For example:

    Code:
    ("velocity",10f)SetValueFloat.ThisRotor;
    Makes no sense. In the best case scenario, the computer will try to find a variable called "SetValueFloat" and return its 'ThisRotor' property as a custom variable type called "velocity, 10f". Which would definitely halt the script.

    \Steam\SteamApps\common\SpaceEngineers\Tools\Documentation.chm is where you can find the expected syntax of functions in SE that are not covered here:
    https://msdn.microsoft.com/en-US/library/618ayhy6.aspx in the official reference documents of the C# language.
    A typical example from Documentation.chm is this:
    (fancy HTML formatting removed)
    MathHelper.ToDegrees Method (Single)
    Converts radians to degrees
    Namespace: VRageMath
    Assembly: VRage.Math (in VRage.Math.dll) Version: 1.0.0.0
    Syntax
    public static float ToDegrees(
    float radians
    )
    Parameters
    radians
    Type: System.Single
    The angle in radians

    Return Value
    Type: Single
    This tells you first the name and inheritance of the function. In this case, it is the ToDegrees() method belonging to the MathHelper class. It may then tell you what it does (this one does). It also tells you the name space to find it under, namespaces are listed down the left hand side of the Documentation.chm. After that is a confusing bit labelled Syntax. What this is telling you is that it is a public function, so can be used anywhere in the code. It is also a static function, so it cannot be changed or renamed, and will persist between runs. Then it tells you that it will return a float value. After that is the name of the function itself ToDegrees. It then shows you the parenthesis and what type of information it needs do its job. Float radians means it needs a parameter called radians that is of the float type. If you look below that, you will see the parameters listed by the names used in the syntax key. The radians here is referring to the float radians above. It tells you that the radians parameter must be a Single type, and that it should represent an angle in radians. We know that we can do this now;

    Code:
    float AngleInDegrees = MathHelper.ToDegrees(ThisRotor.Angle);
    Because we know that the Angle property of IMyMotorStator is a float (also called a single, remember) and that it returns the current angle of the rotor in radians (ok, I knew that, but you would too after looking it up in the Documentation). So we can use that instead of typing in a number. After that, it reminds us that the return type will be a float.
    That’s the basics of syntax. Some things are really common, like the syntax of the '=' operator. The value on the left will be made to equal the value on the right every time it’s used.

    C# program structure
    Ok, I think that’s enough explaining of terms. Let’s look at program structure. In SE, the entirety of the programming block is an object in the program that is the SE engine. Your script is a method attached to this object.
    The basic program structure is

    Code:
    void Main()
    {
    //all your stuff goes here
    }
    Void Main() is the main method (remember this is a method attached to the programming block object). The script will begin execution here. It must be called Main() the parenthesis identify it as a method.
    The braces/curly brackets ( { } ) encapsulate your code. When statements are encapsulated like this, they are called a block. Notice the double backslash (//) this is a comment mark. It basically just tells the computer to ignore everything on that line, they allow you to add notes to yourself and others that describe the code. They can make reading code much easier. To comment out an entire block place /* at the beginning and */ at the end. You can have as many lines of code in between as you like, they will all be ignored by the computer. Remember that the asterisks point toward the code to ignore.
    A very simple example:

    Code:
    void Main()
    {
    Echo("Hello World");
    }
    This is a complete script. It will run but it doesn’t do very much does it?
    All that does is make "hello world" pop up in the detailed information panel of the system menu. It is actually a really handy de-bugging tool, I’ll talk more on that later.
    Before we get into a complete script that does something observable and useful we should cover another operator. What follows is an If statement. These are extremely useful. They let you make decisions with your script. They work like this:

    Code:
    if (check if this is true)
    {
    //things to do if true;
    //other things to do if true;
    }
    else
    {
    //things to do if false;
    }
    
    The 'if' (lowercase) is followed by the logical comparison inside the '( )' . This must be a statement that evaluates as true or false and the variable types on both sides must match. You can use a number of Boolean operators here:

    • > greater than (5>4) evaluates as True​
    • < less than (5<4) evaluates as False​
    • >= greater than or equal to (5>=4) evaluates as True
      <= less than or equal to (5<=4) evaluates as False​
    • == equal to (Note: this is not the same as = which is not a logical operator) (5==5) evaluates as True. This can also be used with strings (“hello”==”hello”) evaluates as True​
    • && and, this operator returns true if and only if the value on both sides is true, this is most useful when Boolean type parameters are used ( ThisLight.Enabled() && ThatLight.Enabled() ) will evaluate as true if both lights are switched on. It can also be used this way ( (5>4) && (4<5) ) both sides evaluate as true so this ends up as (True && True) which evaluates as True.​
    • || or, this operator returns true if the value of at least one side is true. This is used in a similar manner to ‘and’, except if either side is True it will evaluate as True. ( (5>4) || (4>5) ) will evaluate as true because one side is true. If they are both true it will also evaluate as true.​
    There are others, worth looking up on MSDN. If you can’t figure out a way to build the logical comparison you want, try googling it. I can almost guarantee someone somewhere has tried to do the same thing you are and has found a solution.

    The '{ }' form blocks that immediately follow the logical comparison. This is the code that executes if the comparison is true. If it is false, this block is skipped and the computer starts reading again at the end of the block.
    The else is optional. This block executes if the logical comparison is not true.


    Making things happen
    To do things, we need to get some stuff to do them to. So we need some objects in there, and some variables.
    To set the following script up, place a rotor on the same grid as the PB, and name it 'This Rotor'. Make sure to set the ownership to 'me' (the PB too).
    Place a timer as well, set up its actions to 'trigger now' itself, and run the PB (you can leave the argument blank). This makes the timer run the programming blocks script every game tick. SE uses the Havok physics engine, which has variable simulated time, so if your computer is having trouble keeping up with the physics calculations, it slows down the in game time. This is your sim speed and it doesn’t have any real relation to real time. If your sim speed is 0.5, that means for every real second that passes, only half a second passes in game. Havok calculates physics 60 times every in game second. The game engine and graphics engine are processed in between the Havok ticks. The script in your PB runs in between Havok ticks as well, which means a timer set up like this will run your script 60 times per in game second. For most uses that’s more than sufficient.

    Now for a complete script that actually does something:

    Code:
    void Main()
    {
    float TargetAngle = 180f;
    IMyMotorStator ThisRotor = GridTerminalSystem.GetBlockWithName("This Rotor") as IMyMotorStator;
    float AngleInRadians = ThisRotor.Angle;
    float AngleInDegrees = MathHelper.ToDegrees(AngleInRadians);
    float AngleDifference = TargetAngle-AngleInDegrees;
    if (AngleDifference > 30f)
    {
    AngleDifference=30f;
    }
    if (AngleDifference < -30f)
    {
    AngleDifference=-30f;
    }
    ThisRotor.SetValueFloat("Velocity",AngleDifference);
    }
    
    So to explain all this step by step. We covered void Main(), the next is a variable declaration and assignment in one statement. The declaration is the 'float TargetAngle' which tells the variable what kind of data it will hold, and what its name is. Then there is the assignment '= 180f;' the = is the assignment operator. It forces the variable on the left to equal the value on the right. In this case, 180f (remember the 'f' makes sure the computer knows it is a float) followed by the semicolon end of statement operator.

    Then we have an object declaration and assignment (it is actually called an instance, but it works the same as variable assignment). This object will be a MyMotorStator type called 'ThisRotor', which doesn’t have to be the actual name of the block in the system menu. Then the assignment operator as before. Then it gets tricky. GridTerminalSystem is every block the PB can currently access. It is the same as what you can see in the system menu when you press K on the PB. If you can see it on your list, this command can see it. The member access operator (the dot) allows access to a function belonging to GridTerminalSystem. It is called GetBlockWithName() and it returns the block with the name you type into the brackets ("This Rotor") if it is currently visible to the PB, if not it will crash the script. Remember that the name of the block is a string property and needs to be in double quotes. Finally we have the 'as' operator casting the returned block as IMyMotorStator. Remember that a block can belong to multiple classes. In this case we want to use the functions attached to the IMyMotorStator type and not any of the others it may belong to. The statement is finished with the ';'.

    Now we have a simple way to address a single block. Next we declare another variable, also a float and assign the current angle of ThisRotor to it. Remember that ThisRotor is an Object of the IMyMotorStator type, which has an Angle property that returns the current rotor angle in radians.

    As I have trouble thinking in radians, we need to convert radians to degrees. To do that we declare another variable and assign the value returned by the ToDegrees function we covered earlier. This does the math of converting radians to degrees for us.

    Next we declare another variable and assign the return value of the target angle minus the current angle.

    In the example, we don't use an else on the if statements because there are three options and two are mutually exclusive, so it isn’t necessary to have an else. In this case, if both comparisons are false, the AngleDifference variable is unchanged. This little section is in here so the script doesn't try to set the rotor’s velocity (RPM) to greater than 30 RPM forward (+30) or reverse (-30), because that would halt the script.

    Finally we set the rotors velocity parameter to the value of the angle difference. If you haven’t guessed by now, this is a servomechanism using negative feedback to position a rotor at the target angle.

    Because the timer is set up to run 60 times per simulated second, the angle difference will be recalculated in what passes for real time. This means that the rotors RPM will slow down as the difference between the target angle and the current angle decreases. Theoretically, it should settle on the target angle.

    Run the script by triggering the timer, you should see the rotor swing around to 180 degrees. To change the angle, just edit the script and type in a different value for TargetAngle.

    You will notice that the rotor moves a bit too fast to settle, it may be bouncing around and oscillating about 180 degrees. See if you can adjust the maximum speed of the rotor by altering the if statements.

    Or, see if you can add another if statement to add a dead zone (for those not familiar with the term, a dead zone is a range of inputs that have no effect on the output) to force the RPM to zero if the rotor is within a degree either side of the target angle.
    (Hint: an ‘and’ comparison is useful here)

    Another thing to try is condensing the script, I’ve spaced this one out so you could see each step clearly, but it can also be written like this:

    Code:
    void Main()
    {
    IMyMotorStator ThisRotor = GridTerminalSystem.GetBlockWithName("This Rotor") as IMyMotorStator;
    float AngleDifference = 180f-(MathHelper.ToDegrees(ThisRotor.Angle));
    if (AngleDifference > 30f){AngleDifference=30f;}
    if (AngleDifference < -30f){AngleDifference=-30f;}
    ThisRotor.SetValueFloat("Velocity",AngleDifference);
    }
    
    It can be made smaller than that even, but I’ve had trouble with Clamp and negative numbers.
    Please keep in mind that condensing scripts does not necessarily mean it will be smaller once compiled. The condensed script avoids declaring a few variables, but the information itself is still temporarily stored in memory. Both scripts will have nearly the same size and nearly the same impact on performance. Condensing scripts to much does not make them better. It can make them harder to read, but in some cases can improve readability, like in our if statements (that only works here because the true block is a single short statement). A script can be condensed into one line, as the ( ; ) marks the end of a statement, but that makes it near unreadable and serves no useful purpose. Carriage returns and spaces are omitted when the script is compiled, so removing them won’t make it any smaller. What will help is removing unneeded declarations and function calls, those take up more space and processor time than just inserting the value as a parameter directly into the statement.

    There is a lot more, and as you learn you will discover that some of what I’ve told you isn’t the exact truth. There likely are a couple of accidental lies in there, but for the lies I told on purpose I did to make it easier for you to gain an initial understanding upon which to build (“the earth is like an egg, but not really”). I hope that this primer helps you to learn SE programming a little easier.

    Things to do if it doesn’t work.
    If it doesn't compile (throws errors when you check script).
    It will tell you which line the error is on and what it is. The bottom left of the edit screen will tell you what line your cursor is on. Check your spelling, syntax, and case on that line.

    If it fails on run, it won’t be so kind as to tell you what line it failed on. Try putting in some numbered echos ( Echo("1") ); and watching the detailed info pane to narrow down which line is causing the problem. Then again, check your spelling, syntax, and case on that line.

    If it runs, but doesn’t do what you expected, grab a calculator and pencil and step through the program by hand (excel is handy for this) look for incorrect assumptions, math that doesn’t work, or just plain forgetting to add something in.

    If all else fails, have a look online to see if anyone else has had a similar issue, for problems with the SE specific library (pretty much anything in Documentation.chm) it’s probably best to check the In Game Programming forum for help.

    Good luck.

    Reference documents:
    \Steam\SteamApps\common\SpaceEngineers\Tools\Documentation.chm
    The Sandbox.ModAPI.Ingame, VRageMath, and parts of some other namespaces are where you will find most of your information.
    https://msdn.microsoft.com/en-US/library/618ayhy6.aspx is the official reference documents of the C# language.
    https://stackoverflow.com/ A number of my searches for help have landed me on this site, it often has some good answers
    https://www.mathsisfun.com/index.htm This site is good for brushing up your math, which you need more often than you may think
    https://www.i-programmer.info/ this site has a lot of articles that can help you understand more advanced concepts
    https://forum.keenswh.com/forums/guides-tools.410941/ and https://forum.keenswh.com/forums/questions-suggestions.410942/ are also great to have a look at (read it all!) but you can often find valuable pieces of information and advice scattered throughout the forums in general. Don’t be afraid to create a post asking for help if you get really stuck. SE has a helpful and friendly programming community that is full of knowledgeable programmers, even a few professionals.

    This is readable and makes sense because of the editing skills and patience of @SenorZorros, thanks for your hard work.

    edit: to remove smiling cats every where i typed ( ; ) without spaces.
     
    • Like Like x 5
  2. Squida

    Squida Trainee Engineer

    Messages:
    77
    Could someone please show us a starting layout for C# in Visual Studio 2015.

    Awesome guide as well thank you for the time, only trouble I seem to have is what DLL files to use for references and the "using" term.

    Code:
    using Sandbox.ModAPI;
    using Sandbox.Common;
    using Sandbox.Common.ObjectBuilders;
    using Sandbox.Common.Components;
    using System;
    using System.Collections.Generic;
    using System.Text;
     
    namespace ConsoleApplication2
    {
    	[MyEntityComponentDescriptor(typeof(MyObjectBuilder_Beacon))]
    	public class MyBeaconLogic : MyGameLogicComponent
    	{
    		Sandbox.Common.ObjectBuilders.MyObjectBuilder_EntityBase m_objectBuilder = null;
    		private bool m_greeted;
    		public override void Close()
    		{
    		}
     
    		public override void Init(Sandbox.Common.ObjectBuilders.MyObjectBuilder_EntityBase objectBuilder)
    		{
    			Entity.NeedsUpdate |= MyEntityUpdateEnum.EACH_100TH_FRAME;
    			m_objectBuilder = objectBuilder;
    		}
     
    		public override void MarkForClose()
    		{
    		}
     
    		public override void UpdateAfterSimulation()
    		{
    		}
     
    		public override void UpdateAfterSimulation10()
    		{
    		}
     
    		public override void UpdateAfterSimulation100()
    		{
    		}
     
    		public override void UpdateBeforeSimulation()
    		{
    		}
     
    		public override void UpdateBeforeSimulation10()
    		{
    		}
     
    		public override void UpdateBeforeSimulation100()
    		{
    			if (MyAPIGateway.Session.Player == null)
    			{
    				return;
    			}
    			if ((MyAPIGateway.Session.Player.GetPosition() - Entity.GetPosition()).Length() < 10)
    			{
    				if (!m_greeted)
    				{
    					MyAPIGateway.Utilities.ShowNotification(string.Format("Hello I am {0}", (Entity as Sandbox.ModAPI.Ingame.IMyTerminalBlock).DisplayNameText), 1000, MyFontEnum.Red);
    					m_greeted = true;
    				}
    			}
    			else
    				m_greeted = false;
    		}
     
    		public override void UpdateOnceBeforeFrame()
    		{
    		}
     
    		public override MyObjectBuilder_EntityBase GetObjectBuilder(bool copy = false)
    		{
    			return m_objectBuilder;
    		}
    	}
    }
    
    Is this the template we use for Visual Studio?
     
    Last edited: Mar 2, 2016
  3. Sinbad

    Sinbad Senior Engineer

    Messages:
    2,788
    I can't help you there as I don't use visual studio. I use notepad++. sorry.
     
  4. Phoera

    Phoera Senior Engineer

    Messages:
    1,713
    • Like Like x 1
  5. mexmer

    mexmer Senior Engineer

    Messages:
    1,977
    this is for modscript, not for PB script
    PB scripts doesn't have access to game logic, PB api is rather limited.
    modscripts are processed by client directly (like any other mod), attaching to different parts of game, while PB scripts are run inside programable block, and have more limited access (for example they honor block ownership)
     
    • Like Like x 1
  6. Squida

    Squida Trainee Engineer

    Messages:
    77

    So is that the c# template and "using" extensions we need. Because just know, Yes I am new and yes I am still learning. and would love more help to get me in the right direction.

    My aim is to create a block, like how the uranium centrifuge creator has made a block or even the stone extractor. Of course I had a look at the code (Would never copy it for my own though) to get an idea on the hooks and so on. The code looked way different to C# but yet its a mod. so was really confused and wanted a starting guide to show me the correct "using's command and sequence for starting script that is current today. I had a good read of the guide that is in this thread. It opened my eyes to a heap of info. Thanks by the way. just the biggest things I was confused about is the dll files and usings and the up to date layout for C# for space engineers. I really do hope this makes sense, I will re-write if it does not.
     
  7. Cuber

    Cuber Apprentice Engineer

    Messages:
    262
    What Mexmer is trying to say that perhaps you could try the Modding section, since you're trying to create a mod. This is the forum section for the in-game programmable block and things related to it :)
     
  8. Squida

    Squida Trainee Engineer

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