Refactor store module: rename StoreStore to StorefrontStore, update initialization and checkout logic, and enhance documentation #7

Merged
J.Schmidt92 merged 2 commits from feature/surrealdb-storage into master 2026-04-17 18:15:49 -05:00
10 changed files with 79 additions and 15 deletions

View File

@ -46,7 +46,7 @@ if (isNil QEGVAR(org,OrgPayloadBuilder)) then { call EFUNC(org,initPayloadBuilde
if (isNil QEGVAR(org,OrgStore)) then { call EFUNC(org,initOrgStore); }; if (isNil QEGVAR(org,OrgStore)) then { call EFUNC(org,initOrgStore); };
// Store // Store
if (isNil QEGVAR(store,StoreStore)) then { call EFUNC(store,initStoreStore); }; if (isNil QEGVAR(store,StorefrontStore)) then { call EFUNC(store,initStorefrontStore); };
// Validation Harness // Validation Harness
if (isNil QGVAR(ValidationHarness)) then { call FUNC(initValidationHarness); }; if (isNil QGVAR(ValidationHarness)) then { call FUNC(initValidationHarness); };

View File

@ -100,7 +100,7 @@ GVAR(ValidationHarness) = createHashMapObject [[
_self call ["logResult", [_self call ["buildResult", [_actionLower, false, "Store checkout validation payload was invalid.", createHashMap]]]] _self call ["logResult", [_self call ["buildResult", [_actionLower, false, "Store checkout validation payload was invalid.", createHashMap]]]]
}; };
private _result = EGVAR(store,StoreStore) call ["checkout", [_uid, _player, toJSON _payloadMap]]; private _result = EGVAR(store,StorefrontStore) call ["checkout", [_uid, _player, toJSON _payloadMap]];
private _success = _result getOrDefault ["success", false]; private _success = _result getOrDefault ["success", false];
private _message = _result getOrDefault ["message", "Store checkout validation completed."]; private _message = _result getOrDefault ["message", "Store checkout validation completed."];

View File

@ -1,3 +1,18 @@
# forge_server_store # forge_server_store
Description for this addon Server-side SQF module for storefront entities, catalog hydration, and checkout
coordination.
## Stores and Services
- `StorefrontStore` builds storefront hydrate payloads, validates checkout
requests, calls the Rust `store:checkout` backend, syncs UI patches, and saves
hot state for related modules.
- `StoreCatalogService` scans live Arma config categories, builds catalog
responses, resolves checkout entries, and calculates authoritative prices.
## Editor Entities
`fnc_initStore` marks editor-placed store objects with `isStore = true`. It
matches non-null mission namespace objects whose variable names contain
`store`, mirroring the garage entity initialization pattern.

View File

@ -1,2 +1,3 @@
PREP(initCatalogService); PREP(initCatalogService);
PREP(initStoreStore); PREP(initStore);
PREP(initStorefrontStore);

View File

@ -1,3 +1,3 @@
#include "script_component.hpp" #include "script_component.hpp"
// call FUNC(initStore); call FUNC(initStore);

View File

@ -38,7 +38,7 @@ PREP_RECOMPILE_END;
private _player = [_uid] call EFUNC(common,getPlayer); private _player = [_uid] call EFUNC(common,getPlayer);
if (_player isEqualTo objNull) exitWith {}; if (_player isEqualTo objNull) exitWith {};
private _payload = GVAR(StoreStore) call ["buildHydratePayload", [_uid]]; private _payload = GVAR(StorefrontStore) call ["buildHydratePayload", [_uid]];
if (_payload isEqualTo createHashMap) exitWith {}; if (_payload isEqualTo createHashMap) exitWith {};
[CRPC(store,responseHydrateStore), [_payload, _bridgeEvent], _player] call CFUNC(targetEvent); [CRPC(store,responseHydrateStore), [_payload, _bridgeEvent], _player] call CFUNC(targetEvent);
@ -54,6 +54,6 @@ PREP_RECOMPILE_END;
private _player = [_uid] call EFUNC(common,getPlayer); private _player = [_uid] call EFUNC(common,getPlayer);
if (_player isEqualTo objNull) exitWith {}; if (_player isEqualTo objNull) exitWith {};
private _result = GVAR(StoreStore) call ["checkout", [_uid, _player, _payloadJson]]; private _result = GVAR(StorefrontStore) call ["checkout", [_uid, _player, _payloadJson]];
[CRPC(store,responseCheckout), [_result], _player] call CFUNC(targetEvent); [CRPC(store,responseCheckout), [_result], _player] call CFUNC(targetEvent);
}] call CFUNC(addEventHandler); }] call CFUNC(addEventHandler);

View File

@ -0,0 +1,32 @@
#include "..\script_component.hpp"
/*
* File: fnc_initStore.sqf
* Author: IDSolutions
* Date: 2026-04-17
* Public: No
*
* Description:
* Initializes all editor-placed store entities.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* call forge_server_store_fnc_initStore
*/
private _stores = (allVariables missionNamespace) select {
private _var = missionNamespace getVariable _x;
("store" in _x) && { _var isEqualType objNull } && { !isNull _var }
};
if (_stores isEqualTo []) exitWith { ["INFO", "No editor-placed stores found."] call EFUNC(common,log) };
{
private _store = missionNamespace getVariable _x;
SETPVAR(_store,isStore,true);
} forEach _stores;

View File

@ -1,23 +1,23 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* File: fnc_initStoreStore.sqf * File: fnc_initStorefrontStore.sqf
* Author: IDSolutions * Author: IDSolutions
* Date: 2026-03-12 * Date: 2026-03-12
* Last Update: 2026-04-04 * Last Update: 2026-04-04
* Public: No * Public: No
* *
* Description: * Description:
* Initializes the server-side store checkout flow. * Initializes the server-side storefront state and checkout flow.
*/ */
if (isNil QGVAR(StoreCatalogService)) then { call FUNC(initCatalogService); }; if (isNil QGVAR(StoreCatalogService)) then { call FUNC(initCatalogService); };
#pragma hemtt ignore_variables ["_self"] #pragma hemtt ignore_variables ["_self"]
GVAR(StoreBaseStore) = compileFinal createHashMapFromArray [ GVAR(StorefrontBaseStore) = compileFinal createHashMapFromArray [
["#type", "StoreBaseStore"], ["#type", "StorefrontBaseStore"],
["#create", compileFinal { ["#create", compileFinal {
["INFO", "Store checkout service initialized!"] call EFUNC(common,log); ["INFO", "Storefront store initialized!"] call EFUNC(common,log);
}], }],
["buildHydratePayload", compileFinal { ["buildHydratePayload", compileFinal {
params [["_uid", "", [""]]]; params [["_uid", "", [""]]];
@ -405,5 +405,5 @@ GVAR(StoreBaseStore) = compileFinal createHashMapFromArray [
}] }]
]; ];
GVAR(StoreStore) = createHashMapObject [GVAR(StoreBaseStore)]; GVAR(StorefrontStore) = createHashMapObject [GVAR(StorefrontBaseStore)];
GVAR(StoreStore) GVAR(StorefrontStore)

View File

@ -28,7 +28,7 @@ docs/ Framework-level documentation
| 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:*` | | 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:*` | | 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:*` | | 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` | | Store | Storefront entity setup, catalog hydration, 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:*` | | 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 unlock storage. | via garage/org UI | server extension only | `lib/models/src/v_garage.rs`, `lib/services/src/v_garage.rs` | `owned:garage:*` | | Owned Garage | Organization or owner-scoped vehicle unlock 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 arsenal unlock storage. | via locker/org UI | server extension only | `lib/models/src/v_locker.rs`, `lib/services/src/v_locker.rs` | `owned:locker:*` | | Owned Locker | Organization or owner-scoped arsenal unlock storage. | via locker/org UI | server extension only | `lib/models/src/v_locker.rs`, `lib/services/src/v_locker.rs` | `owned:locker:*` |

View File

@ -4,6 +4,22 @@ The store module processes checkout requests. It charges a payment source and
grants purchased items to the player locker, virtual arsenal locker, and grants purchased items to the player locker, virtual arsenal locker, and
virtual garage unlocks. virtual garage unlocks.
## Server SQF Module
The server addon uses two long-lived module objects:
- `StorefrontStore` is the storefront workflow facade. It builds hydrate
payloads, validates checkout requests, calls the Rust `store:checkout`
command, syncs UI patches, and asks related module stores to save hot state.
- `StoreCatalogService` scans configured item and vehicle categories, builds
catalog responses, resolves checkout entries, and calculates authoritative
prices.
Editor-placed store entities are initialized by `fnc_initStore` during store
post-init. The initializer matches non-null mission namespace objects whose
variable names contain `store` and sets `isStore = true`, following the same
pattern used by garage entities.
## Checkout Model ## Checkout Model
`store:checkout` accepts one JSON context. `store:checkout` accepts one JSON context.