diff --git a/arma/server/addons/main/functions/fnc_initStores.sqf b/arma/server/addons/main/functions/fnc_initStores.sqf index d1b9275..e3486f9 100644 --- a/arma/server/addons/main/functions/fnc_initStores.sqf +++ b/arma/server/addons/main/functions/fnc_initStores.sqf @@ -46,7 +46,7 @@ if (isNil QEGVAR(org,OrgPayloadBuilder)) then { call EFUNC(org,initPayloadBuilde if (isNil QEGVAR(org,OrgStore)) then { call EFUNC(org,initOrgStore); }; // Store -if (isNil QEGVAR(store,StoreStore)) then { call EFUNC(store,initStoreStore); }; +if (isNil QEGVAR(store,StorefrontStore)) then { call EFUNC(store,initStorefrontStore); }; // Validation Harness if (isNil QGVAR(ValidationHarness)) then { call FUNC(initValidationHarness); }; diff --git a/arma/server/addons/main/functions/fnc_initValidationHarness.sqf b/arma/server/addons/main/functions/fnc_initValidationHarness.sqf index 786531b..26cb19a 100644 --- a/arma/server/addons/main/functions/fnc_initValidationHarness.sqf +++ b/arma/server/addons/main/functions/fnc_initValidationHarness.sqf @@ -100,7 +100,7 @@ GVAR(ValidationHarness) = createHashMapObject [[ _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 _message = _result getOrDefault ["message", "Store checkout validation completed."]; diff --git a/arma/server/addons/store/README.md b/arma/server/addons/store/README.md index 84beb40..08d733a 100644 --- a/arma/server/addons/store/README.md +++ b/arma/server/addons/store/README.md @@ -1,3 +1,18 @@ # 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. diff --git a/arma/server/addons/store/XEH_PREP.hpp b/arma/server/addons/store/XEH_PREP.hpp index cf3f040..310c381 100644 --- a/arma/server/addons/store/XEH_PREP.hpp +++ b/arma/server/addons/store/XEH_PREP.hpp @@ -1,2 +1,3 @@ PREP(initCatalogService); -PREP(initStoreStore); +PREP(initStore); +PREP(initStorefrontStore); diff --git a/arma/server/addons/store/XEH_postInit.sqf b/arma/server/addons/store/XEH_postInit.sqf index b911595..b6cbab5 100644 --- a/arma/server/addons/store/XEH_postInit.sqf +++ b/arma/server/addons/store/XEH_postInit.sqf @@ -1,3 +1,3 @@ #include "script_component.hpp" -// call FUNC(initStore); +call FUNC(initStore); diff --git a/arma/server/addons/store/XEH_preInit.sqf b/arma/server/addons/store/XEH_preInit.sqf index ed11957..21a2764 100644 --- a/arma/server/addons/store/XEH_preInit.sqf +++ b/arma/server/addons/store/XEH_preInit.sqf @@ -38,7 +38,7 @@ PREP_RECOMPILE_END; private _player = [_uid] call EFUNC(common,getPlayer); if (_player isEqualTo objNull) exitWith {}; - private _payload = GVAR(StoreStore) call ["buildHydratePayload", [_uid]]; + private _payload = GVAR(StorefrontStore) call ["buildHydratePayload", [_uid]]; if (_payload isEqualTo createHashMap) exitWith {}; [CRPC(store,responseHydrateStore), [_payload, _bridgeEvent], _player] call CFUNC(targetEvent); @@ -54,6 +54,6 @@ PREP_RECOMPILE_END; private _player = [_uid] call EFUNC(common,getPlayer); 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); }] call CFUNC(addEventHandler); diff --git a/arma/server/addons/store/functions/fnc_initStore.sqf b/arma/server/addons/store/functions/fnc_initStore.sqf new file mode 100644 index 0000000..b50dbde --- /dev/null +++ b/arma/server/addons/store/functions/fnc_initStore.sqf @@ -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; diff --git a/arma/server/addons/store/functions/fnc_initStoreStore.sqf b/arma/server/addons/store/functions/fnc_initStorefrontStore.sqf similarity index 97% rename from arma/server/addons/store/functions/fnc_initStoreStore.sqf rename to arma/server/addons/store/functions/fnc_initStorefrontStore.sqf index b77f94f..9b43e46 100644 --- a/arma/server/addons/store/functions/fnc_initStoreStore.sqf +++ b/arma/server/addons/store/functions/fnc_initStorefrontStore.sqf @@ -1,23 +1,23 @@ #include "..\script_component.hpp" /* - * File: fnc_initStoreStore.sqf + * File: fnc_initStorefrontStore.sqf * Author: IDSolutions * Date: 2026-03-12 * Last Update: 2026-04-04 * Public: No * * 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); }; #pragma hemtt ignore_variables ["_self"] -GVAR(StoreBaseStore) = compileFinal createHashMapFromArray [ - ["#type", "StoreBaseStore"], +GVAR(StorefrontBaseStore) = compileFinal createHashMapFromArray [ + ["#type", "StorefrontBaseStore"], ["#create", compileFinal { - ["INFO", "Store checkout service initialized!"] call EFUNC(common,log); + ["INFO", "Storefront store initialized!"] call EFUNC(common,log); }], ["buildHydratePayload", compileFinal { params [["_uid", "", [""]]]; @@ -405,5 +405,5 @@ GVAR(StoreBaseStore) = compileFinal createHashMapFromArray [ }] ]; -GVAR(StoreStore) = createHashMapObject [GVAR(StoreBaseStore)]; -GVAR(StoreStore) +GVAR(StorefrontStore) = createHashMapObject [GVAR(StorefrontBaseStore)]; +GVAR(StorefrontStore) diff --git a/docs/MODULE_REFERENCE.md b/docs/MODULE_REFERENCE.md index bba9161..ce417d3 100644 --- a/docs/MODULE_REFERENCE.md +++ b/docs/MODULE_REFERENCE.md @@ -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:*` | | 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` | +| 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:*` | | 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:*` | diff --git a/docs/STORE_USAGE_GUIDE.md b/docs/STORE_USAGE_GUIDE.md index befa519..f947863 100644 --- a/docs/STORE_USAGE_GUIDE.md +++ b/docs/STORE_USAGE_GUIDE.md @@ -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 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 `store:checkout` accepts one JSON context.