» Programmable Blocks and Visual Studio

The Programmable Block

I’ve been playing Space Engineers a lot recently — for some definition of “playing”, anyway.  Space Engineers has an in-game programmable block that allows you to code to interact with objects in the game. A significant chunk of my game time has been spent either staring at one of these things, or standing aimlessly in game while reading documentation.

Two versions of the Programmable Block in Space Engineers
Two models of Programmable Block. On the left is the stock model found in the game, and on the right is a spruced up version from the workshop.

While the programmable blocks add some great functionality, the experience is…. unideal.  The default model for the block looks like a mainframe was accidentally teleported out of the 1980s and into a space station. Unfortunately, the UI you’re presented with to edit code looks like it’s a few decades out of time as well. It’s also full of fun little quirks: opening the Steam overlay to use the in-game browser will insert a tab into your code if you use the default shortcut (shift+tab), and alt+tabbing out of the game and back in again seems to revert the code to the last saved state. SE is still in early access so there’s a lot of time for all the bugs and quirks to be ironed out, but that doesn’t stop it being rage inducing as it stands now.

Window in Space Engineers showing a text editor containing code
The in-game code editor.

The biggest problem, though, is that the code editor is just a text editor. There’s no syntax highlighting, no code completion, and the only way to find out about errors is to try to compile it and read the results in a pop-up window. As someone used to the creature comforts of an IDE, it’s not a fun experience.

The obvious solution is to use an actual IDE to do the development, and simply copy the scripts into the game once they’re ready to be tested. The scripts are written in C#, and there’s this little IDE with good C# support called Visual Studio, so why don’t we give that a try? There are a few guides out there already, but most seem to be outdated or unnecessarily complicated.  After a bit of trial and error, I present a five-step guide for the latest-and-greatest versions of SE (01.110) and VS (2015).

Setting up Visual Studio

  1. If you don’t have it, go and get Visual Studio 2015 Community Edition. It’s free, and more than featureful enough for SE scripting purposes.
  2. Create a new C# project in Visual Studio. Select Class Library, and pick a name for the project, a location on disk, and a name for the overall solution.
  3. In the Solution Explorer, right-click on the References node, and select ‘Add Reference…’
  4. Select ‘Browse’ and navigate to the Bin directory in the main Space Engineers install. That should be %SteamDirectory% > steamapps > common > SpaceEngineers > Bin.
  5. Select the following DLLs, click “Add”, then “OK”.
    • Sandbox.Common.dll
    • Sandbox.Game.dll
    • VRage.Game.dll
    • VRage.Library.dll
    • VRage.Math.dll

You can now access all of the classes available to the in game scripting API. The code you write in-game extends from a base class, though… It’d be helpful if we could replicate that in VS.

Creating a base class

Scripts in the Programmable Blocks all extend from an implementation of IMyGridProgram. This provides a number of useful properties including access to the GridTerminalSystem, through which you interact with the rest of the game. We won’t be writing very interesting scripts without that.

To create a skeleton script in VS, create a new class and have it implement IMyGridProgram. Visual Studio can then stub out all of the implementations and you end up with something like this:

using System;

using Sandbox.ModAPI.Ingame;
using Sandbox.ModAPI;

namespace Skeleton
{
    public abstract class Skeleton : IMyGridProgram
    {
        public Action<string> Echo
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public TimeSpan ElapsedTime
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public IMyGridTerminalSystem GridTerminalSystem
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public bool HasMainMethod
        {
            get { throw new NotImplementedException(); }
        }

        public IMyProgrammableBlock Me
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public string Storage
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        void IMyGridProgram.Main(string argument)
        {
            throw new NotImplementedException();
        }
    }
}

Your scripts can now extend from the Skeleton class and Visual Studio will play nicely when you access the properties.

Writing a script

All that’s left is to actually write a script. Create a new class and extend your Skeleton class. Add in the main method, and start writing. When you’re ready to move it over to the game, simply copy everything inside your class and paste it into the programmable block’s editor (i.e., don’t copy the class definition, or anything before it like the namespace or using ines).

Screenshot of code in Visual Studio
The same code as before, now with syntax highlighting and code completion. Bliss.

One final note: because your code is being interpreted as the body of a class, you can’t use ‘using’ statements when using programmable blocks. If you need to access something that the game doesn’t automatically include for you, you’ll need to use a fully-qualified reference. i.e., instead of using System.Text.RegularExpressions and then just referring to Regex, you’ll need to write it out in full as System.Text.RegularExpressions.Regex. Fortunately, Visual Studio can do that for you when you reference a previously unused class.

I’ll try to keep this guide up to date with future VS and SE updates. If you notice anything wrong, please leave a comment.

comments powered by Disqus