Try SpatialOS

Sites

Menu
These are the docs for 12.2, an old version of SpatialOS. 13.2 is the newest →

Generated code

All code examples in this section assume you have defined a MyComponents function as described in Providing components, and set up the following preamble:

#include <improbable/standard_library.h>
#include <improbable/worker.h>
#include <example.h>

using namespace improbable;

The C++ schema-generated code consists of two main parts: data classes and component classes.

Data classes

Data classes are used to represent data at rest and correspond to the schemalang type definitions.

A data class is generated for each type defined in the schema, with fields corresponding to each field in the schema definition.

Data representation

  • Strings are represented as UTF-8 encoded std::string members. Make sure to use this same encoding when updating a component.
  • list<T> fields are represented as a worker::List<T> of the repeated type. This type is very similar to std::vector<T> and has most of the methods you’d expect.
  • map<Key, Value> fields are represented as worker::Map<Key, Value>. This type is very similar to std::unordered_map<Key, Value> and has most of the methods you’d expect.

    The biggest difference is it has a well-defined iteration order, which is insertion order.

  • option<T> fields are represented as worker::Option<T>. First, check if the option contains a value with !option.empty() or if (option) { ... }, then dereference the option to access the contained value. This type is very similar to the std::optional<T> type introduced in C++17.

Component classes

Component classes correspond to schemalang component definitions and contain metadata and classes for sending and receiving component data (updates, command requests and command responses).

For each component, we generate:

  • a metaclass.

    These metaclasses are used when referring to specific components when using the API - every template parameter T expects a metaclass argument.

  • an Update class nested inside the metaclass.

    This has an optional field for each field in the component (since it represents a diff).

  • command metaclasses nested inside the metaclass, as SomeComponent::Commands::SomeCommand.

    These work in a similar way to component metaclasses, but for command-related functions.

Example

Given the following simple schema (in package example):

type StatusEffect {
  string name = 1;
  int32 multiplier = 2;
}

component Creature {
  id = 12345;
  int32 health = 1;
  list<StatusEffect> effects = 2;
}

The generated code will contain a data class StatusEffect corresponding to type defined in the schema. For the creature component, a Creature metaclass containing a Creature::Update class will be generated, alongside a CreatureData data class.

The Creature metaclass can be passed as a template parameter to any templated API function, for example to send an update for the creature component. Note that the Creature metaclass is also used with the worker::Entity class (which the View uses to represent entities) to inspect component data “at rest”.

Here are some ways that these classes can be used with the API:

void GeneratedCodeExamples(worker::Connection& connection) {
  worker::Dispatcher dispatcher(MyComponents());

  dispatcher.OnAuthorityChange<example::Creature>([&](const worker::AuthorityChangeOp& op) {
    if (op.Authority == worker::Authority::kAuthoritative) {
      // We were granted authority over the creature component. Send an update.
      example::Creature::Update update;
      update.set_health(10);
      connection.SendComponentUpdate<example::Creature>(op.EntityId, update);
    } else {
      // Authority was revoked.
    }
  });

  dispatcher.OnComponentUpdate<example::Creature>(
      [&](const worker::ComponentUpdateOp<example::Creature>& op) {
        const example::Creature::Update& update = op.Update;
        if (update.effects()) {
          auto effects = update.effects().data();
          for (const auto& effect : *effects) {
            std::cout << op.EntityId << " has effect " << effect.name() << " with multiplier "
                      << effect.multiplier() << std::endl;
          }
        }
      });
}

Search results

Was this page helpful?

Thanks for letting us know!

Thanks for your feedback

Need more help? Ask on the forums