Refactor module hydration and init flow

This commit is contained in:
Jacob Schmidt 2026-03-25 20:29:51 -05:00
parent 6c0ce9e867
commit db565d1e51
29 changed files with 397 additions and 405 deletions

View File

@ -1,3 +1,2 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -4,7 +4,7 @@
* File: fnc_initActorClass.sqf
* Author: IDSolutions
* Date: 2026-01-28
* Last Update: 2026-02-17
* Last Update: 2026-03-25
* Public: Yes
*
* Description:
@ -33,6 +33,7 @@ GVAR(ActorBaseClass) = compileFinal createHashMapFromArray [
["init", compileFinal {
private _uid = _self get "uid";
[SRPC(actor,requestInitActor), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["Actor loaded for %1", (name player)];
diag_log "[FORGE:Client:Actor] Actor Class Initialized!";

View File

@ -10,7 +10,7 @@ if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
[QGVAR(responseInitBank), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(BankClass) call ["sync", [_data, true]];
GVAR(BankClass) call ["markLoaded", []];
if !(isNil QGVAR(BankUIBridge)) then {
GVAR(BankUIBridge) call ["refreshSession", []];
};
@ -19,7 +19,7 @@ if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
[QGVAR(responseSyncBank), {
params [["_data", createHashMap, [createHashMap]], ["_jip", false, [false]]];
GVAR(BankClass) call ["sync", [_data, _jip]];
GVAR(BankClass) call ["markLoaded", []];
if !(isNil QGVAR(BankUIBridge)) then {
GVAR(BankUIBridge) call ["refreshSession", []];
};
@ -34,10 +34,7 @@ if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
}] call CFUNC(addEventHandler);
[QGVAR(responseBankNotice), {
params [
["_type", "error", [""]],
["_message", "", [""]]
];
params [["_type", "error", [""]], ["_message", "", [""]]];
if !(isNil QGVAR(BankUIBridge)) then {
GVAR(BankUIBridge) call ["handleNoticeResponse", [_type, _message]];
@ -45,7 +42,7 @@ if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
}] call CFUNC(addEventHandler);
[{
getPlayerUID player isNotEqualTo "";
EGVAR(actor,ActorClass) get "isLoaded";
}, {
[QGVAR(initBank), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);

View File

@ -1,3 +1,2 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -6,7 +6,7 @@
* Public: No
*
* Description:
* Initializes the bank class for account sync and access helpers.
* Initializes the bank class for lifecycle and save helpers.
*/
#pragma hemtt ignore_variables ["_self"]
@ -14,46 +14,24 @@ GVAR(BankBaseClass) = compileFinal createHashMapFromArray [
["#type", "BankBaseClass"],
["#create", compileFinal {
_self set ["uid", getPlayerUID player];
_self set ["account", createHashMapFromArray [
["bank", 0],
["cash", 0],
["earnings", 0],
["transactions", []]
]];
_self set ["isLoaded", false];
_self set ["lastSave", time];
}],
["getAccountState", compileFinal {
_self getOrDefault ["account", createHashMap]
}],
["get", compileFinal {
params [["_key", "", [""]], ["_default", nil, [[], "", 0, false, createHashMap]]];
private _account = _self getOrDefault ["account", createHashMap];
_account getOrDefault [_key, _default]
}],
["init", compileFinal {
[SRPC(bank,requestInitBank), [getPlayerUID player]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["Bank loaded for %1", (name player)];
diag_log "[FORGE:Client:Bank] Bank Class Initialized!";
}],
["markLoaded", compileFinal {
if !(_self getOrDefault ["isLoaded", false]) then { _self set ["isLoaded", true]; };
true
}],
["save", compileFinal {
[SRPC(bank,requestSaveBank), [getPlayerUID player]] call CFUNC(serverEvent);
_self set ["lastSave", time];
}],
["sync", compileFinal {
params [["_data", createHashMap, [createHashMap]], ["_jip", false, [false]]];
private _account = _self getOrDefault ["account", createHashMap];
{
_account set [_x, _y];
} forEach _data;
_self set ["account", _account];
if !(_self getOrDefault ["isLoaded", false]) then {
_self set ["isLoaded", true];
};
true
}]
];

View File

@ -79,9 +79,7 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
params [["_data", createHashMap, [createHashMap]]];
private _pin = _data getOrDefault ["pin", ""];
if !(_pin isEqualType "") then {
_pin = str _pin;
};
if !(_pin isEqualType "") then { _pin = str _pin; };
[SRPC(bank,requestSubmitPin), [getPlayerUID player, _pin]] call CFUNC(serverEvent);
true
@ -128,9 +126,7 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
params [["_mode", "bank", [""]]];
private _finalMode = toLowerANSI _mode;
if !(_finalMode in ["bank", "atm"]) then {
_finalMode = "bank";
};
if !(_finalMode in ["bank", "atm"]) then { _finalMode = "bank"; };
_self set ["mode", _finalMode];
_finalMode

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@
bridge.on("bank::hydrate", hydrate);
bridge.on("bank::sync", hydrate);
bridge.on("bank::notice", (payloadData) => {
store.finishAction();
if (BankApp.actions) {
BankApp.actions.showNotice(
payloadData.type || "error",

View File

@ -1,3 +1,2 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -4,7 +4,7 @@
* File: fnc_initClass.sqf
* Author: IDSolutions
* Date: 2025-12-17
* Last Update: 2026-02-13
* Last Update: 2026-03-25
* Public: No
*
* Description:
@ -35,6 +35,7 @@ GVAR(GarageBaseClass) = compileFinal createHashMapFromArray [
private _garage = _self get "garage";
[SRPC(garage,requestInitGarage), [_uid, _garage]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["Garage loaded for %1", (name player)];
diag_log "[FORGE:Client:Garage] Garage Class Initialized!";

View File

@ -4,7 +4,7 @@
* File: fnc_initVGClass.sqf
* Author: IDSolutions
* Date: 2025-12-16
* Last Update: 2026-02-13
* Last Update: 2026-03-25
* Public: No
*
* Description:
@ -37,6 +37,7 @@ GVAR(VGBaseClass) = compileFinal createHashMapFromArray [
private _vGarage = _self get "vGarage";
[SRPC(garage,requestInitVG), [_uid, _vGarage]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["VGarage loaded for %1", (name player)];
diag_log "[FORGE:Client:VGarage] VGarage Class Initialized!";

View File

@ -4,7 +4,7 @@
* File: fnc_initLockerClass.sqf
* Author: IDSolutions
* Date: 2025-12-17
* Last Update: 2026-02-13
* Last Update: 2026-03-25
* Public: No
*
* Description:
@ -34,6 +34,7 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
private _uid = _self get "uid";
[SRPC(locker,requestInitLocker), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["Locker loaded for %1", (name player)];
diag_log "[FORGE:Client:Locker] Locker Class Initialized!";

View File

@ -4,7 +4,7 @@
* File: fnc_init.sqf
* Author: IDSolutions
* Date: 2025-12-16
* Last Update: 2026-02-13
* Last Update: 2026-03-25
* Public: No
*
* Description:
@ -34,6 +34,7 @@ GVAR(VABaseClass) = compileFinal createHashMapFromArray [
private _uid = _self get "uid";
FORGE_Locker_Box = "ReammoBox_F" createVehicleLocal [0, 0, -999];
[SRPC(locker,requestInitVA), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["VArsenal loaded for %1", (name player)];
diag_log "[FORGE:Client:VArsenal] VArsenal Class Initialized!";

View File

@ -1,7 +1,7 @@
#include "script_component.hpp"
[{
EGVAR(actor,ActorClass) get "isLoaded";
EGVAR(locker,VAClass) get "isLoaded";
}, {
("NotificationHudLayer" call BFUNC(rscLayer)) cutRsc ["RscNotifications", "PLAIN"];
call FUNC(openUI);

View File

@ -1,3 +1,2 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -3,24 +3,24 @@
if (isNil QGVAR(OrgClass)) then { call FUNC(initClass); };
if (isNil QGVAR(OrgUIBridge)) then { call FUNC(initUIBridge); };
[QGVAR(initOrg), {
GVAR(OrgClass) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseInitOrg), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(OrgClass) call ["sync", [_data, true]];
GVAR(OrgUIBridge) call ["refreshPortal", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseSyncOrg), {
params [["_data", createHashMap, [createHashMap]], ["_jip", false, [false]]];
GVAR(OrgClass) call ["sync", [_data, _jip]];
GVAR(OrgUIBridge) call ["refreshPortal", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseHydrateOrg), {
params [["_payload", createHashMap, [createHashMap]], ["_bridgeEvent", "org::sync", [""]]];
GVAR(OrgUIBridge) call ["handleHydrateResponse", [_payload, _bridgeEvent]];
}] call CFUNC(addEventHandler);
[QGVAR(responseCreateOrg), {
params [["_payload", createHashMap, [createHashMap]]];
@ -46,7 +46,7 @@ if (isNil QGVAR(OrgUIBridge)) then { call FUNC(initUIBridge); };
}] call CFUNC(addEventHandler);
[{
EGVAR(actor,ActorClass) get "isLoaded";
EGVAR(locker,VAClass) get "isLoaded";
}, {
[QGVAR(initOrg), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);

View File

@ -1,3 +1,2 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -3,21 +3,21 @@
/*
* File: fnc_initClass.sqf
* Author: IDSolutions
* Date: 2026-02-13
* Last Update: 2026-02-13
* Date: 2026-03-25
* Last Update: 2026-03-25
* Public: No
*
* Description:
* Initializes the org class.
* No description added yet.
*
* Arguments:
* None
* Parameter(s):
* N/A
*
* Return Value:
* Org class object [HASHMAP OBJECT]
* Returns:
* Something [BOOL]
*
* Examples:
* call forge_client_org_fnc_initClass
* Example(s):
* [parameter] call forge_x_component_fnc_myFunction
*/
#pragma hemtt ignore_variables ["_self"]
@ -25,155 +25,24 @@ GVAR(OrgBaseClass) = compileFinal createHashMapFromArray [
["#type", "OrgBaseClass"],
["#create", compileFinal {
_self set ["uid", getPlayerUID player];
_self set ["org", createHashMap];
_self set ["isLoaded", false];
_self set ["lastSave", time];
private _org = createHashMap;
_org set ["id", ""];
_org set ["owner", ""];
_org set ["name", ""];
_org set ["funds", 0];
_org set ["reputation", 0];
_org set ["credit_lines", createHashMap];
_org set ["assets", createHashMap];
_org set ["fleet", createHashMap];
_org set ["members", createHashMap];
_self set ["org", _org];
}],
["init", compileFinal {
private _uid = _self get "uid";
private _org = _self get "org";
[SRPC(org,requestInitOrg), [_uid, _org]] call CFUNC(serverEvent);
[SRPC(org,requestInitOrg), [getPlayerUID player]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["Org loaded for %1", (name player)];
diag_log "[FORGE:Client:Org] Org Class Initialized!";
}],
["markLoaded", compileFinal {
if !(_self getOrDefault ["isLoaded", false]) then { _self set ["isLoaded", true]; };
true
}],
["save", compileFinal {
params [["_sync", false, [false]]];
private _uid = _self get "uid";
[SRPC(org,requestSaveOrg), [_uid, _sync]] call CFUNC(serverEvent);
[SRPC(bank,requestSaveOrg), [getPlayerUID player]] call CFUNC(serverEvent);
_self set ["lastSave", time];
}],
["sync", compileFinal {
params [["_data", createHashMap, [createHashMap]], ["_jip", false, [false]]];
private _isLoaded = _self get "isLoaded";
private _org = _self get "org";
{ _org set [_x, _y]; } forEach _data;
_self set ["org", _org];
if !(_isLoaded) then { _self set ["isLoaded", true]; };
diag_log "[FORGE:Client:Org] Sync completed";
}],
["buildPortalPayload", compileFinal {
private _orgData = _self get "org";
private _name = _orgData get "name";
private _id = _orgData get "id";
private _ownerUid = _orgData get "owner";
private _funds = _orgData get "funds";
private _reputation = _orgData get "reputation";
private _creditLinesRaw = _orgData getOrDefault ["credit_lines", createHashMap];
private _assetsRaw = _orgData get "assets";
private _fleetRaw = _orgData get "fleet";
private _membersRaw = _orgData get "members";
private _isDefaultOrg = (_orgData getOrDefault ["default", false])
|| {toLower _id isEqualTo "default"}
|| {toLower _ownerUid isEqualTo "server"};
private _playerName = name player;
private _playerUid = getPlayerUID player;
private _playerVar = vehicleVarName player;
private _sessionRole = "Member";
private _sessionIsCeo = _isDefaultOrg && {_playerVar isEqualTo "ceo"};
private _ownerName = ["", "Server"] select (toLower _ownerUid isEqualTo "server");
private _membersList = [];
{
private _memberData = _y;
private _memberName = _memberData getOrDefault ["name", "Unknown"];
private _memberUid = _memberData getOrDefault ["uid", ""];
if (_memberUid isEqualTo _ownerUid && {_ownerName isEqualTo ""}) then { _ownerName = _memberName; };
if (_memberUid isEqualTo _playerUid) then { _sessionRole = "Member"; };
_membersList pushBack (createHashMapFromArray [
["uid", _memberUid],
["name", _memberName]
]);
} forEach _membersRaw;
if (_ownerName isEqualTo "" && { _ownerUid isEqualTo _playerUid }) then { _ownerName = _playerName; };
if (_ownerName isEqualTo "" && { _ownerUid isNotEqualTo "" }) then { _ownerName = "Unknown Owner"; };
if (_ownerUid isEqualTo _playerUid) then { _sessionRole = "Leader"; };
private _assetsList = [];
{
private _assetData = _y;
_assetsList pushBack (createHashMapFromArray [
["name", _assetData getOrDefault ["name", "Unknown Asset"]],
["type", _assetData getOrDefault ["type", "items"]],
["quantity", str (_assetData getOrDefault ["quantity", 0])]
]);
} forEach _assetsRaw;
private _fleetList = [];
{
private _vehicleData = _y;
_fleetList pushBack (createHashMapFromArray [
["name", _vehicleData getOrDefault ["name", "Unknown Vehicle"]],
["type", _vehicleData getOrDefault ["type", "other"]],
["status", _vehicleData getOrDefault ["status", "Unknown"]],
["damage", _vehicleData getOrDefault ["damage", "0%"]]
]);
} forEach _fleetRaw;
private _creditLinesList = [];
{
private _creditLineData = _y;
_creditLinesList pushBack (createHashMapFromArray [
["uid", _creditLineData getOrDefault ["uid", _x]],
["member", _creditLineData getOrDefault ["name", "Unknown Member"]],
["amount", _creditLineData getOrDefault ["amount", 0]]
]);
} forEach _creditLinesRaw;
createHashMapFromArray [
["session", createHashMapFromArray [
["actorName", _playerName],
["actorUid", _playerUid],
["role", _sessionRole],
["ceo", _sessionIsCeo]
]],
["portalData", createHashMapFromArray [
["org", createHashMapFromArray [
["name", _name],
["tag", _id],
["owner", _ownerName],
["ownerUid", _ownerUid],
["isDefault", _isDefaultOrg]
]],
["funds", _funds],
["reputation", _reputation],
["creditLines", _creditLinesList],
["members", _membersList],
["fleet", _fleetList],
["assets", _assetsList],
["activity", []]
]]
]
}],
["get", compileFinal {
params [["_key", "", [""]], ["_default", nil, [[], "", 0, false, createHashMap]]];
private _org = _self get "org";
_org getOrDefault [_key, _default];
}]
];

View File

@ -50,20 +50,42 @@ GVAR(OrgUIBridgeBaseClass) = compileFinal createHashMapFromArray [
_self call ["setActiveBrowserControl", [_control]];
_control
}],
["hasOpenScreen", compileFinal {
private _screen = _self call ["getScreen", []];
private _control = _self call ["getActiveBrowserControl", []];
!(isNull _control) && { _screen call ["isReady", []] }
}],
["requestHydrate", compileFinal {
params [["_bridgeEvent", "org::sync", [""]]];
if !(_self call ["hasOpenScreen", []]) exitWith { false };
private _event = _bridgeEvent;
if !(_event in ["org::login::success", "org::create::success", "org::sync"]) then {
_event = "org::sync";
};
[SRPC(org,requestHydrateOrg), [getPlayerUID player, _event]] call CFUNC(serverEvent);
true
}],
["handleHydrateResponse", compileFinal {
params [["_payload", createHashMap, [createHashMap]], ["_bridgeEvent", "org::sync", [""]]];
if !(_self call ["hasOpenScreen", []]) exitWith { false };
private _event = _bridgeEvent;
if !(_event in ["org::login::success", "org::create::success", "org::sync"]) then {
_event = "org::sync";
};
_self call ["sendEvent", [_event, _payload, _self call ["getActiveBrowserControl", []]]]
}],
["handleLoginRequest", compileFinal {
params [["_control", controlNull, [controlNull]]];
private _orgData = GVAR(OrgClass) get "org";
private _orgId = _orgData getOrDefault ["id", ""];
private _orgName = _orgData getOrDefault ["name", ""];
if (_orgId isEqualTo "" && { _orgName isEqualTo "" }) exitWith {
_self call ["sendEvent", ["org::login::failure", createHashMapFromArray [
["message", "No organization data is available for this player."]
], _control]];
};
_self call ["sendEvent", ["org::login::success", GVAR(OrgClass) call ["buildPortalPayload", []], _control]];
_self call ["setActiveBrowserControl", [_control]];
_self call ["requestHydrate", ["org::login::success"]];
}],
["handleCreateRequest", compileFinal {
params [["_control", controlNull, [controlNull]], ["_data", createHashMap, [createHashMap]]];
@ -91,11 +113,11 @@ GVAR(OrgUIBridgeBaseClass) = compileFinal createHashMapFromArray [
], _control]];
};
private _orgData = _payload getOrDefault ["org", createHashMap];
GVAR(OrgClass) call ["sync", [_orgData, true]];
if !(isNull _control) then {
_self call ["setActiveBrowserControl", [_control]];
};
if (isNull _control) exitWith {};
_self call ["sendEvent", ["org::create::success", GVAR(OrgClass) call ["buildPortalPayload", []], _control]];
_self call ["requestHydrate", ["org::create::success"]];
}],
["handleDisbandResponse", compileFinal {
params [["_payload", createHashMap, [createHashMap]]];
@ -155,10 +177,7 @@ GVAR(OrgUIBridgeBaseClass) = compileFinal createHashMapFromArray [
[SRPC(org,requestAssignCreditLine), [getPlayerUID player, _memberUid, _memberName, _amount]] call CFUNC(serverEvent);
}],
["refreshPortal", compileFinal {
private _control = _self call ["getActiveBrowserControl", []];
if (isNull _control) exitWith { false };
_self call ["sendEvent", ["org::sync", GVAR(OrgClass) call ["buildPortalPayload", []], _control]]
_self call ["requestHydrate", ["org::sync"]]
}]
];

View File

@ -1,5 +1,3 @@
PREP(buildUIPayload);
PREP(handleUIEvents);
PREP(initClass);
PREP(initUIBridge);
PREP(openUI);

View File

@ -1,6 +1,5 @@
#include "script_component.hpp"
if (isNil QGVAR(StoreClass)) then { call FUNC(initClass); };
if (isNil QGVAR(StoreUIBridge)) then { call FUNC(initUIBridge); };
[QGVAR(responseCategory), {
@ -9,6 +8,12 @@ if (isNil QGVAR(StoreUIBridge)) then { call FUNC(initUIBridge); };
GVAR(StoreUIBridge) call ["handleCategoryResponse", [_payload]];
}] call CFUNC(addEventHandler);
[QGVAR(responseHydrateStore), {
params [["_payload", createHashMap, [createHashMap]], ["_bridgeEvent", "store::hydrate", [""]]];
GVAR(StoreUIBridge) call ["handleHydrateResponse", [_payload, _bridgeEvent]];
}] call CFUNC(addEventHandler);
[QGVAR(responseCheckout), {
params [["_payload", createHashMap, [createHashMap]]];

View File

@ -1,125 +0,0 @@
#include "..\script_component.hpp"
/*
* File: fnc_buildUIPayload.sqf
* Author: IDSolutions
* Date: 2026-03-13
* Public: No
*
* Description:
* Builds the browser hydrate payload for the store UI from current client state.
*
* Arguments:
* None
*
* Return Value:
* Store UI payload [HASHMAP]
*/
private _storeState = createHashMap;
private _budget = 50000;
private _creditLine = 0;
private _cashBalance = 0;
private _bankBalance = 0;
private _orgFunds = 0;
private _orgId = "";
private _orgName = "";
private _orgOwnerUid = "";
private _orgCreditLines = createHashMap;
private _playerUid = getPlayerUID player;
private _playerVar = toLowerANSI (vehicleVarName player);
private _isOrgLeader = false;
private _isDefaultOrg = false;
private _isDefaultOrgCeo = false;
if !(isNil QGVAR(StoreClass)) then {
_storeState = GVAR(StoreClass) call ["getStoreState", []];
_budget = _storeState getOrDefault ["budget", _budget];
};
if !(isNil QEGVAR(bank,BankClass)) then {
_cashBalance = EGVAR(bank,BankClass) call ["get", ["cash", 0]];
_bankBalance = EGVAR(bank,BankClass) call ["get", ["bank", 0]];
};
if !(isNil QEGVAR(org,OrgClass)) then {
_orgId = EGVAR(org,OrgClass) call ["get", ["id", ""]];
_orgName = EGVAR(org,OrgClass) call ["get", ["name", ""]];
_orgOwnerUid = EGVAR(org,OrgClass) call ["get", ["owner", ""]];
_orgFunds = EGVAR(org,OrgClass) call ["get", ["funds", 0]];
_orgCreditLines = EGVAR(org,OrgClass) call ["get", ["credit_lines", createHashMap]];
_isDefaultOrg = (_orgId isEqualTo "default") || { toLowerANSI _orgOwnerUid isEqualTo "server" };
_isOrgLeader = _orgOwnerUid isEqualTo _playerUid;
_isDefaultOrgCeo = _isDefaultOrg && { _playerVar isEqualTo "ceo" };
};
if (_orgCreditLines isEqualType createHashMap) then {
private _playerCreditLine = _orgCreditLines getOrDefault [_playerUid, createHashMap];
if (_playerCreditLine isEqualType createHashMap) then {
_creditLine = _playerCreditLine getOrDefault ["amount", 0];
};
};
private _canUseOrgFunds = _isOrgLeader || _isDefaultOrgCeo;
private _orgFundsEnabled = _canUseOrgFunds && { _orgFunds > 0 };
private _paymentSources = [
createHashMapFromArray [
["id", "cash"],
["label", "Cash"],
["balance", _cashBalance],
["enabled", _cashBalance > 0],
["detail", "Use on-hand cash carried by the player."]
],
createHashMapFromArray [
["id", "bank"],
["label", "Bank"],
["balance", _bankBalance],
["enabled", _bankBalance > 0],
["detail", "Charge the player bank account."]
],
createHashMapFromArray [
["id", "org_funds"],
["label", "Org Funds"],
["balance", _orgFunds],
["enabled", _orgFundsEnabled],
["detail", [
"Only organization leaders or the default-org CEO can use treasury funds.",
[
"Charge organization treasury funds.",
"No organization funds are currently available."
] select _orgFundsEnabled
] select _canUseOrgFunds]
],
createHashMapFromArray [
["id", "credit_line"],
["label", "Credit Line"],
["balance", _creditLine],
["enabled", _creditLine > 0],
["detail", [
"No approved credit line is assigned to this member.",
"Use the approved procurement credit line."
] select (_creditLine > 0)]
]
];
createHashMapFromArray [
["session", createHashMapFromArray [
["actorName", name player],
["actorUid", _playerUid],
["approval", "Field Access"],
["orgId", _orgId],
["orgName", _orgName],
["orgLeader", _isOrgLeader],
["defaultOrgCeo", _isDefaultOrgCeo],
["canUseOrgFunds", _canUseOrgFunds]
]],
["storeConfig", createHashMapFromArray [
["budget", _budget],
["creditLine", _creditLine],
["availability", _storeState getOrDefault ["availability", "In-Stock"]],
["moduleState", _storeState getOrDefault ["moduleState", "Preview"]],
["paymentSources", _paymentSources],
["defaultPaymentSource", "cash"]
]],
["cartItems", []]
]

View File

@ -1,42 +0,0 @@
#include "..\script_component.hpp"
/*
* File: fnc_initClass.sqf
* Author: IDSolutions
* Date: 2026-01-28
* Last Update: 2026-03-12
* Public: Yes
*
* Description:
* Initializes the store class for managing store data.
*
* Arguments:
* None
*
* Return Value:
* Store class object [HASHMAP OBJECT]
*
* Example:
* call forge_client_store_fnc_initClass
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(StoreBaseClass) = compileFinal createHashMapFromArray [
["#type", "StoreBaseClass"],
["#create", compileFinal {
_self set ["uid", getPlayerUID player];
_self set ["store", createHashMapFromArray [
["budget", 50000],
["availability", "In-Stock"],
["moduleState", "Preview"]
]];
_self set ["isLoaded", false];
_self set ["lastSave", time];
}],
["getStoreState", compileFinal {
_self getOrDefault ["store", createHashMap]
}]
];
GVAR(StoreClass) = createHashMapObject [GVAR(StoreBaseClass)];
GVAR(StoreClass)

View File

@ -4,7 +4,7 @@
* File: fnc_initUIBridge.sqf
* Author: IDSolutions
* Date: 2026-03-10
* Last Update: 2026-03-12
* Last Update: 2026-03-25
* Public: No
*
* Description:
@ -47,8 +47,12 @@ GVAR(StoreUIBridgeBaseClass) = compileFinal createHashMapFromArray [
["handleReady", compileFinal {
params [["_control", controlNull, [controlNull]]];
private _payload = call FUNC(buildUIPayload);
_self call ["sendBridgeEvent", ["store::hydrate", _payload, _control]];
private _uid = getPlayerUID player;
if (_uid isEqualTo "") exitWith {
_self call ["sendBridgeEvent", ["store::hydrate", createHashMap, _control]];
};
[SRPC(store,requestHydrateStore), [_uid, "store::hydrate"]] call CFUNC(serverEvent);
}],
["handleCategoryRequest", compileFinal {
params [["_data", createHashMap, [createHashMap]]];
@ -79,8 +83,19 @@ GVAR(StoreUIBridgeBaseClass) = compileFinal createHashMapFromArray [
_self call ["sendBridgeEvent", [_bridgeEvent, _payload]];
}],
["refreshStoreConfig", compileFinal {
private _payload = call FUNC(buildUIPayload);
_self call ["sendBridgeEvent", ["store::config::hydrate", _payload]];
private _uid = getPlayerUID player;
if (_uid isEqualTo "") exitWith { false };
[SRPC(store,requestHydrateStore), [_uid, "store::config::hydrate"]] call CFUNC(serverEvent);
true
}],
["handleHydrateResponse", compileFinal {
params [["_payload", createHashMap, [createHashMap]], ["_bridgeEvent", "store::hydrate", [""]]];
private _event = _bridgeEvent;
if !(_event in ["store::hydrate", "store::config::hydrate"]) then { _event = "store::hydrate"; };
_self call ["sendBridgeEvent", [_event, _payload]]
}],
["handleCheckoutRequest", compileFinal {
params [["_data", createHashMap, [createHashMap]]];

View File

@ -4,6 +4,8 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
GVAR(PlayerBootstrapRegistry) = createHashMap;
["forge_icom_event", {
params [["_event", "", [""]], ["_data", createHashMap, [createHashMap]]];
@ -54,3 +56,11 @@ addMissionEventHandler ["ExtensionCallback", {
}]);
};
}];
addMissionEventHandler ["PlayerConnected", {
params ["_id", "_uid", "_name", "_jip", "_owner", "_idStr"];
}];
addMissionEventHandler ["PlayerDisconnected", {
params ["_id", "_uid", "_name", "_jip", "_owner", "_idStr"];
}];

View File

@ -14,6 +14,24 @@ PREP_RECOMPILE_END;
GVAR(OrgStore) call ["init", [_uid]];
}] call CFUNC(addEventHandler);
[QGVAR(requestHydrateOrg), {
params [["_uid", "", [""]], ["_bridgeEvent", "org::sync", [""]]];
if (_uid isEqualTo "") exitWith { diag_log "[FORGE:Server:Org] Empty/Invalid UID!" };
if !(_bridgeEvent in ["org::login::success", "org::create::success", "org::sync"]) then {
_bridgeEvent = "org::sync";
};
private _player = [_uid] call EFUNC(common,getPlayer);
if (_player isEqualTo objNull) exitWith {};
private _payload = GVAR(OrgStore) call ["buildPortalPayload", [_uid]];
if (_payload isEqualTo createHashMap) exitWith {};
[CRPC(org,responseHydrateOrg), [_payload, _bridgeEvent], _player] call CFUNC(targetEvent);
}] call CFUNC(addEventHandler);
[QGVAR(requestCreateOrg), {
params [["_uid", "", [""]], ["_orgName", "", [""]]];

View File

@ -167,6 +167,118 @@ GVAR(OrgBaseStore) = compileFinal createHashMapFromArray [
["assignCreditLine", compileFinal {
GVAR(OrgTreasuryService) call ["assignCreditLine", _this]
}],
["buildPortalPayload", compileFinal {
params [["_uid", "", [""]]];
if (_uid isEqualTo "") exitWith { createHashMap };
private _player = [_uid] call EFUNC(common,getPlayer);
if (isNull _player) exitWith { createHashMap };
private _actor = EGVAR(actor,Registry) getOrDefault [_uid, createHashMap];
private _orgID = _actor getOrDefault ["organization", "default"];
if (_orgID isEqualTo "") then { _orgID = "default"; };
private _org = _self call ["loadById", [_orgID]];
if (_org isEqualTo createHashMap) then {
_org = _self call ["init", [_uid]];
};
if (_org isEqualTo createHashMap) exitWith { createHashMap };
private _name = _org getOrDefault ["name", ""];
private _id = _org getOrDefault ["id", _orgID];
private _ownerUid = _org getOrDefault ["owner", ""];
private _funds = _org getOrDefault ["funds", 0];
private _reputation = _org getOrDefault ["reputation", 0];
private _creditLinesRaw = _org getOrDefault ["credit_lines", createHashMap];
private _assetsRaw = _org getOrDefault ["assets", createHashMap];
private _fleetRaw = _org getOrDefault ["fleet", createHashMap];
private _membersRaw = _org getOrDefault ["members", createHashMap];
private _isDefaultOrg = (_org getOrDefault ["default", false])
|| { toLower _id isEqualTo "default" }
|| { toLower _ownerUid isEqualTo "server" };
private _playerName = name _player;
private _playerVar = vehicleVarName _player;
private _sessionRole = "Member";
private _sessionIsCeo = _isDefaultOrg && { _playerVar isEqualTo "ceo" };
private _ownerName = ["", "Server"] select (toLower _ownerUid isEqualTo "server");
private _membersList = [];
{
private _memberData = _y;
private _memberName = _memberData getOrDefault ["name", "Unknown"];
private _memberUid = _memberData getOrDefault ["uid", ""];
if (_memberUid isEqualTo _ownerUid && { _ownerName isEqualTo "" }) then { _ownerName = _memberName; };
if (_memberUid isEqualTo _uid) then { _sessionRole = "Member"; };
_membersList pushBack (createHashMapFromArray [
["uid", _memberUid],
["name", _memberName]
]);
} forEach _membersRaw;
if (_ownerName isEqualTo "" && { _ownerUid isEqualTo _uid }) then { _ownerName = _playerName; };
if (_ownerName isEqualTo "" && { _ownerUid isNotEqualTo "" }) then { _ownerName = "Unknown Owner"; };
if (_ownerUid isEqualTo _uid) then { _sessionRole = "Leader"; };
private _assetsList = [];
{
private _assetData = _y;
_assetsList pushBack (createHashMapFromArray [
["name", _assetData getOrDefault ["name", "Unknown Asset"]],
["type", _assetData getOrDefault ["type", "items"]],
["quantity", str (_assetData getOrDefault ["quantity", 0])]
]);
} forEach _assetsRaw;
private _fleetList = [];
{
private _vehicleData = _y;
_fleetList pushBack (createHashMapFromArray [
["name", _vehicleData getOrDefault ["name", "Unknown Vehicle"]],
["type", _vehicleData getOrDefault ["type", "other"]],
["status", _vehicleData getOrDefault ["status", "Unknown"]],
["damage", _vehicleData getOrDefault ["damage", "0%"]]
]);
} forEach _fleetRaw;
private _creditLinesList = [];
{
private _creditLineData = _y;
_creditLinesList pushBack (createHashMapFromArray [
["uid", _creditLineData getOrDefault ["uid", _x]],
["member", _creditLineData getOrDefault ["name", "Unknown Member"]],
["amount", _creditLineData getOrDefault ["amount", 0]]
]);
} forEach _creditLinesRaw;
createHashMapFromArray [
["session", createHashMapFromArray [
["actorName", _playerName],
["actorUid", _uid],
["role", _sessionRole],
["ceo", _sessionIsCeo]
]],
["portalData", createHashMapFromArray [
["org", createHashMapFromArray [
["name", _name],
["tag", _id],
["owner", _ownerName],
["ownerUid", _ownerUid],
["isDefault", _isDefaultOrg]
]],
["funds", _funds],
["reputation", _reputation],
["creditLines", _creditLinesList],
["members", _membersList],
["fleet", _fleetList],
["assets", _assetsList],
["activity", []]
]]
]
}],
["buildChargeResult", compileFinal {
GVAR(OrgTreasuryService) call ["buildChargeResult", _this]
}],

View File

@ -24,6 +24,26 @@ PREP_RECOMPILE_END;
[CRPC(store,responseCategory), [_result], _player] call CFUNC(targetEvent);
}] call CFUNC(addEventHandler);
[QGVAR(requestHydrateStore), {
params [["_uid", "", [""]], ["_bridgeEvent", "store::hydrate", [""]]];
if (_uid isEqualTo "") exitWith {
diag_log "[FORGE:Server:Store] Invalid hydrate request payload."
};
if !(_bridgeEvent in ["store::hydrate", "store::config::hydrate"]) then {
_bridgeEvent = "store::hydrate";
};
private _player = [_uid] call EFUNC(common,getPlayer);
if (_player isEqualTo objNull) exitWith {};
private _payload = GVAR(StoreStore) call ["buildHydratePayload", [_uid]];
if (_payload isEqualTo createHashMap) exitWith {};
[CRPC(store,responseHydrateStore), [_payload, _bridgeEvent], _player] call CFUNC(targetEvent);
}] call CFUNC(addEventHandler);
[QGVAR(requestCheckout), {
params [["_uid", "", [""]], ["_payloadJson", "", [""]]];

View File

@ -19,6 +19,127 @@ GVAR(StoreBaseStore) = compileFinal createHashMapFromArray [
["#create", compileFinal {
["INFO", "Store checkout service initialized!"] call EFUNC(common,log);
}],
["buildHydratePayload", compileFinal {
params [["_uid", "", [""]]];
if (_uid isEqualTo "") exitWith { createHashMap };
private _player = [_uid] call EFUNC(common,getPlayer);
if (isNull _player) exitWith { createHashMap };
private _budget = 50000;
private _creditLine = 0;
private _cashBalance = 0;
private _bankBalance = 0;
private _orgFunds = 0;
private _orgName = "";
private _orgOwnerUid = "";
private _orgCreditLines = createHashMap;
private _playerVar = toLowerANSI (vehicleVarName _player);
private _isOrgLeader = false;
private _isDefaultOrg = false;
private _isDefaultOrgCeo = false;
private _bankAccount = EGVAR(bank,Registry) getOrDefault [_uid, createHashMap];
if (_bankAccount isEqualTo createHashMap) then {
_bankAccount = EGVAR(bank,BankStore) call ["init", [_uid]];
};
if (_bankAccount isNotEqualTo createHashMap) then {
_cashBalance = _bankAccount getOrDefault ["cash", 0];
_bankBalance = _bankAccount getOrDefault ["bank", 0];
};
private _actor = EGVAR(actor,Registry) getOrDefault [_uid, createHashMap];
private _orgId = _actor getOrDefault ["organization", "default"];
if (_orgId isEqualTo "") then { _orgId = "default"; };
private _org = EGVAR(org,OrgStore) call ["loadById", [_orgId]];
if (_org isEqualTo createHashMap) then {
_org = EGVAR(org,OrgStore) call ["loadById", ["default"]];
_orgId = _org getOrDefault ["id", "default"];
};
if (_org isNotEqualTo createHashMap) then {
_orgName = _org getOrDefault ["name", ""];
_orgOwnerUid = _org getOrDefault ["owner", ""];
_orgFunds = _org getOrDefault ["funds", 0];
_orgCreditLines = _org getOrDefault ["credit_lines", createHashMap];
_isDefaultOrg = (_orgId isEqualTo "default") || { toLowerANSI _orgOwnerUid isEqualTo "server" };
_isOrgLeader = _orgOwnerUid isEqualTo _uid;
_isDefaultOrgCeo = _isDefaultOrg && { _playerVar isEqualTo "ceo" };
};
if (_orgCreditLines isEqualType createHashMap) then {
private _playerCreditLine = _orgCreditLines getOrDefault [_uid, createHashMap];
if (_playerCreditLine isEqualType createHashMap) then {
_creditLine = _playerCreditLine getOrDefault ["amount", 0];
};
};
private _canUseOrgFunds = _isOrgLeader || _isDefaultOrgCeo;
private _orgFundsEnabled = _canUseOrgFunds && { _orgFunds > 0 };
private _paymentSources = [
createHashMapFromArray [
["id", "cash"],
["label", "Cash"],
["balance", _cashBalance],
["enabled", _cashBalance > 0],
["detail", "Use on-hand cash carried by the player."]
],
createHashMapFromArray [
["id", "bank"],
["label", "Bank"],
["balance", _bankBalance],
["enabled", _bankBalance > 0],
["detail", "Charge the player bank account."]
],
createHashMapFromArray [
["id", "org_funds"],
["label", "Org Funds"],
["balance", _orgFunds],
["enabled", _orgFundsEnabled],
["detail", [
"Only organization leaders or the default-org CEO can use treasury funds.",
[
"Charge organization treasury funds.",
"No organization funds are currently available."
] select _orgFundsEnabled
] select _canUseOrgFunds]
],
createHashMapFromArray [
["id", "credit_line"],
["label", "Credit Line"],
["balance", _creditLine],
["enabled", _creditLine > 0],
["detail", [
"No approved credit line is assigned to this member.",
"Use the approved procurement credit line."
] select (_creditLine > 0)]
]
];
createHashMapFromArray [
["session", createHashMapFromArray [
["actorName", name _player],
["actorUid", _uid],
["approval", "Field Access"],
["orgId", _orgId],
["orgName", _orgName],
["orgLeader", _isOrgLeader],
["defaultOrgCeo", _isDefaultOrgCeo],
["canUseOrgFunds", _canUseOrgFunds]
]],
["storeConfig", createHashMapFromArray [
["budget", _budget],
["creditLine", _creditLine],
["availability", "In-Stock"],
["moduleState", "Preview"],
["paymentSources", _paymentSources],
["defaultPaymentSource", "cash"]
]],
["cartItems", []]
]
}],
["buildResult", compileFinal {
params [["_message", "Checkout failed.", [""]], ["_paymentMethod", "cash", [""]]];