This article assumes that you are developing in .NET Core and intend to use the NydusNetwork wrapper. I have attempted to front-load the article with general applicable knowledge such that it can provide value to users of other solutions too.


Message Types

The StarCraft II API includes quite a few messages. They are all wrapped in the request message, so that is the only message you will ever send – and the client will respond with response message which wraps all the possible responses.

The basic flow of request sent to the client.

The diagram showcase a simply request message flow of an agent. These are the only necessary requests (step can even be omitted in realtime mode) to create a functioning bot – but it is beneficial to have basic understanding of all types;

  • CreateGame
    Setup a new game, equivalent to creating a lobby in the regular game. This message can only be sent in the launched state or ended state.
    - Disable fog, if off will allow your bot to see everything (no fog of war).
    - Realtime, tell the client not to wait for StepRequest to advance the game.
    - PlayerSetup, list of race and 'type' (AI or Blizzard AI) of each player.
    - LocalMap, path to game map to play OR
    - BattlenetMapName, name of official SC2 map
  • JoinGame
    Starts the game you are hosting or joins another host. This message contains your InterfaceOptions where you tell the client what information your agent needs. What is referred to as raw is a representation of the game state as a list of visible units, tiles, etc. which is easy (for a computer) to interpret. It equates to being able to see the entire map at once – which a human components would never be able to do. The alternative is feature layers – the game state represented through multiple color-coded images that more closely resemble the information available to a human (meant for Machine Learning).
  • RestartGame
    Empty message that tell the game to restart with the same settings as last game. This only works for single player games (against Blizzard AI) and requires that the client is in the game ended state.
  • StartReplay
    Allows you to watch a recorded match. Useful for machine learning.
  • LeaveGame
    Empty message that leaves the match.
  • QuickSave
    Empty messages that quick saves.
  • QuickLoad
    Empty messages that loads previous quick save.
  • Quit
    Empty message that closes the client (gracefully). Applies in all states.
  • GameInfo
    Request that the client transfer game info which is meta data about the current game being played. Players, interface options, name of the map. It also contains StartRaw which is important when using the raw API as the terrain map and placement grid is included here.
  • Observation
    Empty message that request a game observation – this is where the entire game state is being transferred based on the settings you applied in JoinGame.
  • Action
    Message that includes a list of actions. This is how your agent will interact with the actual game. Move a unit, build a unit, use ability - it's all an action.
  • ObserverAction
    Actions that an observer can apply (non-player).
  • Step
    Ask the client to advance the game simulation with x steps. The client will per default wait for this message before advancing the game, unless playing in realtime which can be configured in CreateGame.
  • Data
    Request SC2 data on abilities, buffs, damage modifiers, units, upgrades and weapons. This includes info like unit cost and health – it is available through the API as Blizzard often tweaks these values. They can beneficially be cached for each version of the game.
  • Query
    Request info on pathing, available abilities and building placement.
  • SaveReplay
    Save the game as a replay – can be done in-game or in ended state.
  • ReplayInfo
    Load meta data about replay.
  • AvailableMaps
    Get a list of available maps. This list can be empty if your client has never downloaded the map. Download it manually or force it by creating a game using the regular client on the map you want.
  • SaveMap
    Save the map data to a local path.
  • MapCommand
    Manually execute a map trigger.
  • Ping
    Well... surprisingly not a true ping message. The client responds with game version, data version, data build version and base build version.
  • Debug
    Execute a list of DebugCommand which allows you to draw on screen or manipulate the game by spawning units, killing units, updating their values etc.

Installing an API wrapper

Using an API wrapper saves you a lot of hassle – a lot! This section assumes that you are writing in .NET Core and wish to use NydusNetwork as your API wrapper, but you can find many alternatives in other languages here. You can also always write your own from scratch, in which case this guide might prove useful;

[adq_src] S2Client-Proto
Introduction to the official StarCraft II API - a request/response message system in protocol buffers.

NydusNetwork is a StarCraft II API wrapper written in .NET Core that was created as part of the Abathur framework, but has been written as a separate component that can be used independently of Abathur. I recommend cloning SC2Abathur if you intend to opt for the full framework experience – it comes pre-installed there.

Alternatively, to proceed without Abathur, simply install it using the nuget package manager and start using it in your custom bot. This is the approach I will assume you chose as Abathur encapsulates NydusNetwork.

Install-Package NydusNetwork
Install NydusNetwork through Package Manager console
dotnet add package NydusNetwork
Install NydusNetwork through dotnet CLI

Using NydusNetwork

Importing NydusNetwork.Model gives you access to all message types supported by the official StarCraft II API. The most basic usage of the NydusNetwork is simply using the SendRequest(Request r) to send raw messages to the client.

using NydusNetwork;

namespace AdequateSource
{
  class Example
  {
    void QuitGame(GameClient client)
      => client.QuitRequest();
  }
}

Basically all API wrappers will give you this direct raw interface to the client, but NydusNetwork comes with a few extra features than a thin API wrapper.

Shorthands

The most basic of these is shorthands for empty request. The API includes quite a few empty request messages, so it allows us to clean up the code a bit.

using NydusNetwork;

namespace AdequateSource
{
  class Example
  {
    void QuitGame(GameClient client)
      => client.QuitRequest();
  }
}


Complete Game Initialisation

NydusNetwork also aids in game creation. The initialise method will connect to the client based on the supplied settings – and launch it if an the client application is not running. After connection is confirmed simply called CreateGameRequest() and JoinGameRequest() and you are up and running. Local multiplayer (bot vs bot) is also supported by these methods.

using NydusNetwork;
using NydusNetwork.API.Protocol;
using NydusNetwork.Model;
using System.Collections.ObjectModel;

namespace AdequateSource
{
  class Example
  {
    void Initilize() {
      var client = new GameClient(
        new GameSettings
        {
          FolderPath = @"C:\Program Files (x86)\StarCraft II",
          ConnectionAddress = "127.0 0.1",
          ConnectionServerPort = 8165,
          ConnectionClientPort = 8170,
          MultiplayerSharedPort = 8175,
          InterfaceOptions = new InterfaceOptions {
            Raw = true, Score = true
          },
          Fullscreen = false,
          ClientWindowWidth = 1024,
          ClientWindowHeight = 768,
          GameMap = "Cloud Kingdom LE",
          Realtime = false,
          DisableFog = false,
          ParticipantRace = Race.Random,
          Opponents = new Collection<PlayerSetup> {
            new PlayerSetup {
              Type = PlayerType.Computer,
              Race = Race.Random,
              Difficulty = Difficulty.VeryEasy
            }
          }
        }
      );
      client.Initialize(asHost: true);
      client.CreateGameRequest();
      client.JoinGameRequest();
    }
  }
}


Getting a Response

Two ways of getting a response from the client are supported. The simplest is TryWait{Type}Request where you block execution flow until the request is received or fails. This method supports optional timeouts.

The second method is by registering a handler that listens to specific response types. The handler will be called each time that type of response is received until you deregister the handler. This is how the TryWait{Type}Request is implemented behind the scene.

using NydusNetwork;
using NydusNetwork.API.Protocol;
using System;

namespace AdequateSource
{
  class Example
  {
    void Ping(GameClient client) {
      if (client.TryWaitPingRequest(out var r, wait: 3000))
        Console.WriteLine(r.Ping.GameVersion);
    }

    void ListenForPing(GameClient client)
    {
      var action = new Action<Response>(r => {
        Console.WriteLine($"Heard ping! {r.Ping.GameVersion}");
      });
      client.RegisterHandler(Response.ResponseOneofCase.Ping, action);
    }
  }
}

Why Handlers?

The client is not a neat little rest API that answers when you call it, it is a web socket that answers you when it please. Some requests will not be answered immediately by the client. The StepRequest for example is answered once the client has received it from everyone in the game – which in single-player means immediately, but in multiplayer can be whenever.

Improvised diagram of web socket stream.

This means that requests might not receive responses in the same order. The client does however make sure to handle requests of the same type sequentially so ActionsRequests for example will always be processed in order (the alternative could alternate the game). Note that multiple actions for the same unit will override it's action – so the most important one has to be the last.