---
title: "Phone Usage Guide"
description: "The phone module stores contacts, messages, and emails for each UID. It is a server-extension state module backed by SurrealDB."
---

## Storage Model

```json
{
  "contacts": ["76561198000000000", "field_commander"],
  "messages": [
    {
      "id": "phone-message:sender:receiver:1",
      "from": "sender",
      "to": "receiver",
      "message": "Text body",
      "timestamp": 123.45,
      "read": false
    }
  ],
  "emails": [
    {
      "id": "phone-email:sender:receiver:2",
      "from": "sender",
      "to": "receiver",
      "subject": "Subject",
      "body": "Email body",
      "timestamp": 123.45,
      "read": false
    }
  ]
}
```

Rules validated by the Rust service:

- UID arguments cannot be empty.
- Message and email bodies cannot be empty.
- Empty email subjects become `No subject`.
- Player messages and emails cannot target `field_commander`.
- `field_commander` can send messages or emails to players.
- Deleting a message or email removes it only from the requesting UID's index.

## Commands

| Command | Arguments | Returns |
| --- | --- | --- |
| `phone:init` | `uid` | Full phone payload. |
| `phone:contacts:list` | `uid` | Contact UID array. |
| `phone:contacts:add` | `uid`, `contact_uid` | `true` or `false`. |
| `phone:contacts:remove` | `uid`, `contact_uid` | `true` or `false`. |
| `phone:messages:list` | `uid` | Message array. |
| `phone:messages:thread` | `uid`, `other_uid` | Message array for both participants. |
| `phone:messages:send` | `from_uid`, `to_uid`, `message`, `timestamp` | Message JSON. |
| `phone:messages:mark_read` | `uid`, `message_id` | `true` or `false`. |
| `phone:messages:delete` | `uid`, `message_id` | `true` or `false`. |
| `phone:emails:list` | `uid` | Email array. |
| `phone:emails:send` | `from_uid`, `to_uid`, `subject`, `body`, `timestamp` | Email JSON. |
| `phone:emails:mark_read` | `uid`, `email_id` | `true` or `false`. |
| `phone:emails:delete` | `uid`, `email_id` | `true` or `false`. |
| `phone:remove` | `uid` | `OK`. |

## Initialize Phone State

`phone:init` creates phone state if needed and seeds self-contact plus
`field_commander`.

```sqf
private _result = "forge_server" callExtension ["phone:init", [getPlayerUID player]];
private _payload = _result select 0;

if (_payload find "Error:" == 0) exitWith {
    systemChat format ["Phone init failed: %1", _payload];
};

private _phone = fromJSON _payload;
```

## Send a Message

```sqf
private _timestamp = str diag_tickTime;

private _result = "forge_server" callExtension ["phone:messages:send", [
    getPlayerUID player,
    _targetUid,
    "Move to checkpoint Alpha.",
    _timestamp
]];
```

## Read a Conversation

```sqf
private _result = "forge_server" callExtension ["phone:messages:thread", [
    getPlayerUID player,
    _otherUid
]];

private _messages = fromJSON (_result select 0);
```

## Send an Email

```sqf
private _result = "forge_server" callExtension ["phone:emails:send", [
    getPlayerUID player,
    _targetUid,
    "Supply Request",
    "Requesting resupply at grid 123456.",
    str diag_tickTime
]];
```

## Mark and Delete Records

```sqf
"forge_server" callExtension ["phone:messages:mark_read", [
    getPlayerUID player,
    _messageId
]];

"forge_server" callExtension ["phone:emails:delete", [
    getPlayerUID player,
    _emailId
]];
```

## Error Handling

```sqf
private _payload = (_result select 0);
if (_payload find "Error:" == 0) then {
    systemChat format ["Phone error: %1", _payload];
};
```
