- Split BankBaseStore into SessionManager, Messenger, Model, Store, Validator - Extract validation logic into BankValidator with try/catch and per-action methods - Remove duplicate notifications from transaction actions - Update event handlers to call validator first, forward context to store/session - Fix locker grantItems: add missing 'attachment' category mapping to 'item' - Fix locker grantItems: replace exitWith with if/else to prevent skipping remaining items Co-Authored-By: Oz <oz-agent@warp.dev>
260 lines
10 KiB
Plaintext
260 lines
10 KiB
Plaintext
#include "..\script_component.hpp"
|
|
|
|
/*
|
|
* File: fnc_validator.sqf
|
|
* Author: IDSolutions
|
|
* Date: 2026-03-16
|
|
* Last Update: 2026-03-16
|
|
* Public: No
|
|
*
|
|
* Description:
|
|
* Initializes the bank validator for pre-checking action payloads
|
|
* before they reach the bank store. Each method uses try/catch to
|
|
* validate inputs and state, sending a notice to the player on
|
|
* failure and returning false. On success returns a context hashmap
|
|
* containing resolved data (account, balances, etc.) for the store.
|
|
*
|
|
* Parameter(s):
|
|
* None
|
|
*
|
|
* Returns:
|
|
* Validator object [HASHMAP OBJECT]
|
|
*
|
|
* Example(s):
|
|
* call forge_server_bank_fnc_validator
|
|
*/
|
|
|
|
#pragma hemtt ignore_variables ["_self"]
|
|
GVAR(BankValidator) = createHashMapObject [[
|
|
["#type", "BankValidator"],
|
|
["resolveAccount", compileFinal {
|
|
params [["_uid", "", [""]]];
|
|
|
|
private _account = GVAR(Registry) getOrDefault [_uid, createHashMap];
|
|
if (_account isEqualTo createHashMap) then {
|
|
throw "Bank account data is unavailable.";
|
|
};
|
|
|
|
_account
|
|
}],
|
|
["validateDeposit", compileFinal {
|
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
|
|
private _context = createHashMap;
|
|
|
|
[_uid, _amount] try {
|
|
if (_uid isEqualTo "") then { throw "Empty/Invalid UID!" };
|
|
if (_amount <= 0) then { throw "Enter a valid deposit amount." };
|
|
|
|
private _session = GVAR(BankSessionManager) call ["getSessionState", [_uid]];
|
|
if ((_session getOrDefault ["mode", "bank"]) isEqualTo "atm") then {
|
|
if !(_session getOrDefault ["atmAuthorized", false]) then {
|
|
throw "ATM authorization is required before deposit.";
|
|
};
|
|
};
|
|
|
|
private _account = _self call ["resolveAccount", [_uid]];
|
|
private _bank = _account getOrDefault ["bank", 0];
|
|
private _cash = _account getOrDefault ["cash", 0];
|
|
|
|
if (_cash < _amount) then { throw "Cash on hand cannot cover that deposit." };
|
|
|
|
_context set ["account", _account];
|
|
_context set ["bank", _bank];
|
|
_context set ["cash", _cash];
|
|
} catch {
|
|
["ERROR", format ["Deposit validation failed: %1", _exception]] call EFUNC(common,log);
|
|
GVAR(BankMessenger) call ["sendNotice", [_uid, "error", _exception]];
|
|
};
|
|
|
|
if (_context isEqualTo createHashMap) exitWith { false };
|
|
_context
|
|
}],
|
|
["validateWithdraw", compileFinal {
|
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
|
|
private _context = createHashMap;
|
|
|
|
[_uid, _amount] try {
|
|
if (_uid isEqualTo "") then { throw "Empty/Invalid UID!" };
|
|
if (_amount <= 0) then { throw "Enter a valid withdrawal amount." };
|
|
|
|
private _session = GVAR(BankSessionManager) call ["getSessionState", [_uid]];
|
|
if ((_session getOrDefault ["mode", "bank"]) isEqualTo "atm") then {
|
|
if !(_session getOrDefault ["atmAuthorized", false]) then {
|
|
throw "ATM authorization is required before withdrawal.";
|
|
};
|
|
};
|
|
|
|
private _account = _self call ["resolveAccount", [_uid]];
|
|
private _bank = _account getOrDefault ["bank", 0];
|
|
private _cash = _account getOrDefault ["cash", 0];
|
|
|
|
if (_bank < _amount) then { throw "Bank balance cannot cover that withdrawal." };
|
|
|
|
_context set ["account", _account];
|
|
_context set ["bank", _bank];
|
|
_context set ["cash", _cash];
|
|
} catch {
|
|
["ERROR", format ["Withdraw validation failed: %1", _exception]] call EFUNC(common,log);
|
|
GVAR(BankMessenger) call ["sendNotice", [_uid, "error", _exception]];
|
|
};
|
|
|
|
if (_context isEqualTo createHashMap) exitWith { false };
|
|
_context
|
|
}],
|
|
["validateTransfer", compileFinal {
|
|
params [["_uid", "", [""]], ["_target", "", [""]], ["_from", "", [""]], ["_amount", 0, [0]]];
|
|
|
|
private _context = createHashMap;
|
|
|
|
[_uid, _target, _from, _amount] try {
|
|
if (_uid isEqualTo "") then { throw "Empty/Invalid UID!" };
|
|
if (_uid isEqualTo _target) then { throw "You cannot transfer funds to yourself." };
|
|
if (_amount <= 0) then { throw "Enter a valid transfer amount." };
|
|
|
|
private _session = GVAR(BankSessionManager) call ["getSessionState", [_uid]];
|
|
if ((_session getOrDefault ["mode", "bank"]) isNotEqualTo "bank") then {
|
|
throw "Transfers are only available from the full bank interface.";
|
|
};
|
|
|
|
private _account = _self call ["resolveAccount", [_uid]];
|
|
|
|
private _targetAccount = GVAR(Registry) getOrDefault [_target, createHashMap];
|
|
if (_targetAccount isEqualTo createHashMap) then {
|
|
_targetAccount = GVAR(BankStore) call ["init", [_target]];
|
|
};
|
|
if (_targetAccount isEqualTo createHashMap) then {
|
|
throw "Selected transfer recipient is unavailable.";
|
|
};
|
|
|
|
private _sourceField = ["bank", "cash"] select (toLowerANSI _from isEqualTo "cash");
|
|
private _selected = _account getOrDefault [_sourceField, 0];
|
|
if (_selected < _amount) then {
|
|
private _message = [
|
|
"Bank balance cannot cover that transfer.",
|
|
"Cash on hand cannot cover that transfer."
|
|
] select (_sourceField isEqualTo "cash");
|
|
throw _message;
|
|
};
|
|
|
|
_context set ["account", _account];
|
|
_context set ["targetAccount", _targetAccount];
|
|
_context set ["sourceField", _sourceField];
|
|
_context set ["sourceBalance", _selected];
|
|
_context set ["targetBank", _targetAccount getOrDefault ["bank", 0]];
|
|
} catch {
|
|
["ERROR", format ["Transfer validation failed: %1", _exception]] call EFUNC(common,log);
|
|
GVAR(BankMessenger) call ["sendNotice", [_uid, "error", _exception]];
|
|
};
|
|
|
|
if (_context isEqualTo createHashMap) exitWith { false };
|
|
_context
|
|
}],
|
|
["validateDepositEarnings", compileFinal {
|
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
|
|
private _context = createHashMap;
|
|
|
|
[_uid, _amount] try {
|
|
if (_uid isEqualTo "") then { throw "Empty/Invalid UID!" };
|
|
|
|
private _session = GVAR(BankSessionManager) call ["getSessionState", [_uid]];
|
|
if ((_session getOrDefault ["mode", "bank"]) isNotEqualTo "bank") then {
|
|
throw "Earnings deposits are only available from the full bank interface.";
|
|
};
|
|
|
|
if (_amount <= 0) then { throw "No earnings are available to deposit." };
|
|
|
|
private _account = _self call ["resolveAccount", [_uid]];
|
|
private _bank = _account getOrDefault ["bank", 0];
|
|
private _earnings = _account getOrDefault ["earnings", 0];
|
|
|
|
if (_earnings < _amount) then { throw "Pending earnings cannot cover that deposit request." };
|
|
|
|
_context set ["account", _account];
|
|
_context set ["bank", _bank];
|
|
_context set ["earnings", _earnings];
|
|
} catch {
|
|
["ERROR", format ["DepositEarnings validation failed: %1", _exception]] call EFUNC(common,log);
|
|
GVAR(BankMessenger) call ["sendNotice", [_uid, "error", _exception]];
|
|
};
|
|
|
|
if (_context isEqualTo createHashMap) exitWith { false };
|
|
_context
|
|
}],
|
|
["validatePayment", compileFinal {
|
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
|
|
private _context = createHashMap;
|
|
|
|
[_uid, _amount] try {
|
|
if (_uid isEqualTo "") then { throw "Empty/Invalid UID!" };
|
|
if (_amount <= 0) then { throw "Enter a valid payment amount." };
|
|
|
|
private _account = _self call ["resolveAccount", [_uid]];
|
|
private _bank = _account getOrDefault ["bank", 0];
|
|
|
|
_context set ["account", _account];
|
|
_context set ["bank", _bank];
|
|
} catch {
|
|
["ERROR", format ["Payment validation failed: %1", _exception]] call EFUNC(common,log);
|
|
GVAR(BankMessenger) call ["sendNotice", [_uid, "error", _exception]];
|
|
};
|
|
|
|
if (_context isEqualTo createHashMap) exitWith { false };
|
|
_context
|
|
}],
|
|
["validateSubmitPin", compileFinal {
|
|
params [["_uid", "", [""]], ["_pin", "", [""]]];
|
|
|
|
private _context = createHashMap;
|
|
|
|
[_uid, _pin] try {
|
|
if (_uid isEqualTo "") then { throw "Empty/Invalid UID!" };
|
|
|
|
private _session = GVAR(BankSessionManager) call ["getSessionState", [_uid]];
|
|
if ((_session getOrDefault ["mode", "bank"]) isNotEqualTo "atm") then {
|
|
_session = GVAR(BankSessionManager) call ["setSessionState", [_uid, createHashMapFromArray [
|
|
["atmAuthorized", false],
|
|
["mode", "atm"]
|
|
]]];
|
|
};
|
|
|
|
private _account = GVAR(Registry) getOrDefault [_uid, createHashMap];
|
|
if (_account isEqualTo createHashMap) then {
|
|
_account = GVAR(BankStore) call ["init", [_uid]];
|
|
};
|
|
if (_account isEqualTo createHashMap) then {
|
|
throw "Bank account data is unavailable.";
|
|
};
|
|
|
|
private _enteredPin = _pin;
|
|
if !(_enteredPin isEqualType "") then {
|
|
_enteredPin = str _enteredPin;
|
|
};
|
|
if ((count _enteredPin) isNotEqualTo 4) then {
|
|
throw "Enter your four-digit access PIN.";
|
|
};
|
|
|
|
private _accountPin = str (_account getOrDefault ["pin", 1234]);
|
|
if (_enteredPin isNotEqualTo _accountPin) then {
|
|
GVAR(BankSessionManager) call ["setSessionState", [_uid, createHashMapFromArray [["atmAuthorized", false]]]];
|
|
throw "Incorrect PIN.";
|
|
};
|
|
|
|
_context set ["account", _account];
|
|
_context set ["session", _session];
|
|
} catch {
|
|
["ERROR", format ["SubmitPin validation failed: %1", _exception]] call EFUNC(common,log);
|
|
GVAR(BankMessenger) call ["sendNotice", [_uid, "error", _exception]];
|
|
GVAR(BankStore) call ["hydrateSession", [_uid, "atm", false]];
|
|
};
|
|
|
|
if (_context isEqualTo createHashMap) exitWith { false };
|
|
_context
|
|
}]
|
|
]];
|
|
|
|
GVAR(BankValidator)
|