- replace placeholder garage interaction with real UI open flow - add catalog/session/UI bridge services for hydrate, sync, store, and retrieve actions - migrate garage web UI bundle to new app shell/runtime structure - align org/store function naming with shared init and UI bridge patterns
299 lines
11 KiB
Plaintext
299 lines
11 KiB
Plaintext
#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)
|