--- 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]; }; ```