Guide to StarCraft II Proto API

Jens Schmidt
Level Up Coding
Published in
6 min readAug 20, 2020

--

Official Artwork by Blizzard Entertainment

This article will take you through the initial steps of writing your own API for the StarCraft II client. This is not required at all, community APIs exist in most popular languages. However, the article provides some insights into how a basic SC2 API wrapper works.

The client exposes a request-response style API that accepts protobuf messages. I wrote an article on the subject of protobuf for readers unfamiliar with the format, but it is essentially just a binary data-interchange format.

Launching the Client

Download the StarCraft II client if you do not already have it installed — it is free to play (since November 14, 2017) and having the full version is not required. We are going to use the default game client but launch it in a special mode. This mode does not feature any in-game menu.

The StarCraft II client creates a new folder when updated (this is presumably mainly to support game replays from older versions) — you might therefore find multiple folders on your computer with a client. Navigate to the one with the highest version number and launch it using localhost and a desired port.

Windows:
On Windows we also need to specify the working directory which is \Support or \Support64. Failing to do so will result in a ‘iccuc52.dll’ does not exist error.

cd 'C:\Program Files (x84)\StarCraft II\'
start /D .\Support .\Versions\Base{version}\SC2.exe -listen 127.0.0.1 -port 8168

Linux:

cd 'StarCraft II\Versions\Base{version}\'
SC2_x64 -listen 127.0.0.1 -port 8168 -headlessNoRender

Mac OS:

cd '/Applications/StarCraft II/Versions/Base{version}/'
open SC2.app --args -listen 127.0.0.1 -port 8168

If this works correctly it will launch the client with a black screen and the iconic StarCraft II mouse — this is the desired behaviour. Everything is good.

The client also supports a few optional arguments that come in handy when running multiple clients at the same time;

  • -displaymode {1/0} … 1 for fullscreen, 0 for window mode
  • -windowwidth {int} … width of window in pixels
  • -windowheight {int} … height of window in pixels
  • -windowx {int} … horizontal placement of window in pixels
  • -windowy {int} … vertical placement of window in pixels

Connecting to the Client

The StarCraft II client will open a web socket on the port you specified when launching the application. Remember to use an available port and to give each client a unique port when launching multiple instances. In our case the absolute URI would read for the API would read:

ws://127.0.0.1:8168/sc2api

You can connect to this socket using the language of your choice and start manipulating the client. The API expects a request message and will respond with a response message. These messages are simply byte arrays which can be interpreted using the official protobuf schema for StarCraft II.

In order to confirm the connection, without having to handle protobuf just yet, the byte array {66,0} can be sent to the client. This corresponds to the binary form of Request { Quit = RequestQuit() } and will make the application shutdown when received. Here is a C# code snippet for achieving this.

using System;
using System.Diagnostics;
using System.Net.WebSockets;
using System.Threading;
namespace AdequateSource {
class StarCraftConnectionExample {
public void LaunchClient() {
// Default folder path for Windows
string folderPath = @"C:\Program Files (x86)\StarCraft II";
var pInfo = new ProcessStartInfo {
// Location of correct AI client
FileName = $ "{folderPath}\\Versions\\Base60321\\SC2.exe",
// Displaymode 0 = windowed mode
Arguments = @"-listen 127.0.0.1 -port 8168 -displaymode 0",
// Give working directory to prevent missing icuin52.dll
WorkingDirectory = $ "{folderPath}\\Support"
};
Process.Start(pInfo);
}
public ClientWebSocket ConnectToClient() {
// URI = ws://{ipaddress}:{port}/sc2api
var uri = new Uri("ws://127.0.0.1:8168/sc2api");
var ws = new ClientWebSocket();
ws.ConnectAsync(uri, CancellationToken.None).Wait();
return ws;
}
public void SendQuit(ClientWebSocket ws) {
// Binary representation of a Quit-Command
var message = new byte[] {66,0};
// Send command to StarCraft II Client
ws.SendAsync(new ArraySegment < byte > (),
WebSocketMessageType.Binary,
true,
CancellationToken.None
);
}
}
}

Client Control Flow

It is beneficial to understand the different states that the client can be in before diving into the specific request/response message.

Simplified state diagram for the StarCraft II client. Diagram by AdequateSource

The client starts in the launched state which allows you to create a game or join an existing game. This corresponds to creating or joining a multiplayer lobby in the regular version of the game.

Joining a game will result in the clients state machine transitioning into in-game mode which is the primary mode. StarCraft II calculates everything in small logical steps under the hood, these are referred to as simulation steps.

The client will, per default, wait for all connected agents to send a step request before advancing the game any further. This pending state is where your agent should request game information, calculate desired actions and submit unit orders to the client. The game will advance once your agent indicate it is ready by sending a step request. This essentially continues until a winner is found.

The game can also be played in real-time mode which simply means the client automatically will advance the simulation. It will run in ‘faster’ game speed, which corresponds to 22.5 simulation steps per second.

The client will transition into the ended state after a winner is found which corresponds to the statistics screen shown after a normal game. From here you need to restart the game (not supported in multiplayer games) or leave.

Generating Protobuf Files

The protobuf message files are generated using protoc. It takes protocol buffers schema files and generate source files with the necessary data models.

Protocol Buffers file generation. Diagram by AdequateSource

There is quite a few ways to obtain protoc, but I found the easiest way is to install protoc, at least in the NET Core universe, is through the nuget package. For other languages refer to this.

dotnet new console
dotnet add package Google.Protobuf.Tools --version 3.13.0

Which will put a pre-compiled version at this location on Windows:

%userprofile%\.nuget\packages\google.protobuf.tools\{version}\tools

…and here for Linux and Mac OS:

~/.nuget/packages/google.protobuf.tools/{version}/tools

Download the StarCraft II proto files and compile them using protoc. This will generate the files you need if using C++, Java and Python.

protoc -I={path} --cpp_output={dir} {path}\s2clientprotocol\sc2api.proto

Upgrading to Proto3 (C#, Dart, Go Requirement)

The StarCraft II API is written in proto2, which is not supported by C#, Dart and Go. In order to use these languages we must first upgrade the proto files to proto3.

  • Remove the optional keyword from all the .proto files as fields are optional by default in proto3.
  • Add a index 0 option, if none exist, to all enums in the .proto files. These will never be used — but it is an requirement in proto3. It is important that you make up a new value and DO NOT change the index of existing ones.
  • Update from syntax = “proto2” to syntax = “proto3”.

These changes upgrades the proto schema to proto3 which allows us to compile it using protoc into C#, Dart or Go.

Conclusion

This should get you past the worst hurdles of writing your own API for StarCraft II. Alternatively you can pick up one of the many pre-made SC2 API wrappers — for example NydusNetwork for .NET Core

Thanks to Timo for Linux corrections.

Originally published at https://adequatesource.com on August 20, 2020.

--

--