Align client module naming and org member hydrate

This commit is contained in:
Jacob Schmidt 2026-03-27 19:00:32 -05:00
parent db565d1e51
commit 65f33ee02a
36 changed files with 592 additions and 681 deletions

View File

@ -1,3 +1,3 @@
PREP(handleUIEvents);
PREP(initActorClass);
PREP(initRepository);
PREP(openUI);

View File

@ -23,17 +23,17 @@ player addEventHandler ["Respawn", {
[SRPC(economy,onRespawn), [_unit, _corpse, _uid]] call CFUNC(serverEvent);
}];
if (isNil QGVAR(ActorClass)) then { call FUNC(initActorClass); };
if (isNil QGVAR(ActorRepository)) then { call FUNC(initRepository); };
[QGVAR(initActor), {
GVAR(ActorClass) call ["init", []];
GVAR(ActorRepository) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(onActorRespawn), {
params [["_loadout", [], [[]]], ["_medSpawnPos", [0,0,0], [[]]], ["_medSpawnDir", 0, [0]]];
private _message = ["warning", "Medical Alert", "You have been revived at a medical facility.", 5000];
EGVAR(notifications,NotificationClass) call ["create", _message];
EGVAR(notifications,NotificationService) call ["create", _message];
player setUnitLoadout _loadout;
player setPosATL _medSpawnPos;
@ -53,14 +53,14 @@ if (isNil QGVAR(ActorClass)) then { call FUNC(initActorClass); };
[QGVAR(responseInitActor), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(ActorClass) call ["sync", [_data, true]];
GVAR(ActorRepository) call ["sync", [_data, true]];
cutText ["", "PLAIN", 1];
}] call CFUNC(addEventHandler);
[QGVAR(responseSyncActor), {
params [["_data", createHashMap, [createHashMap]], ["_jip", false, [false]]];
GVAR(ActorClass) call ["sync", [_data, _jip]];
GVAR(ActorRepository) call ["sync", [_data, _jip]];
}] call CFUNC(addEventHandler);
[QGVAR(initActor), []] call CFUNC(localEvent);
@ -68,6 +68,6 @@ if (isNil QGVAR(ActorClass)) then { call FUNC(initActorClass); };
[{
GETVAR(player,FORGE_isLoaded,false)
}, {
private _holster = GVAR(ActorClass) call ["get", ["holster", true]];
private _holster = GVAR(ActorRepository) call ["get", ["holster", true]];
if (_holster) then { [player] call AFUNC(weaponselect,putWeaponAway); };
}] call CFUNC(waitUntilAndExecute);

View File

@ -31,7 +31,7 @@ private _data = _alert get "data";
diag_log format ["[FORGE:Client:Actor] Handling UI event: %1 with data: %2", _event, _data];
switch (_event) do {
case "actor::get::actions": { GVAR(ActorClass) call ["getNearbyActions", [_control]]; };
case "actor::get::actions": { GVAR(ActorRepository) call ["getNearbyActions", [_control]]; };
case "actor::close::menu": { closeDialog 1; };
case "actor::open::atm": { [true] spawn EFUNC(bank,openUI); };
case "actor::open::bank": { [] spawn EFUNC(bank,openUI); };

View File

@ -1,29 +1,27 @@
#include "..\script_component.hpp"
/*
* File: fnc_initActorClass.sqf
* File: fnc_initRepository.sqf
* Author: IDSolutions
* Date: 2026-01-28
* Last Update: 2026-03-25
* Public: Yes
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the actor class for managing player data.
* Provides methods for saving, loading, and applying actor data.
* Initializes the actor repository for managing player actor data.
*
* Arguments:
* None
*
* Return Value:
* Actor class object [HASHMAP OBJECT]
* Actor repository object [HASHMAP OBJECT]
*
* Example:
* call forge_client_actor_fnc_initActorClass
* call forge_client_actor_fnc_initRepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(ActorBaseClass) = compileFinal createHashMapFromArray [
["#type", "ActorBaseClass"],
GVAR(ActorRepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "ActorRepositoryBaseClass"],
["#create", compileFinal {
_self set ["uid", getPlayerUID player];
_self set ["actor", createHashMap];
@ -35,8 +33,8 @@ GVAR(ActorBaseClass) = compileFinal createHashMapFromArray [
[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!";
systemChat format ["Actor loaded for %1", name player];
diag_log "[FORGE:Client:Actor] Actor Repository Initialized!";
}],
["save", compileFinal {
params [["_sync", false, [false]]];
@ -69,29 +67,23 @@ GVAR(ActorBaseClass) = compileFinal createHashMapFromArray [
_self set ["actor", _actor];
SETPVAR(player,FORGE_isLoaded,true);
if !(_isLoaded) then { _self set ["isLoaded", true]; };
diag_log "[FORGE:Client:Actor] Sync completed";
}],
["get", compileFinal {
params [["_key", "", [""]], ["_default", nil, [[], "", 0, false, createHashMap]]];
private _actor = _self get "actor";
_actor getOrDefault [_key, _default];
}],
["applyPosition", compileFinal {
private _position = _self call ["get", ["position", [0, 0, 0]]];
if (GVAR(enableLoc)) then {
player setPosASL _position;
private _pAlt = ((getPosATLVisual player) select 2);
private _pVelZ = ((velocity player) select 2);
if (_pAlt > 5 && _pVelZ < 0) then {
player setVelocity [0, 0, 0];
player setPosATL [((getPosATLVisual player) select 0), ((getPosATLVisual player) select 1), 1];
hint "You logged off mid air. You were moved to a safe position on the ground";
};
};
@ -114,9 +106,7 @@ GVAR(ActorBaseClass) = compileFinal createHashMapFromArray [
}],
["getNearbyActions", compileFinal {
params [["_control", controlNull, [controlNull]]];
private _nearbyActions = [];
{
private _storeType = _x getVariable ["storeType", ""];
private _isAtm = _x getVariable ["isAtm", false];
@ -141,5 +131,5 @@ GVAR(ActorBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(ActorClass) = createHashMapObject [GVAR(ActorBaseClass)];
GVAR(ActorClass)
GVAR(ActorRepository) = createHashMapObject [GVAR(ActorRepositoryBaseClass)];
GVAR(ActorRepository)

View File

@ -1,4 +1,4 @@
PREP(handleUIEvents);
PREP(initClass);
PREP(initRepository);
PREP(initUIBridge);
PREP(openUI);

View File

@ -1,16 +1,16 @@
#include "script_component.hpp"
if (isNil QGVAR(BankClass)) then { call FUNC(initClass); };
if (isNil QGVAR(BankRepository)) then { call FUNC(initRepository); };
if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
[QGVAR(initBank), {
GVAR(BankClass) call ["init", []];
GVAR(BankRepository) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseInitBank), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(BankClass) call ["markLoaded", []];
GVAR(BankRepository) 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 ["markLoaded", []];
GVAR(BankRepository) call ["markLoaded", []];
if !(isNil QGVAR(BankUIBridge)) then {
GVAR(BankUIBridge) call ["refreshSession", []];
};
@ -42,7 +42,7 @@ if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
}] call CFUNC(addEventHandler);
[{
EGVAR(actor,ActorClass) get "isLoaded";
EGVAR(actor,ActorRepository) get "isLoaded";
}, {
[QGVAR(initBank), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);

View File

@ -1,17 +1,27 @@
#include "..\script_component.hpp"
/*
* File: fnc_initClass.sqf
* File: fnc_initRepository.sqf
* Author: IDSolutions
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the bank class for lifecycle and save helpers.
* Initializes the bank repository for client bank lifecycle state.
*
* Arguments:
* None
*
* Return Value:
* Bank repository object [HASHMAP OBJECT]
*
* Example:
* call forge_client_bank_fnc_initRepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(BankBaseClass) = compileFinal createHashMapFromArray [
["#type", "BankBaseClass"],
GVAR(BankRepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "BankRepositoryBaseClass"],
["#create", compileFinal {
_self set ["uid", getPlayerUID player];
_self set ["isLoaded", false];
@ -21,12 +31,11 @@ GVAR(BankBaseClass) = compileFinal createHashMapFromArray [
[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!";
systemChat format ["Bank loaded for %1", name player];
diag_log "[FORGE:Client:Bank] Bank Repository Initialized!";
}],
["markLoaded", compileFinal {
if !(_self getOrDefault ["isLoaded", false]) then { _self set ["isLoaded", true]; };
true
}],
["save", compileFinal {
@ -35,5 +44,5 @@ GVAR(BankBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(BankClass) = createHashMapObject [GVAR(BankBaseClass)];
GVAR(BankClass)
GVAR(BankRepository) = createHashMapObject [GVAR(BankRepositoryBaseClass)];
GVAR(BankRepository)

View File

@ -3,10 +3,20 @@
/*
* File: fnc_initUIBridge.sqf
* Author: IDSolutions
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the bank web UI bridge.
* Initializes the bank UI bridge for browser control state and bank UI events.
*
* Arguments:
* None
*
* Return Value:
* Bank UI bridge object [HASHMAP OBJECT]
*
* Example:
* call forge_client_bank_fnc_initUIBridge;
*/
#pragma hemtt ignore_variables ["_self"]

View File

@ -1,8 +1,10 @@
PREP(handleUIEvents);
PREP(initCatalogService);
PREP(initClass);
PREP(initSessionService);
PREP(initActionService);
PREP(initContextService);
PREP(initHelperService);
PREP(initPayloadService);
PREP(initRepository);
PREP(initUIBridge);
PREP(initVGClass);
PREP(initVGRepository);
PREP(openUI);
PREP(openVG);

View File

@ -1,19 +1,21 @@
#include "script_component.hpp"
if (isNil QGVAR(GarageCatalogService)) then { call FUNC(initCatalogService); };
if (isNil QGVAR(GarageClass)) then { call FUNC(initClass); };
if (isNil QGVAR(GarageSessionService)) then { call FUNC(initSessionService); };
if (isNil QGVAR(GarageHelperService)) then { call FUNC(initHelperService); };
if (isNil QGVAR(GarageRepository)) then { call FUNC(initRepository); };
if (isNil QGVAR(GarageContextService)) then { call FUNC(initContextService); };
if (isNil QGVAR(GaragePayloadService)) then { call FUNC(initPayloadService); };
if (isNil QGVAR(GarageActionService)) then { call FUNC(initActionService); };
if (isNil QGVAR(GarageUIBridge)) then { call FUNC(initUIBridge); };
if (isNil QGVAR(VGClass)) then { call FUNC(initVGClass); };
if (isNil QGVAR(VGRepository)) then { call FUNC(initVGRepository); };
[QGVAR(initGarage), {
GVAR(GarageClass) call ["init", []];
GVAR(GarageRepository) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseInitGarage), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(GarageClass) call ["sync", [_data]];
GVAR(GarageRepository) call ["sync", [_data]];
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["refreshGarage", []];
};
@ -22,7 +24,7 @@ if (isNil QGVAR(VGClass)) then { call FUNC(initVGClass); };
[QGVAR(responseSyncGarage), {
params [["_data", createHashMap, [createHashMap, []]]];
GVAR(GarageClass) call ["sync", [_data]];
GVAR(GarageRepository) call ["sync", [_data]];
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["refreshGarage", []];
};
@ -31,35 +33,35 @@ if (isNil QGVAR(VGClass)) then { call FUNC(initVGClass); };
[QGVAR(responseGarageAction), {
params [["_payload", createHashMap, [createHashMap]]];
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["handleActionResponse", [_payload]];
if !(isNil QGVAR(GarageActionService)) then {
GVAR(GarageActionService) call ["handleActionResponse", [_payload]];
};
}] call CFUNC(addEventHandler);
[QGVAR(initVG), {
GVAR(VGClass) call ["init", []];
GVAR(VGRepository) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseInitVG), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(VGClass) call ["sync", [_data]];
GVAR(VGRepository) call ["sync", [_data]];
}] call CFUNC(addEventHandler);
[QGVAR(responseSyncVG), {
params [["_data", createHashMap, [createHashMap, []]]];
GVAR(VGClass) call ["sync", [_data]];
GVAR(VGRepository) call ["sync", [_data]];
}] call CFUNC(addEventHandler);
[{
EGVAR(bank,BankClass) get "isLoaded";
EGVAR(bank,BankRepository) get "isLoaded";
}, {
[QGVAR(initGarage), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);
[{
GVAR(GarageClass) get "isLoaded";
GVAR(GarageRepository) get "isLoaded";
}, {
[QGVAR(initVG), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);

View File

@ -44,13 +44,13 @@ switch (_event) do {
};
};
case "garage::vehicle::retrieve::request": {
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["handleRetrieveRequest", [_data]];
if !(isNil QGVAR(GarageActionService)) then {
GVAR(GarageActionService) call ["handleRetrieveRequest", [_data]];
};
};
case "garage::vehicle::store::request": {
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["handleStoreRequest", [_data]];
if !(isNil QGVAR(GarageActionService)) then {
GVAR(GarageActionService) call ["handleStoreRequest", [_data]];
};
};
case "garage::refresh": {

View File

@ -0,0 +1,133 @@
#include "..\script_component.hpp"
/*
* File: fnc_initActionService.sqf
* Author: IDSolutions
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the garage action service for retrieve and store world actions.
*
* Arguments:
* None
*
* Return Value:
* Garage action service object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initActionService;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(GarageActionServiceBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageActionServiceBaseClass"],
["#create", compileFinal {
_self set ["pendingStoreVehicle", objNull];
_self set ["pendingRetrieve", createHashMap];
}],
["handleRetrieveRequest", compileFinal {
params [["_data", createHashMap, [createHashMap]]];
private _plate = _data getOrDefault ["plate", ""];
if (_plate isEqualTo "") exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [["message", "Select a stored vehicle to retrieve."]]]];
};
private _garageMap = if (isNil QGVAR(GarageRepository)) then { createHashMap } else { GVAR(GarageRepository) call ["getState", []] };
private _vehicleData = _garageMap getOrDefault [_plate, createHashMap];
if (_vehicleData isEqualTo createHashMap) exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [["message", "Stored vehicle record could not be found."]]]];
};
private _context = GVAR(GarageContextService) call ["getContext", []];
private _spawnPosition = _context getOrDefault ["spawnPosition", getPosATL player];
private _spawnHeading = _context getOrDefault ["spawnHeading", getDir player];
private _spawnRadius = _context getOrDefault ["spawnRadius", 6];
private _blockingVehicles = [];
{ _blockingVehicles pushBackUnique _x; } forEach (_spawnPosition nearEntities [["Car", "Tank", "Air", "Ship"], _spawnRadius]);
{ _blockingVehicles pushBackUnique _x; } forEach (nearestObjects [_spawnPosition, ["Car", "Tank", "Air", "Ship"], _spawnRadius]);
if (_blockingVehicles isNotEqualTo []) exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [["message", "The garage spawn area is blocked."]]]];
};
private _className = _vehicleData getOrDefault ["classname", ""];
if (_className isEqualTo "") exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [["message", "Stored vehicle record is missing a classname."]]]];
};
private _vehicle = createVehicle [_className, _spawnPosition, [], 0, "CAN_COLLIDE"];
_vehicle setDir _spawnHeading;
_vehicle setFuel (_vehicleData getOrDefault ["fuel", 0]);
_vehicle setDamage (_vehicleData getOrDefault ["damage", 0]);
private _hitPoints = _vehicleData getOrDefault ["hit_points", createHashMap];
private _hitPointNames = _hitPoints getOrDefault ["names", []];
private _hitPointValues = _hitPoints getOrDefault ["values", []];
for "_index" from 0 to ((count _hitPointNames) - 1) do {
_vehicle setHitPointDamage [_hitPointNames param [_index, ""], _hitPointValues param [_index, 0]];
};
_vehicle setVariable ["forge_garage_plate", _plate, true];
_vehicle setVariable ["forge_garage_owner_uid", getPlayerUID player, true];
_self set ["pendingRetrieve", createHashMapFromArray [["plate", _plate], ["vehicle", _vehicle]]];
[SRPC(garage,requestRetrieveVehicle), [getPlayerUID player, _plate]] call CFUNC(serverEvent);
}],
["handleStoreRequest", compileFinal {
params [["_data", createHashMap, [createHashMap]]];
private _netId = _data getOrDefault ["netId", ""];
if (_netId isEqualTo "") exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::store::failure", createHashMapFromArray [["message", "Select a nearby vehicle to store."]]]];
};
private _vehicle = objectFromNetId _netId;
if (isNull _vehicle) exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::store::failure", createHashMapFromArray [["message", "The selected vehicle is no longer available."]]]];
};
if (crew _vehicle isNotEqualTo []) exitWith {
GVAR(GarageUIBridge) call ["sendEvent", ["garage::store::failure", createHashMapFromArray [["message", "All crew must exit the vehicle before storing it."]]]];
};
private _rawHitPoints = getAllHitPointsDamage _vehicle;
private _hitPointsJson = toJSON (createHashMapFromArray [["names", _rawHitPoints param [0, []]], ["selections", _rawHitPoints param [1, []]], ["values", _rawHitPoints param [2, []]]]);
_self set ["pendingStoreVehicle", _vehicle];
[SRPC(garage,requestStoreVehicle), [getPlayerUID player, typeOf _vehicle, fuel _vehicle, damage _vehicle, _hitPointsJson]] call CFUNC(serverEvent);
}],
["handleActionResponse", compileFinal {
params [["_payload", createHashMap, [createHashMap]]];
private _action = _payload getOrDefault ["action", ""];
private _success = _payload getOrDefault ["success", false];
private _message = _payload getOrDefault ["message", "Garage action failed."];
switch (_action) do {
case "retrieve": {
private _pendingRetrieve = _self getOrDefault ["pendingRetrieve", createHashMap];
private _vehicle = _pendingRetrieve getOrDefault ["vehicle", objNull];
if (!_success && { !isNull _vehicle }) then { deleteVehicle _vehicle; };
_self set ["pendingRetrieve", createHashMap];
GVAR(GarageUIBridge) call ["sendEvent", [[ "garage::retrieve::failure", "garage::retrieve::success" ] select _success, createHashMapFromArray [["message", _message]]]];
};
case "store": {
private _vehicle = _self getOrDefault ["pendingStoreVehicle", objNull];
if (_success && { !isNull _vehicle }) then { deleteVehicle _vehicle; };
_self set ["pendingStoreVehicle", objNull];
GVAR(GarageUIBridge) call ["sendEvent", [[ "garage::store::failure", "garage::store::success" ] select _success, createHashMapFromArray [["message", _message]]]];
};
};
[] spawn {
sleep 0.05;
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["refreshGarage", []];
};
};
}]
];
GVAR(GarageActionService) = createHashMapObject [GVAR(GarageActionServiceBaseClass)];
GVAR(GarageActionService)

View File

@ -0,0 +1,146 @@
#include "..\script_component.hpp"
/*
* File: fnc_initContextService.sqf
* Author: IDSolutions
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the garage context service for local garage context and nearby state.
*
* Arguments:
* None
*
* Return Value:
* Garage context service object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initContextService;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(GarageContextServiceBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageContextServiceBaseClass"],
["#create", compileFinal { _self set ["lastContext", createHashMap]; }],
["#delete", compileFinal { _self set ["lastContext", createHashMap]; }],
["createDefaultContext", compileFinal {
createHashMapFromArray [
["name", "Vehicle Garage"],
["anchorPosition", getPosATL player],
["sourceObject", objNull],
["spawnHeading", getDir player],
["spawnPosition", player getPos [8, getDir player]],
["spawnRadius", 6],
["nearbyRadius", 30]
]
}],
["scanEntryValues", compileFinal {
params [["_values", [], [[]]], ["_state", createHashMap, [createHashMap]]];
{
if (_x isEqualType "" && { (_state getOrDefault ["name", "Vehicle Garage"]) isEqualTo "Vehicle Garage" }) then { _state set ["name", _x]; };
if (_x isEqualType "") then {
private _resolvedObject = _state getOrDefault ["sourceObject", objNull];
if (isNull _resolvedObject) then {
private _namedObject = missionNamespace getVariable [_x, objNull];
if (!isNull _namedObject) then { _state set ["sourceObject", _namedObject]; };
};
if ((_state getOrDefault ["anchorPosition", []]) isEqualTo [] && { _x in allMapMarkers }) then { _state set ["anchorPosition", markerPos _x]; };
continue;
};
if (_x isEqualType objNull && { isNull (_state getOrDefault ["sourceObject", objNull]) }) then {
_state set ["sourceObject", _x];
if ((_state getOrDefault ["anchorPosition", []]) isEqualTo []) then { _state set ["anchorPosition", getPosATL _x]; };
continue;
};
if (_x isEqualType 0 && { (_state getOrDefault ["spawnHeading", -1]) < 0 }) then { _state set ["spawnHeading", _x]; continue; };
if (_x isEqualType [] && { count _x > 0 }) then {
if ({ _x isEqualType 0 } count _x >= 2 && { ((_state getOrDefault ["offset", []]) isEqualTo []) || ((_state getOrDefault ["anchorPosition", []]) isEqualTo []) }) then {
if ((_state getOrDefault ["anchorPosition", []]) isEqualTo []) then { _state set ["anchorPosition", _x]; } else { _state set ["offset", _x]; };
continue;
};
_self call ["scanEntryValues", [_x, _state]];
};
} forEach _values;
_state
}],
["resolveEntry", compileFinal {
params [["_entry", [], [[]]]];
private _state = createHashMapFromArray [["name", "Vehicle Garage"], ["anchorPosition", []], ["sourceObject", objNull], ["offset", []], ["spawnHeading", -1]];
_self call ["scanEntryValues", [_entry, _state]];
private _anchorPosition = _state getOrDefault ["anchorPosition", []];
private _offset = _state getOrDefault ["offset", []];
private _spawnPosition = if (_anchorPosition isEqualTo []) then { [] } else { if (_offset isEqualTo []) then { _anchorPosition } else { _anchorPosition vectorAdd _offset } };
createHashMapFromArray [["name", _state getOrDefault ["name", "Vehicle Garage"]], ["anchorPosition", _anchorPosition], ["sourceObject", _state getOrDefault ["sourceObject", objNull]], ["spawnHeading", _state getOrDefault ["spawnHeading", -1]], ["spawnPosition", _spawnPosition]]
}],
["resolveContext", compileFinal {
private _context = _self call ["createDefaultContext", []];
private _locations = (missionConfigFile >> "FORGE_CfgGarages" >> "locations") call BFUNC(getCfgData);
if !(_locations isEqualType []) exitWith { _self set ["lastContext", _context]; _context };
private _nearestEntry = [];
private _nearestDistance = 1e10;
{
private _entry = _self call ["resolveEntry", [_x]];
private _anchorPosition = _entry getOrDefault ["anchorPosition", []];
if (_anchorPosition isEqualTo []) then { continue; };
private _distance = player distance2D _anchorPosition;
if (_distance < _nearestDistance) then { _nearestDistance = _distance; _nearestEntry = _entry; };
} forEach _locations;
if (_nearestEntry isEqualTo []) exitWith { _self set ["lastContext", _context]; _context };
private _anchorPosition = _nearestEntry getOrDefault ["anchorPosition", []];
private _garageObject = _nearestEntry getOrDefault ["sourceObject", objNull];
private _garageName = _nearestEntry getOrDefault ["name", "Vehicle Garage"];
private _spawnHeading = _nearestEntry getOrDefault ["spawnHeading", getDir player];
if (_spawnHeading < 0) then { _spawnHeading = if (!isNull _garageObject) then { getDir _garageObject } else { getDir player }; };
private _spawnPosition = _nearestEntry getOrDefault ["spawnPosition", []];
if (_spawnPosition isEqualTo []) then { _spawnPosition = if (_anchorPosition isEqualTo []) then { player getPos [8, _spawnHeading] } else { _anchorPosition }; };
_context set ["name", _garageName];
_context set ["anchorPosition", _anchorPosition];
_context set ["sourceObject", _garageObject];
_context set ["spawnHeading", _spawnHeading];
_context set ["spawnPosition", _spawnPosition];
_self set ["lastContext", _context];
_context
}],
["getContext", compileFinal { _self call ["resolveContext", []] }],
["buildNearbyState", compileFinal {
private _context = _self call ["getContext", []];
private _anchorPosition = _context getOrDefault ["anchorPosition", []];
private _spawnPosition = _context getOrDefault ["spawnPosition", getPosATL player];
private _spawnRadius = _context getOrDefault ["spawnRadius", 6];
private _nearbyRadius = _context getOrDefault ["nearbyRadius", 30];
private _nearbyOrigin = [_anchorPosition, _spawnPosition] select (_anchorPosition isEqualTo []);
private _nearbyVehicles = [];
private _nearbyEntities = [];
private _candidateVehicles = [];
{ _candidateVehicles pushBackUnique _x; } forEach (_nearbyOrigin nearEntities [["Car", "Tank", "Air", "Ship"], _nearbyRadius]);
{ _candidateVehicles pushBackUnique _x; } forEach ((getPosATL player) nearEntities [["Car", "Tank", "Air", "Ship"], _nearbyRadius]);
{ _candidateVehicles pushBackUnique _x; } forEach (nearestObjects [_nearbyOrigin, ["AllVehicles"], _nearbyRadius]);
{ _candidateVehicles pushBackUnique _x; } forEach (nearestObjects [getPosATL player, ["AllVehicles"], _nearbyRadius]);
{
if (isNull _x) then { continue; };
if (_x isKindOf "CAManBase") then { continue; };
if !(_x isKindOf "Car" || _x isKindOf "Tank" || _x isKindOf "Air" || _x isKindOf "Ship") then { continue; };
_nearbyEntities pushBackUnique _x;
} forEach _candidateVehicles;
{
if (isNull _x) then { continue; };
private _builtVehicle = GVAR(GarageHelperService) call ["buildNearbyVehicle", [_x, _nearbyOrigin]];
if (_builtVehicle isEqualTo createHashMap) then { continue; };
_nearbyVehicles pushBack _builtVehicle;
} forEach _nearbyEntities;
private _nearbyVehiclePairs = _nearbyVehicles apply { [_x getOrDefault ["distance", 0], _x] };
_nearbyVehiclePairs sort true;
_nearbyVehicles = _nearbyVehiclePairs apply { _x param [1, createHashMap] };
private _spawnBlocked = ((_spawnPosition nearEntities [["Car", "Tank", "Air", "Ship"], _spawnRadius]) + (nearestObjects [_spawnPosition, ["Car", "Tank", "Air", "Ship"], _spawnRadius])) isNotEqualTo [];
createHashMapFromArray [["session", createHashMapFromArray [["garageName", _context getOrDefault ["name", "Vehicle Garage"]], ["nearbyCount", count _nearbyVehicles], ["spawnBlocked", _spawnBlocked], ["spawnStatus", ["Ready", "Blocked"] select _spawnBlocked]]], ["nearby", createHashMapFromArray [["vehicles", _nearbyVehicles]]]]
}]
];
GVAR(GarageContextService) = createHashMapObject [GVAR(GarageContextServiceBaseClass)];
GVAR(GarageContextService)

View File

@ -1,18 +1,27 @@
#include "..\script_component.hpp"
/*
* File: fnc_initCatalogService.sqf
* File: fnc_initHelperService.sqf
* Author: IDSolutions
* Date: 2026-03-14
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the garage catalog service for vehicle metadata and UI-friendly shaping.
* Initializes the garage helper service for vehicle metadata and UI-friendly shaping.
*
* Arguments:
* None
*
* Return Value:
* Garage helper service object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initHelperService;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(GarageCatalogServiceBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageCatalogServiceBaseClass"],
GVAR(GarageHelperServiceBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageHelperServiceBaseClass"],
["resolveCategory", compileFinal {
params [["_className", "", [""]]];
@ -156,5 +165,5 @@ GVAR(GarageCatalogServiceBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(GarageCatalogService) = createHashMapObject [GVAR(GarageCatalogServiceBaseClass)];
GVAR(GarageCatalogService)
GVAR(GarageHelperService) = createHashMapObject [GVAR(GarageHelperServiceBaseClass)];
GVAR(GarageHelperService)

View File

@ -0,0 +1,44 @@
#include "..\script_component.hpp"
/*
* File: fnc_initPayloadService.sqf
* Author: IDSolutions
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the garage payload service for browser hydrate payload composition.
*
* Arguments:
* None
*
* Return Value:
* Garage payload service object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initPayloadService;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(GaragePayloadServiceBaseClass) = compileFinal createHashMapFromArray [
["#type", "GaragePayloadServiceBaseClass"],
["buildStoredVehicles", compileFinal {
private _garageMap = if (isNil QGVAR(GarageRepository)) then { createHashMap } else { GVAR(GarageRepository) call ["getState", []] };
private _storedVehicles = [];
{ _storedVehicles pushBack (GVAR(GarageHelperService) call ["buildStoredVehicle", [_x, _y]]); } forEach _garageMap;
private _storedVehiclePairs = _storedVehicles apply { [toLowerANSI (_x getOrDefault ["displayName", ""]), _x] };
_storedVehiclePairs sort true;
_storedVehiclePairs apply { _x param [1, createHashMap] }
}],
["buildPayload", compileFinal {
private _localState = GVAR(GarageContextService) call ["buildNearbyState", []];
private _storedVehicles = _self call ["buildStoredVehicles", []];
private _session = +(_localState getOrDefault ["session", createHashMap]);
_session set ["capacityUsed", count _storedVehicles];
_session set ["capacityMax", 5];
createHashMapFromArray [["session", _session], ["garage", createHashMapFromArray [["vehicles", _storedVehicles]]], ["nearby", +(_localState getOrDefault ["nearby", createHashMap])]]
}]
];
GVAR(GaragePayloadService) = createHashMapObject [GVAR(GaragePayloadServiceBaseClass)];
GVAR(GaragePayloadService)

View File

@ -1,49 +1,44 @@
#include "..\script_component.hpp"
/*
* File: fnc_initClass.sqf
* File: fnc_initRepository.sqf
* Author: IDSolutions
* Date: 2025-12-17
* Last Update: 2026-03-25
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the Garage class for managing player vehicles.
* Provides methods for syncing, saving, and applying vehicles to the player's garage.
* Initializes the garage repository for persisted stored vehicle records.
*
* Arguments:
* None
*
* Return Value:
* Garage class object [HASHMAP OBJECT]
* Garage repository object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initClass
* call forge_client_garage_fnc_initRepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(GarageBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageBaseClass"],
GVAR(GarageRepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageRepositoryBaseClass"],
["#create", compileFinal {
_self set ["uid", (getPlayerUID player)];
_self set ["uid", getPlayerUID player];
_self set ["garage", createHashMap];
_self set ["isLoaded", false];
_self set ["lastSave", time];
}],
["init", compileFinal {
private _uid = _self get "uid";
private _garage = _self get "garage";
[SRPC(garage,requestInitGarage), [_uid, _garage]] call CFUNC(serverEvent);
[SRPC(garage,requestInitGarage), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["Garage loaded for %1", (name player)];
diag_log "[FORGE:Client:Garage] Garage Class Initialized!";
systemChat format ["Garage loaded for %1", name player];
diag_log "[FORGE:Client:Garage] Garage Repository Initialized!";
}],
["save", compileFinal {
private _uid = _self get "uid";
[SRPC(garage,requestSaveGarage), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
}],
["sync", compileFinal {
@ -51,14 +46,13 @@ GVAR(GarageBaseClass) = compileFinal createHashMapFromArray [
private _isLoaded = _self get "isLoaded";
private _garage = createHashMap;
{ _garage set [_x, _y]; } forEach _data;
_self set ["garage", _garage];
if !(_isLoaded) then { _self set ["isLoaded", true]; };
diag_log "[FORGE:Client:Garage] Sync completed";
diag_log "[FORGE:Client:Garage] Repository sync completed";
}],
["getGarageState", compileFinal {
["getState", compileFinal {
_self getOrDefault ["garage", createHashMap]
}],
["get", compileFinal {
@ -69,5 +63,5 @@ GVAR(GarageBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(GarageClass) = createHashMapObject [GVAR(GarageBaseClass)];
GVAR(GarageClass)
GVAR(GarageRepository) = createHashMapObject [GVAR(GarageRepositoryBaseClass)];
GVAR(GarageRepository)

View File

@ -1,298 +0,0 @@
#include "..\script_component.hpp"
/*
* File: fnc_initSessionService.sqf
* Author: IDSolutions
* Date: 2026-03-14
* Public: No
*
* Description:
* Initializes the typed garage session service responsible for resolving the
* active garage context and building the browser hydrate payload.
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(GarageSessionServiceBaseClass) = compileFinal createHashMapFromArray [
["#type", "GarageSessionServiceBaseClass"],
["#create", compileFinal {
_self set ["lastContext", createHashMap];
}],
["#delete", compileFinal {
_self set ["lastContext", createHashMap];
}],
["createDefaultContext", compileFinal {
createHashMapFromArray [
["name", "Vehicle Garage"],
["anchorPosition", getPosATL player],
["sourceObject", objNull],
["spawnHeading", getDir player],
["spawnPosition", player getPos [8, getDir player]],
["spawnRadius", 6],
["nearbyRadius", 30]
]
}],
["scanEntryValues", compileFinal {
params [
["_values", [], [[]]],
["_state", createHashMap, [createHashMap]]
];
{
if (_x isEqualType "" && { (_state getOrDefault ["name", "Vehicle Garage"]) isEqualTo "Vehicle Garage" }) then {
_state set ["name", _x];
};
if (_x isEqualType "") then {
private _resolvedObject = _state getOrDefault ["sourceObject", objNull];
if (isNull _resolvedObject) then {
private _namedObject = missionNamespace getVariable [_x, objNull];
if (!isNull _namedObject) then {
_state set ["sourceObject", _namedObject];
};
};
if ((_state getOrDefault ["anchorPosition", []]) isEqualTo [] && { _x in allMapMarkers }) then {
_state set ["anchorPosition", markerPos _x];
};
continue;
};
if (_x isEqualType objNull && { isNull (_state getOrDefault ["sourceObject", objNull]) }) then {
_state set ["sourceObject", _x];
if ((_state getOrDefault ["anchorPosition", []]) isEqualTo []) then {
_state set ["anchorPosition", getPosATL _x];
};
continue;
};
if (_x isEqualType 0 && { (_state getOrDefault ["spawnHeading", -1]) < 0 }) then {
_state set ["spawnHeading", _x];
continue;
};
if (_x isEqualType [] && { count _x > 0 }) then {
if (
{ _x isEqualType 0 } count _x >= 2 &&
{
((_state getOrDefault ["offset", []]) isEqualTo []) ||
((_state getOrDefault ["anchorPosition", []]) isEqualTo [])
}
) then {
if ((_state getOrDefault ["anchorPosition", []]) isEqualTo []) then {
_state set ["anchorPosition", _x];
} else {
_state set ["offset", _x];
};
continue;
};
_self call ["scanEntryValues", [_x, _state]];
};
} forEach _values;
_state
}],
["resolveEntry", compileFinal {
params [["_entry", [], [[]]]];
private _state = createHashMapFromArray [
["name", "Vehicle Garage"],
["anchorPosition", []],
["sourceObject", objNull],
["offset", []],
["spawnHeading", -1]
];
_self call ["scanEntryValues", [_entry, _state]];
private _anchorPosition = _state getOrDefault ["anchorPosition", []];
private _offset = _state getOrDefault ["offset", []];
private _spawnPosition = if (_anchorPosition isEqualTo []) then {
[]
} else {
if (_offset isEqualTo []) then {
_anchorPosition
} else {
_anchorPosition vectorAdd _offset
}
};
createHashMapFromArray [
["name", _state getOrDefault ["name", "Vehicle Garage"]],
["anchorPosition", _anchorPosition],
["sourceObject", _state getOrDefault ["sourceObject", objNull]],
["spawnHeading", _state getOrDefault ["spawnHeading", -1]],
["spawnPosition", _spawnPosition]
]
}],
["resolveContext", compileFinal {
private _context = _self call ["createDefaultContext", []];
private _locations = (missionConfigFile >> "FORGE_CfgGarages" >> "locations") call BFUNC(getCfgData);
if !(_locations isEqualType []) exitWith {
_self set ["lastContext", _context];
_context
};
private _nearestEntry = [];
private _nearestDistance = 1e10;
{
private _entry = _self call ["resolveEntry", [_x]];
private _anchorPosition = _entry getOrDefault ["anchorPosition", []];
if (_anchorPosition isEqualTo []) then {
continue;
};
private _distance = player distance2D _anchorPosition;
if (_distance < _nearestDistance) then {
_nearestDistance = _distance;
_nearestEntry = _entry;
};
} forEach _locations;
if (_nearestEntry isEqualTo []) exitWith {
_self set ["lastContext", _context];
_context
};
private _anchorPosition = _nearestEntry getOrDefault ["anchorPosition", []];
private _garageObject = _nearestEntry getOrDefault ["sourceObject", objNull];
private _garageName = _nearestEntry getOrDefault ["name", "Vehicle Garage"];
private _spawnHeading = _nearestEntry getOrDefault ["spawnHeading", getDir player];
if (_spawnHeading < 0) then {
_spawnHeading = if (!isNull _garageObject) then { getDir _garageObject } else { getDir player };
};
private _spawnPosition = _nearestEntry getOrDefault ["spawnPosition", []];
if (_spawnPosition isEqualTo []) then {
_spawnPosition = if (_anchorPosition isEqualTo []) then {
player getPos [8, _spawnHeading]
} else {
_anchorPosition
};
};
_context set ["name", _garageName];
_context set ["anchorPosition", _anchorPosition];
_context set ["sourceObject", _garageObject];
_context set ["spawnHeading", _spawnHeading];
_context set ["spawnPosition", _spawnPosition];
_self set ["lastContext", _context];
_context
}],
["getContext", compileFinal {
_self call ["resolveContext", []]
}],
["buildPayload", compileFinal {
private _context = _self call ["getContext", []];
private _garageMap = if (isNil QGVAR(GarageClass)) then {
createHashMap
} else {
GVAR(GarageClass) call ["getGarageState", []]
};
private _anchorPosition = _context getOrDefault ["anchorPosition", []];
private _spawnPosition = _context getOrDefault ["spawnPosition", getPosATL player];
private _spawnRadius = _context getOrDefault ["spawnRadius", 6];
private _nearbyRadius = _context getOrDefault ["nearbyRadius", 30];
private _nearbyOrigin = [_anchorPosition, _spawnPosition] select (_anchorPosition isEqualTo []);
private _storedVehicles = [];
private _nearbyVehicles = [];
private _nearbyEntities = [];
private _candidateVehicles = [];
{
_candidateVehicles pushBackUnique _x;
} forEach (_nearbyOrigin nearEntities [["Car", "Tank", "Air", "Ship"], _nearbyRadius]);
{
_candidateVehicles pushBackUnique _x;
} forEach ((getPosATL player) nearEntities [["Car", "Tank", "Air", "Ship"], _nearbyRadius]);
{
_candidateVehicles pushBackUnique _x;
} forEach (nearestObjects [_nearbyOrigin, ["AllVehicles"], _nearbyRadius]);
{
_candidateVehicles pushBackUnique _x;
} forEach (nearestObjects [getPosATL player, ["AllVehicles"], _nearbyRadius]);
{
if (isNull _x) then {
continue;
};
if (_x isKindOf "CAManBase") then {
continue;
};
if !(
_x isKindOf "Car" ||
_x isKindOf "Tank" ||
_x isKindOf "Air" ||
_x isKindOf "Ship"
) then {
continue;
};
_nearbyEntities pushBackUnique _x;
} forEach _candidateVehicles;
{
_storedVehicles pushBack (
GVAR(GarageCatalogService) call ["buildStoredVehicle", [_x, _y]]
);
} forEach _garageMap;
private _storedVehiclePairs = _storedVehicles apply {
[toLowerANSI (_x getOrDefault ["displayName", ""]), _x]
};
_storedVehiclePairs sort true;
_storedVehicles = _storedVehiclePairs apply { _x param [1, createHashMap] };
{
if (isNull _x) then {
continue;
};
private _builtVehicle = GVAR(GarageCatalogService) call ["buildNearbyVehicle", [_x, _nearbyOrigin]];
if (_builtVehicle isEqualTo createHashMap) then {
continue;
};
_nearbyVehicles pushBack _builtVehicle;
} forEach _nearbyEntities;
private _nearbyVehiclePairs = _nearbyVehicles apply {
[_x getOrDefault ["distance", 0], _x]
};
_nearbyVehiclePairs sort true;
_nearbyVehicles = _nearbyVehiclePairs apply { _x param [1, createHashMap] };
private _spawnBlocked = (
(_spawnPosition nearEntities [["Car", "Tank", "Air", "Ship"], _spawnRadius]) +
(nearestObjects [_spawnPosition, ["Car", "Tank", "Air", "Ship"], _spawnRadius])
) isNotEqualTo [];
createHashMapFromArray [
["session", createHashMapFromArray [
["garageName", _context getOrDefault ["name", "Vehicle Garage"]],
["capacityUsed", count _storedVehicles],
["capacityMax", 5],
["nearbyCount", count _nearbyVehicles],
["spawnBlocked", _spawnBlocked],
["spawnStatus", ["Ready", "Blocked"] select _spawnBlocked]
]],
["garage", createHashMapFromArray [
["vehicles", _storedVehicles]
]],
["nearby", createHashMapFromArray [
["vehicles", _nearbyVehicles]
]]
]
}]
];
GVAR(GarageSessionService) = createHashMapObject [GVAR(GarageSessionServiceBaseClass)];
GVAR(GarageSessionService)

View File

@ -3,11 +3,20 @@
/*
* File: fnc_initUIBridge.sqf
* Author: IDSolutions
* Date: 2026-03-14
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the garage UI bridge for browser control state and retrieve/store actions.
* Initializes the garage UI bridge for browser control state and UI events.
*
* Arguments:
* None
*
* Return Value:
* Garage UI bridge object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initUIBridge;
*/
#pragma hemtt ignore_variables ["_self"]
@ -17,10 +26,6 @@ private _webUIBridgeDeclaration = _webUIDeclarations get "bridgeDeclaration";
GVAR(GarageUIBridgeBaseClass) = compileFinal createHashMapFromArray [
["#base", _webUIBridgeDeclaration],
["#type", "GarageUIBridgeBaseClass"],
["#create", compileFinal {
_self set ["pendingStoreVehicle", objNull];
_self set ["pendingRetrieve", createHashMap];
}],
["getActiveBrowserControl", compileFinal {
private _display = uiNamespace getVariable ["RscGarage", displayNull];
if (isNull _display) exitWith {
@ -40,164 +45,13 @@ GVAR(GarageUIBridgeBaseClass) = compileFinal createHashMapFromArray [
_screen call ["markReady", [true]];
_self call ["flushPendingEvents", []];
_self call ["sendEvent", ["garage::hydrate", GVAR(GarageSessionService) call ["buildPayload", []], _control]];
_self call ["sendEvent", ["garage::hydrate", GVAR(GaragePayloadService) call ["buildPayload", []], _control]];
}],
["refreshGarage", compileFinal {
private _control = _self call ["getActiveBrowserControl", []];
if (isNull _control) exitWith { false };
_self call ["sendEvent", ["garage::sync", GVAR(GarageSessionService) call ["buildPayload", []], _control]]
}],
["handleRetrieveRequest", compileFinal {
params [["_data", createHashMap, [createHashMap]]];
private _plate = _data getOrDefault ["plate", ""];
if (_plate isEqualTo "") exitWith {
_self call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [
["message", "Select a stored vehicle to retrieve."]
]]];
};
private _garageMap = if (isNil QGVAR(GarageClass)) then {
createHashMap
} else {
GVAR(GarageClass) call ["getGarageState", []]
};
private _vehicleData = _garageMap getOrDefault [_plate, createHashMap];
if (_vehicleData isEqualTo createHashMap) exitWith {
_self call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [
["message", "Stored vehicle record could not be found."]
]]];
};
private _context = GVAR(GarageSessionService) call ["getContext", []];
private _spawnPosition = _context getOrDefault ["spawnPosition", getPosATL player];
private _spawnHeading = _context getOrDefault ["spawnHeading", getDir player];
private _spawnRadius = _context getOrDefault ["spawnRadius", 6];
private _blockingVehicles = [];
{
_blockingVehicles pushBackUnique _x;
} forEach (_spawnPosition nearEntities [["Car", "Tank", "Air", "Ship"], _spawnRadius]);
{
_blockingVehicles pushBackUnique _x;
} forEach (nearestObjects [_spawnPosition, ["Car", "Tank", "Air", "Ship"], _spawnRadius]);
if (_blockingVehicles isNotEqualTo []) exitWith {
_self call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [
["message", "The garage spawn area is blocked."]
]]];
};
private _className = _vehicleData getOrDefault ["classname", ""];
if (_className isEqualTo "") exitWith {
_self call ["sendEvent", ["garage::retrieve::failure", createHashMapFromArray [
["message", "Stored vehicle record is missing a classname."]
]]];
};
private _vehicle = createVehicle [_className, _spawnPosition, [], 0, "CAN_COLLIDE"];
_vehicle setDir _spawnHeading;
_vehicle setFuel (_vehicleData getOrDefault ["fuel", 0]);
_vehicle setDamage (_vehicleData getOrDefault ["damage", 0]);
private _hitPoints = _vehicleData getOrDefault ["hit_points", createHashMap];
private _hitPointNames = _hitPoints getOrDefault ["names", []];
private _hitPointValues = _hitPoints getOrDefault ["values", []];
for "_index" from 0 to ((count _hitPointNames) - 1) do {
_vehicle setHitPointDamage [_hitPointNames param [_index, ""], _hitPointValues param [_index, 0]];
};
_vehicle setVariable ["forge_garage_plate", _plate, true];
_vehicle setVariable ["forge_garage_owner_uid", getPlayerUID player, true];
_self set ["pendingRetrieve", createHashMapFromArray [
["plate", _plate],
["vehicle", _vehicle]
]];
[SRPC(garage,requestRetrieveVehicle), [getPlayerUID player, _plate]] call CFUNC(serverEvent);
}],
["handleStoreRequest", compileFinal {
params [["_data", createHashMap, [createHashMap]]];
private _netId = _data getOrDefault ["netId", ""];
if (_netId isEqualTo "") exitWith {
_self call ["sendEvent", ["garage::store::failure", createHashMapFromArray [
["message", "Select a nearby vehicle to store."]
]]];
};
private _vehicle = objectFromNetId _netId;
if (isNull _vehicle) exitWith {
_self call ["sendEvent", ["garage::store::failure", createHashMapFromArray [
["message", "The selected vehicle is no longer available."]
]]];
};
if (crew _vehicle isNotEqualTo []) exitWith {
_self call ["sendEvent", ["garage::store::failure", createHashMapFromArray [
["message", "All crew must exit the vehicle before storing it."]
]]];
};
private _rawHitPoints = getAllHitPointsDamage _vehicle;
private _hitPointsJson = toJSON (createHashMapFromArray [
["names", _rawHitPoints param [0, []]],
["selections", _rawHitPoints param [1, []]],
["values", _rawHitPoints param [2, []]]
]);
_self set ["pendingStoreVehicle", _vehicle];
[SRPC(garage,requestStoreVehicle), [
getPlayerUID player,
typeOf _vehicle,
fuel _vehicle,
damage _vehicle,
_hitPointsJson
]] call CFUNC(serverEvent);
}],
["handleActionResponse", compileFinal {
params [["_payload", createHashMap, [createHashMap]]];
private _action = _payload getOrDefault ["action", ""];
private _success = _payload getOrDefault ["success", false];
private _message = _payload getOrDefault ["message", "Garage action failed."];
switch (_action) do {
case "retrieve": {
private _pendingRetrieve = _self getOrDefault ["pendingRetrieve", createHashMap];
private _vehicle = _pendingRetrieve getOrDefault ["vehicle", objNull];
if (!_success && { !isNull _vehicle }) then {
deleteVehicle _vehicle;
};
_self set ["pendingRetrieve", createHashMap];
_self call ["sendEvent", [[
"garage::retrieve::failure",
"garage::retrieve::success"
] select _success, createHashMapFromArray [["message", _message]]]];
};
case "store": {
private _vehicle = _self getOrDefault ["pendingStoreVehicle", objNull];
if (_success && { !isNull _vehicle }) then {
deleteVehicle _vehicle;
};
_self set ["pendingStoreVehicle", objNull];
_self call ["sendEvent", [[
"garage::store::failure",
"garage::store::success"
] select _success, createHashMapFromArray [["message", _message]]]];
};
};
[] spawn {
sleep 0.05;
if !(isNil QGVAR(GarageUIBridge)) then {
GVAR(GarageUIBridge) call ["refreshGarage", []];
};
};
_self call ["sendEvent", ["garage::sync", GVAR(GaragePayloadService) call ["buildPayload", []], _control]]
}]
];

View File

@ -1,51 +1,45 @@
#include "..\script_component.hpp"
/*
* File: fnc_initVGClass.sqf
* File: fnc_initVGRepository.sqf
* Author: IDSolutions
* Date: 2025-12-16
* Last Update: 2026-03-25
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the Virtual Garage class for managing player garage unlocks.
* Provides methods for syncing, saving, and applying virtual items to BIS Garage.
* Initializes the virtual garage repository for BIS virtual garage state.
*
* Arguments:
* None
*
* Return Value:
* vGarage class object [HASHMAP OBJECT]
* Virtual garage repository object [HASHMAP OBJECT]
*
* Example:
* call forge_client_garage_fnc_initVGClass;
* call forge_client_garage_fnc_initVGRepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(VGBaseClass) = compileFinal createHashMapFromArray [
["#type", "VGBaseClass"],
GVAR(VGRepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "VGRepositoryBaseClass"],
["#create", compileFinal {
GVAR(isPreLoaded) = false;
_self set ["uid", (getPlayerUID player)];
_self set ["uid", getPlayerUID player];
_self set ["vGarage", createHashMap];
_self set ["isLoaded", false];
_self set ["lastSave", time];
}],
["init", compileFinal {
private _uid = _self get "uid";
private _vGarage = _self get "vGarage";
[SRPC(garage,requestInitVG), [_uid, _vGarage]] call CFUNC(serverEvent);
[SRPC(garage,requestInitVG), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
systemChat format ["VGarage loaded for %1", (name player)];
diag_log "[FORGE:Client:VGarage] VGarage Class Initialized!";
systemChat format ["VGarage loaded for %1", name player];
diag_log "[FORGE:Client:VGarage] Repository Initialized!";
}],
["save", compileFinal {
private _uid = _self get "uid";
[SRPC(garage,requestSaveVG), [_uid]] call CFUNC(serverEvent);
_self set ["lastSave", time];
}],
["sync", compileFinal {
@ -56,7 +50,6 @@ GVAR(VGBaseClass) = compileFinal createHashMapFromArray [
{
_vGarage set [_x, _y];
switch (_x) do {
case "cars": { _self call ["apply", ["cars"]]; };
case "armor": { _self call ["apply", ["armor"]]; };
@ -69,9 +62,8 @@ GVAR(VGBaseClass) = compileFinal createHashMapFromArray [
} forEach _data;
_self set ["vGarage", _vGarage];
if !(_isLoaded) then { _self set ["isLoaded", true]; };
diag_log "[FORGE:Client:VGarage] Sync completed";
diag_log "[FORGE:Client:VGarage] Repository sync completed";
}],
["get", compileFinal {
params [["_key", "", [""]], ["_default", nil, [[], "", 0, false, createHashMap]]];
@ -84,7 +76,6 @@ GVAR(VGBaseClass) = compileFinal createHashMapFromArray [
private _vehicles = _self call ["get", [_key, []]];
private _appliedVehicles = [];
{
_appliedVehicles append [getText (configFile >> "CfgVehicles" >> _x >> "model"), [configFile >> "CfgVehicles" >> _x]];
} forEach _vehicles;
@ -101,5 +92,5 @@ GVAR(VGBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(VGClass) = createHashMapObject [GVAR(VGBaseClass)];
GVAR(VGClass)
GVAR(VGRepository) = createHashMapObject [GVAR(VGRepositoryBaseClass)];
GVAR(VGRepository)

View File

@ -89,7 +89,7 @@ if !(GVAR(isPreLoaded)) then {
private _nearVehicles = FORGE_VehSpawnPos nearEntities [["Car", "Tank", "Air", "Ship"], 5];
if (_nearVehicles isNotEqualTo []) exitWith {
private _params = ["warning", "Virtual Garage", "Vehicle spawn position is blocked. Please move the vehicle before accessing the garage.", 3000];
EGVAR(notifications,NotificationClass) call ["create", _params];
EGVAR(notifications,NotificationService) call ["create", _params];
};
["Open", true] call BFUNC(garage);

View File

@ -1,2 +1,2 @@
PREP(initLockerClass);
PREP(initVAClass);
PREP(initRepository);
PREP(initVARepository);

View File

@ -1,48 +1,48 @@
#include "script_component.hpp"
if (isNil QGVAR(LockerClass)) then { call FUNC(initLockerClass); };
if (isNil QGVAR(VAClass)) then { call FUNC(initVAClass); };
if (isNil QGVAR(LockerRepository)) then { call FUNC(initRepository); };
if (isNil QGVAR(VARepository)) then { call FUNC(initVARepository); };
[QGVAR(initLocker), {
GVAR(LockerClass) call ["init", []];
GVAR(LockerRepository) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseInitLocker), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(LockerClass) call ["sync", [_data]];
GVAR(LockerRepository) call ["sync", [_data]];
}] call CFUNC(addEventHandler);
[QGVAR(responseSyncLocker), {
params [["_data", createHashMap, [createHashMap, []]], ["_jip", false, [false]]];
GVAR(LockerClass) call ["sync", [_data, _jip]];
GVAR(LockerRepository) call ["sync", [_data, _jip]];
}] call CFUNC(addEventHandler);
[QGVAR(initVA), {
GVAR(VAClass) call ["init", []];
GVAR(VARepository) call ["init", []];
}] call CFUNC(addEventHandler);
[QGVAR(responseInitVA), {
params [["_data", createHashMap, [createHashMap]]];
GVAR(VAClass) call ["sync", [_data]];
GVAR(VARepository) call ["sync", [_data]];
}] call CFUNC(addEventHandler);
[QGVAR(responseSyncVA), {
params [["_data", createHashMap, [createHashMap, []]], ["_jip", false, [false]]];
GVAR(VAClass) call ["sync", [_data, _jip]];
GVAR(VARepository) call ["sync", [_data, _jip]];
}] call CFUNC(addEventHandler);
[{
EGVAR(garage,GarageClass) get "isLoaded";
EGVAR(garage,GarageRepository) get "isLoaded";
}, {
[QGVAR(initLocker), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);
[{
GVAR(LockerClass) get "isLoaded";
GVAR(LockerRepository) get "isLoaded";
}, {
[QGVAR(initVA), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);

View File

@ -1,31 +1,29 @@
#include "..\script_component.hpp"
/*
* File: fnc_initLockerClass.sqf
* File: fnc_initRepository.sqf
* Author: IDSolutions
* Date: 2025-12-17
* Last Update: 2026-03-25
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the Locker class for managing player locker items.
* Provides methods for syncing, saving, and applying locker items to the player's locker.
* Initializes the locker repository for managing player locker items.
*
* Arguments:
* None
*
* Return Value:
* Locker class object [HASHMAP OBJECT]
* Locker repository object [HASHMAP OBJECT]
*
* Example:
* call forge_client_locker_fnc_initLockerClass
* call forge_client_locker_fnc_initRepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
["#type", "LockerBaseClass"],
GVAR(LockerRepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "LockerRepositoryBaseClass"],
["#create", compileFinal {
_self set ["uid", (getPlayerUID player)];
_self set ["uid", getPlayerUID player];
_self set ["isLoaded", false];
_self set ["lastSave", time];
_self set ["locker", createHashMap];
@ -36,8 +34,8 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
[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!";
systemChat format ["Locker loaded for %1", name player];
diag_log "[FORGE:Client:Locker] Locker Repository Initialized!";
}],
["get", compileFinal {
params [["_key", "", [""]], ["_default", nil, [[], "", 0, false, createHashMap]]];
@ -84,8 +82,8 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
private _cfgWeapons = configFile >> "CfgWeapons" >> _containerClass;
private _itemInfoType = getNumber (_cfgWeapons >> "ItemInfo" >> "type");
private _isBackpack = isClass _cfgVehicles;
private _isUniform = isClass _cfgWeapons && {_itemInfoType == TYPE_UNIFORM};
private _isVest = isClass _cfgWeapons && {_itemInfoType == TYPE_VEST};
private _isUniform = isClass _cfgWeapons && { _itemInfoType == TYPE_UNIFORM };
private _isVest = isClass _cfgWeapons && { _itemInfoType == TYPE_VEST };
if (!_isBackpack && !_isVest && !_isUniform) then { continue; };
@ -142,7 +140,6 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
private _weaponItems = weaponsItemsCargo _container;
{
// private _weapon = _x param [0, ""];
private _muzzle = _x param [1, ""];
private _pointer = _x param [2, ""];
private _optic = _x param [3, ""];
@ -150,7 +147,7 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
private _underbarrel = _x param [5, ""];
private _bipod = _x param [6, ""];
private _secondaryMag = _x param [7, ["", 0]];
private _attachments = [_muzzle, _pointer, _optic, _underbarrel, _bipod] select {(_x isEqualType "") && {_x != ""}};
private _attachments = [_muzzle, _pointer, _optic, _underbarrel, _bipod] select { (_x isEqualType "") && { _x != "" } };
{
private _existing = _locker getOrDefault [_x, createHashMap];
private _existingCount = _existing getOrDefault ["amount", 0];
@ -163,7 +160,7 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
} forEach _attachments;
if (_primaryMag isNotEqualTo ["", 0]) then {
_primaryMag params ["_magClass", "_ammoCount"]; // TODO: Add ammo count to locker
_primaryMag params ["_magClass", "_ammoCount"];
if (_magClass != "") then {
private _existing = _locker getOrDefault [_magClass, createHashMap];
private _existingCount = _existing getOrDefault ["amount", 0];
@ -177,7 +174,7 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
};
if (_secondaryMag isNotEqualTo ["", 0]) then {
_secondaryMag params ["_magClass", "_ammoCount"]; // TODO: Add ammo count to locker
_secondaryMag params ["_magClass", "_ammoCount"];
if (_magClass != "") then {
private _existing = _locker getOrDefault [_magClass, createHashMap];
private _existingCount = _existing getOrDefault ["amount", 0];
@ -205,7 +202,7 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
_locker addEventHandler ["ContainerOpened", {
params ["_container", "_unit"];
private _index = GVAR(LockerClass) get "locker";
private _index = GVAR(LockerRepository) get "locker";
clearBackpackCargo _container;
clearItemCargo _container;
@ -228,7 +225,7 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
if (count _index > 25) then {
private _params = ["warning", "Over Capacity", "Locker has more then 25 items, please remove some items", 3000];
GVAR(NotificationClass) call ["create", _params];
GVAR(NotificationService) call ["create", _params];
};
}];
@ -236,17 +233,17 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
params ["_container", "_unit"];
private _newLocker = createHashMap;
_newLocker = GVAR(LockerClass) call ["getCargo", [_container, _newLocker]];
_newLocker = GVAR(LockerClass) call ["getContainerItems", [_container, _newLocker]];
_newLocker = GVAR(LockerClass) call ["getAttachments", [_container, _newLocker]];
_newLocker = GVAR(LockerRepository) call ["getCargo", [_container, _newLocker]];
_newLocker = GVAR(LockerRepository) call ["getContainerItems", [_container, _newLocker]];
_newLocker = GVAR(LockerRepository) call ["getAttachments", [_container, _newLocker]];
private _uid = getPlayerUID _unit;
[SRPC(locker,requestOverrideLocker), [_uid, _newLocker]] call CFUNC(serverEvent);
GVAR(LockerClass) set ["locker", _newLocker];
GVAR(LockerRepository) set ["locker", _newLocker];
if (count _newLocker > 25) then {
private _params = ["warning", "Over Capacity", "Locker has more then 25 items, please remove some items", 3000];
GVAR(NotificationClass) call ["create", _params];
GVAR(NotificationService) call ["create", _params];
};
}];
}],
@ -296,5 +293,5 @@ GVAR(LockerBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(LockerClass) = createHashMapObject [GVAR(LockerBaseClass)];
GVAR(LockerClass)
GVAR(LockerRepository) = createHashMapObject [GVAR(LockerRepositoryBaseClass)];
GVAR(LockerRepository)

View File

@ -1,31 +1,29 @@
#include "..\script_component.hpp"
/*
* File: fnc_init.sqf
* File: fnc_initVARepository.sqf
* Author: IDSolutions
* Date: 2025-12-16
* Last Update: 2026-03-25
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the Virtual Arsenal class for managing player arsenal unlocks.
* Provides methods for syncing, saving, and applying virtual items to BIS Arsenal.
* Initializes the virtual arsenal repository for managing player arsenal unlocks.
*
* Arguments:
* None
*
* Return Value:
* vArsenal class object [HASHMAP OBJECT]
* Virtual arsenal repository object [HASHMAP OBJECT]
*
* Example:
* call forge_client_locker_fnc_init;
* call forge_client_locker_fnc_initVARepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(VABaseClass) = compileFinal createHashMapFromArray [
["#type", "VABaseClass"],
GVAR(VARepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "VARepositoryBaseClass"],
["#create", compileFinal {
_self set ["uid", (getPlayerUID player)];
_self set ["uid", getPlayerUID player];
_self set ["vArsenal", createHashMap];
_self set ["isLoaded", false];
_self set ["lastSave", time];
@ -36,8 +34,8 @@ GVAR(VABaseClass) = compileFinal createHashMapFromArray [
[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!";
systemChat format ["VArsenal loaded for %1", name player];
diag_log "[FORGE:Client:VArsenal] Repository Initialized!";
}],
["save", compileFinal {
private _uid = _self get "uid";
@ -92,5 +90,5 @@ GVAR(VABaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(VAClass) = createHashMapObject [GVAR(VABaseClass)];
GVAR(VAClass)
GVAR(VARepository) = createHashMapObject [GVAR(VARepositoryBaseClass)];
GVAR(VARepository)

View File

@ -1,3 +1,3 @@
PREP(handleUIEvents);
PREP(initNotificationClass);
PREP(initService);
PREP(openUI);

View File

@ -1,16 +1,16 @@
#include "script_component.hpp"
[{
EGVAR(locker,VAClass) get "isLoaded";
EGVAR(locker,VARepository) get "isLoaded";
}, {
("NotificationHudLayer" call BFUNC(rscLayer)) cutRsc ["RscNotifications", "PLAIN"];
call FUNC(openUI);
if (isNil QGVAR(NotificationClass)) then { call FUNC(initNotificationClass); };
if (isNil QGVAR(NotificationService)) then { call FUNC(initService); };
}] call CFUNC(waitUntilAndExecute);
[QGVAR(recieveNotification), {
params [["_type", "", [""]], ["_title", "", [""]], ["_content", "", [""]], ["_duration", 4000, [4000]]];
playSound QGVAR(notify);
GVAR(NotificationClass) call ["create", [_type, _title, _content, _duration]];
GVAR(NotificationService) call ["create", [_type, _title, _content, _duration]];
}] call CFUNC(addEventHandler);

View File

@ -32,7 +32,7 @@ diag_log format ["[FORGE:Client:Notifications] Handling UI event: %1 with data:
switch (_event) do {
case "notifications::ready": {
GVAR(NotificationClass) call ["init", []];
GVAR(NotificationService) call ["init", []];
};
default { hint format ["[FORGE:Client:Notifications] Unhandled event: %1", _event]; };
};

View File

@ -1,29 +1,27 @@
#include "..\script_component.hpp"
/*
* File: fnc_initNotificationClass.sqf
* File: fnc_initService.sqf
* Author: IDSolutions
* Date: 2026-01-28
* Last Update: 2026-01-30
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the notification class for managing player notifications.
* Provides methods for creating and displaying notifications.
* Initializes the notification service for client notification display.
*
* Arguments:
* None
*
* Return Value:
* Notification class object [HASHMAP OBJECT]
* Notification service object [HASHMAP OBJECT]
*
* Example:
* call forge_client_notifications_fnc_initNotificationClass
* call forge_client_notifications_fnc_initService;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(NotificationClass) = createHashMapObject [[
["#type", "INotificationClass"],
GVAR(NotificationService) = createHashMapObject [[
["#type", "INotificationService"],
["#create", {
private _display = uiNamespace getVariable ["RscNotifications", nil];
private _control = _display displayCtrl 1004;
@ -37,8 +35,8 @@ GVAR(NotificationClass) = createHashMapObject [[
_self call ["create", _params];
_self set ["isLoaded", true];
systemChat format ["Notifications loaded for %1", (name player)];
diag_log "[FORGE:Client:Notifications] Notification Class Initialized!";
systemChat format ["Notifications loaded for %1", name player];
diag_log "[FORGE:Client:Notifications] Notification Service Initialized!";
}],
["create", {
params [["_type", "", ["info"]], ["_title", "", [""]], ["_content", "", [""]], ["_duration", 4000]];
@ -55,4 +53,4 @@ GVAR(NotificationClass) = createHashMapObject [[
}]
]];
GVAR(NotificationClass)
GVAR(NotificationService)

View File

@ -1,4 +1,4 @@
PREP(handleUIEvents);
PREP(initClass);
PREP(initRepository);
PREP(initUIBridge);
PREP(openUI);

View File

@ -1,6 +1,6 @@
#include "script_component.hpp"
if (isNil QGVAR(OrgClass)) then { call FUNC(initClass); };
if (isNil QGVAR(OrgRepository)) then { call FUNC(initRepository); };
if (isNil QGVAR(OrgUIBridge)) then { call FUNC(initUIBridge); };
[QGVAR(responseInitOrg), {
@ -46,7 +46,7 @@ if (isNil QGVAR(OrgUIBridge)) then { call FUNC(initUIBridge); };
}] call CFUNC(addEventHandler);
[{
EGVAR(locker,VAClass) get "isLoaded";
EGVAR(locker,VARepository) get "isLoaded";
}, {
[QGVAR(initOrg), []] call CFUNC(localEvent);
}] call CFUNC(waitUntilAndExecute);

View File

@ -1,19 +1,24 @@
#include "..\script_component.hpp"
/*
* File: fnc_handleUIEvents.sqf
* Author: IDSolutions
* Handles the UI events.
* Date: 2026-03-27
* Public: No
*
* Description:
* Handles the org UI events.
*
* Arguments:
* None
* 0: [CONTROL] - The control that triggered the event
* 1: [BOOL] - Whether the event is from a confirm dialog
* 2: [STRING] - The message containing the event data
*
* Return Value:
* None
* UI events handled [BOOL]
*
* Example:
* call forge_client_org_fnc_handleUIEvents;
*
* Public: No
*/
params ["_control", "_isConfirmDialog", "_message"];

View File

@ -1,28 +1,27 @@
#include "..\script_component.hpp"
/*
* File: fnc_initClass.sqf
* File: fnc_initRepository.sqf
* Author: IDSolutions
* Date: 2026-03-25
* Last Update: 2026-03-25
* Date: 2026-03-27
* Public: No
*
* Description:
* No description added yet.
* Initializes the org repository for client org lifecycle state.
*
* Parameter(s):
* N/A
* Arguments:
* None
*
* Returns:
* Something [BOOL]
* Return Value:
* Org repository object [HASHMAP OBJECT]
*
* Example(s):
* [parameter] call forge_x_component_fnc_myFunction
* Example:
* call forge_client_org_fnc_initRepository;
*/
#pragma hemtt ignore_variables ["_self"]
GVAR(OrgBaseClass) = compileFinal createHashMapFromArray [
["#type", "OrgBaseClass"],
GVAR(OrgRepositoryBaseClass) = compileFinal createHashMapFromArray [
["#type", "OrgRepositoryBaseClass"],
["#create", compileFinal {
_self set ["uid", getPlayerUID player];
_self set ["isLoaded", false];
@ -32,12 +31,11 @@ GVAR(OrgBaseClass) = compileFinal createHashMapFromArray [
[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!";
systemChat format ["Org loaded for %1", name player];
diag_log "[FORGE:Client:Org] Org Repository Initialized!";
}],
["markLoaded", compileFinal {
if !(_self getOrDefault ["isLoaded", false]) then { _self set ["isLoaded", true]; };
true
}],
["save", compileFinal {
@ -46,5 +44,5 @@ GVAR(OrgBaseClass) = compileFinal createHashMapFromArray [
}]
];
GVAR(OrgClass) = createHashMapObject [GVAR(OrgBaseClass)];
GVAR(OrgClass)
GVAR(OrgRepository) = createHashMapObject [GVAR(OrgRepositoryBaseClass)];
GVAR(OrgRepository)

View File

@ -1,19 +1,22 @@
#include "..\script_component.hpp"
/*
* File: fnc_openUI.sqf
* Author: IDSolutions
* Opens the player interaction interface.
* Date: 2026-03-27
* Public: No
*
* Description:
* Opens the org UI.
*
* Arguments:
* None
*
* Return Value:
* None
* UI opened [BOOL]
*
* Example:
* call forge_client_org_fnc_openUI;
*
* Public: No
*/
private _display = createDialog ["RscOrg", true];

View File

@ -3,12 +3,20 @@
/*
* File: fnc_initUIBridge.sqf
* Author: IDSolutions
* Date: 2026-03-10
* Last Update: 2026-03-25
* Date: 2026-03-27
* Public: No
*
* Description:
* Initializes the store UI bridge for browser control state, event routing, and catalog queries.
* Initializes the store UI bridge for browser control state and store UI events.
*
* Arguments:
* None
*
* Return Value:
* Store UI bridge object [HASHMAP OBJECT]
*
* Example:
* call forge_client_store_fnc_initUIBridge;
*/
#pragma hemtt ignore_variables ["_self"]

View File

@ -185,6 +185,12 @@ GVAR(OrgBaseStore) = compileFinal createHashMapFromArray [
};
if (_org isEqualTo createHashMap) exitWith { createHashMap };
// Ensure the requesting player's membership is present in the cached roster
// before shaping the portal payload. This prevents stale org caches from
// omitting the current member while still resolving owner metadata.
_org = _self call ["verifyMember", [_org, _orgID, _uid, _player, _actor]];
GVAR(Registry) set [_orgID, _org, true];
private _name = _org getOrDefault ["name", ""];
private _id = _org getOrDefault ["id", _orgID];
private _ownerUid = _org getOrDefault ["owner", ""];

View File

@ -10,6 +10,9 @@
.PARAMETER Target
Specify which target to build: 'client', 'server', or 'both' (default)
.PARAMETER BuildUI
Rebuild the web UI bundles before running the client build.
.EXAMPLE
.\build-arma.ps1
Builds both client and server
@ -17,12 +20,19 @@
.EXAMPLE
.\build-arma.ps1 -Target client
Builds only the client
.EXAMPLE
.\build-arma.ps1 -Target client -BuildUI
Rebuilds web UI bundles and then builds the client
#>
param(
[Parameter(Mandatory=$false)]
[ValidateSet('client', 'server', 'both')]
[string]$Target = 'both'
[string]$Target = 'both',
[Parameter(Mandatory=$false)]
[switch]$BuildUI
)
$ErrorActionPreference = "Stop"
@ -70,7 +80,9 @@ $serverPath = Join-Path $scriptDir "arma\server"
try {
if ($Target -eq 'client' -or $Target -eq 'both') {
Build-WebUIAssets
if ($BuildUI) {
Build-WebUIAssets
}
Build-HemttProject -ProjectPath $clientPath -ProjectName "Client"
}