refactor(bank): split monolithic store into focused modules; fix locker grant for attachments
- 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>
This commit is contained in:
parent
68218304ab
commit
6c0ce9e867
@ -1,5 +1,4 @@
|
|||||||
PREP(handleUIEvents);
|
PREP(handleUIEvents);
|
||||||
PREP(initClass);
|
PREP(initClass);
|
||||||
PREP(initSessionService);
|
|
||||||
PREP(initUIBridge);
|
PREP(initUIBridge);
|
||||||
PREP(openUI);
|
PREP(openUI);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#include "script_component.hpp"
|
#include "script_component.hpp"
|
||||||
|
|
||||||
if (isNil QGVAR(BankClass)) then { call FUNC(initClass); };
|
if (isNil QGVAR(BankClass)) then { call FUNC(initClass); };
|
||||||
if (isNil QGVAR(BankSessionService)) then { call FUNC(initSessionService); };
|
|
||||||
if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
|
if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
|
||||||
|
|
||||||
[QGVAR(initBank), {
|
[QGVAR(initBank), {
|
||||||
@ -26,8 +25,27 @@ if (isNil QGVAR(BankUIBridge)) then { call FUNC(initUIBridge); };
|
|||||||
};
|
};
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
|
[QGVAR(responseHydrateBank), {
|
||||||
|
params [["_data", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
if !(isNil QGVAR(BankUIBridge)) then {
|
||||||
|
GVAR(BankUIBridge) call ["handleHydrateResponse", [_data, "bank::hydrate"]];
|
||||||
|
};
|
||||||
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
|
[QGVAR(responseBankNotice), {
|
||||||
|
params [
|
||||||
|
["_type", "error", [""]],
|
||||||
|
["_message", "", [""]]
|
||||||
|
];
|
||||||
|
|
||||||
|
if !(isNil QGVAR(BankUIBridge)) then {
|
||||||
|
GVAR(BankUIBridge) call ["handleNoticeResponse", [_type, _message]];
|
||||||
|
};
|
||||||
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[{
|
[{
|
||||||
EGVAR(org,OrgClass) get "isLoaded";
|
getPlayerUID player isNotEqualTo "";
|
||||||
}, {
|
}, {
|
||||||
[QGVAR(initBank), []] call CFUNC(localEvent);
|
[QGVAR(initBank), []] call CFUNC(localEvent);
|
||||||
}] call CFUNC(waitUntilAndExecute);
|
}] call CFUNC(waitUntilAndExecute);
|
||||||
|
|||||||
@ -68,6 +68,11 @@ switch (_event) do {
|
|||||||
GVAR(BankUIBridge) call ["handleDepositEarningsRequest", [_data]];
|
GVAR(BankUIBridge) call ["handleDepositEarningsRequest", [_data]];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
case "bank::pin::request": {
|
||||||
|
if !(isNil QGVAR(BankUIBridge)) then {
|
||||||
|
GVAR(BankUIBridge) call ["handleSubmitPinRequest", [_data]];
|
||||||
|
};
|
||||||
|
};
|
||||||
default {
|
default {
|
||||||
hint format ["Unhandled bank UI event: %1", _event];
|
hint format ["Unhandled bank UI event: %1", _event];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -18,7 +18,6 @@ GVAR(BankBaseClass) = compileFinal createHashMapFromArray [
|
|||||||
["bank", 0],
|
["bank", 0],
|
||||||
["cash", 0],
|
["cash", 0],
|
||||||
["earnings", 0],
|
["earnings", 0],
|
||||||
["pin", 1234],
|
|
||||||
["transactions", []]
|
["transactions", []]
|
||||||
]];
|
]];
|
||||||
_self set ["isLoaded", false];
|
_self set ["isLoaded", false];
|
||||||
|
|||||||
@ -1,80 +0,0 @@
|
|||||||
#include "..\script_component.hpp"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* File: fnc_initSessionService.sqf
|
|
||||||
* Author: IDSolutions
|
|
||||||
* Public: No
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Initializes the bank session service that shapes the browser payload.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma hemtt ignore_variables ["_self"]
|
|
||||||
GVAR(BankSessionServiceBaseClass) = compileFinal createHashMapFromArray [
|
|
||||||
["#type", "BankSessionServiceBaseClass"],
|
|
||||||
["buildTransferTargets", compileFinal {
|
|
||||||
private _targets = [];
|
|
||||||
|
|
||||||
{
|
|
||||||
if (isNull _x || { _x isEqualTo player }) then {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
private _uid = getPlayerUID _x;
|
|
||||||
private _name = name _x;
|
|
||||||
if (_uid isEqualTo "" || { _name isEqualTo "" }) then {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
_targets pushBack (createHashMapFromArray [
|
|
||||||
["name", _name],
|
|
||||||
["uid", _uid]
|
|
||||||
]);
|
|
||||||
} forEach allPlayers;
|
|
||||||
|
|
||||||
private _targetPairs = _targets apply {
|
|
||||||
[toLowerANSI (_x getOrDefault ["name", ""]), _x]
|
|
||||||
};
|
|
||||||
_targetPairs sort true;
|
|
||||||
_targetPairs apply {
|
|
||||||
_x param [1, createHashMap]
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
["buildPayload", compileFinal {
|
|
||||||
params [["_mode", "bank", [""]]];
|
|
||||||
|
|
||||||
private _account = if (isNil QGVAR(BankClass)) then {
|
|
||||||
createHashMap
|
|
||||||
} else {
|
|
||||||
GVAR(BankClass) call ["getAccountState", []]
|
|
||||||
};
|
|
||||||
|
|
||||||
private _orgFunds = 0;
|
|
||||||
private _orgName = "";
|
|
||||||
if !(isNil QEGVAR(org,OrgClass)) then {
|
|
||||||
_orgFunds = EGVAR(org,OrgClass) call ["get", ["funds", 0]];
|
|
||||||
_orgName = EGVAR(org,OrgClass) call ["get", ["name", ""]];
|
|
||||||
};
|
|
||||||
|
|
||||||
createHashMapFromArray [
|
|
||||||
["session", createHashMapFromArray [
|
|
||||||
["mode", ["bank", "atm"] select (toLowerANSI _mode isEqualTo "atm")],
|
|
||||||
["orgFunds", _orgFunds],
|
|
||||||
["orgName", _orgName],
|
|
||||||
["playerName", name player],
|
|
||||||
["transferTargets", _self call ["buildTransferTargets", []]],
|
|
||||||
["uid", getPlayerUID player]
|
|
||||||
]],
|
|
||||||
["account", createHashMapFromArray [
|
|
||||||
["bank", _account getOrDefault ["bank", 0]],
|
|
||||||
["cash", _account getOrDefault ["cash", 0]],
|
|
||||||
["earnings", _account getOrDefault ["earnings", 0]],
|
|
||||||
["pin", str (_account getOrDefault ["pin", 1234])],
|
|
||||||
["transactions", _account getOrDefault ["transactions", []]]
|
|
||||||
]]
|
|
||||||
]
|
|
||||||
}]
|
|
||||||
];
|
|
||||||
|
|
||||||
GVAR(BankSessionService) = createHashMapObject [GVAR(BankSessionServiceBaseClass)];
|
|
||||||
GVAR(BankSessionService)
|
|
||||||
@ -19,9 +19,6 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
|
|||||||
["#create", compileFinal {
|
["#create", compileFinal {
|
||||||
_self set ["mode", "bank"];
|
_self set ["mode", "bank"];
|
||||||
}],
|
}],
|
||||||
["buildPayload", compileFinal {
|
|
||||||
GVAR(BankSessionService) call ["buildPayload", [_self call ["getMode", []]]]
|
|
||||||
}],
|
|
||||||
["getActiveBrowserControl", compileFinal {
|
["getActiveBrowserControl", compileFinal {
|
||||||
private _display = uiNamespace getVariable ["RscBank", displayNull];
|
private _display = uiNamespace getVariable ["RscBank", displayNull];
|
||||||
if (isNull _display) exitWith {
|
if (isNull _display) exitWith {
|
||||||
@ -36,14 +33,16 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
|
|||||||
["getMode", compileFinal {
|
["getMode", compileFinal {
|
||||||
_self getOrDefault ["mode", "bank"]
|
_self getOrDefault ["mode", "bank"]
|
||||||
}],
|
}],
|
||||||
|
["hasOpenScreen", compileFinal {
|
||||||
|
private _screen = _self call ["getScreen", []];
|
||||||
|
private _control = _self call ["getActiveBrowserControl", []];
|
||||||
|
|
||||||
|
!(isNull _control) && { _screen call ["isReady", []] }
|
||||||
|
}],
|
||||||
["handleDepositEarningsRequest", compileFinal {
|
["handleDepositEarningsRequest", compileFinal {
|
||||||
params [["_data", createHashMap, [createHashMap]]];
|
params [["_data", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
private _amount = floor (_data getOrDefault ["amount", 0]);
|
private _amount = floor (_data getOrDefault ["amount", 0]);
|
||||||
if (_amount <= 0) exitWith {
|
|
||||||
_self call ["sendNotice", ["error", "No earnings are available to deposit."]];
|
|
||||||
};
|
|
||||||
|
|
||||||
[SRPC(bank,requestDepositEarnings), [getPlayerUID player, _amount]] call CFUNC(serverEvent);
|
[SRPC(bank,requestDepositEarnings), [getPlayerUID player, _amount]] call CFUNC(serverEvent);
|
||||||
true
|
true
|
||||||
}],
|
}],
|
||||||
@ -51,22 +50,41 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
|
|||||||
params [["_data", createHashMap, [createHashMap]]];
|
params [["_data", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
private _amount = floor (_data getOrDefault ["amount", 0]);
|
private _amount = floor (_data getOrDefault ["amount", 0]);
|
||||||
if (_amount <= 0) exitWith {
|
|
||||||
_self call ["sendNotice", ["error", "Enter a valid deposit amount."]];
|
|
||||||
};
|
|
||||||
|
|
||||||
[SRPC(bank,requestDeposit), [getPlayerUID player, _amount]] call CFUNC(serverEvent);
|
[SRPC(bank,requestDeposit), [getPlayerUID player, _amount]] call CFUNC(serverEvent);
|
||||||
true
|
true
|
||||||
}],
|
}],
|
||||||
|
["handleHydrateResponse", compileFinal {
|
||||||
|
params [["_data", createHashMap, [createHashMap]], ["_event", "bank::hydrate", [""]]];
|
||||||
|
|
||||||
|
if !(_self call ["hasOpenScreen", []]) exitWith { false };
|
||||||
|
|
||||||
|
_self call ["sendEvent", [_event, _data, _self call ["getActiveBrowserControl", []]]]
|
||||||
|
}],
|
||||||
|
["handleNoticeResponse", compileFinal {
|
||||||
|
params [["_type", "error", [""]], ["_message", "", [""]]];
|
||||||
|
|
||||||
|
_self call ["sendNotice", [_type, _message]]
|
||||||
|
}],
|
||||||
["handleReady", compileFinal {
|
["handleReady", compileFinal {
|
||||||
params [["_control", controlNull, [controlNull]], ["_data", createHashMap, [createHashMap]]];
|
params [["_control", controlNull, [controlNull]], ["_data", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
private _screen = _self call ["getScreen", []];
|
private _screen = _self call ["getScreen", []];
|
||||||
_screen call ["setControl", [_control]];
|
_screen call ["setControl", [_control]];
|
||||||
_screen call ["markReady", [true]];
|
_screen call ["markReady", [true]];
|
||||||
|
|
||||||
_self call ["flushPendingEvents", []];
|
_self call ["flushPendingEvents", []];
|
||||||
_self call ["sendEvent", ["bank::hydrate", _self call ["buildPayload", []], _control]];
|
|
||||||
|
_self call ["requestHydrate", [true]]
|
||||||
|
}],
|
||||||
|
["handleSubmitPinRequest", compileFinal {
|
||||||
|
params [["_data", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
private _pin = _data getOrDefault ["pin", ""];
|
||||||
|
if !(_pin isEqualType "") then {
|
||||||
|
_pin = str _pin;
|
||||||
|
};
|
||||||
|
|
||||||
|
[SRPC(bank,requestSubmitPin), [getPlayerUID player, _pin]] call CFUNC(serverEvent);
|
||||||
|
true
|
||||||
}],
|
}],
|
||||||
["handleTransferRequest", compileFinal {
|
["handleTransferRequest", compileFinal {
|
||||||
params [["_data", createHashMap, [createHashMap]]];
|
params [["_data", createHashMap, [createHashMap]]];
|
||||||
@ -75,18 +93,6 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
|
|||||||
private _target = _data getOrDefault ["target", ""];
|
private _target = _data getOrDefault ["target", ""];
|
||||||
private _from = toLowerANSI (_data getOrDefault ["from", "bank"]);
|
private _from = toLowerANSI (_data getOrDefault ["from", "bank"]);
|
||||||
|
|
||||||
if (_target isEqualTo "") exitWith {
|
|
||||||
_self call ["sendNotice", ["error", "Select a transfer recipient."]];
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_target isEqualTo getPlayerUID player) exitWith {
|
|
||||||
_self call ["sendNotice", ["error", "You cannot transfer funds to yourself."]];
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_amount <= 0) exitWith {
|
|
||||||
_self call ["sendNotice", ["error", "Enter a valid transfer amount."]];
|
|
||||||
};
|
|
||||||
|
|
||||||
[SRPC(bank,requestTransfer), [getPlayerUID player, _target, _from, _amount]] call CFUNC(serverEvent);
|
[SRPC(bank,requestTransfer), [getPlayerUID player, _target, _from, _amount]] call CFUNC(serverEvent);
|
||||||
true
|
true
|
||||||
}],
|
}],
|
||||||
@ -94,23 +100,24 @@ GVAR(BankUIBridgeBaseClass) = compileFinal createHashMapFromArray [
|
|||||||
params [["_data", createHashMap, [createHashMap]]];
|
params [["_data", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
private _amount = floor (_data getOrDefault ["amount", 0]);
|
private _amount = floor (_data getOrDefault ["amount", 0]);
|
||||||
if (_amount <= 0) exitWith {
|
|
||||||
_self call ["sendNotice", ["error", "Enter a valid withdrawal amount."]];
|
|
||||||
};
|
|
||||||
|
|
||||||
[SRPC(bank,requestWithdraw), [getPlayerUID player, _amount]] call CFUNC(serverEvent);
|
[SRPC(bank,requestWithdraw), [getPlayerUID player, _amount]] call CFUNC(serverEvent);
|
||||||
true
|
true
|
||||||
}],
|
}],
|
||||||
["refreshSession", compileFinal {
|
["refreshSession", compileFinal {
|
||||||
private _control = _self call ["getActiveBrowserControl", []];
|
_self call ["requestHydrate", [false]]
|
||||||
if (isNull _control) exitWith { false };
|
}],
|
||||||
|
["requestHydrate", compileFinal {
|
||||||
|
params [["_resetAuthorization", false, [false]]];
|
||||||
|
|
||||||
_self call ["sendEvent", ["bank::sync", _self call ["buildPayload", []], _control]]
|
if !(_self call ["hasOpenScreen", []]) exitWith { false };
|
||||||
|
|
||||||
|
[SRPC(bank,requestHydrateBank), [getPlayerUID player, _self call ["getMode", []], _resetAuthorization]] call CFUNC(serverEvent);
|
||||||
|
true
|
||||||
}],
|
}],
|
||||||
["sendNotice", compileFinal {
|
["sendNotice", compileFinal {
|
||||||
params [["_type", "error", [""]], ["_message", "", [""]], ["_control", controlNull, [controlNull]]];
|
params [["_type", "error", [""]], ["_message", "", [""]], ["_control", controlNull, [controlNull]]];
|
||||||
|
|
||||||
if (_message isEqualTo "") exitWith { false };
|
if (_message isEqualTo "" || { !(_self call ["hasOpenScreen", []]) }) exitWith { false };
|
||||||
|
|
||||||
_self call ["sendEvent", ["bank::notice", createHashMapFromArray [
|
_self call ["sendEvent", ["bank::notice", createHashMapFromArray [
|
||||||
["message", _message],
|
["message", _message],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -40,6 +40,9 @@
|
|||||||
requestRefresh() {
|
requestRefresh() {
|
||||||
return bridge.send("bank::refresh", {});
|
return bridge.send("bank::refresh", {});
|
||||||
},
|
},
|
||||||
|
requestSubmitPin(payload) {
|
||||||
|
return bridge.send("bank::pin::request", payload);
|
||||||
|
},
|
||||||
requestTransfer(payload) {
|
requestTransfer(payload) {
|
||||||
return bridge.send("bank::transfer::request", payload);
|
return bridge.send("bank::transfer::request", payload);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
const BankApp = (window.BankApp = window.BankApp || {});
|
const BankApp = (window.BankApp = window.BankApp || {});
|
||||||
|
|
||||||
const defaultSession = {
|
const defaultSession = {
|
||||||
|
atmAuthorized: false,
|
||||||
mode: "bank",
|
mode: "bank",
|
||||||
orgFunds: 0,
|
orgFunds: 0,
|
||||||
orgName: "",
|
orgName: "",
|
||||||
@ -14,7 +15,6 @@
|
|||||||
bank: 0,
|
bank: 0,
|
||||||
cash: 0,
|
cash: 0,
|
||||||
earnings: 0,
|
earnings: 0,
|
||||||
pin: "1234",
|
|
||||||
transactions: [],
|
transactions: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4,14 +4,6 @@
|
|||||||
|
|
||||||
let noticeTimer = null;
|
let noticeTimer = null;
|
||||||
|
|
||||||
function getAccount() {
|
|
||||||
return BankApp.data?.account || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSession() {
|
|
||||||
return BankApp.data?.session || {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeAmount(value) {
|
function normalizeAmount(value) {
|
||||||
const amount = Math.floor(Number(value || 0));
|
const amount = Math.floor(Number(value || 0));
|
||||||
return Number.isFinite(amount) ? amount : 0;
|
return Number.isFinite(amount) ? amount : 0;
|
||||||
@ -58,18 +50,6 @@
|
|||||||
|
|
||||||
function requestDeposit(amountValue) {
|
function requestDeposit(amountValue) {
|
||||||
const amount = normalizeAmount(amountValue);
|
const amount = normalizeAmount(amountValue);
|
||||||
const account = getAccount();
|
|
||||||
|
|
||||||
if (amount <= 0) {
|
|
||||||
showNotice("error", "Enter a valid deposit amount.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount > Number(account.cash || 0)) {
|
|
||||||
showNotice("error", "Cash on hand cannot cover that deposit.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bridge = BankApp.bridge;
|
const bridge = BankApp.bridge;
|
||||||
if (!bridge || typeof bridge.requestDeposit !== "function") {
|
if (!bridge || typeof bridge.requestDeposit !== "function") {
|
||||||
showNotice("error", "Deposit bridge is unavailable.");
|
showNotice("error", "Deposit bridge is unavailable.");
|
||||||
@ -89,18 +69,6 @@
|
|||||||
|
|
||||||
function requestWithdraw(amountValue) {
|
function requestWithdraw(amountValue) {
|
||||||
const amount = normalizeAmount(amountValue);
|
const amount = normalizeAmount(amountValue);
|
||||||
const account = getAccount();
|
|
||||||
|
|
||||||
if (amount <= 0) {
|
|
||||||
showNotice("error", "Enter a valid withdrawal amount.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount > Number(account.bank || 0)) {
|
|
||||||
showNotice("error", "Bank balance cannot cover that withdrawal.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bridge = BankApp.bridge;
|
const bridge = BankApp.bridge;
|
||||||
if (!bridge || typeof bridge.requestWithdraw !== "function") {
|
if (!bridge || typeof bridge.requestWithdraw !== "function") {
|
||||||
showNotice("error", "Withdraw bridge is unavailable.");
|
showNotice("error", "Withdraw bridge is unavailable.");
|
||||||
@ -120,30 +88,8 @@
|
|||||||
|
|
||||||
function requestTransfer(targetUid, amountValue) {
|
function requestTransfer(targetUid, amountValue) {
|
||||||
const amount = normalizeAmount(amountValue);
|
const amount = normalizeAmount(amountValue);
|
||||||
const session = getSession();
|
|
||||||
const account = getAccount();
|
|
||||||
const targetId = String(targetUid || "").trim();
|
const targetId = String(targetUid || "").trim();
|
||||||
|
|
||||||
if (!targetId) {
|
|
||||||
showNotice("error", "Select a transfer recipient.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetId === String(session.uid || "")) {
|
|
||||||
showNotice("error", "You cannot transfer funds to yourself.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount <= 0) {
|
|
||||||
showNotice("error", "Enter a valid transfer amount.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount > Number(account.bank || 0)) {
|
|
||||||
showNotice("error", "Bank balance cannot cover that transfer.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bridge = BankApp.bridge;
|
const bridge = BankApp.bridge;
|
||||||
if (!bridge || typeof bridge.requestTransfer !== "function") {
|
if (!bridge || typeof bridge.requestTransfer !== "function") {
|
||||||
showNotice("error", "Transfer bridge is unavailable.");
|
showNotice("error", "Transfer bridge is unavailable.");
|
||||||
@ -167,21 +113,6 @@
|
|||||||
|
|
||||||
function requestDepositEarnings(amountValue) {
|
function requestDepositEarnings(amountValue) {
|
||||||
const amount = normalizeAmount(amountValue);
|
const amount = normalizeAmount(amountValue);
|
||||||
const account = getAccount();
|
|
||||||
|
|
||||||
if (amount <= 0) {
|
|
||||||
showNotice("error", "No earnings are available to deposit.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount > Number(account.earnings || 0)) {
|
|
||||||
showNotice(
|
|
||||||
"error",
|
|
||||||
"Pending earnings cannot cover that deposit request.",
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bridge = BankApp.bridge;
|
const bridge = BankApp.bridge;
|
||||||
if (!bridge || typeof bridge.requestDepositEarnings !== "function") {
|
if (!bridge || typeof bridge.requestDepositEarnings !== "function") {
|
||||||
showNotice("error", "Earnings bridge is unavailable.");
|
showNotice("error", "Earnings bridge is unavailable.");
|
||||||
@ -224,21 +155,21 @@
|
|||||||
|
|
||||||
function submitPin() {
|
function submitPin() {
|
||||||
const enteredPin = String(store.getEnteredPin() || "");
|
const enteredPin = String(store.getEnteredPin() || "");
|
||||||
const actualPin = String(getAccount().pin || "1234");
|
const bridge = BankApp.bridge;
|
||||||
|
if (!bridge || typeof bridge.requestSubmitPin !== "function") {
|
||||||
if (enteredPin.length !== 4) {
|
showNotice("error", "PIN bridge is unavailable.");
|
||||||
showNotice("error", "Enter your four-digit access PIN.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enteredPin !== actualPin) {
|
store.startAction("pin");
|
||||||
clearPin();
|
const sent = bridge.requestSubmitPin({ pin: enteredPin });
|
||||||
showNotice("error", "Incorrect PIN.");
|
if (!sent) {
|
||||||
|
store.finishAction();
|
||||||
|
showNotice("error", "PIN bridge is unavailable.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearPin();
|
clearPin();
|
||||||
store.setAtmView("menu");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +230,6 @@
|
|||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
store.setCustomAmount("");
|
store.setCustomAmount("");
|
||||||
store.setAtmView("menu");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -314,10 +244,6 @@
|
|||||||
? requestDeposit(amount)
|
? requestDeposit(amount)
|
||||||
: requestWithdraw(amount);
|
: requestWithdraw(amount);
|
||||||
|
|
||||||
if (success) {
|
|
||||||
store.setAtmView("menu");
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,19 +25,35 @@
|
|||||||
const mode = String(payload?.session?.mode || "bank")
|
const mode = String(payload?.session?.mode || "bank")
|
||||||
.trim()
|
.trim()
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
|
const atmAuthorized = Boolean(payload?.session?.atmAuthorized);
|
||||||
const currentMode = this.getMode();
|
const currentMode = this.getMode();
|
||||||
const currentAtmView = this.getAtmView();
|
const currentAtmView = this.getAtmView();
|
||||||
|
const currentPendingAction = this.getPendingAction();
|
||||||
|
|
||||||
this.setMode(mode === "atm" ? "atm" : "bank");
|
this.setMode(mode === "atm" ? "atm" : "bank");
|
||||||
this.setPendingAction("");
|
this.setPendingAction("");
|
||||||
this.setNotice({ text: "", type: "" });
|
|
||||||
this.setEnteredPin("");
|
this.setEnteredPin("");
|
||||||
this.setCustomAmount("");
|
this.setCustomAmount("");
|
||||||
this.setAccountVersion(this.getAccountVersion() + 1);
|
this.setAccountVersion(this.getAccountVersion() + 1);
|
||||||
this.setSessionVersion(this.getSessionVersion() + 1);
|
this.setSessionVersion(this.getSessionVersion() + 1);
|
||||||
|
|
||||||
if (mode === "atm") {
|
if (mode === "atm") {
|
||||||
this.setAtmView(currentMode === "atm" ? currentAtmView : "pin");
|
if (!atmAuthorized) {
|
||||||
|
this.setAtmView("pin");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
currentPendingAction === "deposit" ||
|
||||||
|
currentPendingAction === "withdraw" ||
|
||||||
|
currentAtmView === "pin" ||
|
||||||
|
currentMode !== "atm"
|
||||||
|
) {
|
||||||
|
this.setAtmView("menu");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setAtmView(currentAtmView);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,6 @@
|
|||||||
PREP(initBank);
|
PREP(initBank);
|
||||||
PREP(initBankStore);
|
PREP(initMessenger);
|
||||||
|
PREP(initModel);
|
||||||
|
PREP(initSessionManager);
|
||||||
|
PREP(initStore);
|
||||||
|
PREP(initValidator);
|
||||||
|
|||||||
@ -13,15 +13,24 @@ PREP_RECOMPILE_END;
|
|||||||
GVAR(BankStore) call ["init", [_uid]];
|
GVAR(BankStore) call ["init", [_uid]];
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
|
[QGVAR(requestHydrateBank), {
|
||||||
|
params [["_uid", "", [""]], ["_mode", "bank", [""]], ["_resetAuthorization", false, [false]]];
|
||||||
|
|
||||||
|
if (_uid isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID!" };
|
||||||
|
GVAR(BankStore) call ["hydrateSession", [_uid, _mode, _resetAuthorization]];
|
||||||
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestGetBank), {
|
[QGVAR(requestGetBank), {
|
||||||
params [["_uid", "", [""]], ["_field", "", [""]]];
|
params [["_uid", "", [""]], ["_field", "", [""]]];
|
||||||
|
|
||||||
if (_uid isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID!" };
|
if (_uid isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID!" };
|
||||||
|
|
||||||
private _finalData = GVAR(BankStore) call ["get", [GVAR(Registry), _uid, _field]];
|
private _finalData = GVAR(BankStore) call ["get", [GVAR(Registry), _uid, _field]];
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
if (_field isNotEqualTo "") then {
|
||||||
|
_finalData = createHashMapFromArray [[_field, _finalData]];
|
||||||
|
};
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalData], _player] call CFUNC(targetEvent);
|
GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalData]];
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestSetBank), {
|
[QGVAR(requestSetBank), {
|
||||||
@ -30,9 +39,7 @@ PREP_RECOMPILE_END;
|
|||||||
if (_uid isEqualTo "" || _field isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID or Key!" };
|
if (_uid isEqualTo "" || _field isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID or Key!" };
|
||||||
|
|
||||||
private _hashMap = GVAR(BankStore) call ["set", [GVAR(Registry), "bank:update", _uid, _field, _value, _sync]];
|
private _hashMap = GVAR(BankStore) call ["set", [GVAR(Registry), "bank:update", _uid, _field, _value, _sync]];
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
GVAR(BankMessenger) call ["sendAccountSync", [_uid, _hashMap]];
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_hashMap], _player] call CFUNC(targetEvent);
|
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestMSetBank), {
|
[QGVAR(requestMSetBank), {
|
||||||
@ -42,9 +49,7 @@ PREP_RECOMPILE_END;
|
|||||||
if ((_fieldValuePairs isEqualTo createHashMap) || !(_fieldValuePairs isEqualType createHashMap)) exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid field pairs!" };
|
if ((_fieldValuePairs isEqualTo createHashMap) || !(_fieldValuePairs isEqualType createHashMap)) exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid field pairs!" };
|
||||||
|
|
||||||
private _hashMap = GVAR(BankStore) call ["mset", [GVAR(Registry), "bank:update", _uid, _fieldValuePairs, _sync]];
|
private _hashMap = GVAR(BankStore) call ["mset", [GVAR(Registry), "bank:update", _uid, _fieldValuePairs, _sync]];
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
GVAR(BankMessenger) call ["sendAccountSync", [_uid, _hashMap]];
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_hashMap], _player] call CFUNC(targetEvent);
|
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestSaveBank), {
|
[QGVAR(requestSaveBank), {
|
||||||
@ -53,9 +58,7 @@ PREP_RECOMPILE_END;
|
|||||||
if (_uid isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID!" };
|
if (_uid isEqualTo "") exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID!" };
|
||||||
|
|
||||||
private _finalData = GVAR(BankStore) call ["save", [GVAR(Registry), "bank:update", _uid]];
|
private _finalData = GVAR(BankStore) call ["save", [GVAR(Registry), "bank:update", _uid]];
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
GVAR(BankMessenger) call ["sendAccountSync", [_uid, _finalData]];
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalData], _player] call CFUNC(targetEvent);
|
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestRemoveBank), {
|
[QGVAR(requestRemoveBank), {
|
||||||
@ -68,44 +71,47 @@ PREP_RECOMPILE_END;
|
|||||||
[QGVAR(requestDeposit), {
|
[QGVAR(requestDeposit), {
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
||||||
|
|
||||||
if (_uid isEqualTo "" || _amount isEqualTo 0) exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID or Amount!" };
|
private _context = GVAR(BankValidator) call ["validateDeposit", [_uid, _amount]];
|
||||||
GVAR(BankStore) call ["deposit", [_uid, _amount]];
|
if (_context isEqualTo false) exitWith {};
|
||||||
|
GVAR(BankStore) call ["deposit", [_uid, _amount, _context]];
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestPayment), {
|
[QGVAR(requestPayment), {
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
||||||
|
|
||||||
if (_uid isEqualTo "" || _amount isEqualTo 0) exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID or Amount!" };
|
private _context = GVAR(BankValidator) call ["validatePayment", [_uid, _amount]];
|
||||||
GVAR(BankStore) call ["payment", [_uid, _amount]];
|
if (_context isEqualTo false) exitWith {};
|
||||||
|
GVAR(BankStore) call ["payment", [_uid, _amount, _context]];
|
||||||
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
|
[QGVAR(requestSubmitPin), {
|
||||||
|
params [["_uid", "", [""]], ["_pin", "", [""]]];
|
||||||
|
|
||||||
|
private _context = GVAR(BankValidator) call ["validateSubmitPin", [_uid, _pin]];
|
||||||
|
if (_context isEqualTo false) exitWith {};
|
||||||
|
GVAR(BankSessionManager) call ["submitPin", [_uid, _context]];
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestTransfer), {
|
[QGVAR(requestTransfer), {
|
||||||
params [["_uid", "", [""]], ["_target", "", [""]], ["_from", "", [""]], ["_amount", 0, [0]]];
|
params [["_uid", "", [""]], ["_target", "", [""]], ["_from", "", [""]], ["_amount", 0, [0]]];
|
||||||
|
|
||||||
if (_uid isEqualTo "" || _target isEqualTo "" || _from isEqualTo "" || _amount isEqualTo 0) exitWith {
|
private _context = GVAR(BankValidator) call ["validateTransfer", [_uid, _target, _from, _amount]];
|
||||||
diag_log "[FORGE:Server:Bank] Empty/Invalid UID, Target, From Account, or Amount!"
|
if (_context isEqualTo false) exitWith {};
|
||||||
};
|
GVAR(BankStore) call ["transfer", [_uid, _target, _amount, _context]];
|
||||||
|
|
||||||
if (_uid isEqualTo _target) exitWith {
|
|
||||||
diag_log format ["[FORGE:Server:Bank] SECURITY: Player %1 attempted self-transfer!", _uid];
|
|
||||||
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
[CRPC(notifications,recieveNotification), ["error", "Bank", "Cannot transfer to yourself!"], _player] call CFUNC(targetEvent);
|
|
||||||
};
|
|
||||||
|
|
||||||
GVAR(BankStore) call ["transfer", [_uid, _target, _from, _amount]];
|
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestWithdraw), {
|
[QGVAR(requestWithdraw), {
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
||||||
|
|
||||||
if (_uid isEqualTo "" || _amount isEqualTo 0) exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID or Amount!" };
|
private _context = GVAR(BankValidator) call ["validateWithdraw", [_uid, _amount]];
|
||||||
GVAR(BankStore) call ["withdraw", [_uid, _amount]];
|
if (_context isEqualTo false) exitWith {};
|
||||||
|
GVAR(BankStore) call ["withdraw", [_uid, _amount, _context]];
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|
||||||
[QGVAR(requestDepositEarnings), {
|
[QGVAR(requestDepositEarnings), {
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
||||||
|
|
||||||
if (_uid isEqualTo "" || _amount isEqualTo 0) exitWith { diag_log "[FORGE:Server:Bank] Empty/Invalid UID or Amount!" };
|
private _context = GVAR(BankValidator) call ["validateDepositEarnings", [_uid, _amount]];
|
||||||
GVAR(BankStore) call ["depositEarnings", [_uid, _amount]];
|
if (_context isEqualTo false) exitWith {};
|
||||||
|
GVAR(BankStore) call ["depositEarnings", [_uid, _amount, _context]];
|
||||||
}] call CFUNC(addEventHandler);
|
}] call CFUNC(addEventHandler);
|
||||||
|
|||||||
@ -1,326 +0,0 @@
|
|||||||
#include "..\script_component.hpp"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* File: fnc_initBankStore.sqf
|
|
||||||
* Author: IDSolutions
|
|
||||||
* Date: 2025-12-17
|
|
||||||
* Last Update: 2026-02-17
|
|
||||||
* Public: Yes
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Initializes the bank store for managing player bank accounts.
|
|
||||||
* Provides methods for syncing, saving, and applying bank accounts to the player.
|
|
||||||
*
|
|
||||||
* Arguments:
|
|
||||||
* None
|
|
||||||
*
|
|
||||||
* Return Value:
|
|
||||||
* Bank store object [HASHMAP OBJECT]
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* call forge_server_bank_fnc_initBankStore
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma hemtt ignore_variables ["_self"]
|
|
||||||
GVAR(BankModel) = compileFinal createHashMapObject [[
|
|
||||||
["#type", "BankModel"],
|
|
||||||
["defaults", compileFinal {
|
|
||||||
private _account = createHashMap;
|
|
||||||
|
|
||||||
_account set ["uid", ""];
|
|
||||||
_account set ["name", ""];
|
|
||||||
_account set ["bank", 0];
|
|
||||||
_account set ["cash", 0];
|
|
||||||
_account set ["earnings", 0];
|
|
||||||
_account set ["pin", 1234];
|
|
||||||
_account set ["transactions", []];
|
|
||||||
|
|
||||||
_account
|
|
||||||
}],
|
|
||||||
["fromPlayer", compileFinal {
|
|
||||||
params [["_player", objNull, [objNull]]];
|
|
||||||
|
|
||||||
if (_player isEqualTo objNull) exitWith { _self call ["defaults", []] };
|
|
||||||
|
|
||||||
private _account = _self call ["defaults", []];
|
|
||||||
|
|
||||||
_account set ["uid", getPlayerUID _player];
|
|
||||||
_account set ["name", name _player];
|
|
||||||
_account set ["bank", 0];
|
|
||||||
_account set ["cash", 0];
|
|
||||||
_account set ["earnings", 0];
|
|
||||||
_account set ["pin", 1234];
|
|
||||||
_account set ["transactions", []];
|
|
||||||
|
|
||||||
_account
|
|
||||||
}],
|
|
||||||
["migrate", compileFinal {
|
|
||||||
params [["_account", createHashMap, [createHashMap]]];
|
|
||||||
|
|
||||||
private _defaults = _self call ["defaults", []];
|
|
||||||
|
|
||||||
{
|
|
||||||
if !(_x in _account) then { _account set [_x, _y]; };
|
|
||||||
} forEach _defaults;
|
|
||||||
|
|
||||||
_account
|
|
||||||
}],
|
|
||||||
["validate", compileFinal {
|
|
||||||
params [["_account", createHashMap, [createHashMap]]];
|
|
||||||
|
|
||||||
private _uid = _account getOrDefault ["uid", ""];
|
|
||||||
private _name = _account getOrDefault ["name", ""];
|
|
||||||
private _bank = _account getOrDefault ["bank", 0];
|
|
||||||
private _cash = _account getOrDefault ["cash", 0];
|
|
||||||
private _earnings = _account getOrDefault ["earnings", 0];
|
|
||||||
private _pin = _account getOrDefault ["pin", 1234];
|
|
||||||
|
|
||||||
[_uid, _name, _bank, _cash, _earnings, _pin] try {
|
|
||||||
if (_uid isEqualTo "" || !(_uid isEqualType "")) then { throw "Invalid UID!"; };
|
|
||||||
if (_name isEqualTo "" || !(_name isEqualType "")) then { throw "Invalid Name!"; };
|
|
||||||
if (_bank < 0 || !(_bank isEqualType 0)) then { throw "Invalid Bank!"; };
|
|
||||||
if (_cash < 0 || !(_cash isEqualType 0)) then { throw "Invalid Cash!"; };
|
|
||||||
if (_earnings < 0 || !(_earnings isEqualType 0)) then { throw "Invalid Earnings!"; };
|
|
||||||
if (_pin < 1000 || _pin > 9999 || !(_pin isEqualType 0)) then { throw "Invalid Pin!"; };
|
|
||||||
} catch {
|
|
||||||
["ERROR", format ["Failed to validate account %1!", _exception]] call EFUNC(common,log);
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
true
|
|
||||||
}]
|
|
||||||
]];
|
|
||||||
|
|
||||||
GVAR(BankBaseStore) = compileFinal createHashMapFromArray [
|
|
||||||
["#base", EGVAR(common,BaseStore)],
|
|
||||||
["#type", "BankBaseStore"],
|
|
||||||
["#create", compileFinal {
|
|
||||||
GVAR(IndexRegistry) = createHashMap;
|
|
||||||
GVAR(Registry) = createHashMap;
|
|
||||||
["INFO", "Bank Store Initialized!"] call EFUNC(common,log);
|
|
||||||
}],
|
|
||||||
["init", compileFinal {
|
|
||||||
params [["_uid", "", [""]]];
|
|
||||||
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
private _cached = GVAR(Registry) getOrDefault [_uid, nil];
|
|
||||||
if !(isNil { _cached }) exitWith { [CRPC(bank,responseInitBank), [_cached], _player] call CFUNC(targetEvent); _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];
|
|
||||||
|
|
||||||
private _regEntry = createHashMapFromArray [["uid", _uid], ["name", (name _player)]];
|
|
||||||
GVAR(IndexRegistry) set [_uid, _regEntry];
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _fallbackAccount];
|
|
||||||
[CRPC(bank,responseInitBank), [_fallbackAccount], _player] call CFUNC(targetEvent);
|
|
||||||
|
|
||||||
_fallbackAccount
|
|
||||||
};
|
|
||||||
|
|
||||||
private _finalAccount = createHashMap;
|
|
||||||
|
|
||||||
if (_result == "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];
|
|
||||||
|
|
||||||
private _json = _self call ["toJSON", [_finalAccount]];
|
|
||||||
["bank:create", [_uid, _json]] call EFUNC(extension,extCall) params ["_result", "_isSuccess"];
|
|
||||||
if !(_isSuccess) exitWith {
|
|
||||||
["ERROR", format ["Failed to create bank account %1! Using fallback account.", _uid]] call EFUNC(common,log);
|
|
||||||
|
|
||||||
private _regEntry = createHashMapFromArray [["uid", _uid], ["name", (name _player)]];
|
|
||||||
GVAR(IndexRegistry) set [_uid, _regEntry];
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
[CRPC(bank,responseInitBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
|
|
||||||
_finalAccount
|
|
||||||
};
|
|
||||||
|
|
||||||
["INFO", format ["Created new bank account for %1", _uid]] call EFUNC(common,log);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private _regEntry = createHashMapFromArray [["uid", _uid], ["name", (name _player)]];
|
|
||||||
GVAR(IndexRegistry) set [_uid, _regEntry];
|
|
||||||
|
|
||||||
// _finalAccount = GVAR(BankModel) call ["migrate", [_finalAccount]];
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
[CRPC(bank,responseInitBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
|
|
||||||
_finalAccount
|
|
||||||
}],
|
|
||||||
["deposit", compileFinal {
|
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
||||||
|
|
||||||
["INFO", format ["Deposit %1, for %2", _amount, _uid]] call EFUNC(common,log);
|
|
||||||
|
|
||||||
private _account = GVAR(Registry) getOrDefault [_uid, nil];
|
|
||||||
if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _bank = _account getOrDefault ["bank", 0];
|
|
||||||
private _cash = _account getOrDefault ["cash", 0];
|
|
||||||
if (_cash < _amount) exitWith { ["WARNING", "Insufficient Funds!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _finalAccount = createHashMapFromArray [["bank", (_bank + _amount)], ["cash", (_cash - _amount)]];
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
[CRPC(notifications,recieveNotification), ["info", "Bank", format ["Deposited $%1", _amount]], _player] call CFUNC(targetEvent);
|
|
||||||
}],
|
|
||||||
["payment", compileFinal {
|
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
||||||
|
|
||||||
["INFO", format ["Payment %1, for %2", _amount, _uid]] call EFUNC(common,log);
|
|
||||||
|
|
||||||
private _account = GVAR(Registry) getOrDefault [_uid, nil];
|
|
||||||
if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _bank = _account getOrDefault ["bank", 0];
|
|
||||||
private _finalAccount = createHashMapFromArray [["bank", (_bank + _amount)]];
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
[CRPC(notifications,recieveNotification), ["info", "Bank", format ["Paid $%1", _amount]], _player] call CFUNC(targetEvent);
|
|
||||||
}],
|
|
||||||
["buildChargeResult", compileFinal {
|
|
||||||
params [["_message", "Unable to process bank payment.", [""]]];
|
|
||||||
|
|
||||||
createHashMapFromArray [
|
|
||||||
["success", false],
|
|
||||||
["message", _message],
|
|
||||||
["patch", 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
|
|
||||||
}],
|
|
||||||
["transfer", compileFinal {
|
|
||||||
params [["_uid", "", [""]], ["_target", "", [""]], ["_from", "", [""]], ["_amount", 0, [0]]];
|
|
||||||
|
|
||||||
if (_uid isEqualTo _target) exitWith { ["WARNING", format ["Self-transfer attempt blocked for %1", _uid]] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _account = GVAR(Registry) getOrDefault [_uid, nil];
|
|
||||||
if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _targetAccount = GVAR(Registry) getOrDefault [_target, nil];
|
|
||||||
if (isNil "_targetAccount") exitWith { ["ERROR", "Empty/Invalid Target Account!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _selected = _account getOrDefault [_from, 0];
|
|
||||||
if (_selected < _amount) exitWith { ["WARNING", "Insufficient Funds!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _targetBank = _targetAccount getOrDefault ["bank", 0];
|
|
||||||
private _finalAccount = createHashMapFromArray [[_from, (_selected - _amount)]];
|
|
||||||
private _finalTargetBank = createHashMapFromArray [["bank", (_targetBank + _amount)]];
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
GVAR(Registry) set [_target, _finalTargetBank];
|
|
||||||
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
private _targetPlayer = [_target] call EFUNC(common,getPlayer);
|
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalTargetBank], _targetPlayer] call CFUNC(targetEvent);
|
|
||||||
[CRPC(notifications,recieveNotification), ["info", "Bank", format ["Transferred $%1 to %2", _amount, (name _targetPlayer)]], _player] call CFUNC(targetEvent);
|
|
||||||
[CRPC(notifications,recieveNotification), ["info", "Bank", format ["Received $%1 from %2", _amount, (name _player)]], _targetPlayer] call CFUNC(targetEvent);
|
|
||||||
}],
|
|
||||||
["withdraw", compileFinal {
|
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
||||||
|
|
||||||
["INFO", format ["Withdraw %1, for %2", _amount, _uid]] call EFUNC(common,log);
|
|
||||||
|
|
||||||
private _account = GVAR(Registry) getOrDefault [_uid, nil];
|
|
||||||
if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _bank = _account getOrDefault ["bank", 0];
|
|
||||||
private _cash = _account getOrDefault ["cash", 0];
|
|
||||||
if (_bank < _amount) exitWith { ["WARNING", "Insufficient Funds!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _finalAccount = createHashMapFromArray [["bank", (_bank - _amount)], ["cash", (_cash + _amount)]];
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
[CRPC(notifications,recieveNotification), ["info", "Bank", format ["Withdrew $%1", _amount]], _player] call CFUNC(targetEvent);
|
|
||||||
}],
|
|
||||||
["depositEarnings", compileFinal {
|
|
||||||
params [["_uid", "", [""]], ["_amount", 0, [0]]];
|
|
||||||
|
|
||||||
["INFO", format ["Deposit Earnings %1, for %2", _amount, _uid]] call EFUNC(common,log);
|
|
||||||
|
|
||||||
private _account = GVAR(Registry) getOrDefault [_uid, nil];
|
|
||||||
if (isNil "_account") exitWith { ["ERROR", "Empty/Invalid Account!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _bank = _account getOrDefault ["bank", 0];
|
|
||||||
private _earnings = _account getOrDefault ["earnings", 0];
|
|
||||||
if (_earnings < _amount) exitWith { ["WARNING", "Insufficient Earnings!"] call EFUNC(common,log); };
|
|
||||||
|
|
||||||
private _finalAccount = createHashMapFromArray [["bank", (_bank + _amount)], ["earnings", (_earnings - _amount)]];
|
|
||||||
private _player = [_uid] call EFUNC(common,getPlayer);
|
|
||||||
|
|
||||||
GVAR(Registry) set [_uid, _finalAccount];
|
|
||||||
|
|
||||||
[CRPC(bank,responseSyncBank), [_finalAccount], _player] call CFUNC(targetEvent);
|
|
||||||
[CRPC(notifications,recieveNotification), ["info", "Bank", format ["Deposited $%1 from earnings", _amount]], _player] call CFUNC(targetEvent);
|
|
||||||
}]
|
|
||||||
];
|
|
||||||
|
|
||||||
GVAR(BankStore) = createHashMapObject [GVAR(BankBaseStore)];
|
|
||||||
GVAR(BankStore)
|
|
||||||
75
arma/server/addons/bank/functions/fnc_initMessenger.sqf
Normal file
75
arma/server/addons/bank/functions/fnc_initMessenger.sqf
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File: fnc_initMessenger.sqf
|
||||||
|
* Author: IDSolutions
|
||||||
|
* Date: 2026-03-16
|
||||||
|
* Last Update: 2026-03-16
|
||||||
|
* Public: No
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initializes the bank messenger for all server-to-client
|
||||||
|
* communication including account syncs, toast notifications,
|
||||||
|
* and inline bank UI notices.
|
||||||
|
*
|
||||||
|
* Parameter(s):
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Messenger object [HASHMAP OBJECT]
|
||||||
|
*
|
||||||
|
* Example(s):
|
||||||
|
* call forge_server_bank_fnc_initMessenger
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(BankMessenger) = createHashMapObject [[
|
||||||
|
["#type", "BankMessenger"],
|
||||||
|
["buildClientAccountPatch", compileFinal {
|
||||||
|
params [["_account", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
private _patch = createHashMap;
|
||||||
|
{
|
||||||
|
if (_x in _account) then {
|
||||||
|
_patch set [_x, _account get _x];
|
||||||
|
};
|
||||||
|
} forEach ["uid", "name", "bank", "cash", "earnings", "transactions"];
|
||||||
|
|
||||||
|
_patch
|
||||||
|
}],
|
||||||
|
["sendAccountSync", compileFinal {
|
||||||
|
params [["_uid", "", [""]], ["_account", createHashMap, [createHashMap]], ["_event", CRPC(bank,responseSyncBank), [""]]];
|
||||||
|
|
||||||
|
if (_uid isEqualTo "" || { _account isEqualTo createHashMap }) exitWith { false };
|
||||||
|
|
||||||
|
private _player = [_uid] call EFUNC(common,getPlayer);
|
||||||
|
if (isNull _player) exitWith { false };
|
||||||
|
|
||||||
|
[_event, [_self call ["buildClientAccountPatch", [_account]]], _player] call CFUNC(targetEvent);
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["sendClientNotification", compileFinal {
|
||||||
|
params [["_uid", "", [""]], ["_type", "info", [""]], ["_title", "Bank", [""]], ["_message", "", [""]]];
|
||||||
|
|
||||||
|
if (_uid isEqualTo "" || { _message isEqualTo "" }) exitWith { false };
|
||||||
|
|
||||||
|
private _player = [_uid] call EFUNC(common,getPlayer);
|
||||||
|
if (isNull _player) exitWith { false };
|
||||||
|
|
||||||
|
[CRPC(notifications,recieveNotification), [_type, _title, _message], _player] call CFUNC(targetEvent);
|
||||||
|
true
|
||||||
|
}],
|
||||||
|
["sendNotice", compileFinal {
|
||||||
|
params [["_uid", "", [""]], ["_type", "error", [""]], ["_message", "", [""]]];
|
||||||
|
|
||||||
|
if (_uid isEqualTo "" || { _message isEqualTo "" }) exitWith { false };
|
||||||
|
|
||||||
|
private _player = [_uid] call EFUNC(common,getPlayer);
|
||||||
|
if (isNull _player) exitWith { false };
|
||||||
|
|
||||||
|
[CRPC(bank,responseBankNotice), [_type, _message], _player] call CFUNC(targetEvent);
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
]];
|
||||||
|
|
||||||
|
GVAR(BankMessenger)
|
||||||
91
arma/server/addons/bank/functions/fnc_initModel.sqf
Normal file
91
arma/server/addons/bank/functions/fnc_initModel.sqf
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File: fnc_initModel.sqf
|
||||||
|
* Author: IDSolutions
|
||||||
|
* Date: 2026-03-16
|
||||||
|
* Last Update: 2026-03-16
|
||||||
|
* Public: No
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initializes the bank account data model. Provides default account
|
||||||
|
* schema, player-based account creation, schema migration for
|
||||||
|
* existing accounts, and field-level validation.
|
||||||
|
*
|
||||||
|
* Parameter(s):
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Bank model object [HASHMAP OBJECT]
|
||||||
|
*
|
||||||
|
* Example(s):
|
||||||
|
* call forge_server_bank_fnc_initModel
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(BankModel) = compileFinal createHashMapObject [[
|
||||||
|
["#type", "BankModel"],
|
||||||
|
["defaults", compileFinal {
|
||||||
|
private _account = createHashMap;
|
||||||
|
|
||||||
|
_account set ["uid", ""];
|
||||||
|
_account set ["name", ""];
|
||||||
|
_account set ["bank", 0];
|
||||||
|
_account set ["cash", 0];
|
||||||
|
_account set ["earnings", 0];
|
||||||
|
_account set ["pin", 1234];
|
||||||
|
_account set ["transactions", []];
|
||||||
|
|
||||||
|
_account
|
||||||
|
}],
|
||||||
|
["fromPlayer", compileFinal {
|
||||||
|
params [["_player", objNull, [objNull]]];
|
||||||
|
|
||||||
|
if (_player isEqualTo objNull) exitWith { _self call ["defaults", []] };
|
||||||
|
|
||||||
|
private _account = _self call ["defaults", []];
|
||||||
|
|
||||||
|
_account set ["uid", getPlayerUID _player];
|
||||||
|
_account set ["name", name _player];
|
||||||
|
|
||||||
|
_account
|
||||||
|
}],
|
||||||
|
["migrate", compileFinal {
|
||||||
|
params [["_account", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
private _defaults = _self call ["defaults", []];
|
||||||
|
{
|
||||||
|
if !(_x in _account) then {
|
||||||
|
_account set [_x, _y];
|
||||||
|
};
|
||||||
|
} forEach _defaults;
|
||||||
|
|
||||||
|
_account
|
||||||
|
}],
|
||||||
|
["validate", compileFinal {
|
||||||
|
params [["_account", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
private _uid = _account getOrDefault ["uid", ""];
|
||||||
|
private _name = _account getOrDefault ["name", ""];
|
||||||
|
private _bank = _account getOrDefault ["bank", 0];
|
||||||
|
private _cash = _account getOrDefault ["cash", 0];
|
||||||
|
private _earnings = _account getOrDefault ["earnings", 0];
|
||||||
|
private _pin = _account getOrDefault ["pin", 1234];
|
||||||
|
|
||||||
|
[_uid, _name, _bank, _cash, _earnings, _pin] try {
|
||||||
|
if (_uid isEqualTo "" || !(_uid isEqualType "")) then { throw "Invalid UID!"; };
|
||||||
|
if (_name isEqualTo "" || !(_name isEqualType "")) then { throw "Invalid Name!"; };
|
||||||
|
if (_bank < 0 || !(_bank isEqualType 0)) then { throw "Invalid Bank!"; };
|
||||||
|
if (_cash < 0 || !(_cash isEqualType 0)) then { throw "Invalid Cash!"; };
|
||||||
|
if (_earnings < 0 || !(_earnings isEqualType 0)) then { throw "Invalid Earnings!"; };
|
||||||
|
if (_pin < 1000 || _pin > 9999 || !(_pin isEqualType 0)) then { throw "Invalid Pin!"; };
|
||||||
|
} catch {
|
||||||
|
["ERROR", format ["Failed to validate account %1!", _exception]] call EFUNC(common,log);
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
]];
|
||||||
|
|
||||||
|
GVAR(BankModel)
|
||||||
94
arma/server/addons/bank/functions/fnc_initSessionManager.sqf
Normal file
94
arma/server/addons/bank/functions/fnc_initSessionManager.sqf
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File: fnc_initSessionManager.sqf
|
||||||
|
* Author: IDSolutions
|
||||||
|
* Date: 2026-03-16
|
||||||
|
* Last Update: 2026-03-16
|
||||||
|
* Public: No
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Initializes the bank session manager for managing ATM/bank
|
||||||
|
* session state, mode resolution, and PIN authorization.
|
||||||
|
*
|
||||||
|
* Parameter(s):
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Session manager object [HASHMAP OBJECT]
|
||||||
|
*
|
||||||
|
* Example(s):
|
||||||
|
* call forge_server_bank_fnc_initSessionManager
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma hemtt ignore_variables ["_self"]
|
||||||
|
GVAR(BankSessionManager) = createHashMapObject [[
|
||||||
|
["#type", "BankSessionManager"],
|
||||||
|
["getSessionState", compileFinal {
|
||||||
|
params [["_uid", "", [""]]];
|
||||||
|
|
||||||
|
private _session = GVAR(SessionRegistry) getOrDefault [_uid, createHashMap];
|
||||||
|
if (_session isEqualTo createHashMap) then {
|
||||||
|
_session = createHashMapFromArray [
|
||||||
|
["atmAuthorized", false],
|
||||||
|
["mode", "bank"]
|
||||||
|
];
|
||||||
|
GVAR(SessionRegistry) set [_uid, _session];
|
||||||
|
};
|
||||||
|
|
||||||
|
_session
|
||||||
|
}],
|
||||||
|
["setSessionState", compileFinal {
|
||||||
|
params [["_uid", "", [""]], ["_fieldValuePairs", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
if (_uid isEqualTo "") exitWith { createHashMap };
|
||||||
|
|
||||||
|
private _session = +(_self call ["getSessionState", [_uid]]);
|
||||||
|
{ _session set [_x, _y]; } forEach _fieldValuePairs;
|
||||||
|
|
||||||
|
GVAR(SessionRegistry) set [_uid, _session];
|
||||||
|
_session
|
||||||
|
}],
|
||||||
|
["resolveMode", compileFinal {
|
||||||
|
params [["_mode", "bank", [""]]];
|
||||||
|
|
||||||
|
private _finalMode = toLowerANSI _mode;
|
||||||
|
if !(_finalMode in ["atm", "bank"]) then { _finalMode = "bank"; };
|
||||||
|
|
||||||
|
_finalMode
|
||||||
|
}],
|
||||||
|
["syncSessionMode", compileFinal {
|
||||||
|
params [["_uid", "", [""]], ["_mode", "", [""]], ["_resetAuthorization", false, [false]]];
|
||||||
|
|
||||||
|
private _current = _self call ["getSessionState", [_uid]];
|
||||||
|
private _finalMode = if (_mode isEqualTo "") then {
|
||||||
|
_current getOrDefault ["mode", "bank"]
|
||||||
|
} else {
|
||||||
|
_self call ["resolveMode", [_mode]]
|
||||||
|
};
|
||||||
|
private _atmAuthorized = _current getOrDefault ["atmAuthorized", false];
|
||||||
|
|
||||||
|
if (_finalMode isEqualTo "atm") then {
|
||||||
|
if (_resetAuthorization || { (_current getOrDefault ["mode", "bank"]) isNotEqualTo "atm" }) then {
|
||||||
|
_atmAuthorized = false;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
_atmAuthorized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
_self call ["setSessionState", [_uid, createHashMapFromArray [
|
||||||
|
["atmAuthorized", _atmAuthorized],
|
||||||
|
["mode", _finalMode]
|
||||||
|
]]]
|
||||||
|
}],
|
||||||
|
["submitPin", compileFinal {
|
||||||
|
params [["_uid", "", [""]], ["_context", createHashMap, [createHashMap]]];
|
||||||
|
|
||||||
|
_self call ["setSessionState", [_uid, createHashMapFromArray [["atmAuthorized", true], ["mode", "atm"]]]];
|
||||||
|
GVAR(BankMessenger) call ["sendClientNotification", [_uid, "info", "Bank", "ATM access granted."]];
|
||||||
|
GVAR(BankStore) call ["hydrateSession", [_uid, "atm", false]];
|
||||||
|
true
|
||||||
|
}]
|
||||||
|
]];
|
||||||
|
|
||||||
|
GVAR(BankSessionManager)
|
||||||
350
arma/server/addons/bank/functions/fnc_initStore.sqf
Normal file
350
arma/server/addons/bank/functions/fnc_initStore.sqf
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
#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)
|
||||||
259
arma/server/addons/bank/functions/fnc_initValidator.sqf
Normal file
259
arma/server/addons/bank/functions/fnc_initValidator.sqf
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
#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)
|
||||||
@ -91,33 +91,33 @@ GVAR(LockerBaseStore) = compileFinal createHashMapFromArray [
|
|||||||
private _category = toLowerANSI (_x getOrDefault ["category", ""]);
|
private _category = toLowerANSI (_x getOrDefault ["category", ""]);
|
||||||
private _quantity = floor ((_x getOrDefault ["quantity", 0]) max 0);
|
private _quantity = floor ((_x getOrDefault ["quantity", 0]) max 0);
|
||||||
private _lockerCategory = switch (_category) do {
|
private _lockerCategory = switch (_category) do {
|
||||||
case "item": { "item" };
|
case "item";
|
||||||
|
case "attachment": { "item" };
|
||||||
case "weapon": { "weapon" };
|
case "weapon": { "weapon" };
|
||||||
case "magazine": { "magazine" };
|
case "magazine": { "magazine" };
|
||||||
case "backpack": { "backpack" };
|
case "backpack": { "backpack" };
|
||||||
default { "" };
|
default { "" };
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_className isEqualTo "" || { _lockerCategory isEqualTo "" } || { _quantity <= 0 }) exitWith {
|
if (_className isEqualTo "" || { _lockerCategory isEqualTo "" } || { _quantity <= 0 }) then {
|
||||||
_result set ["message", "Checkout item was missing a valid classname, category, or quantity."];
|
["WARN", format ["Skipping invalid locker grant entry: %1 (category: %2)", _className, _category]] call EFUNC(common,log);
|
||||||
_result set ["success", false];
|
} else {
|
||||||
|
private _entry = +(_locker getOrDefault [_className, createHashMap]);
|
||||||
|
private _amount = _entry getOrDefault ["amount", 0];
|
||||||
|
private _updatedEntry = createHashMapFromArray [
|
||||||
|
["amount", (_amount + _quantity)],
|
||||||
|
["classname", _className],
|
||||||
|
["category", _lockerCategory]
|
||||||
|
];
|
||||||
|
|
||||||
|
_locker set [_className, _updatedEntry];
|
||||||
|
_patch set [_className, _updatedEntry];
|
||||||
|
_granted pushBack (createHashMapFromArray [
|
||||||
|
["classname", _className],
|
||||||
|
["category", _lockerCategory],
|
||||||
|
["quantity", _quantity]
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
private _entry = +(_locker getOrDefault [_className, createHashMap]);
|
|
||||||
private _amount = _entry getOrDefault ["amount", 0];
|
|
||||||
private _updatedEntry = createHashMapFromArray [
|
|
||||||
["amount", (_amount + _quantity)],
|
|
||||||
["classname", _className],
|
|
||||||
["category", _lockerCategory]
|
|
||||||
];
|
|
||||||
|
|
||||||
_locker set [_className, _updatedEntry];
|
|
||||||
_patch set [_className, _updatedEntry];
|
|
||||||
_granted pushBack (createHashMapFromArray [
|
|
||||||
["classname", _className],
|
|
||||||
["category", _lockerCategory],
|
|
||||||
["quantity", _quantity]
|
|
||||||
]);
|
|
||||||
} forEach _items;
|
} forEach _items;
|
||||||
|
|
||||||
if ((count (keys _locker)) > 25) exitWith {
|
if ((count (keys _locker)) > 25) exitWith {
|
||||||
|
|||||||
@ -23,7 +23,11 @@ if (isNil QEGVAR(common,BaseStore)) then { call EFUNC(common,baseStore); };
|
|||||||
if (isNil QEGVAR(actor,ActorStore)) then { call EFUNC(actor,initActorStore); };
|
if (isNil QEGVAR(actor,ActorStore)) then { call EFUNC(actor,initActorStore); };
|
||||||
|
|
||||||
// Bank
|
// Bank
|
||||||
if (isNil QEGVAR(bank,BankStore)) then { call EFUNC(bank,initBankStore); };
|
if (isNil QEGVAR(bank,BankSessionManager)) then { call EFUNC(bank,initSessionManager); };
|
||||||
|
if (isNil QEGVAR(bank,BankMessenger)) then { call EFUNC(bank,initMessenger); };
|
||||||
|
if (isNil QEGVAR(bank,BankModel)) then { call EFUNC(bank,initModel); };
|
||||||
|
if (isNil QEGVAR(bank,BankStore)) then { call EFUNC(bank,initStore); };
|
||||||
|
if (isNil QEGVAR(bank,BankValidator)) then { call EFUNC(bank,initValidator); };
|
||||||
|
|
||||||
// Garage
|
// Garage
|
||||||
if (isNil QEGVAR(garage,GarageStore)) then { call EFUNC(garage,initGarageStore); };
|
if (isNil QEGVAR(garage,GarageStore)) then { call EFUNC(garage,initGarageStore); };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user