130 lines
4.6 KiB
Markdown
130 lines
4.6 KiB
Markdown
# 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/<module>.rs`.
|
|
2. Export the model from `lib/models/src/lib.rs`.
|
|
3. Add repository traits in `lib/repositories/src/<module>.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/<module>.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/<module>.rs`.
|
|
13. Register the command group in `arma/server/extension/src/lib.rs`.
|
|
14. Add server addon functions under `arma/server/addons/<module>` if SQF needs a module-level API.
|
|
15. Add client addon or browser UI files under `arma/client/addons/<module>` 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: <message>"` 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.
|