feat: Add ICOM usage guide and update related documentation
This commit is contained in:
parent
264559306d
commit
3cadcce32a
@ -40,4 +40,5 @@ For install links and Forge-specific setup steps, see
|
||||
|
||||
- [API Reference](./api-reference.md)
|
||||
- [Usage Examples](./usage-examples.md)
|
||||
- [ICOM Usage Guide](../../../docs/ICOM_USAGE_GUIDE.md)
|
||||
- [Framework Module Guides](../../../docs/README.md)
|
||||
|
||||
@ -27,6 +27,7 @@ Game systems should call the domain APIs instead of raw database operations:
|
||||
- `store:*`
|
||||
- `task:*`
|
||||
- `cad:*`
|
||||
- `icom:*`
|
||||
- `owned:garage:*`
|
||||
- `owned:locker:*`
|
||||
- `transport:*`
|
||||
@ -47,3 +48,4 @@ needed by `forge_server_addons_extension_fnc_extCall`.
|
||||
- [Phone](../../../docs/PHONE_USAGE_GUIDE.md)
|
||||
- [Store](../../../docs/STORE_USAGE_GUIDE.md)
|
||||
- [Task](../../../docs/TASK_USAGE_GUIDE.md)
|
||||
- [ICOM](../../../docs/ICOM_USAGE_GUIDE.md)
|
||||
|
||||
@ -212,7 +212,7 @@ client.listen_for_events(|msg| {
|
||||
|
||||
The Forge server extension includes full ICOM integration:
|
||||
|
||||
1. **Initialization**: Connects to ICOM on extension startup (or manually via `icom:connect`)
|
||||
1. **Initialization**: Connect with `icom:connect` after the ICOM hub is running.
|
||||
2. **Event Listener**: Spawns background task to receive events continuously
|
||||
3. **Callback System**: Forwards events to Arma via CBA event handlers
|
||||
4. **Extension Commands**: Provides SQF commands to send/receive events
|
||||
@ -221,7 +221,7 @@ The Forge server extension includes full ICOM integration:
|
||||
|
||||
- The extension uses `try_read()` to avoid deadlocks when accessing context from async tasks
|
||||
- Broadcast events are **not** sent back to the originating server
|
||||
- Connection can be initiated manually if automatic startup connection fails
|
||||
- Connection is initiated through the `icom:connect` extension command.
|
||||
|
||||
### SQF Usage
|
||||
|
||||
|
||||
195
docs/ICOM_USAGE_GUIDE.md
Normal file
195
docs/ICOM_USAGE_GUIDE.md
Normal file
@ -0,0 +1,195 @@
|
||||
# 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.
|
||||
@ -203,7 +203,7 @@ See [Owned Storage Usage Guide](./OWNED_STORAGE_USAGE_GUIDE.md) for examples.
|
||||
| Command Group | Purpose |
|
||||
| --- | --- |
|
||||
| `store:checkout` | Run store checkout behavior. |
|
||||
| `icom:connect`, `icom:broadcast`, `icom:send_event` | ICom connection and event forwarding. |
|
||||
| `icom:connect`, `icom:broadcast`, `icom:send_event` | ICOM connection and event forwarding. See [ICOM Usage Guide](./ICOM_USAGE_GUIDE.md). |
|
||||
| `terrain:exportSVG` | Export terrain data as SVG. |
|
||||
| `transport:invoke`, `transport:invoke_stored` | Invoke commands through transport. |
|
||||
| `transport:request:append`, `transport:request:clear` | Manage stored request chunks. |
|
||||
|
||||
@ -23,6 +23,7 @@ collects framework-level documentation for those pieces.
|
||||
- [CAD Usage Guide](./CAD_USAGE_GUIDE.md)
|
||||
- [Economy Usage Guide](./ECONOMY_USAGE_GUIDE.md)
|
||||
- [Garage Usage Guide](./GARAGE_USAGE_GUIDE.md)
|
||||
- [ICOM Usage Guide](./ICOM_USAGE_GUIDE.md)
|
||||
- [Locker Usage Guide](./LOCKER_USAGE_GUIDE.md)
|
||||
- [Organization Usage Guide](./ORG_USAGE_GUIDE.md)
|
||||
- [Owned Storage Usage Guide](./OWNED_STORAGE_USAGE_GUIDE.md)
|
||||
|
||||
@ -204,7 +204,7 @@ See [Owned Storage Usage Guide](/server-modules/owned-storage) for examples.
|
||||
| Command Group | Purpose |
|
||||
| --- | --- |
|
||||
| `store:checkout` | Run store checkout behavior. |
|
||||
| `icom:connect`, `icom:broadcast`, `icom:send_event` | ICom connection and event forwarding. |
|
||||
| `icom:connect`, `icom:broadcast`, `icom:send_event` | ICOM connection and event forwarding. See [ICOM Usage Guide](/server-extension/icom). |
|
||||
| `terrain:exportSVG` | Export terrain data as SVG. |
|
||||
| `transport:invoke`, `transport:invoke_stored` | Invoke commands through transport. |
|
||||
| `transport:request:append`, `transport:request:clear` | Manage stored request chunks. |
|
||||
|
||||
@ -39,4 +39,5 @@ For install links and Forge-specific setup steps, see
|
||||
|
||||
- [API Reference](/server-extension/api-reference)
|
||||
- [Usage Examples](/server-extension/usage-examples)
|
||||
- [ICOM Usage Guide](/server-extension/icom)
|
||||
- [Framework Module Guides](/getting-started)
|
||||
|
||||
@ -26,6 +26,7 @@ Game systems should call the domain APIs instead of raw database operations:
|
||||
- `store:*`
|
||||
- `task:*`
|
||||
- `cad:*`
|
||||
- `icom:*`
|
||||
- `owned:garage:*`
|
||||
- `owned:locker:*`
|
||||
- `transport:*`
|
||||
@ -46,3 +47,4 @@ needed by `forge_server_addons_extension_fnc_extCall`.
|
||||
- [Phone](/server-modules/phone)
|
||||
- [Store](/server-modules/store)
|
||||
- [Task](/server-modules/task)
|
||||
- [ICOM](/server-extension/icom)
|
||||
|
||||
194
docus/content/2.server-extension/4.icom.md
Normal file
194
docus/content/2.server-extension/4.icom.md
Normal file
@ -0,0 +1,194 @@
|
||||
---
|
||||
title: "ICOM Usage Guide"
|
||||
description: "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.
|
||||
@ -146,6 +146,18 @@ Documentation Areas
|
||||
Extension architecture, command surface, and SQF usage examples.
|
||||
:::
|
||||
|
||||
:::u-page-feature
|
||||
---
|
||||
icon: i-lucide-network
|
||||
to: /server-extension/icom
|
||||
---
|
||||
#title
|
||||
ICOM [Events]{.text-primary}
|
||||
|
||||
#description
|
||||
Inter-server event routing through the Forge ICOM hub and extension commands.
|
||||
:::
|
||||
|
||||
:::u-page-feature
|
||||
---
|
||||
icon: i-lucide-layers-3
|
||||
|
||||
@ -118,15 +118,6 @@ private _playerJoinData = createHashMapFromArray [
|
||||
"forge_server" callExtension ["icom:broadcast", ["player_join", (toJSON _playerJoinData)]];
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// STEP 3: Test the connection
|
||||
// ============================================================================
|
||||
|
||||
// Test if ICOM is working
|
||||
"forge_server" callExtension ["icom:test_callback", []];
|
||||
// Should trigger forge_icom_event with a handshake event
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// TIPS AND BEST PRACTICES
|
||||
// ============================================================================
|
||||
|
||||
@ -39,6 +39,10 @@ const generatedPages = [
|
||||
source: 'arma/server/addons/common/README.md',
|
||||
target: '2.server-extension/3.common.md'
|
||||
},
|
||||
{
|
||||
source: 'docs/ICOM_USAGE_GUIDE.md',
|
||||
target: '2.server-extension/4.icom.md'
|
||||
},
|
||||
{
|
||||
source: 'docs/ACTOR_USAGE_GUIDE.md',
|
||||
target: '3.server-modules/1.actor.md'
|
||||
@ -293,6 +297,18 @@ Documentation Areas
|
||||
Extension architecture, command surface, and SQF usage examples.
|
||||
:::
|
||||
|
||||
:::u-page-feature
|
||||
---
|
||||
icon: i-lucide-network
|
||||
to: /server-extension/icom
|
||||
---
|
||||
#title
|
||||
ICOM [Events]{.text-primary}
|
||||
|
||||
#description
|
||||
Inter-server event routing through the Forge ICOM hub and extension commands.
|
||||
:::
|
||||
|
||||
:::u-page-feature
|
||||
---
|
||||
icon: i-lucide-layers-3
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user