Difference between revisions of "Programming Guide/zh"
PurplePopo (talk | contribs) |
PurplePopo (talk | contribs) |
||
Line 6: | Line 6: | ||
=== Main 方法 === | === Main 方法 === | ||
当编辑器第一次打开时,代码编辑器中会出现void Main() 方法。 | 当编辑器第一次打开时,代码编辑器中会出现void Main() 方法。 | ||
− | + | 这是执行脚本时程序调用的入口方法。 如果删除/重命名Main方法,脚本将不会运行,您将在可编程块详细信息区域中收到通知。 | |
可以定义和使用自定义方法/变量,但只调用Main方法而不引用。 | 可以定义和使用自定义方法/变量,但只调用Main方法而不引用。 | ||
− | === | + | === 变量的生命周期 === |
− | + | 脚本中有两种类型的变量: | |
− | + | 局部变量(定义在方法内部) - 这些变量仅在方法被执行期间保持其值。方法结束时,变量值将“丢失”。 | |
− | + | 全局变量(定义在方法外部) - 这些变量将在整个脚本的生命周期内保持其值。 | |
− | + | 例如:如果变量需要在程序运行时保持值,则需要在方法之外定义它。 | |
− | + | 按“保存并退出”或“保存”按钮后,之前的脚本将被覆盖,之前所有的全局变量都将丢失。 | |
− | + | 除了内置的保留变量之外的所有变量(局部和全局变量)将在重新编译代码时以及在已保存的游戏加载之间丢失其值或返回其默认值。 | |
− | + | 保留变量的独特之处在于它可以将在保存中和重新编译时的数据存储为字符串。 | |
− | |||
=== Compiling === | === Compiling === |
Revision as of 16:44, 1 September 2018
在太空工程师游戏内编程是通过可编程块完成的,可以使用C#(念做 C Sharp)语言来编写脚本。 它可用于制造自主式采矿无人机,远距离玩家捕杀鱼雷,船舶建造用自动焊接臂等等。
Contents
介绍
编辑权限
同一时间只有一个玩家可以编辑同一个脚本。 如果已经有一个人在当前块打开编辑器,而此时其他人试图打开该块的编辑器时,会显示一条通知,表示编辑器已经打开。
Main 方法
当编辑器第一次打开时,代码编辑器中会出现void Main() 方法。 这是执行脚本时程序调用的入口方法。 如果删除/重命名Main方法,脚本将不会运行,您将在可编程块详细信息区域中收到通知。 可以定义和使用自定义方法/变量,但只调用Main方法而不引用。
变量的生命周期
脚本中有两种类型的变量: 局部变量(定义在方法内部) - 这些变量仅在方法被执行期间保持其值。方法结束时,变量值将“丢失”。 全局变量(定义在方法外部) - 这些变量将在整个脚本的生命周期内保持其值。 例如:如果变量需要在程序运行时保持值,则需要在方法之外定义它。 按“保存并退出”或“保存”按钮后,之前的脚本将被覆盖,之前所有的全局变量都将丢失。 除了内置的保留变量之外的所有变量(局部和全局变量)将在重新编译代码时以及在已保存的游戏加载之间丢失其值或返回其默认值。 保留变量的独特之处在于它可以将在保存中和重新编译时的数据存储为字符串。
Compiling
When the “Check code” button is pressed, the code will be compiled and the result of the compilation will be shown. There are two steps of the compilation process: First the code inside editor is compiled by c# compiler for language errors. If there are any errors during compilation the following dialog is shown: It this case “aaa” string is placed before Main method. This is the wrong language construction and the compilation failed. In the error dialog the Line number error and description of the error is shown.
After compilation, the code is checked for usage of disallowed namespaces and types. In case that check fails, the following dialog is shown: In this case System.IO.Directory was used to delete some directory. This is forbidden and error is shown that “Not allowed type was used in script”.
If compilation and checks pass, a dialog is shown, confirming the checks passed, and the code is saved.
Script execution
When “Run” button is pressed or “Run” is assigned as terminal action, script is executed. Currently “Run” needs to be called manually e.g. user need to click on “Run” button or attach it as terminal action. Script is executed only on server even if it’s triggered from client. If there is any exception during script execution, all clients will be notified in programmable block details area about failure. In case of exception during script execution, script will not run again unless User opens editor and change script. A timer can also continuesly run the script by having a run action (you may be prompt to input an argument) and then starting/triggering itself or being started/triggered via script code (if going by the letter the timer will stop if the script crash).
Counting of instructions
Every time script is executed, every instruction of script is counted. If script executes more instruction than limit, execution is stopped and user is notified that script is too complex for execution. This prevents scripts to “freeze” game.
Whitelist
The types and classes allowed in scripts are restricted. Refer to the Scripting Whitelist to see what you are allowed to use.
Available interfaces
Possible Actions
Currently only terminal actions can be triggered inside scripts. User can access terminal system for grid on which programmable block is located and trigger any terminal action on any block at grid.
Block Classes (Action List)
Same block class for different SubTypeID
Some blocks have same parent (e.g. <TypeId> in cubeblocks.sbc) and differs only by subtype (e.g. <SubtypeId>). This means there is no distinction between these block in code.
Example of these blocks is the Cargo Container: there are 3 types of cargo containers in the game: small, medium and large. These three types differ only by subtype and Type is same for them e.g. large cargo container id is:
<Id>
<TypeId>CargoContainer</TypeId>
<SubtypeId>LargeBlockLargeContainer</SubtypeId>
</Id>
Medium is:
<Id>
<TypeId>CargoContainer</TypeId>
<SubtypeId>SmallBlockMediumContainer</SubtypeId>
</Id>
And small is:
<Id>
<TypeId>CargoContainer</TypeId>
<SubtypeId>LargeBlockSmallContainer</SubtypeId>
</Id>
In this case there is only one class IMyCargoContainer for all types of cargo containers.
Example programs
Hello world
The standard Hello World program in Space Engineers can be written as such:
public void Main() { Echo ("Hello, world!"); }
If this program is entered into a programmable block and run, it will result in "Hello, world!" being displayed in the programmable block's interface on the lower right hand side of the screen.
Getting your position
This program will show the current GPS coordinates of your programming block's position in the world.
public void Main() { var pos = Me.GetPosition(); Echo (pos.ToString()); }
Checking a sensor
It's easy to get a sensor to open a door or trigger some other action even without any programming if you just place that action in the sensor's "Setup actions" list. However, triggering an action when a sensor does not detect something is more difficult, and cannot be done with timer blocks. This program will automatically check a sensor every 10 ticks (working out to about 6 times per second) and close a door if the sensor does not detect anything. This can easily be applied to other purposes, like turning off drills when asteroids are not in sensor range.
List<MyDetectedEntityInfo> entity_list = new List<MyDetectedEntityInfo>(); public Program() { Runtime.UpdateFrequency = UpdateFrequency.Update10; //This makes the program automatically run every 10 ticks. } public void Main() { var door_sensor = GridTerminalSystem.GetBlockWithName("Door Sensor 1") as IMySensorBlock; door_sensor.DetectedEntities (entity_list); if (entity_list.Count == 0) { var door = GridTerminalSystem.GetBlockWithName("Door 1") as IMyDoor; door.ApplyAction ("Open_Off"); } }
For this script to work, the sensor must be named "Door Sensor 1" and the door must be named "Door 1". If you configure the sensor to open the door, the door will automatically open when the player enters the sensor range and close when the player leaves the sensor range.
Compilation errors
This is a list (in progress) of known compilation errors and what causes them.
- Method name expected: The compiler found parentheses when it wasn't expecting them. You could be missing a method name before the parentheses, or you might be inappropriately using parentheses instead of square or curly brackets, depending on what you're trying to do.
See also
- MyGridTerminalSystem - Methods for getting object references to your various ship components.
- Programming Guide/Action List - Actions you can apply to objects via the Object.ApplyAction method. Also includes some of the object properties. Data appears incomplete as of March 19th, 2018.
External links
- [Guide] Programmable Block - C# 101 For Space Engineers - Basic intro to C# programming for Space Engineers.
- [Guide] Programmable Block - C# 102 for Space Engineers: Loops, Strings, and Other Things - Basic intro to using loops and strings in C#
- [Guide] Programmable Block - C# 103 for Space Engineers - Math Class - Basic intro to using the Math library in C#
- Programmable Block Inter-Grid Communication Guide - Using antennas to enable programming blocks to remotely communicate with each other.
- Continuous Running No Timers Needed - Configuring programming blocks to run automatically without needing to use a timer.
- Tutorial: Constructor And Save - Saving and reloading data
- C# Operators - C# language reference for all operators, such as and, or, greater than, less than, etc.
- Space Engineers API documentation
- Space Engineers ModAPI Documentation - Includes many API methods and properties which can be used by Programmable Blocks.