#include "..\script_component.hpp" /* * File: fnc_initStore.sqf * Author: IDSolutions * Date: 2025-12-17 * Last Update: 2026-03-16 * Public: No * * Description: * Initializes the bank store for managing player bank accounts. * Handles account lifecycle (init/fetch/create/migrate), transaction * mutations, checkout charges, and session hydration. * * Parameter(s): * None * * Returns: * Bank store object [HASHMAP OBJECT] * * Example(s): * call forge_server_bank_fnc_initStore */ #pragma hemtt ignore_variables ["_self"] GVAR(BankBaseStore) = compileFinal createHashMapFromArray [ ["#base", EGVAR(common,BaseStore)], ["#type", "BankBaseStore"], ["#create", compileFinal { GVAR(IndexRegistry) = createHashMap; GVAR(Registry) = createHashMap; GVAR(SessionRegistry) = createHashMap; ["INFO", "Bank Store Initialized!"] call EFUNC(common,log); }], ["buildChargeResult", compileFinal { params [["_message", "Unable to process bank payment.", [""]]]; createHashMapFromArray [ ["success", false], ["message", _message], ["patch", createHashMap] ] }], ["buildHydratePayload", compileFinal { params [["_uid", "", [""]], ["_mode", "", [""]], ["_resetAuthorization", false, [false]]]; if (_uid isEqualTo "") exitWith { createHashMap }; private _account = GVAR(Registry) getOrDefault [_uid, createHashMap]; if (_account isEqualTo createHashMap) then { _account = _self call ["init", [_uid]]; }; if (_account isEqualTo createHashMap) exitWith { createHashMap }; private _session = GVAR(BankSessionManager) call ["syncSessionMode", [_uid, _mode, _resetAuthorization]]; private _orgState = _self call ["resolveOrgState", [_uid]]; private _player = [_uid] call EFUNC(common,getPlayer); private _playerName = if (isNull _player) then { _account getOrDefault ["name", "Unknown"] } else { name _player }; createHashMapFromArray [ ["session", createHashMapFromArray [ ["atmAuthorized", _session getOrDefault ["atmAuthorized", false]], ["mode", _session getOrDefault ["mode", "bank"]], ["orgFunds", _orgState getOrDefault ["funds", 0]], ["orgName", _orgState getOrDefault ["name", ""]], ["playerName", _playerName], ["transferTargets", _self call ["buildTransferTargets", [_uid]]], ["uid", _uid] ]], ["account", GVAR(BankMessenger) call ["buildClientAccountPatch", [_account]]] ] }], ["buildTransferTargets", compileFinal { params [["_sourceUid", "", [""]]]; private _targets = []; { if (isNull _x) then { continue; }; private _targetUid = getPlayerUID _x; private _targetName = name _x; if (_targetUid isEqualTo "" || { _targetUid isEqualTo _sourceUid } || { _targetName isEqualTo "" }) then { continue; }; _targets pushBack (createHashMapFromArray [ ["name", _targetName], ["uid", _targetUid] ]); } forEach allPlayers; private _targetPairs = _targets apply { [toLowerANSI (_x getOrDefault ["name", ""]), _x] }; _targetPairs sort true; _targetPairs apply { _x param [1, createHashMap] } }], ["chargeCheckout", compileFinal { params [["_uid", "", [""]], ["_source", "cash", [""]], ["_amount", 0, [0]], ["_commit", false, [false]]]; private _result = _self call ["buildChargeResult", []]; private _field = switch (toLowerANSI _source) do { case "cash": { "cash" }; case "bank": { "bank" }; default { "" }; }; if (_field isEqualTo "") exitWith { _result set ["message", "Selected bank payment source is unsupported."]; _result }; private _account = GVAR(Registry) getOrDefault [_uid, createHashMap]; if (_account isEqualTo createHashMap) exitWith { _result set ["message", "Bank account data is unavailable for checkout."]; _result }; private _balance = _account getOrDefault [_field, 0]; if (_balance < _amount) exitWith { private _message = [ "Bank balance cannot cover this checkout.", "Cash on hand cannot cover this checkout." ] select (_field isEqualTo "cash"); _result set ["message", _message]; _result }; private _patch = createHashMapFromArray [[_field, (_balance - _amount)]]; if (_commit) then { _patch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _patch, false]]; }; _result set ["success", true]; _result set ["message", ""]; _result set ["patch", _patch]; _result }], ["deposit", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]], ["_context", createHashMap, [createHashMap]]]; ["INFO", format ["Deposit %1, for %2", _amount, _uid]] call EFUNC(common,log); private _bank = _context getOrDefault ["bank", 0]; private _cash = _context getOrDefault ["cash", 0]; private _patch = createHashMapFromArray [ ["bank", (_bank + _amount)], ["cash", (_cash - _amount)] ]; private _finalPatch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _patch, false]]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalPatch]]; GVAR(BankMessenger) call ["sendClientNotification", [_uid, "info", "Bank", format ["Deposited $%1", _amount]]]; true }], ["hydrateSession", compileFinal { params [["_uid", "", [""]], ["_mode", "", [""]], ["_resetAuthorization", false, [false]]]; private _payload = _self call ["buildHydratePayload", [_uid, _mode, _resetAuthorization]]; if (_payload isEqualTo createHashMap) exitWith { false }; private _player = [_uid] call EFUNC(common,getPlayer); if (isNull _player) exitWith { false }; [CRPC(bank,responseHydrateBank), [_payload], _player] call CFUNC(targetEvent); true }], ["init", compileFinal { params [["_uid", "", [""]]]; if (_uid isEqualTo "") exitWith { createHashMap }; private _player = [_uid] call EFUNC(common,getPlayer); private _playerName = if (isNull _player) then { "Unknown" } else { name _player }; private _cached = GVAR(Registry) getOrDefault [_uid, createHashMap]; if (_cached isNotEqualTo createHashMap) exitWith { GVAR(BankMessenger) call ["sendAccountSync", [_uid, _cached, CRPC(bank,responseInitBank)]]; _cached }; ["bank:exists", [_uid]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"]; if !(_isSuccess) exitWith { ["ERROR", format ["Failed to check if bank account %1 exists! Using fallback account.", _uid]] call EFUNC(common,log); private _fallbackAccount = GVAR(BankModel) call ["fromPlayer", [_player]]; _fallbackAccount set ["uid", _uid]; if ((_fallbackAccount getOrDefault ["name", ""]) isEqualTo "") then { _fallbackAccount set ["name", _playerName]; }; private _regEntry = createHashMapFromArray [["uid", _uid], ["name", _playerName]]; GVAR(IndexRegistry) set [_uid, _regEntry]; GVAR(Registry) set [_uid, _fallbackAccount]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _fallbackAccount, CRPC(bank,responseInitBank)]]; _fallbackAccount }; private _finalAccount = createHashMap; if (_result isEqualTo "true") then { _finalAccount = _self call ["fetch", ["bank:get", _uid]]; ["INFO", format ["Found bank account for %1", _uid]] call EFUNC(common,log); } else { _finalAccount = GVAR(BankModel) call ["fromPlayer", [_player]]; _finalAccount set ["uid", _uid]; if ((_finalAccount getOrDefault ["name", ""]) isEqualTo "") then { _finalAccount set ["name", _playerName]; }; private _json = _self call ["toJSON", [_finalAccount]]; ["bank:create", [_uid, _json]] call EFUNC(extension,extCall) params ["_createResult", "_createSuccess"]; if (!_createSuccess) exitWith { ["ERROR", format ["Failed to create bank account %1! Using fallback account.", _uid]] call EFUNC(common,log); private _regEntry = createHashMapFromArray [["uid", _uid], ["name", _playerName]]; GVAR(IndexRegistry) set [_uid, _regEntry]; GVAR(Registry) set [_uid, _finalAccount]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalAccount, CRPC(bank,responseInitBank)]]; _finalAccount }; ["INFO", format ["Created new bank account for %1", _uid]] call EFUNC(common,log); }; _finalAccount = GVAR(BankModel) call ["migrate", [_finalAccount]]; if ((_finalAccount getOrDefault ["uid", ""]) isEqualTo "") then { _finalAccount set ["uid", _uid]; }; if ((_finalAccount getOrDefault ["name", ""]) isEqualTo "") then { _finalAccount set ["name", _playerName]; }; GVAR(IndexRegistry) set [_uid, createHashMapFromArray [["uid", _uid], ["name", _playerName]]]; GVAR(Registry) set [_uid, _finalAccount]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalAccount, CRPC(bank,responseInitBank)]]; _finalAccount }], ["payment", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]], ["_context", createHashMap, [createHashMap]]]; ["INFO", format ["Payment %1, for %2", _amount, _uid]] call EFUNC(common,log); private _bank = _context getOrDefault ["bank", 0]; private _patch = createHashMapFromArray [["bank", (_bank + _amount)]]; private _finalPatch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _patch, false]]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalPatch]]; GVAR(BankMessenger) call ["sendClientNotification", [_uid, "info", "Bank", format ["Paid $%1", _amount]]]; true }], ["resolveOrgState", compileFinal { params [["_uid", "", [""]]]; private _defaultState = createHashMapFromArray [ ["funds", 0], ["name", ""] ]; if (_uid isEqualTo "") exitWith { _defaultState }; 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"]]; }; if (_org isEqualTo createHashMap) exitWith { _defaultState }; createHashMapFromArray [ ["funds", _org getOrDefault ["funds", 0]], ["name", _org getOrDefault ["name", ""]] ] }], ["transfer", compileFinal { params [["_uid", "", [""]], ["_target", "", [""]], ["_amount", 0, [0]], ["_context", createHashMap, [createHashMap]]]; private _account = _context getOrDefault ["account", createHashMap]; private _targetAccount = _context getOrDefault ["targetAccount", createHashMap]; private _sourceField = _context getOrDefault ["sourceField", "bank"]; private _selected = _context getOrDefault ["sourceBalance", 0]; private _targetBank = _context getOrDefault ["targetBank", 0]; private _sourcePatch = createHashMapFromArray [[_sourceField, (_selected - _amount)]]; private _targetPatch = createHashMapFromArray [["bank", (_targetBank + _amount)]]; private _finalSourcePatch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _sourcePatch, false]]; private _finalTargetPatch = _self call ["mset", [GVAR(Registry), "bank:update", _target, _targetPatch, false]]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalSourcePatch]]; GVAR(BankMessenger) call ["sendAccountSync", [_target, _finalTargetPatch]]; private _targetPlayer = [_target] call EFUNC(common,getPlayer); private _targetName = if (isNull _targetPlayer) then { _targetAccount getOrDefault ["name", "Recipient"] } else { name _targetPlayer }; private _player = [_uid] call EFUNC(common,getPlayer); private _playerName = if (isNull _player) then { _account getOrDefault ["name", "Unknown"] } else { name _player }; GVAR(BankMessenger) call ["sendClientNotification", [_uid, "info", "Bank", format ["Transferred $%1 to %2", _amount, _targetName]]]; GVAR(BankMessenger) call ["sendClientNotification", [_target, "info", "Bank", format ["Received $%1 from %2", _amount, _playerName]]]; true }], ["withdraw", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]], ["_context", createHashMap, [createHashMap]]]; ["INFO", format ["Withdraw %1, for %2", _amount, _uid]] call EFUNC(common,log); private _bank = _context getOrDefault ["bank", 0]; private _cash = _context getOrDefault ["cash", 0]; private _patch = createHashMapFromArray [ ["bank", (_bank - _amount)], ["cash", (_cash + _amount)] ]; private _finalPatch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _patch, false]]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalPatch]]; GVAR(BankMessenger) call ["sendClientNotification", [_uid, "info", "Bank", format ["Withdrew $%1", _amount]]]; true }], ["depositEarnings", compileFinal { params [["_uid", "", [""]], ["_amount", 0, [0]], ["_context", createHashMap, [createHashMap]]]; ["INFO", format ["Deposit Earnings %1, for %2", _amount, _uid]] call EFUNC(common,log); private _bank = _context getOrDefault ["bank", 0]; private _earnings = _context getOrDefault ["earnings", 0]; private _patch = createHashMapFromArray [ ["bank", (_bank + _amount)], ["earnings", (_earnings - _amount)] ]; private _finalPatch = _self call ["mset", [GVAR(Registry), "bank:update", _uid, _patch, false]]; GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalPatch]]; GVAR(BankMessenger) call ["sendClientNotification", [_uid, "info", "Bank", format ["Deposited $%1 from earnings", _amount]]]; true }] ]; GVAR(BankStore) = createHashMapObject [GVAR(BankBaseStore)]; GVAR(BankStore)