System entities

Introduction

System entities are entities that represent data concerning the current state of a running game - for example, entities that represent connected client-worker instances.

All system entities have the improbable.restricted.System component. You can’t create, update, or delete system entities, and worker instances do not gain authority over any components on them. You can only interact with system entities via commands defined in the improbable.restricted package.

System entities can contain sensitive data, such as the unique identifier that confirms that a specific player is who they claim to be. It is important that this data does not end up on external player clients that could be compromised (for example, by malicious parties trying to break a game or impersonate other players).

For these reasons:

You need to use version 13.7.0 or later of the SpatialOS SDK to interact with or read data from system entities. If you’re on an earlier SDK version, you can view them in the Inspector, but not interact with or read data from them from worker instances.

Accessing data about system entities

You can access data about system entities:

  • in the Inspector
  • using query-based interest. Make sure that you trust all worker instances that have the permission to gain authority over the improbable.Interest component.
  • using queries. Queries have an existing permission system to determine which queries are permitted by each worker type, so you can make sure that your player clients can't use queries to access system entity data.

Types of system entity

There is currently only one type of system entity: a worker entity.

Worker entities

Worker entities are entities that represent a worker instance that is interacting with a deployment.

The structure of a worker entity looks like this (populated with dummy data):

[Entity] 
	[improbable.restricted.System]
	[improbable.restricted.Worker]
		worker_id = “MyGameClient-1234
		worker_type = “GameClient”
		connection
			connected_since_utc = 1553868663
	[improbable.Position]
		position = (1.0, 2.0, 3.0)
	[improbable.EntityAcl]
		read = {{“ServerWorker”}, {“PlayerManagementWorker”}}
		write = {{{}}}

If the worker instance corresponds to a player, its corresponding worker entity has an additional component:

[improbable.restricted.PlayerClient]
		player_identity = “Player12345”
		provider = “myauthenticationprovider.com”
		metadata = 0x6f70617175652064617461

Client-worker entities won't have the improbable.restricted.PlayerClient component if you’re using the deprecated authentication flow.

For information about the components that make up a system entity, see the schema library documentation on system (restricted) components.

Worker entity fields

Component: improbable.restricted.Worker

Fields:

  • worker_id: The worker ID that this worker instance connected with.
  • worker_type: The worker type of this worker instance.
  • connected_since_utc: This represents the time at which the Runtime received a connection from the worker instance. The time is epoch time in milliseconds. If the worker instance is not connected, the value is 0.

Component: improbable.Position

Fields:

  • position: This is a rough approximation of the center of the worker instance’s area of authority in the world. You shouldn’t depend on this value for gameplay, but it’s helpful to visualize in the Inspector.
    If the worker instance does not have write access authority over any components on any entities (and therefore has no area of interest), then the position is not meaningful, and defaults to the center of the world.

Component: improbable.EntityAcl

Fields:

  • read: The read field of the EntityAcl component. This is configured such that all worker instances with the permission to make commands to system entities have read access to this entity.
  • write: The write field of the EntityAcl component. This will never contain any entries.

Component: improbable.restricted.PlayerClient

Fields:

  • player_identity: The contents of this component correspond exactly to the fields set in the player login request.
  • provider: The authentication provider used in the player login request.
  • metadata: Optional additional data supplied during the login process. Corresponds to a field in the PlayerIdentityToken. See the API documentation for Metadata, under CreatePlayerIdentityTokenRequest > Properties.

Worker entity lifecycle

  1. The Runtime creates a worker entity when the worker instance that it represents has connected to the deployment.
  2. When the worker instance connects, the worker connection state becomes CONNECTED.
  3. When the worker instance disconnects, for example because it crashes or the connection closes, the Runtime deletes the worker entity.

Interacting with client-worker entities

You can send a command to disconnect a client-worker entity’s underlying worker instance. This is useful if, for example, you need to remove cheating players from your game, or you need to disconnect all players so you can carry out maintenance.

You do this by issuing the disconnect entity command against the worker entity that corresponds to the relevant worker instance.

GDK for Unreal

If you're using the GDK for Unreal, the following code sample does not apply to you. For information about entities in the GDK for Unreal, see the Entity glossary entry in the GDK documentation.

For example:

public static void DisconnectPlayer(string playerWorkerId, Connection connection, Dispatcher dispatcher) 
{
    // Find the system entities for all the worker instances in the game world.
    var query = new Improbable.Worker.Query.EntityQuery{
        Constraint = new Improbable.Worker.Query.ComponentConstraint(Improbable.Restricted.Worker.ComponentId),
        ResultType = new Improbable.Worker.Query.SnapshotResultType()
        };

    // Register a callback to handle the entity query response. 
    dispatcher.OnEntityQueryResponse(op =>
    {
        if (op.StatusCode == StatusCode.Success) 
        {
            // Search through the results of the query for the entity which has a Worker component with a workerId equal to playerWorkerId.
            foreach(var result in op.Result)
            {
                var entityId = result.Key;
                var entity = result.Value;
                var workerComponentData = (Improbable.Restricted.Worker.Data) entity.Get<Improbable.Restricted.Worker>().Value;
                if (workerComponentData.Value.workerId == playerWorkerId) 
                {
                    // Issue a command to disconnect the player.
                    connection.SendCommandRequest(entityId, new Improbable.Restricted.Worker.Commands.Disconnect.Request(), 1000 /* timeout */);
                }
            }
        }
    });

    // Register a callback to handle the disconnect command response.
    dispatcher.OnCommandResponse<Improbable.Restricted.Worker.Commands.Disconnect>(op =>
    {
        // Logic to be executed on command completion.
    });

    // Send the entity query.
    connection.SendEntityQueryRequest(query, 1000 /* timeout */);
}

This command can only succeed if the worker instance that issues it is of a worker type that has permission to send the command. This permission is included in the all permission, or you can configure it separately using the system_entity_command permission.

Updated about a year ago


System entities


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.