From 2063efab806def08faebb8fc6e8bc97180f14731 Mon Sep 17 00:00:00 2001 From: Jacob Schmidt Date: Fri, 17 Apr 2026 17:39:20 -0500 Subject: [PATCH] Add framework module documentation --- README.md | 7 ++ docs/DEVELOPMENT_GUIDE.md | 129 +++++++++++++++++++++++ docs/FRAMEWORK_ARCHITECTURE.md | 133 ++++++++++++++++++++++++ docs/MODULE_REFERENCE.md | 180 +++++++++++++++++++++++++++++++++ docs/README.md | 31 ++++++ 5 files changed, 480 insertions(+) create mode 100644 docs/DEVELOPMENT_GUIDE.md create mode 100644 docs/FRAMEWORK_ARCHITECTURE.md create mode 100644 docs/MODULE_REFERENCE.md create mode 100644 docs/README.md diff --git a/README.md b/README.md index 2902ee8..11ee9da 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,13 @@ npm run build:webui .\build-arma.ps1 ``` +## Documentation + +- [Framework Documentation](./docs/README.md) +- [Framework Architecture](./docs/FRAMEWORK_ARCHITECTURE.md) +- [Module Reference](./docs/MODULE_REFERENCE.md) +- [Development Guide](./docs/DEVELOPMENT_GUIDE.md) + ## Extension Status ```sqf diff --git a/docs/DEVELOPMENT_GUIDE.md b/docs/DEVELOPMENT_GUIDE.md new file mode 100644 index 0000000..e41603b --- /dev/null +++ b/docs/DEVELOPMENT_GUIDE.md @@ -0,0 +1,129 @@ +# Development Guide + +This guide covers the usual path for adding or changing a Forge module. + +## Local Checks + +Run these before pushing Rust or extension changes: + +```powershell +cargo fmt --check +cargo check +cargo test +cargo build +cargo clippy --all-targets --all-features -- -D warnings +``` + +Run this after changing browser UI sources: + +```powershell +npm run build:webui +``` + +Build Arma packages with: + +```powershell +.\build-arma.ps1 +``` + +## Module Boundaries + +Keep each layer responsible for one kind of work: + +| Layer | Owns | Avoid | +| --- | --- | --- | +| `lib/models` | Data structures, serde defaults, validation helpers. | Database calls, SQF-specific context. | +| `lib/repositories` | Repository traits and in-memory stores. | SurrealDB-specific code. | +| `lib/services` | Business rules, workflow orchestration, structured results. | Arma engine calls, extension transport details. | +| `arma/server/extension` | Command parsing, context resolution, SurrealDB implementations, serialization to SQF. | Business rules that belong in services. | +| `arma/server/addons` | Server SQF lifecycle, game-object integration, calls into `forge_server`. | Direct database logic. | +| `arma/client/addons` | Client UI, keybinds, local UI events. | Authoritative persistence. | + +## Adding a Domain Module + +1. Add the model in `lib/models/src/.rs`. +2. Export the model from `lib/models/src/lib.rs`. +3. Add repository traits in `lib/repositories/src/.rs`. +4. Add in-memory repository support if the service needs tests or hot state. +5. Export the traits from `lib/repositories/src/lib.rs`. +6. Add service logic in `lib/services/src/.rs`. +7. Add focused unit tests for service behavior. +8. Export the service from `lib/services/src/lib.rs`. +9. Add a SurrealDB schema module under `arma/server/extension/src/schema`. +10. Add the concrete storage adapter under `arma/server/extension/src/storage`. +11. Register the storage adapter in `arma/server/extension/src/storage.rs`. +12. Add an extension command group under `arma/server/extension/src/.rs`. +13. Register the command group in `arma/server/extension/src/lib.rs`. +14. Add server addon functions under `arma/server/addons/` if SQF needs a module-level API. +15. Add client addon or browser UI files under `arma/client/addons/` if the module has player-facing UI. +16. Add documentation in `docs/` and module-level READMEs. + +## Extension Command Rules + +Commands should return one of these forms: + +- JSON string for structured results. +- `"true"` or `"false"` for simple existence and boolean operations. +- `"OK"` for successful destructive operations with no response body. +- `"Error: "` for failures. + +Prefer stable JSON shapes over ad hoc strings. SQF callers should always check +for the `"Error:"` prefix before parsing JSON. + +Example: + +```sqf +private _result = "forge_server" callExtension ["actor:get", [getPlayerUID player]]; +private _payload = _result select 0; + +if (_payload find "Error:" == 0) exitWith { + systemChat format ["Actor request failed: %1", _payload]; +}; + +private _actor = fromJSON _payload; +``` + +## Persistence Rules + +SurrealDB is the durable store. Keep database-specific mapping in the extension +storage adapters, not in services or repository traits. + +When changing persisted data: + +- Update or add the matching `.surql` schema module. +- Update the concrete storage adapter. +- Preserve existing records when possible through serde defaults or migration + logic. +- Add tests at the service level for behavior, and add storage tests only when + database mapping is the risk. + +## Hot-State Rules + +Use hot state for data that is read or mutated frequently during a player +session. Hot-state modules usually provide: + +- `init` to load durable state into memory. +- `get` to read the runtime copy. +- `override` or focused mutation commands to update the runtime copy. +- `save` to write the runtime copy back to SurrealDB. +- `remove` to evict the runtime copy. + +Do not assume hot state is durable until `save` succeeds. + +## Web UI Rules + +Browser UI source files live under each client addon. Built assets usually land +under that addon's `ui/_site` directory. + +Use the existing common bridge in `arma/client/addons/common` when a UI needs +to send events back to SQF. Keep UI state and rendering in JavaScript, and keep +server-authoritative decisions in server SQF or Rust services. + +## Documentation Checklist + +When adding or changing a module, update: + +- `docs/MODULE_REFERENCE.md` for framework-level inventory. +- A module-specific README in the addon directory when SQF or UI usage changes. +- `arma/server/docs/api-reference.md` when extension commands change. +- Existing usage guides when payload shapes or workflows change. diff --git a/docs/FRAMEWORK_ARCHITECTURE.md b/docs/FRAMEWORK_ARCHITECTURE.md new file mode 100644 index 0000000..61a8033 --- /dev/null +++ b/docs/FRAMEWORK_ARCHITECTURE.md @@ -0,0 +1,133 @@ +# Framework Architecture + +Forge is organized around domain modules. A domain usually has SQF addon +entry points, Rust models, repository traits, service logic, extension command +handlers, and optional browser UI. + +## Runtime Flow + +```text +Arma client UI or SQF action + -> client addon bridge + -> server addon function + -> forge_server callExtension command + -> extension command group + -> forge-services domain service + -> forge-repositories trait + -> SurrealDB repository implementation + -> SurrealDB +``` + +For small payloads, server SQF calls `forge_server` directly through the +extension bridge. For large payloads, `arma/server/addons/extension` stages +request and response chunks through the extension transport module. + +## Main Layers + +### 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 +durable or authoritative state, it routes work to the matching server addon +instead of touching persistence directly. + +### Server Addons + +Server addons live under `arma/server/addons`. They own server-side SQF +initialization, game-object integration, validation near the Arma runtime, and +calls into the Rust extension. The `extension` addon is the shared bridge for +`callExtension` and transport handling. + +### Rust Extension + +The server extension lives under `arma/server/extension`. It registers the +`forge_server` command groups, loads configuration, initializes SurrealDB, and +maps SQF command inputs into service calls. + +The extension should stay thin: + +- Parse and validate command arguments that arrive from SQF. +- Resolve Arma-specific context such as player UID when required. +- Call the matching service. +- Serialize the service result back to JSON or a simple string. + +### Shared Rust Crates + +The `lib` workspace contains reusable Rust crates: + +- `forge-models`: shared domain structs and serialization rules. +- `forge-repositories`: storage-agnostic repository traits and in-memory + implementations used by tests and hot-state services. +- `forge-services`: domain behavior, validation, and mutation workflows. +- `forge-shared`: cross-crate helpers. + +### Persistence + +Durable storage is SurrealDB. Schema modules live under +`arma/server/extension/src/schema`, and concrete SurrealDB repository +implementations live under `arma/server/extension/src/storage`. + +Repository traits stay in `lib/repositories` so service logic remains testable +without a database. + +## Hot State + +Several domains have `hot` command groups. Hot state keeps a runtime copy of +frequently accessed data in memory, then saves it back to durable storage when +requested. This is useful for player state that changes often during a session. + +Typical hot-state flow: + +```text +actor:hot:init +actor:hot:get +actor:hot:override +actor:hot:save +actor:hot:remove +``` + +Use hot state for session workflows. Use normal domain commands for direct +durable CRUD operations. + +## Transport Layer + +The transport layer exists because Arma extension calls have practical payload +size limits. It provides chunked request and response handling while still +routing to the same domain command groups. + +Common direct command: + +```sqf +"forge_server" callExtension ["status", []]; +``` + +Common transport path: + +```text +server addon fnc_extCall + -> transport:request:append + -> transport:invoke_stored + -> transport:response:get +``` + +## Configuration + +The server extension reads `config.toml` next to the extension DLL. The current +persistence section is: + +```toml +[surreal] +endpoint = "127.0.0.1:8000" +namespace = "forge" +database = "main" +username = "root" +password = "root" +connect_timeout_ms = 5000 +``` + +Check persistence readiness before issuing commands that require storage: + +```sqf +"forge_server" callExtension ["status", []]; +"forge_server" callExtension ["surreal:status", []]; +``` diff --git a/docs/MODULE_REFERENCE.md b/docs/MODULE_REFERENCE.md new file mode 100644 index 0000000..ed9c76f --- /dev/null +++ b/docs/MODULE_REFERENCE.md @@ -0,0 +1,180 @@ +# Module Reference + +This reference lists the main Forge modules and where each layer lives. + +## Directory Map + +```text +arma/client/addons/ Client-side Arma addons and browser UIs +arma/server/addons/ Server-side Arma addons and extension bridge +arma/server/extension/ Rust arma-rs extension and SurrealDB adapters +bin/icom/ Interprocess communication helper +lib/models/ Shared domain data models +lib/repositories/ Repository traits and in-memory stores +lib/services/ Domain services and workflow logic +lib/shared/ Cross-crate helpers +tools/ Web UI build tooling +docs/ Framework-level documentation +``` + +## Gameplay Domains + +| Domain | Purpose | Client addon | Server addon | Service/model layer | Extension group | +| --- | --- | --- | --- | --- | --- | +| Actor | Player identity, loadout, position, status, contact identifiers, and persistent character data. | `arma/client/addons/actor` | `arma/server/addons/actor` | `lib/models/src/actor.rs`, `lib/services/src/actor.rs` | `actor:*` | +| Bank | Player accounts, cash/bank balances, PIN validation, transfers, checkout charging, and transaction context. | `arma/client/addons/bank` | `arma/server/addons/bank` | `lib/models/src/bank.rs`, `lib/services/src/bank.rs` | `bank:*`, `bank:hot:*` | +| CAD | Dispatch requests, assignments, orders, activity stream, profiles, groups, and hydrated dispatcher views. | `arma/client/addons/cad` | `arma/server/addons/cad` | `lib/models/src/cad.rs`, `lib/services/src/cad.rs` | `cad:*` | +| Garage | Player vehicle storage with plate IDs, fuel, damage, and hit point state. | `arma/client/addons/garage` | `arma/server/addons/garage` | `lib/models/src/garage.rs`, `lib/services/src/garage.rs` | `garage:*`, `garage:hot:*` | +| Locker | Player item storage keyed by classname with category and amount. | `arma/client/addons/locker` | `arma/server/addons/locker` | `lib/models/src/locker.rs`, `lib/services/src/locker.rs` | `locker:*`, `locker:hot:*` | +| Organization | Player organizations, membership, treasury, credit lines, shared assets, and fleet data. | `arma/client/addons/org` | `arma/server/addons/org` | `lib/models/src/org.rs`, `lib/services/src/org.rs` | `org:*`, `org:hot:*` | +| Phone | Contacts, messages, and email state. | `arma/client/addons/phone` | `arma/server/addons/phone` | `lib/models/src/phone.rs`, `lib/services/src/phone.rs` | `phone:*` | +| Store | Store catalog checkout workflows and checkout charging integration. | `arma/client/addons/store` | `arma/server/addons/store` | `lib/models/src/store.rs`, `lib/services/src/store.rs` | `store:checkout` | +| Task | Mission/task catalog, ownership, status, reward context, and task counters. | none | `arma/server/addons/task` | `lib/models/src/task.rs`, `lib/services/src/task.rs` | `task:*` | +| Owned Garage | Organization or owner-scoped vehicle storage. | via garage/org UI | server extension only | `lib/models/src/v_garage.rs`, `lib/services/src/v_garage.rs` | `owned:garage:*` | +| Owned Locker | Organization or owner-scoped item storage. | via locker/org UI | server extension only | `lib/models/src/v_locker.rs`, `lib/services/src/v_locker.rs` | `owned:locker:*` | + +## Infrastructure Modules + +| Module | Purpose | Location | +| --- | --- | --- | +| `common` | Shared SQF helpers, base stores, utility functions, and shared UI bridge pieces. | `arma/client/addons/common`, `arma/server/addons/common` | +| `extension` | Server SQF bridge around `forge_server` extension calls and chunked transport. | `arma/server/addons/extension` | +| `main` | Mod-level configuration, pre-init wiring, and server/client startup glue. | `arma/client/addons/main`, `arma/server/addons/main` | +| `economy` | Server-side economy store initialization and economy-specific state helpers. | `arma/server/addons/economy` | +| `notifications` | Client notification UI, sounds, and UI event handling. | `arma/client/addons/notifications` | +| `icom` | Rust helper for interprocess communication and event broadcasting. | `bin/icom`, `arma/server/extension/src/icom.rs` | +| `terrain` | Extension-side terrain export helper. | `arma/server/extension/src/terrain.rs` | +| `transport` | Chunked request/response handling for large extension payloads. | `arma/server/extension/src/transport.rs` | +| `surreal` | SurrealDB connection lifecycle and status reporting. | `arma/server/extension/src/surreal.rs` | + +## Extension Command Groups + +Commands are invoked with: + +```sqf +"forge_server" callExtension ["group:command", [_arg1, _arg2]]; +``` + +Nested groups use additional `:` separators, for example +`bank:hot:deposit`. + +### Core + +| Command | Purpose | +| --- | --- | +| `version` | Return the extension version string. | +| `status` | Return SurrealDB connection state. | +| `surreal:status` | Return SurrealDB connection state directly from the Surreal module. | + +### Actor + +| Command | Purpose | +| --- | --- | +| `actor:get` | Fetch actor data for a resolved player UID. | +| `actor:create` | Create actor data from JSON. | +| `actor:update` | Apply actor JSON updates. | +| `actor:exists` | Return `true` or `false`. | +| `actor:delete` | Delete actor data. | +| `actor:hot:init`, `actor:hot:get`, `actor:hot:keys`, `actor:hot:override`, `actor:hot:save`, `actor:hot:remove` | Manage actor hot state. | + +### Bank + +| Command | Purpose | +| --- | --- | +| `bank:get`, `bank:create`, `bank:update`, `bank:exists`, `bank:delete` | Durable bank CRUD. | +| `bank:hot:init`, `bank:hot:get`, `bank:hot:override`, `bank:hot:patch`, `bank:hot:save`, `bank:hot:remove` | Manage bank hot state. | +| `bank:hot:deposit`, `bank:hot:withdraw`, `bank:hot:deposit_earnings`, `bank:hot:transfer` | Mutate hot bank balances with operation context. | +| `bank:hot:charge_checkout` | Charge a checkout against hot bank state. | +| `bank:hot:validate_pin` | Validate a PIN for bank operations. | + +### Garage + +| Command | Purpose | +| --- | --- | +| `garage:create`, `garage:get`, `garage:add`, `garage:update`, `garage:patch`, `garage:remove`, `garage:delete`, `garage:exists` | Durable player garage operations. | +| `garage:hot:init`, `garage:hot:get`, `garage:hot:override`, `garage:hot:add`, `garage:hot:remove_vehicle`, `garage:hot:save`, `garage:hot:remove` | Manage player garage hot state. | + +See [Garage Usage Guide](./GARAGE_USAGE_GUIDE.md) for examples. + +### Locker + +| Command | Purpose | +| --- | --- | +| `locker:create`, `locker:get`, `locker:add`, `locker:update`, `locker:patch`, `locker:remove`, `locker:delete`, `locker:exists` | Durable player locker operations. | +| `locker:hot:init`, `locker:hot:get`, `locker:hot:override`, `locker:hot:save`, `locker:hot:remove` | Manage player locker hot state. | + +See [Locker Usage Guide](./LOCKER_USAGE_GUIDE.md) for examples. + +### Organization + +| Command | Purpose | +| --- | --- | +| `org:get`, `org:create`, `org:update`, `org:exists`, `org:delete` | Durable organization CRUD. | +| `org:assets:get`, `org:assets:update` | Manage organization assets. | +| `org:fleet:get`, `org:fleet:update` | Manage organization fleet entries. | +| `org:members:get`, `org:members:add`, `org:members:remove` | Manage organization membership. | +| `org:hot:*` | Runtime organization workflows including registration, invites, credit lines, checkout charging, assets, fleet, leave, disband, save, and remove. | + +### Phone + +| Command | Purpose | +| --- | --- | +| `phone:init` | Initialize phone state for a UID. | +| `phone:contacts:list`, `phone:contacts:add`, `phone:contacts:remove` | Manage contacts. | +| `phone:messages:list`, `phone:messages:thread`, `phone:messages:send`, `phone:messages:mark_read`, `phone:messages:delete` | Manage messages. | +| `phone:emails:list`, `phone:emails:send`, `phone:emails:mark_read`, `phone:emails:delete` | Manage emails. | +| `phone:remove` | Remove phone state for a UID. | + +### CAD + +| Command Group | Purpose | +| --- | --- | +| `cad:activity:append`, `cad:activity:recent` | Append and read recent activity. | +| `cad:assignments:list`, `cad:assignments:assign`, `cad:assignments:acknowledge`, `cad:assignments:decline`, `cad:assignments:upsert`, `cad:assignments:delete` | Manage dispatch assignments. | +| `cad:orders:list`, `cad:orders:create`, `cad:orders:create_from_context`, `cad:orders:close`, `cad:orders:upsert`, `cad:orders:delete` | Manage orders. | +| `cad:requests:list`, `cad:requests:submit`, `cad:requests:submit_from_context`, `cad:requests:close`, `cad:requests:upsert`, `cad:requests:delete` | Manage requests. | +| `cad:profiles:list`, `cad:profiles:update_from_context`, `cad:profiles:upsert`, `cad:profiles:delete` | Manage profiles. | +| `cad:groups:build` | Build grouped CAD state. | +| `cad:view:hydrate` | Build the dispatcher view model. | + +### Task + +| Command Group | Purpose | +| --- | --- | +| `task:reset` | Reset task state. | +| `task:catalog:active`, `task:catalog:get`, `task:catalog:upsert`, `task:catalog:delete` | Manage task catalog entries. | +| `task:ownership:bind`, `task:ownership:release`, `task:ownership:accept`, `task:ownership:reward_context` | Manage task ownership and rewards. | +| `task:status:set`, `task:status:get`, `task:status:clear` | Manage task status. | +| `task:defuse:increment`, `task:defuse:get` | Manage defuse counters. | +| `task:clear` | Clear task state. | + +### Owned Storage + +| Command Group | Purpose | +| --- | --- | +| `owned:garage:create`, `owned:garage:fetch`, `owned:garage:get`, `owned:garage:add`, `owned:garage:remove`, `owned:garage:delete`, `owned:garage:exists` | Owner-scoped vehicle storage. | +| `owned:garage:hot:*` | Owner-scoped vehicle hot state. | +| `owned:locker:create`, `owned:locker:fetch`, `owned:locker:get`, `owned:locker:add`, `owned:locker:remove`, `owned:locker:delete`, `owned:locker:exists` | Owner-scoped item storage. | +| `owned:locker:hot:*` | Owner-scoped item hot state. | + +### Other Extension Groups + +| Command Group | Purpose | +| --- | --- | +| `store:checkout` | Run store checkout behavior. | +| `icom:connect`, `icom:broadcast`, `icom:send_event` | ICom connection and event forwarding. | +| `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. | +| `transport:response:get`, `transport:response:clear` | Manage stored response chunks. | + +## Rust Crates + +| Crate | Role | +| --- | --- | +| `forge-models` | Domain models and validation. Keep these serializable and free of persistence details. | +| `forge-repositories` | Repository traits and in-memory implementations. Keep these storage-agnostic. | +| `forge-services` | Business rules and workflows. Depend on repository traits, not concrete databases. | +| `forge-shared` | Cross-crate helpers. Keep dependencies light. | +| `forge-server` | Arma extension crate. Owns command registration, SurrealDB runtime wiring, and concrete storage adapters. | +| `forge-icom` | ICom helper binary and client library. | diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..06637f1 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,31 @@ +# Forge Documentation + +Forge is split into Arma client addons, Arma server addons, a Rust server +extension, shared Rust domain crates, and web UI build tooling. This directory +collects framework-level documentation for those pieces. + +## Start Here + +- [Framework Architecture](./FRAMEWORK_ARCHITECTURE.md): how SQF, web UIs, + Rust services, repositories, and SurrealDB fit together. +- [Module Reference](./MODULE_REFERENCE.md): module inventory for gameplay + domains, extension command groups, client addons, server addons, and Rust + crates. +- [Development Guide](./DEVELOPMENT_GUIDE.md): how to add or change a module + without breaking the framework boundaries. + +## Existing Usage Guides + +- [Garage Usage Guide](./GARAGE_USAGE_GUIDE.md) +- [Locker Usage Guide](./LOCKER_USAGE_GUIDE.md) + +## Related Documentation + +- [Server Extension Docs](../arma/server/docs/README.md) +- [Server Extension API Reference](../arma/server/docs/api-reference.md) +- [Server Extension Usage Examples](../arma/server/docs/usage-examples.md) +- [Client Addon Docs](../arma/client/docs/README.md) +- [Shared Rust Libraries](../lib/README.md) +- [Repository Crate](../lib/repositories/README.md) +- [Service Crate](../lib/services/README.md) +- [Model Crate](../lib/models/README.md) -- 2.47.2