196 lines
5.1 KiB
Markdown
196 lines
5.1 KiB
Markdown
# ICOM Usage Guide
|
|
|
|
ICOM is the Forge inter-server communication helper. It lets multiple Arma 3
|
|
servers exchange generic JSON events through a central TCP hub instead of
|
|
connecting directly to each other.
|
|
|
|
## Runtime Shape
|
|
|
|
```text
|
|
Arma server SQF
|
|
-> forge_server extension icom:* command
|
|
-> ICOM client inside the extension
|
|
-> forge-icom TCP hub
|
|
-> target server extension
|
|
-> forge_icom_event CBA server event
|
|
```
|
|
|
|
The ICOM hub lives in `bin/icom`. The Arma server extension integrates with it
|
|
through `arma/server/extension/src/icom.rs`.
|
|
|
|
## Components
|
|
|
|
| Component | Path | Role |
|
|
| --- | --- | --- |
|
|
| ICOM hub binary | `bin/icom` | Standalone TCP router for connected servers. |
|
|
| ICOM client library | `bin/icom/src/client.rs` | Rust client used by the Forge server extension and examples. |
|
|
| Extension command group | `arma/server/extension/src/icom.rs` | Exposes `icom:*` commands to SQF and forwards inbound events to Arma. |
|
|
| SQF callback bridge | `arma/server/addons/main/XEH_preInit.sqf` | Receives extension callbacks and re-emits `forge_icom_event` through CBA. |
|
|
|
|
## Build and Run the Hub
|
|
|
|
Build the release binary:
|
|
|
|
```powershell
|
|
cargo build --release -p forge-icom
|
|
```
|
|
|
|
Run it during development:
|
|
|
|
```powershell
|
|
cargo run -p forge-icom
|
|
```
|
|
|
|
The default bind address is `0.0.0.0:9090`.
|
|
|
|
## Hub Configuration
|
|
|
|
Copy `bin/icom/config.example.toml` to `config.toml` beside the `forge-icom`
|
|
executable or into the working directory used to launch it.
|
|
|
|
```toml
|
|
[server]
|
|
host = "0.0.0.0"
|
|
port = 9090
|
|
```
|
|
|
|
Use `127.0.0.1` for same-machine testing. Use `0.0.0.0` when remote Arma
|
|
servers need to connect, and secure the port at the firewall or host network
|
|
layer.
|
|
|
|
## Extension Commands
|
|
|
|
ICOM commands are exposed through the `icom` command group in `forge_server`.
|
|
|
|
| Command | Arguments | Returns |
|
|
| --- | --- | --- |
|
|
| `icom:connect` | `address`, `server_id` | `Connection initiated` or `ERROR: Already connected`. |
|
|
| `icom:send_event` | `target_server`, `event_name`, `data_json` | `OK` or `ERROR: <reason>`. |
|
|
| `icom:broadcast` | `event_name`, `data_json` | `OK` or `ERROR: <reason>`. |
|
|
|
|
The current extension connects when `icom:connect` is called. Start the ICOM hub
|
|
first, then connect each Arma server with a unique `server_id`.
|
|
|
|
```sqf
|
|
private _result = "forge_server" callExtension [
|
|
"icom:connect",
|
|
["127.0.0.1:9090", "server_1"]
|
|
];
|
|
diag_log format ["[ICOM] Connect result: %1", _result select 0];
|
|
```
|
|
|
|
## Send an Event
|
|
|
|
Send a targeted event to one connected server:
|
|
|
|
```sqf
|
|
private _data = createHashMapFromArray [
|
|
["coords", [1234, 5678, 0]],
|
|
["supplies", ["ammo_box", "medical_supplies"]]
|
|
];
|
|
|
|
"forge_server" callExtension [
|
|
"icom:send_event",
|
|
["server_2", "supply_drop", toJSON _data]
|
|
];
|
|
```
|
|
|
|
Broadcast to every connected server except the sender:
|
|
|
|
```sqf
|
|
private _alert = createHashMapFromArray [
|
|
["message", "Server restart in 5 minutes"],
|
|
["severity", "warning"]
|
|
];
|
|
|
|
"forge_server" callExtension [
|
|
"icom:broadcast",
|
|
["global_alert", toJSON _alert]
|
|
];
|
|
```
|
|
|
|
## Receive Events
|
|
|
|
Inbound ICOM events are forwarded to SQF as the CBA server event
|
|
`forge_icom_event`.
|
|
|
|
```sqf
|
|
["forge_icom_event", {
|
|
params ["_eventName", "_data"];
|
|
|
|
switch (_eventName) do {
|
|
case "supply_drop": {
|
|
private _coords = _data getOrDefault ["coords", []];
|
|
private _supplies = _data getOrDefault ["supplies", []];
|
|
diag_log format ["[ICOM] Supply drop at %1: %2", _coords, _supplies];
|
|
};
|
|
case "global_alert": {
|
|
private _message = _data getOrDefault ["message", ""];
|
|
if (_message isNotEqualTo "") then {
|
|
[_message] remoteExec ["hint", 0];
|
|
};
|
|
};
|
|
default {
|
|
diag_log format ["[ICOM] Unhandled event: %1 | %2", _eventName, _data];
|
|
};
|
|
};
|
|
}] call CBA_fnc_addEventHandler;
|
|
```
|
|
|
|
## Message Protocol
|
|
|
|
The hub uses newline-delimited JSON. The first message from each client is a
|
|
registration payload:
|
|
|
|
```json
|
|
{
|
|
"type": "register",
|
|
"server_id": "server_1"
|
|
}
|
|
```
|
|
|
|
Targeted events use `type: "event"`:
|
|
|
|
```json
|
|
{
|
|
"type": "event",
|
|
"target_server": "server_2",
|
|
"event_name": "supply_drop",
|
|
"data": {
|
|
"coords": [1234, 5678, 0]
|
|
}
|
|
}
|
|
```
|
|
|
|
Broadcasts use `type: "broadcast"` and are routed to all connected servers
|
|
except the sender.
|
|
|
|
## Operational Notes
|
|
|
|
- Server IDs must be unique. If the same ID reconnects, the hub replaces the old
|
|
connection.
|
|
- Event names are mission/application contracts. ICOM only routes them; it does
|
|
not validate gameplay meaning.
|
|
- Always send valid JSON in the `data_json` argument.
|
|
- `icom:send_event` and `icom:broadcast` return quickly after scheduling async
|
|
work in the extension. Check extension and ICOM hub logs for delivery errors.
|
|
- Keep event payloads small and stable. Use IDs or compact data where possible.
|
|
|
|
## Testing
|
|
|
|
Start the hub:
|
|
|
|
```powershell
|
|
cargo run -p forge-icom
|
|
```
|
|
|
|
Run example clients in separate terminals:
|
|
|
|
```powershell
|
|
cargo run -p forge-icom --example server_1_client
|
|
cargo run -p forge-icom --example server_2_client
|
|
```
|
|
|
|
For Arma testing, start the hub, connect the server with `icom:connect`, register
|
|
a `forge_icom_event` handler, then send an event from another connected server.
|