# Messages

Messages in comms are binary data *packets*, serialized using [protocol buffers](https://github.com/protocolbuffers/protobuf). They carry text and voice chat, positional updates, profile changes and other real-time interactions.

{% hint style="info" %}
You can see the comms protocol in action and experiment with it using the open-source [Comms Station](https://decentraland.github.io/comms-station/).
{% endhint %}

All message definitions are available in the [protocol repository](https://github.com/decentraland/protocol), and each message type below has a link to its declaration.

**`Packet`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L8)

The `Packet` structure is the container for all messages.

| Field     | Type   | Value                                                                                                                                                                                                 |
| --------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `message` | `enum` | <p>One of <code>Chat</code>, <code>Voice</code>, <code>Position</code>, <code>AnnounceProfileVersion</code>,<br><code>ProfileRequest</code>, <code>ProfileResponse</code>, or <code>Scene</code>.</p> |

### Text and Voice Chat

Clients chat by broadcasting text messages and audio clips to all connected peers (usually players in the same island).

Only two `Packet` types are involved, one for each use-case. Under typical circumstances, clients broadcast these messages to all other clients in their island, which is the group of nearby players they can interact with.

***

**`Chat`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L56)

Sends a text chat message to other clients.

| Field       | Type     | Value                  |
| ----------- | -------- | ---------------------- |
| `message`   | `string` | Text of the message    |
| `timestamp` | `double` | Sender's UTC timestamp |

***

**`Voice`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L66)

Sends an encoded voice sample to other clients.

| Field             | Type     | Value                                                  |
| ----------------- | -------- | ------------------------------------------------------ |
| `encoded_samples` | `bytes`  | Encoded audio data                                     |
| `codec`           | `enum`   | Only `VC_OPUS` (no other codecs are supported for now) |
| `index`           | `uint32` | An incremental counter set by the sender               |

The `codec` field is an `enum` value. Custom codecs are not supported.

### Movement

Clients that control avatars send and receive positional updates within their island, in order to synchronize movement and posture among players.

***

**`Position`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L20)

Updates other clients on the position and orientation of an avatar.

| Field                                                                                                               | Type     | Value                                    |
| ------------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------------- |
| <p><code>position\_x</code><br><code>position\_y</code><br><code>position\_z</code></p>                             | `float`  | Avatar position in the world map         |
| <p><code>rotation\_x</code><br><code>rotation\_y</code><br><code>rotation\_z</code><br><code>rotation\_w</code></p> | `float`  | Avatar rotation quaternion               |
| `index`                                                                                                             | `uint32` | An incremental counter set by the sender |

Clients typically send `Position` updates with a low frequency (such as once every 1 or 2 seconds), and switch to a high frequency (several times per second) when moving or interacting.

{% hint style="info" %}
When sending positional updates, speed is usually better than reliability. The perceived performance is better when delivery is faster, even if a `Position` message is ocasionally dropped or reordered. Some transports (e.g. [LiveKit](https://github.com/decentraland/docs/blob/main/contributor/communications/transport-types/livekit/README.md)) can change between fast and reliable modes on a per-message basis.
{% endhint %}

The low-frequency broadcasts are recommended as a simple solution for deliverying updates to clients that momentarily lost connectivity or failed to catch a message while they joined the island.

The `index` field is an incremental counter, set by the sender so receivers can sort updates that arrive out-of-order.

### Profile Sharing

Clients within an island can request the avatar information of other players, in order to render their avatars, display their names and pictures, etc.

Since profiles changes are rare (compared with positional updates, for example), the system is designed to simplify the task of maintaining a local profile cache, and only fetch profiles when needed.

There's 3 [`Packet`](#Packet) types involved: a [`ProfileRequest`](#ProfileRequest)/[`ProfileResponse`](#ProfileResponse) pair used by clients to share profiles on demand, and the [`AnnounceProfileVersion`](#AnnounceProfileVersion) message to tell peers what the latest version is, so they can decide whether to request it.

Clients typically broadcast `AnnounceProfileVersion` messages periodically, plus immediately when their profile changes.

{% @mermaid/diagram content="sequenceDiagram
participant Client1 as Client 1
participant Client2 as Client 2
participant Client3 as Client 3

```
Note over Client1: Broadcast profile version
Client1->>Client1: AnnounceProfileVersion(v1)
Client1->>Client1: AnnounceProfileVersion(v1)

Note over Client3: Request profile
Client3->>Client1: ProfileRequest(@client 1)
Client1->>Client3: ProfileResponse(v1)

Client1->>Client1: AnnounceProfileVersion(v1)

Note over Client1: Profile updated
Client1->>Client1: AnnounceProfileVersion(v2)

Note over Client2,Client3: Multiple clients request
Client2->>Client1: ProfileRequest(@client 1)
Client3->>Client1: ProfileRequest(@client 1)
Client1->>Client2: ProfileResponse(v2)
Client1->>Client3: ProfileResponse(v2)" %}
```

***

**`AnnounceProfileVersion`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L34)

Signals other clients that there's a [profile entity](https://github.com/decentraland/docs/blob/main/contributor/content/entity-types/profiles/README.md) they can request.

| Field             | Type     | Value                                                 |
| ----------------- | -------- | ----------------------------------------------------- |
| `profile_version` | `uint32` | A version number incremented with every modification. |

Receivers that cache profiles can use the `profile_version` number to decide whether their local copy is up-to-date, or if they need to send a [`ProfileRequest`](#ProfileRequest).

***

**`ProfileRequest`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L41)

Requests a profile of a specified version from a particular peer.

| Field             | Type     | Value                                    |
| ----------------- | -------- | ---------------------------------------- |
| `address`         | string   | The identifying address for the profile. |
| `profile_version` | `uint32` | The wanted profile version.              |

Receivers can reply with [`ProfileResponse`](#ProfileResponse) messages to provide the requested profile.

***

**`ProfileResponse`** [**↗ source**](https://github.com/decentraland/protocol/blob/c48ea0aa00d8173084571552463a6a05a7f49636/proto/decentraland/kernel/comms/rfc4/comms.proto#L46)

Sends a profile in response to a [`ProfileRequest`](#ProfileRequest).

| Field                | Type     | Value                                                          |
| -------------------- | -------- | -------------------------------------------------------------- |
| `serialized_profile` | string   | JSON-serialized profile entity.                                |
| `base_url`           | `uint32` | base URL for a filesystem endpoint, recommended by the sender. |

The `serialized_profile` field contains the JSON serialization of a [profile entity](https://github.com/decentraland/docs/blob/main/contributor/content/entity-types/profiles/README.md).

If the sender wants to recommend a content server to download entities referenced in their profile (such as wearables), it can set the `base_url` field as a hint. Clients are free to use or ignore this URL.
