Add architecture flow diagram in SVG format

This commit is contained in:
Jacob Schmidt 2026-05-16 09:57:02 -05:00
parent c176837a2c
commit df325e2114
9 changed files with 10076 additions and 7205 deletions

View File

@ -6,6 +6,8 @@ handlers, and optional browser UI.
## Runtime Flow
![Architectural Flow Diagram](architecture-flow.svg)
```text
Arma client UI or SQF action
-> client addon bridge
@ -27,7 +29,7 @@ request and response chunks through the extension transport module.
### Client Addons
Client addons live under `arma/client/addons`. They own local player UX,
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs`
durable or authoritative state, it routes work to the matching server addon
instead of touching persistence directly.

101
docs/SURREALDB_SETUP.md Normal file
View File

@ -0,0 +1,101 @@
# SurrealDB Setup
Forge uses SurrealDB for durable storage. The Rust server extension connects to
SurrealDB on startup and applies Forge schema modules automatically, so setup
comes down to running a reachable database and matching the Forge config.
## Choose the Right Path
### Developer or Server Operator
Use this path if you are building Forge, running a local test server, or
hosting the live Arma server.
Official SurrealDB resources:
- [SurrealDB install page](https://surrealdb.com/install)
- [SurrealDB CLI `start` reference](https://surrealdb.com/docs/reference/cli/surrealdb-cli/commands/start)
Install SurrealDB with the official method for your platform:
```powershell
# Windows
iwr https://windows.surrealdb.com -useb | iex
```
```bash
# macOS
brew install surrealdb/tap/surreal
```
```bash
# Linux
curl -sSf https://install.surrealdb.com | sh
```
For Forge, start a persistent local database instead of the default in-memory
mode:
```powershell
surreal start surrealkv://forge.db --bind 127.0.0.1:8000 --user root --pass root
```
Then copy `arma/server/extension/config.example.toml` to `config.toml` next to
`forge_server_x64.dll` and keep the values aligned with the database you
started:
```toml
[surreal]
endpoint = "127.0.0.1:8000"
namespace = "forge"
database = "main"
username = "root"
password = "root"
connect_timeout_ms = 5000
```
After that:
1. Start the Arma server with the Forge extension enabled.
2. Let the extension connect and apply the Forge schema modules.
3. Verify the connection state:
```sqf
"forge_server" callExtension ["status", []];
"forge_server" callExtension ["surreal:status", []];
```
If you change the endpoint, namespace, database, username, or password in
SurrealDB, change the same values in Forge's `config.toml`.
### Mission Designer or Community Manager/Leader
Use this path if you mostly need to inspect, query, or adjust data for a test
or live server and you are not changing Forge source code.
Official SurrealDB resources:
- [Surrealist installation](https://surrealdb.com/docs/explore/surrealist/installation)
- [Surrealist web app](https://app.surrealdb.com)
- [Surrealist local database serving](https://surrealdb.com/docs/explore/surrealist/concepts/local-database-serving)
Recommended approach:
1. Install **Surrealist Desktop**. It is the better fit for Forge because the
official docs note that the web app can be limited when connecting to
`localhost` or non-HTTPS endpoints.
2. Connect Surrealist to the same database Forge uses.
3. Use the values from the server's `config.toml`:
```text
Endpoint: http://127.0.0.1:8000
Namespace: forge
Database: main
Username: root
Password: root
```
If you need your own local sandbox instead of connecting to an existing Forge
server, install SurrealDB first and follow the developer/server-operator path
above. Surrealist Desktop can also launch a local database for you after the
`surreal` executable is installed and available on your `PATH`.

View File

@ -6,6 +6,8 @@ handlers, and optional browser UI.
## Runtime Flow
![Architectural Flow Diagram](architecture-flow.svg)
```text
Arma client UI or SQF action
-> client addon bridge
@ -27,7 +29,7 @@ request and response chunks through the extension transport module.
### Client Addons
Client addons live under `arma/client/addons`. They own local player UX,
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs`
durable or authoritative state, it routes work to the matching server addon
instead of touching persistence directly.

View File

@ -4,9 +4,6 @@ Forge uses SurrealDB for durable storage. The Rust server extension connects to
SurrealDB on startup and applies Forge schema modules automatically, so setup
comes down to running a reachable database and matching the Forge config.
Forge currently targets the SurrealDB `3.x` server line. Do not pair this
build of the extension with a `2.x` SurrealDB server.
## Choose the Right Path
### Developer or Server Operator
@ -17,7 +14,23 @@ hosting the live Arma server.
Official SurrealDB resources:
- [SurrealDB install page](https://surrealdb.com/install)
- [SurrealDB CLI `start` reference](https://surrealdb.com/docs/reference/cli/surrealdb-cli/commands/start)
- [SurrealDB CLI `start` reference](https://surrealdb.com/docs/surrealdb/cli/start)
Forge also includes helper scripts under `arma/server/surrealdb`:
```powershell
cd arma/server/surrealdb
.\UpdateMe.bat
.\RunMe.bat
```
On Linux or macOS:
```bash
cd arma/server/surrealdb
./setup.sh
./run.sh
```
Install SurrealDB with the official method for your platform:
@ -40,9 +53,12 @@ For Forge, start a persistent local database instead of the default in-memory
mode:
```powershell
surreal start surrealkv://forge.db --bind 127.0.0.1:8000 --user root --pass root
surreal start --user root --pass root --bind 127.0.0.1:8000 rocksdb://forge.db
```
`root`/`root` is only the local development default. For a public or shared
server, set a real password and keep `config.toml` aligned.
Then copy `arma/server/extension/config.example.toml` to `config.toml` next to
`forge_server_x64.dll` and keep the values aligned with the database you
started:

View File

@ -0,0 +1,98 @@
# Forge Server Common
## Overview
The common addon provides shared SQF utilities used by server-side Forge
addons. It contains lightweight helpers only; gameplay domain state belongs in
the specific domain addons or the Rust extension.
## Dependencies
- `forge_server_main`
## Main Components
- `fnc_baseStore.sqf` provides shared hash-map object behavior such as JSON
conversion.
- `fnc_eventBus.sqf` provides a framework-wide in-process event bus for
cross-addon notifications.
- `fnc_log.sqf` standardizes server log messages.
- `fnc_getPlayer.sqf` resolves online players by UID.
- `fnc_formatNumber.sqf` formats numeric values for notifications and UI text.
- `fnc_generateHash.sqf` and `fnc_generateSecureData.sqf` provide hashing and
random data helpers.
- `fnc_timeToSeconds.sqf` converts time values into seconds.
## Notes
Keep this addon free of domain-specific behavior. If a helper needs actor,
bank, org, task, store, or CAD state, it belongs in that addon instead.
## Event Bus
The event bus is initialized as `forge_server_common_EventBus` during store
bootstrap. It is synchronous and in-process: listeners run immediately when an
event is emitted.
### Event Naming
Use lower-case dot-separated names:
- `<domain>.<entity>.<action>` for domain events, such as `cad.assignment.assigned`
- `<domain>.<action>` for simple lifecycle events, such as `task.started`
Prefer past-tense action names for events that report completed state changes:
`created`, `started`, `assigned`, `acknowledged`, `declined`, `completed`,
`failed`, `cleared`, `updated`, `closed`.
Payloads should be hash maps and should include stable identifiers first:
`taskID`, `requestID`, `groupID`, `uid`, `orgID`, or `accountID` as appropriate.
The event bus adds `event`, `source`, and `timestamp` when the event is emitted.
### Current Events
Task lifecycle:
- `task.created`
- `task.started`
- `task.completed`
- `task.failed`
- `task.cleared`
Task rewards and notifications:
- `task.reward.requested`
- `task.reward.applied`
- `task.reward.failed`
- `task.rating.applied`
- `task.rating.failed`
- `task.notification.requested`
- `task.reward.notification.requested`
CAD state:
- `cad.assignment.assigned`
- `cad.assignment.created`
- `cad.assignment.acknowledged`
- `cad.assignment.declined`
- `cad.assignment.closed`
- `cad.request.submitted`
- `cad.request.closed`
- `cad.group.updated`
Client sync and notification requests:
- `notification.requested`
- `bank.account.sync.requested`
- `org.sync.requested`
- `locker.sync.requested`
- `locker.va.sync.requested`
- `garage.vgarage.sync.requested`
```sqf
private _token = EGVAR(common,EventBus) call ["on", [
"task.completed",
{
params ["_event"];
["INFO", format ["Task completed: %1", _event getOrDefault ["taskID", ""]]] call EFUNC(common,log);
},
"example"
]];
EGVAR(common,EventBus) call ["emit", [
"task.completed",
createHashMapFromArray [["taskID", "task_001"]],
createHashMapFromArray [["source", "task"]]
]];
EGVAR(common,EventBus) call ["off", [_token]];
```

View File

@ -199,10 +199,254 @@ Available task modules:
- `FORGE_Module_Hostage`: sync to `FORGE_Module_Hostages` and
`FORGE_Module_Shooters`.
- `FORGE_Module_HVT`: sync directly to HVT units.
- `FORGE_Module_Defend`: configure the defense marker and wave settings.
- `FORGE_Module_Defend`: configure the defense marker and wave settings; sync
enemy units to use their groups as wave templates.
These modules delegate to `forge_server_task_fnc_startTask`.
## Mission Designer Guide
This section is the practical Eden setup guide for mission designers.
### General Rules
Use these rules for every Forge task:
1. Give every task a unique `TaskID`.
2. Use area markers for zone-style fields such as:
- `DefenseZone`
- `DeliveryZone`
- `ExtZone`
- `CBRNZone`
3. Prefer `RECTANGLE` or `ELLIPSE` markers with real size.
4. Set success and fail limits explicitly instead of relying on defaults.
5. If a task uses a timer, the countdown now waits until the task is assigned.
6. Grouping modules such as `Explosive Entities`, `Protected Entities`,
`Cargo`, `Hostages`, and `Shooters` should be synced to real world objects,
not other logic modules.
### Attack Task
Use `FORGE_Module_Attack` when players need to eliminate hostile units or
vehicles.
Setup:
1. Place the enemy units or vehicles.
2. Place `FORGE_Module_Attack`.
3. Set `TaskID`.
4. Set `LimitSuccess` to the number of targets that must be killed.
5. Set `LimitFail` if you want a fail threshold.
6. Set rewards, rating, and optional `TimeLimit`.
7. Sync the attack module directly to the target units or vehicles.
Notes:
- This module reads its synced entities directly.
- `TimeLimit` uses seconds. `0` means no limit.
### Destroy Task
Use `FORGE_Module_Destroy` when players must destroy objects, vehicles, or
units.
Setup:
1. Place the objects, vehicles, or units that must be destroyed.
2. Place `FORGE_Module_Destroy`.
3. Set `TaskID`.
4. Set `LimitSuccess` to the number of targets that must be destroyed.
5. Set `LimitFail` if the mission should fail after too many losses.
6. Set rewards, rating, and optional `TimeLimit`.
7. Sync the destroy module directly to the targets.
Notes:
- This module reads its synced entities directly.
- `TimeLimit` uses seconds. `0` means no limit.
### Defuse Task
Use `FORGE_Module_Defuse` when players must defuse one or more explosives while
protecting other entities.
Required module layout:
```text
[Defuse Task] --> [Explosive Entities] --> explosive objects
[Defuse Task] --> [Protected Entities] --> protected objects/vehicles/units
```
Setup:
1. Place the explosive objects that players must defuse.
2. Place `FORGE_Module_Explosives`.
3. Sync each explosive object to `FORGE_Module_Explosives`.
4. Place the objects, vehicles, or units that must survive.
5. Place `FORGE_Module_Protected`.
6. Sync each protected entity to `FORGE_Module_Protected`.
7. Place `FORGE_Module_Defuse`.
8. Set `TaskID`.
9. Set `LimitSuccess` to the number of explosives that must be defused.
10. Set `LimitFail` to the number of protected entities that can be lost before failure.
11. Set `TimeLimit` to the IED countdown in seconds. This is per-IED countdown behavior, not a global mission timer.
12. Set rewards, rating, and end-state options.
13. Sync `FORGE_Module_Defuse` to `FORGE_Module_Explosives`.
14. Sync `FORGE_Module_Defuse` to `FORGE_Module_Protected`.
Notes:
- The module reads grouped objects from the `Explosive Entities` and
`Protected Entities` modules, not from direct object syncs.
- Logic objects are filtered out already, so only real explosives and protected
entities are counted.
- The ACE defuse event is wired to the task system and resolves IEDs back to
the correct task.
### Delivery Task
Use `FORGE_Module_Delivery` when players must move cargo into a delivery zone.
Required module layout:
```text
[Delivery Task] --> [Cargo] --> cargo objects
```
Setup:
1. Place the cargo objects.
2. Create an area marker for the delivery zone.
3. Place `FORGE_Module_Cargo`.
4. Sync each cargo object to `FORGE_Module_Cargo`.
5. Place `FORGE_Module_Delivery`.
6. Set `TaskID`.
7. Set `DeliveryZone` to the marker name.
8. Set `LimitSuccess` to the number of cargo objects that must arrive.
9. Set `LimitFail` to the number of cargo objects that can be damaged past the fail threshold.
10. Set rewards, rating, and optional `TimeLimit`.
11. Sync `FORGE_Module_Delivery` to `FORGE_Module_Cargo`.
Notes:
- The runtime checks `inArea DeliveryZone`, so the zone must be an area marker.
### Hostage Task
Use `FORGE_Module_Hostage` when players must rescue hostages and move them to
an extraction zone.
Required module layout:
```text
[Hostage Task] --> [Hostage Entities] --> hostage units
[Hostage Task] --> [Shooter Entities] --> hostile shooter units
```
Setup:
1. Place the hostage AI units.
2. Place the hostile shooter AI units.
3. Create an area marker for the extraction zone.
4. If using the CBRN variant, create an area marker for the `CBRNZone`.
5. Place `FORGE_Module_Hostages`.
6. Sync the hostage units to `FORGE_Module_Hostages`.
7. Place `FORGE_Module_Shooters`.
8. Sync the shooter units to `FORGE_Module_Shooters`.
9. Place `FORGE_Module_Hostage`.
10. Set `TaskID`.
11. Set `ExtZone` to the extraction marker name.
12. Set `LimitSuccess` to the number of hostages that must be rescued.
13. Set `LimitFail` to the number of hostages that can be lost before failure.
14. Set `Execution` or `CBRN` as needed for the mission variant.
15. If `CBRN` is enabled, set `CBRNZone`.
16. Set rewards, rating, and optional `TimeLimit`.
17. Sync `FORGE_Module_Hostage` to `FORGE_Module_Hostages`.
18. Sync `FORGE_Module_Hostage` to `FORGE_Module_Shooters`.
Notes:
- Hostages and shooters are filtered to real units only.
- Hostages are protected immediately on task registration to avoid startup race conditions.
- The hostage timer now waits until the task is assigned before counting down.
- `ExtZone` is checked with `inArea`, so it must be an area marker.
### HVT Task
Use `FORGE_Module_HVT` when players must capture or eliminate a high-value
target.
Setup:
1. Place the HVT unit or units.
2. If using capture mode, create an area marker for the extraction zone.
3. Place `FORGE_Module_HVT`.
4. Set `TaskID`.
5. Set `CaptureHVT` as needed:
- enabled for capture/extract
- disabled for kill/eliminate
6. If using capture mode, set `ExtZone` to the extraction marker name.
7. Set `LimitSuccess` to the number of HVTs that must be captured or eliminated.
8. Set `LimitFail` if the mission should fail after too many HVT deaths in capture mode.
9. Set rewards, rating, and optional `TimeLimit`.
10. Sync the HVT module directly to the HVT unit or units.
Notes:
- Capture mode uses `ExtZone` with `inArea`, so use an area marker.
- Elimination mode does not require an extraction zone.
- The HVT timer now waits until the task is assigned before counting down.
### Defend Task
Use `FORGE_Module_Defend` when players must hold an area against spawned enemy
waves.
Setup:
1. Create an area marker for the defense zone.
2. Place `FORGE_Module_Defend`.
3. Set `TaskID`.
4. Set `DefenseZone` to the defense marker name.
5. Set `DefendTime` to how long the area must be held.
6. Set `WaveCount`.
7. Set `WaveCooldown`.
8. Set `MinBlufor` to the minimum number of friendlies required in the zone.
9. Place one or more enemy groups or units to use as wave templates.
10. Sync any unit from each enemy group to the defend module.
11. Set rewards, rating, and end-state options.
Notes:
- Synced enemy units are treated as templates. Syncing one unit from a group
makes the whole group available as a wave composition.
- If no enemy units are synced, the defend task falls back to default CSAT
infantry waves.
- The defend task waits for the required number of BLUFOR to enter the zone
before the timer, waves, and empty-zone failure checks begin.
- `DefenseZone` must be an area marker.
### Quick Reference
Use direct syncs:
- `Attack Task` -> target units/vehicles
- `Destroy Task` -> target objects/vehicles/units
- `HVT Task` -> HVT units
Use grouping modules:
- `Defuse Task` -> `Explosive Entities`, `Protected Entities`
- `Delivery Task` -> `Cargo`
- `Hostage Task` -> `Hostage Entities`, `Shooter Entities`
Use area markers:
- `DefenseZone`
- `DeliveryZone`
- `ExtZone`
- `CBRNZone`
## Scripted Start Task
Use `forge_server_task_fnc_startTask` when creating tasks from modules,

16801
docus/package-lock.json generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB