From 613f05d52ae50d9c55736fbfa898f4272524bd49 Mon Sep 17 00:00:00 2001 From: Jacob Schmidt Date: Fri, 28 Mar 2025 09:46:24 -0500 Subject: [PATCH] Refactor: Database and Client Updates This commit introduces several changes related to database interactions and client-side functionality: * **Database Response Handling:** Implements a mechanism to handle responses from server requests, specifically for database operations. This includes setting up a callback system to process results based on request IDs. * **Store Functionality:** Corrects a typo in the `fnc_buyItem.sqf` script, changing `EFUNC(armory,addArmoryItem)` to `EFUNC(arsenal,addArmoryItem)`. * **Inventory Management:** Improves the `fnc_moveInventory.sqf` script by correcting a conditional statement to ensure proper handling of inventory items. * **Configuration Updates:** Updates the mod configuration (`CfgMods.hpp`) to use the correct path for the mod picture. * **Client Initialization:** Adds a client registration call to the server during client post-initialization (`XEH_postInit_client.sqf`). * **Workflow Update:** Updates the build workflow to use the latest Ubuntu runner. * **Database Preparation:** Removes unnecessary preparations from `XEH_postInit.sqf` and `XEH_PREP.hpp`. --- .github/workflows/build.yml | 2 +- addons/db.7z | Bin 0 -> 5457 bytes addons/db/XEH_PREP.hpp | 4 +- addons/db/XEH_postInit.sqf | 4 +- addons/db/XEH_postInit_client.sqf | 4 +- addons/db/XEH_preInit.sqf | 14 ++ addons/db/functions/02282025.7z | Bin 0 -> 2197 bytes addons/db/functions/fnc_requestServerDB.sqf | 35 +++++ addons/db/functions/fnc_saveToMission.sqf | 111 --------------- addons/db/functions/fnc_saveToProfile.sqf | 69 --------- addons/db/functions/fnc_saveToTempDB.sqf | 51 ------- addons/main/CfgMods.hpp | 2 +- .../medical/functions/fnc_moveInventory.sqf | 2 +- addons/org/$PBOPREFIX$ | 1 + addons/org/CfgEventHandlers.hpp | 19 +++ addons/org/XEH_PREP.hpp | 13 ++ addons/org/XEH_postInit.sqf | 1 + addons/org/XEH_postInit_client.sqf | 6 + addons/org/XEH_preInit.sqf | 8 ++ addons/org/XEH_preInit_server.sqf | 1 + addons/org/XEH_preStart.sqf | 2 + addons/org/config.cpp | 16 +++ addons/org/functions/fnc_acceptInvite.sqf | 31 ++++ addons/org/functions/fnc_addAsset.sqf | 49 +++++++ addons/org/functions/fnc_addFunds.sqf | 44 ++++++ addons/org/functions/fnc_addReputation.sqf | 44 ++++++ addons/org/functions/fnc_create.sqf | 43 ++++++ addons/org/functions/fnc_disband.sqf | 33 +++++ addons/org/functions/fnc_initOrgStore.sqf | 134 ++++++++++++++++++ addons/org/functions/fnc_invite.sqf | 76 ++++++++++ addons/org/functions/fnc_join.sqf | 86 +++++++++++ addons/org/functions/fnc_leave.sqf | 50 +++++++ addons/org/functions/fnc_listInvites.sqf | 36 +++++ addons/org/functions/fnc_removeAsset.sqf | 52 +++++++ addons/org/functions/fnc_verifyOrgStore.sqf | 22 +++ addons/org/script_component.hpp | 16 +++ addons/store/functions/fnc_buyItem.sqf | 2 +- 37 files changed, 841 insertions(+), 242 deletions(-) create mode 100644 addons/db.7z create mode 100644 addons/db/functions/02282025.7z create mode 100644 addons/db/functions/fnc_requestServerDB.sqf delete mode 100644 addons/db/functions/fnc_saveToMission.sqf delete mode 100644 addons/db/functions/fnc_saveToProfile.sqf delete mode 100644 addons/db/functions/fnc_saveToTempDB.sqf create mode 100644 addons/org/$PBOPREFIX$ create mode 100644 addons/org/CfgEventHandlers.hpp create mode 100644 addons/org/XEH_PREP.hpp create mode 100644 addons/org/XEH_postInit.sqf create mode 100644 addons/org/XEH_postInit_client.sqf create mode 100644 addons/org/XEH_preInit.sqf create mode 100644 addons/org/XEH_preInit_server.sqf create mode 100644 addons/org/XEH_preStart.sqf create mode 100644 addons/org/config.cpp create mode 100644 addons/org/functions/fnc_acceptInvite.sqf create mode 100644 addons/org/functions/fnc_addAsset.sqf create mode 100644 addons/org/functions/fnc_addFunds.sqf create mode 100644 addons/org/functions/fnc_addReputation.sqf create mode 100644 addons/org/functions/fnc_create.sqf create mode 100644 addons/org/functions/fnc_disband.sqf create mode 100644 addons/org/functions/fnc_initOrgStore.sqf create mode 100644 addons/org/functions/fnc_invite.sqf create mode 100644 addons/org/functions/fnc_join.sqf create mode 100644 addons/org/functions/fnc_leave.sqf create mode 100644 addons/org/functions/fnc_listInvites.sqf create mode 100644 addons/org/functions/fnc_removeAsset.sqf create mode 100644 addons/org/functions/fnc_verifyOrgStore.sqf create mode 100644 addons/org/script_component.hpp diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b78e31..72513ec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ on: jobs: build: name: Build - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: Checkout Source Code uses: actions/checkout@v4 diff --git a/addons/db.7z b/addons/db.7z new file mode 100644 index 0000000000000000000000000000000000000000..bcca499ecb4b0e87daf5a7f91e99028dcf8103ed GIT binary patch literal 5457 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 H1%Chlf#ZI% literal 0 HcmV?d00001 diff --git a/addons/db/XEH_PREP.hpp b/addons/db/XEH_PREP.hpp index 7dbd5dc..90ee6a8 100644 --- a/addons/db/XEH_PREP.hpp +++ b/addons/db/XEH_PREP.hpp @@ -1,3 +1 @@ -PREP(saveToMission); -PREP(saveToProfile); -PREP(saveToTempDB); \ No newline at end of file +PREP(requestServerDB); \ No newline at end of file diff --git a/addons/db/XEH_postInit.sqf b/addons/db/XEH_postInit.sqf index a3c56cd..84f2529 100644 --- a/addons/db/XEH_postInit.sqf +++ b/addons/db/XEH_postInit.sqf @@ -1,3 +1 @@ -#include "script_component.hpp" - -GVAR(tempDB) = []; \ No newline at end of file +#include "script_component.hpp" \ No newline at end of file diff --git a/addons/db/XEH_postInit_client.sqf b/addons/db/XEH_postInit_client.sqf index 84f2529..02bbb78 100644 --- a/addons/db/XEH_postInit_client.sqf +++ b/addons/db/XEH_postInit_client.sqf @@ -1 +1,3 @@ -#include "script_component.hpp" \ No newline at end of file +#include "script_component.hpp" + +["forge_db_registerClient", [getPlayerUID player, clientOwner]] call CBA_fnc_serverEvent; \ No newline at end of file diff --git a/addons/db/XEH_preInit.sqf b/addons/db/XEH_preInit.sqf index d7d59fe..dc52c1c 100644 --- a/addons/db/XEH_preInit.sqf +++ b/addons/db/XEH_preInit.sqf @@ -5,4 +5,18 @@ PREP_RECOMPILE_START; #include "XEH_PREP.hpp" PREP_RECOMPILE_END; +// Handle responses from server requests +["forge_db_response", { + params ["_targetUID", "_requestType", "_result", "_requestID"]; + + if (_targetUID isEqualTo getPlayerUID player) then { + if (!isNil QGVAR(pendingCallbacks)) then { + private _callback = GVAR(pendingCallbacks) getOrDefault [_requestID, {}]; + GVAR(pendingCallbacks) deleteAt _requestID; + + [_result, _requestType] call _callback; + }; + }; +}] call CBA_fnc_addEventHandler; + ADDON = true; \ No newline at end of file diff --git a/addons/db/functions/02282025.7z b/addons/db/functions/02282025.7z new file mode 100644 index 0000000000000000000000000000000000000000..c970469891d9606c6057d60861b4ed7215bd55ce GIT binary patch literal 2197 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 X0|5aAT>uaO01Sa%3IW@cR=WTIY&|Ce literal 0 HcmV?d00001 diff --git a/addons/db/functions/fnc_requestServerDB.sqf b/addons/db/functions/fnc_requestServerDB.sqf new file mode 100644 index 0000000..9daef63 --- /dev/null +++ b/addons/db/functions/fnc_requestServerDB.sqf @@ -0,0 +1,35 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_db_fnc_requestServerDB + * Author: J. Schmidt + * + * Description: + * Sends database requests to the server using CBA events + * + * Arguments: + * 0: _type - Type of database operation + * 1: _data - Data for the operation + * 2: _callback - Function to call when data is returned + * + * Return Value: + * Request ID + */ + +params [ + ["_type", "", [""]], + ["_data", nil, [createHashMap, [], "", 0, true, objNull]], + ["_callback", {}, [{}]] +]; + +private _requestID = format ["%1_%2", diag_tickTime, random 1000]; + +if (isNil QGVAR(pendingCallbacks)) then { + GVAR(pendingCallbacks) = createHashMap; +}; + +GVAR(pendingCallbacks) set [_requestID, _callback]; + +["forge_db_request", [getPlayerUID player, _type, _data, _requestID]] call CBA_fnc_serverEvent; + +_requestID \ No newline at end of file diff --git a/addons/db/functions/fnc_saveToMission.sqf b/addons/db/functions/fnc_saveToMission.sqf deleted file mode 100644 index 5f2035e..0000000 --- a/addons/db/functions/fnc_saveToMission.sqf +++ /dev/null @@ -1,111 +0,0 @@ -#include "..\script_component.hpp" - -/* - * Function: forge_client_db_fnc_saveToMission - * Author: J.Schmidt - * Edit: 07.23.2024 - * Copyright © 2024 J.Schmidt, All rights reserved - * - * Do not edit without permission! - * - * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivative 4.0 International License. - * To view a copy of this license, vist https://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to Creative Commons, - * PO Box 1866, Mountain View, CA 94042 - * - * [Description] - * Store mission and player data in Mission Namespace. - * - * Arguments: - * N/A - * - * Return Value: - * N/A - * - * Examples: - * [] call forge_client_db_fnc_saveToMission; - * - * Public: Yes - */ - -if (isNil "companyFunds") then { companyFunds = 0 }; -if (isNil "companyRating") then { companyRating = 0 }; -if (isNil "companyGenerals") then { companyGenerals = [] }; -if (isNil "companyGarageUnlocks") then { companyGarageUnlocks = [] }; -if (isNil EGVAR(arsenal,armory_unlocks)) then { EGVAR(arsenal,armory_unlocks) = [[],[],[],[]] }; -if (isNil EGVAR(arsenal,garage_unlocks)) then { EGVAR(arsenal,garage_unlocks) = [[],[],[],[],[],[]] }; - -private _vdata = []; -private _pdata = []; -private _cdata = [ -["key", "CompanyState"], -["funds", [companyFunds]], -["rating", [companyRating]], -["operations", [companyGenerals]], -["garage_unlocks", [companyGarageUnlocks]] -]; - -private _vehicles = nearestObjects [player, ["LandVehicle"], 50] apply { - createHashMapFromArray [ - ["vehicle", _x], - ["class", [typeOf _x]], - ["position", [getPosATL _x]], - ["direction", [getDir _x]], - ["health", [damage _x]] - ]; -}; - -{ - if (alive _x) then { - _vdata pushBackUnique _x; - }; -} forEach _vehicles; - -{ - private _data = [ - ["key", getPlayerUID player], - // ["armory_unlocks", [forge_client_armory_arsenalUnlocks]], - // ["garage_unlocks", [forge_client_armory_garageUnlocks]], - ["armory_unlocks", [EGVAR(arsenal,armory_unlocks)]], - ["garage_unlocks", [EGVAR(arsenal,garage_unlocks)]], - // ["locker", [player getVariable ["Locker", []]]], - // ["garage", [player getVariable ["Garage", []]]], - ["locker", [GETVAR(player,FORGE_Locker,[])]], - ["garage", [GETVAR(player,FORGE_Garage,[])]], - // ["cash", [player getVariable ["FORGE_Cash", 0]]], - // ["bank", [player getVariable ["FORGE_Bank", 0]]], - ["cash", [GETVAR(player,FORGE_Cash,0)]], - ["bank", [GETVAR(player,FORGE_Bank,0)]], - // ["number", [player getVariable ["FORGE_Phone_Number", "unknown"]]], - // ["email", [player getVariable ["FORGE_Email", "unknown@spearnet.mil"]]], - ["number", [GETVAR(player,FORGE_Phone_Number,"unknown")]], - ["email", [GETVAR(player,FORGE_Email,"unknown@spearnet.mil")]], - // ["paygrade", [player getVariable ["Paygrade", "E1"]]], - ["paygrade", [GETVAR(player,FORGE_Paygrade,"E1")]], - ["reputation", [rating player]], - ["loadout", [getUnitLoadout player]], - // ["holster", [player getVariable ["FORGE_Holster_Weapon", true]]], - ["holster", [GETVAR(player,FORGE_Holster_Weapon,true)]], - ["position", [getPosASLVisual player]], - ["direction", [getDirVisual player]] - ]; - - if (isNull objectParent player) then { - _data pushBack "currentWeapon"; - _data pushBack [currentMuzzle player]; - _data pushBack "stance"; - _data pushBack [stance player]; - }; - - _pdata pushBackUnique _data; -} forEach playableUnits; - -private _cHashMap = createHashMapFromArray _cdata; -private _pHashMap = createHashMapFromArray _pdata; -private _vHashMap = createHashMapFromArray _vdata; - -// missionProfileNamespace setVariable ["FORGE_MissionData", _cHashMap]; -// missionProfileNamespace setVariable ["FORGE_PlayerData", _pHashMap]; -// missionProfileNamespace setVariable ["FORGE_VehicleData", _vHashMap]; -SETPVAR(missionNamespace,FORGE_MissionData,_cHashMap); -SETPVAR(missionNamespace,FORGE_PlayerData,_pHashMap); -SETPVAR(missionNamespace,FORGE_VehicleData,_vHashMap); \ No newline at end of file diff --git a/addons/db/functions/fnc_saveToProfile.sqf b/addons/db/functions/fnc_saveToProfile.sqf deleted file mode 100644 index 2e3a22c..0000000 --- a/addons/db/functions/fnc_saveToProfile.sqf +++ /dev/null @@ -1,69 +0,0 @@ -#include "..\script_component.hpp" - -/* - * Function: forge_client_db_fnc_saveToProfile - * Author: J.Schmidt - * Edit: 07.23.2024 - * Copyright © 2024 J.Schmidt, All rights reserved - * - * Do not edit without permission! - * - * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivative 4.0 International License. - * To view a copy of this license, vist https://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to Creative Commons, - * PO Box 1866, Mountain View, CA 94042 - * - * [Description] - * Store player data in Profile Namespace. - * - * Arguments: - * N/A - * - * Return Value: - * N/A - * - * Examples: - * [] call forge_client_db_fnc_saveToProfile; - * - * Public: Yes - */ - -// if (isNil "forge_client_armory_arsenalUnlocks") then { forge_client_armory_arsenalUnlocks = [] }; -// if (isNil "forge_client_armory_garageUnlocks") then { forge_client_armory_garageUnlocks = [] }; -if (isNil EGVAR(arsenal,armory_unlocks)) then { EGVAR(arsenal,armory_unlocks) = [[],[],[],[]] }; -if (isNil EGVAR(arsenal,garage_unlocks)) then { EGVAR(arsenal,garage_unlocks) = [[],[],[],[],[],[]] }; - -private _data = [ -["key", getPlayerUID player], -["armory_unlocks", [EGVAR(arsenal,armory_unlocks)]], -["garage_unlocks", [EGVAR(arsenal,garage_unlocks)]], -// ["locker", [player getVariable ["Locker", []]]], -// ["garage", [player getVariable ["Garage", []]]], -["locker", [GETVAR(player,FORGE_Locker,[])]], -["garage", [GETVAR(player,FORGE_Garage,[])]], -// ["cash", [player getVariable ["FORGE_Cash", 0]]], -// ["bank", [player getVariable ["FORGE_Bank", 0]]], -["cash", [GETVAR(player,FORGE_Cash,0)]], -["bank", [GETVAR(player,FORGE_Bank,0)]], -// ["number", [player getVariable ["FORGE_Phone_Number", "unknown"]]], -// ["email", [player getVariable ["FORGE_Email", "unknown@spearnet.mil"]]], -["number", [GETVAR(player,FORGE_PhoneNumber,"unknown")]], -["email", [GETVAR(player,FORGE_Email,"unknown@spearnet.mil")]], -// ["paygrade", [player getVariable ["Paygrade", "E1"]]], -["paygrade", [GETVAR(player,FORGE_Paygrade,"E1")]], -["reputation", [rating player]], -["loadout", [getUnitLoadout player]], -// ["holster", [player getVariable ["FORGE_Holster_Weapon", true]]], -["holster", [GETVAR(player,FORGE_Holster_Weapon,true)]], -["position", [getPosASLVisual player]], -["direction", [getDirVisual player]] -]; - -if (isNull objectParent player) then { - _data pushBack ["currentWeapon", [currentMuzzle player]]; - _data pushBack ["stance", [stance player]]; -}; - -private _hashMap = createHashMapFromArray _data; - -// profileNamespace setVariable ["FORGE_PlayerData", _hashMap]; -SETVAR(profileNamespace,FORGE_PlayerData,_hashMap); \ No newline at end of file diff --git a/addons/db/functions/fnc_saveToTempDB.sqf b/addons/db/functions/fnc_saveToTempDB.sqf deleted file mode 100644 index ec097f0..0000000 --- a/addons/db/functions/fnc_saveToTempDB.sqf +++ /dev/null @@ -1,51 +0,0 @@ -#include "..\script_component.hpp" - -/* - * Function: forge_client_db_fnc_saveToTempDB - * Author: J.Schmidt - * Edit: 07.23.2024 - * Copyright © 2024 J.Schmidt, All rights reserved - * - * Do not edit without permission! - * - * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivative 4.0 International License. - * To view a copy of this license, vist https://creativecommons.org/licenses/by-nc-nd/4.0/ or send a letter to Creative Commons, - * PO Box 1866, Mountain View, CA 94042 - * - * [Description] - * Store data in Temp DB. - * - * Arguments: - * 0: Name of Event - * 1: Name of DB - * 2: UID of Player - * 3: Name of Key - * 4: Value to store in key - * - * Return Value: - * N/A - * - * Examples: - * ["playerStatus", "players", "76561198027566824", "status", "available"] call forge_client_db_fnc_saveToTempDB; - * - * Public: Yes - */ - -params [["_event", "", [""]], ["_db", "", [""]], ["_uid", "", [""]], ["_key", "", [""]], ["_value", "", [[], 0, "", false]]]; - -if (isNil "_event") exitWith { ["No Event provided"] call BFUNC(log); }; -if (isNil "_db") exitWith { ["No DB provided"] call BFUNC(log); }; -if (isNil "_uid") exitWith { ["No UID provided"] call BFUNC(log); }; -if (isNil "_key") exitWith { ["No key provided"] call BFUNC(log); }; -if (isNil "_value") exitWith { ["No Value provided"] call BFUNC(log); }; - -["Received event: %1", _this] call BFUNC(logFormat); - -private _response = [GVAR(tempDB), [_db, _uid, _key], _value] call BFUNC(dbValueSet); - -if !(_response) then { - ["Failed to set Key '%1' for UID '%2' with '%3' to DB", _key, _uid, _value] call BFUNC(logFormat); -} else { - SETPVAR(missionNamespace,FORGE_TempDb,GVAR(tempDB)); - ["Successfully set key '%1' for UID '%2' with '%3'", _key, _uid, _value] call BFUNC(logFormat); -}; \ No newline at end of file diff --git a/addons/main/CfgMods.hpp b/addons/main/CfgMods.hpp index 01054b7..b60efa4 100644 --- a/addons/main/CfgMods.hpp +++ b/addons/main/CfgMods.hpp @@ -3,7 +3,7 @@ class CfgMods { dir = "@forge_client"; name = "FORGE Client"; author = "IDSolutions"; - picture = "A3\Ui_f\data\Logos\arma3_expansion_alpha_ca"; + picture = "A3\Ui_f\data\Logos\arma3_expansion_alpha_ca.paa"; hideName = "false"; hidePicture = "false"; action = "https://innovativedevsolutions.org"; diff --git a/addons/medical/functions/fnc_moveInventory.sqf b/addons/medical/functions/fnc_moveInventory.sqf index d25a886..52fbb2c 100644 --- a/addons/medical/functions/fnc_moveInventory.sqf +++ b/addons/medical/functions/fnc_moveInventory.sqf @@ -59,7 +59,7 @@ if (_backpack != "") then { { private _holderWeapons = ((getWeaponCargo _x) select 0) select { _x in _weapons }; - if !(_holderWeapons isEqualTo []) then { + if (_holderWeapons isNotEqualTo []) then { deleteVehicle _x; }; } forEach _nearHolders; \ No newline at end of file diff --git a/addons/org/$PBOPREFIX$ b/addons/org/$PBOPREFIX$ new file mode 100644 index 0000000..6fa59ff --- /dev/null +++ b/addons/org/$PBOPREFIX$ @@ -0,0 +1 @@ +z\forge_client\addons\org \ No newline at end of file diff --git a/addons/org/CfgEventHandlers.hpp b/addons/org/CfgEventHandlers.hpp new file mode 100644 index 0000000..78b189a --- /dev/null +++ b/addons/org/CfgEventHandlers.hpp @@ -0,0 +1,19 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preStart)); + }; +}; + +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + serverInit = QUOTE(call COMPILE_FILE(XEH_preInit_server)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_postInit)); + clientInit = QUOTE(call COMPILE_FILE(XEH_postInit_client)); + }; +}; \ No newline at end of file diff --git a/addons/org/XEH_PREP.hpp b/addons/org/XEH_PREP.hpp new file mode 100644 index 0000000..43b4c4e --- /dev/null +++ b/addons/org/XEH_PREP.hpp @@ -0,0 +1,13 @@ +PREP(acceptInvite); +PREP(addAsset); +PREP(addFunds); +PREP(addReputation); +PREP(create); +PREP(disband); +PREP(initOrgStore); +PREP(invite); +PREP(join); +PREP(leave); +PREP(listInvites); +PREP(removeAsset); +PREP(verifyOrgStore); \ No newline at end of file diff --git a/addons/org/XEH_postInit.sqf b/addons/org/XEH_postInit.sqf new file mode 100644 index 0000000..84f2529 --- /dev/null +++ b/addons/org/XEH_postInit.sqf @@ -0,0 +1 @@ +#include "script_component.hpp" \ No newline at end of file diff --git a/addons/org/XEH_postInit_client.sqf b/addons/org/XEH_postInit_client.sqf new file mode 100644 index 0000000..b16ff31 --- /dev/null +++ b/addons/org/XEH_postInit_client.sqf @@ -0,0 +1,6 @@ +#include "script_component.hpp" + +// Initialize organization store +[{!isNil "FORGE_STORE_REG"}, { + [] call FUNC(initOrgStore); +}] call CFUNC(waitUntilAndExecute); \ No newline at end of file diff --git a/addons/org/XEH_preInit.sqf b/addons/org/XEH_preInit.sqf new file mode 100644 index 0000000..d7d59fe --- /dev/null +++ b/addons/org/XEH_preInit.sqf @@ -0,0 +1,8 @@ +#include "script_component.hpp" +ADDON = false; + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +ADDON = true; \ No newline at end of file diff --git a/addons/org/XEH_preInit_server.sqf b/addons/org/XEH_preInit_server.sqf new file mode 100644 index 0000000..84f2529 --- /dev/null +++ b/addons/org/XEH_preInit_server.sqf @@ -0,0 +1 @@ +#include "script_component.hpp" \ No newline at end of file diff --git a/addons/org/XEH_preStart.sqf b/addons/org/XEH_preStart.sqf new file mode 100644 index 0000000..7dca066 --- /dev/null +++ b/addons/org/XEH_preStart.sqf @@ -0,0 +1,2 @@ +#include "script_component.hpp" +#include "XEH_PREP.hpp" \ No newline at end of file diff --git a/addons/org/config.cpp b/addons/org/config.cpp new file mode 100644 index 0000000..338b901 --- /dev/null +++ b/addons/org/config.cpp @@ -0,0 +1,16 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"forge_client_main"}; + authors[] = {"J. Schmidt", "Creedcoder"}; + author = "IDSolutions"; + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" \ No newline at end of file diff --git a/addons/org/functions/fnc_acceptInvite.sqf b/addons/org/functions/fnc_acceptInvite.sqf new file mode 100644 index 0000000..23126ca --- /dev/null +++ b/addons/org/functions/fnc_acceptInvite.sqf @@ -0,0 +1,31 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_acceptInvite + * Author: J. Schmidt + * + * Description: + * Allows a player to accept an organization invite from their stored invites + * + * Arguments: + * 0: _playerUID - Player UID + * 1: _playerName - Player Name + * 2: _inviteKey - Invite key from the player's invites + * + * Return Value: + * Success + */ + +params [["_playerUID", "", [""]], ["_playerName", "", [""]], ["_inviteKey", "", [""]]]; + +if (_playerUID == "" || _playerName == "" || _inviteKey == "") exitWith { TRACE_3("Invalid parameters for accepting invitation",_playerUID,_playerName,_inviteKey); false }; + +private _playerInvites = GETVAR(profileNamespace,FORGE_ORG_INVITES,createHashMap); +private _invite = _playerInvites get _inviteKey; + +if (isNil "_invite") exitWith { TRACE_1("Invite not found",_inviteKey); false }; + +private _orgName = _invite get "orgName"; +private _ownerUID = _invite get "ownerUID"; + +[_ownerUID, _orgName, _playerUID, _playerName, "member"] call FUNC(join); \ No newline at end of file diff --git a/addons/org/functions/fnc_addAsset.sqf b/addons/org/functions/fnc_addAsset.sqf new file mode 100644 index 0000000..9c863d2 --- /dev/null +++ b/addons/org/functions/fnc_addAsset.sqf @@ -0,0 +1,49 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_addAsset + * Author: J. Schmidt + * + * Description: + * Adds an asset to an organization's inventory + * + * Arguments: + * 0: _uid - Player UID + * 1: _name - Organization name + * 2: _assetType - Type of asset (vehicle, building, etc.) + * 3: _assetData - Asset data + * + * Return Value: + * Updated assets collection + */ + +params [["_uid", "", [""]], ["_name", "", [""]], ["_assetType", "", [""]], ["_assetData", createHashMap, [createHashMap]]]; + +if (_uid == "" || _name == "" || _assetType == "") exitWith { TRACE_3("Invalid parameters for adding asset",_uid,_name,_assetType); nil }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_key); nil }; + +private _assets = _org get "assets"; +private _logs = _org get "logs"; +private _owner = _org get "owner"; + +if (isNil { _assets get _assetType }) then { _assets set [_assetType, []]; }; + +private _typeAssets = _assets get _assetType; + +_typeAssets pushBack _assetData; +_org set ["assets", _assets]; + +_logs pushBack [_dateTime, "ASSET_ADDED", _assetType, _assetData]; +_org set ["logs", _logs]; + +_store call ["post", [_owner, _name]]; + +_assets \ No newline at end of file diff --git a/addons/org/functions/fnc_addFunds.sqf b/addons/org/functions/fnc_addFunds.sqf new file mode 100644 index 0000000..cb3ac8e --- /dev/null +++ b/addons/org/functions/fnc_addFunds.sqf @@ -0,0 +1,44 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_addFunds + * Author: J. Schmidt + * + * Description: + * Adds funds to an organization's account + * + * Arguments: + * 0: _uid - Player UID + * 1: _name - Organization name + * 2: _amount - Amount to add (can be negative for withdrawals) + * + * Return Value: + * New funds amount + */ + +params [["_uid", "", [""]], ["_name", "", [""]], ["_amount", 0, [0]]]; + +if (_uid == "" || _name == "") exitWith { TRACE_2("Invalid parameters for adding funds",_uid,_name); nil }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_key); nil }; + +private _funds = _org get "funds"; +private _logs = _org get "logs"; +private _owner = _org get "owner"; +private _newFunds = _funds + _amount; + +_org set ["funds", _newFunds]; + +_logs pushBack [_dateTime, "FUNDS_ADDED", _amount, _newFunds]; +_org set ["logs", _logs]; + +_store call ["post", [_owner, _name]]; + +_newFunds \ No newline at end of file diff --git a/addons/org/functions/fnc_addReputation.sqf b/addons/org/functions/fnc_addReputation.sqf new file mode 100644 index 0000000..7ce09a9 --- /dev/null +++ b/addons/org/functions/fnc_addReputation.sqf @@ -0,0 +1,44 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_addReputation + * Author: J. Schmidt + * + * Description: + * Adds reputation to an organization + * + * Arguments: + * 0: _uid - Player UID + * 1: _name - Organization name + * 2: _amount - Amount of reputation to add (can be negative) + * + * Return Value: + * New reputation amount + */ + +params [["_uid", "", [""]], ["_name", "", [""]], ["_amount", 0, [0]]]; + +if (_uid == "" || _name == "") exitWith { TRACE_2("Invalid parameters for adding reputation",_uid,_name); nil }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_key); nil }; + +private _reputation = _org get "reputation"; +private _logs = _org get "logs"; +private _owner = _org get "owner"; +private _newReputation = _reputation + _amount; + +_org set ["reputation", _newReputation]; + +_logs pushBack [_dateTime, "REPUTATION", _amount, _newReputation]; +_org set ["logs", _logs]; + +_store call ["post", [_owner, _name]]; + +_newReputation \ No newline at end of file diff --git a/addons/org/functions/fnc_create.sqf b/addons/org/functions/fnc_create.sqf new file mode 100644 index 0000000..b6bbe50 --- /dev/null +++ b/addons/org/functions/fnc_create.sqf @@ -0,0 +1,43 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_create + * Author: J. Schmidt + * + * Description: + * Creates a new organization for a player + * + * Arguments: + * 0: _ownerUID - Player UID + * 1: _ownerName - Player name + * 2: _name - Organization name + * + * Return Value: + * Success + */ + +params [["_ownerUID", "", [""]], ["_ownerName", "", [""]], ["_name", "", [""]]]; + +if (_ownerUID == "" || _ownerName == "" || _name == "") exitWith { TRACE_3("Invalid parameters for organization creation",_ownerUID,_ownerName,_name); false }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _ownerUID, _name]; +private _existingOrg = _store call ["getByKey", [_key]]; +private _playerAlreadyInOrg = false; + +{ + private _org = _x; + private _members = _org get "members"; + if (!isNil { _members get _ownerUID }) exitWith { + _playerAlreadyInOrg = true; + }; +} forEach (_store call ["get", []]); + +if (_playerAlreadyInOrg) exitWith { TRACE_1("Player already in an organization",_ownerUID); false }; + +_store call ["post", [_ownerUID, _name, 0, 0]]; +[_name, _ownerUID, _ownerName, "owner"] call FUNC(join); + +TRACE_2("Organization created successfully",_name,_ownerUID); + +true \ No newline at end of file diff --git a/addons/org/functions/fnc_disband.sqf b/addons/org/functions/fnc_disband.sqf new file mode 100644 index 0000000..5b5b893 --- /dev/null +++ b/addons/org/functions/fnc_disband.sqf @@ -0,0 +1,33 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_disband + * Author: J. Schmidt + * + * Description: + * Disbands an organization if requested by the owner + * + * Arguments: + * 0: _uid - UID of the player attempting to disband + * 1: _name - Organization name + * + * Return Value: + * Success + */ + +params [["_uid", "", [""]], ["_name", "", [""]]]; + +if (_uid == "" || _name == "") exitWith { TRACE_2("Invalid parameters for disbanding organization",_uid,_name); false }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_key); false }; +if ((_org get "owner") != _uid) exitWith { TRACE_2("Player is not the owner of this organization",_uid,_name); false }; + +_store call ["delete", [_key]]; + +TRACE_1("Organization disbanded successfully",_name); + +true \ No newline at end of file diff --git a/addons/org/functions/fnc_initOrgStore.sqf b/addons/org/functions/fnc_initOrgStore.sqf new file mode 100644 index 0000000..6c15eea --- /dev/null +++ b/addons/org/functions/fnc_initOrgStore.sqf @@ -0,0 +1,134 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_initOrgStore + * Author: J. Schmidt + * + * Description: + * Initializes player organization data using the database interface + * + * Arguments: + * None + * + * Return Value: + * Organization interface + */ + +private _orgStoreInterface = createHashMapObject [[ + ["#type", "IOrganizationStore"], + ["#create", { + private _store = GETMVAR(FORGE_STORE_REG,nil); + + if (isNil "_store") exitWith { ERROR_MSG("Store not initialized"); false }; + + private _orgStore = _store call ["getStore", ["organizations"]]; + private _orgNameIndex = _store call ["getStore", ["organizationNameIndex"]]; + private _orgRegistry = GETVAR(profileNamespace,FORGE_ORG_REG,createHashMap); + + if (isNil "_orgStore" || isNil "_orgNameIndex") then { _orgStore = _store call ["createStore", ["organizations"]]; }; + if (isNil "_orgNameIndex") then { _orgNameIndex = _store call ["createStore", ["organizationNameIndex"]]; }; + + private _name = _orgRegistry get "name"; + private _uid = _orgRegistry get "owner"; + + if (!isNil "_name" && !isNil "_uid") then { + private _key = format ["%1_%2", _uid, _name]; + + _orgStore set [_key, _orgRegistry]; + _orgNameIndex set [_key, _name]; + }; + + true + }], + ["post", { + params [["_uid", "", [""]], ["_name", "", [""]], ["_initialFunds", 0, [0]], ["_initialReputation", 0, [0]]]; + + if (_uid == "" || _name == "") exitWith { ERROR_MSG("Owner UID and, or name cannot be empty"); nil }; + + private _store = GETMVAR(FORGE_STORE_REG,nil); + private _key = format ["%1_%2", _uid, _name]; + + private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; + private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + + private _orgRegistry = GETVAR(profileNamespace,FORGE_ORG_REG,createHashMap); + + private _existingOrgKey = _store call ["get", ["organizationNameIndex", _key]]; + private _existingOrg = nil; + private _orgData = nil; + + if !(isNil "_existingOrgKey") then { + _existingOrg = _store call ["get", ["organizations", _existingOrgKey]]; + }; + + if !(isNil "_existingOrg") then { + _orgData = _existingOrg; + } else { + _orgData = createHashMapFromArray [ + ["name", _name], + ["owner", _uid], + ["funds", _initialFunds], + ["reputation", _initialReputation], + ["assets", createHashMap], + ["members", createHashMap], + ["invites", createHashMap], + ["logs", []], + ["created", _dateTime] + ]; + + _orgRegistry set [_key, _orgData]; + + SETVAR(profileNamespace,FORGE_ORG_REG,_orgRegistry); + saveProfileNamespace; + }; + + _store call ["set", ["organizationNameIndex", _key, _name]]; + _store call ["set", ["organizations", _key, _orgData]]; + + _orgData + }], + ["get", { + private _store = GETMVAR(FORGE_STORE_REG,nil); + private _orgStore = _store call ["getStore", ["organizations"]]; + + if (isNil "_orgStore") exitWith { createHashMap }; + + _orgStore + }], + ["getByKey", { + params [["_key", "", [""]]]; + + if (_key == "") exitWith { ERROR_MSG("Key cannot be empty"); nil }; + + private _store = GETMVAR(FORGE_STORE_REG,nil); + private _org = _store call ["get", ["organizations", _key]] + + if (isNil "_org") exitWith { ERROR_MSG_1("Organization with composite key %1 not found", _key); nil }; + + _org + }], + ["delete", { + params [["_key", "", [""]]]; + + if (_key == "") exitWith { ERROR_MSG("Key cannot be empty"); false }; + + private _store = GETMVAR(FORGE_STORE_REG,nil); + private _key = _store call ["get", ["organizationNameIndex", _key, nil]]; + + _store call ["delete", ["organizationNameIndex", _key]]; + + if (isNil "_key") exitWith { ERROR_MSG_1("Key for organization not found", _key); false }; + + _store call ["delete", ["organizations", _key]]; + + private _orgRegistry = GETVAR(profileNamespace,FORGE_ORG_REG,createHashMap); + _orgRegistry deleteAt _key; + SETVAR(profileNamespace,FORGE_ORG_REG,_orgRegistry); + saveProfileNamespace; + + true + }] +]]; + +SETMVAR(FORGE_ORG_STORE_REG,_orgStoreInterface); +GETMVAR(FORGE_ORG_STORE_REG,nil) \ No newline at end of file diff --git a/addons/org/functions/fnc_invite.sqf b/addons/org/functions/fnc_invite.sqf new file mode 100644 index 0000000..3bb4013 --- /dev/null +++ b/addons/org/functions/fnc_invite.sqf @@ -0,0 +1,76 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_invite + * Author: J. Schmidt + * + * Description: + * Sends an invitation to a player to join an organization + * + * Arguments: + * 0: _uid - Player UID + * 1: _name - Organization name + * 2: _targetUID - Target player's UID + * 3: _targetName - Target player's name + * + * Return Value: + * Success + */ + +params [["_uid", "", [""]], ["_name", "", [""]], ["_targetUID", "", [""]], ["_targetName", "", [""]]]; + +if (_uid == "" || _name == "" || _targetUID == "" || _targetName == "") exitWith { TRACE_3("Invalid parameters for organization invitation",_uid,_name,_targetUID); false }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_key); false }; + +private _invites = _org get "invites"; +private _logs = _org get "logs"; + +private _invite = createHashMapFromArray [ + ["uid", _targetUID], + ["name", _targetName], + ["timestamp", _dateTime], + ["status", "pending"] +]; + +_invites set [_targetUID, _invite]; +_org set ["invites", _invites]; + +_logs pushBack [_dateTime, "INVITE", _targetName, _targetUID]; +_org set ["logs", _logs]; + +_store call ["post", [_uid, _name]]; + +[_targetUID, _uid, _name, _dateTime] spawn { + params ["_targetUID", "_ownerUID", "_orgName", "_timestamp"]; + + if (isRemoteExecuted && remoteExecutedOwner != 2) exitWith {}; + + private _target = [_targetUID] call BIS_fnc_getUnitByUID; + + if !(isNull _target) then { + private _orgInvites = GETVAR(profileNamespace,FORGE_ORG_INVITES,createHashMap); + private _inviteKey = format ["%1_%2", _ownerUID, _orgName]; + + _orgInvites set [_inviteKey, createHashMapFromArray [ + ["orgName", _orgName], + ["ownerUID", _ownerUID], + ["timestamp", _timestamp], + ["status", "pending"] + ]]; + + SETVAR(profileNamespace,FORGE_ORG_INVITES,_orgInvites); + saveProfileNamespace; + + [format ["You have been invited to join %1", _orgName]] remoteExec ["hint", _target]; + }; +}; + +true \ No newline at end of file diff --git a/addons/org/functions/fnc_join.sqf b/addons/org/functions/fnc_join.sqf new file mode 100644 index 0000000..6714bf0 --- /dev/null +++ b/addons/org/functions/fnc_join.sqf @@ -0,0 +1,86 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_join + * Author: J. Schmidt + * + * Description: + * Adds a player to an organization, either as a new member or the owner + * + * Arguments: + * 0: _uid - Player UID + * 1: _name - Organization name + * 2: _targetUID - Target player's UID + * 3: _targetName - Target player's name + * 4: _targetRank - Player's rank in organization (default: "member") + * + * Return Value: + * Success + */ + +params [["_uid", "", [""]], ["_name", "", [""]], ["_targetUID", "", [""]], ["_targetName", "", [""]], ["_targetRank", "member", [""]]]; + +if (_uid == "" || _name == "" || _targetUID == "" || _targetName == "") exitWith { TRACE_3("Invalid parameters for joining organization",_name,_targetUID,_targetName); false }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; +private _playerAlreadyInOrg = false; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_key); false }; + +private _invites = _org get "invites"; +private _logs = _org get "logs"; +private _members = _org get "members"; + +{ + private _checkOrg = _x; + private _checkMembers = _checkOrg get "members"; + if (!isNil { _checkMembers get _targetUID }) exitWith { + _playerAlreadyInOrg = true; + }; +} forEach (_store call ["get", []]); + +if (_playerAlreadyInOrg) exitWith { TRACE_2("Player already in an organization",_targetUID,_targetName); false }; + +private _member = createHashMapFromArray [ + ["uid", _targetUID], + ["name", _targetName], + ["rank", _targetRank], + ["joinDate", _dateTime] +]; + +if (_targetRank == "owner") then { + _members set [_targetUID, _member]; + _org set ["members", _members]; + + _store call ["post", [_uid, _name]]; + true +} else { + if !(isNil { _invites get _targetUID }) then { + _invites deleteAt _targetUID; + _members set [_targetUID, _member]; + + _org set ["members", _members]; + _org set ["invites", _invites]; + + _logs pushBack [_dateTime, "JOIN", _targetName, _targetUID]; + _org set ["logs", _logs]; + + private _inviteKey = format ["%1_%2", _uid, _name]; + private _orgInvites = GETVAR(profileNamespace,FORGE_ORG_INVITES,createHashMap); + + _orgInvites deleteAt _inviteKey; + SETVAR(profileNamespace,FORGE_ORG_INVITES,_orgInvites); + saveProfileNamespace; + + _store call ["post", [_uid, _name]]; + true + } else { + TRACE_2("Player not invited to this organization",_targetUID,_name); + false + }; +}; \ No newline at end of file diff --git a/addons/org/functions/fnc_leave.sqf b/addons/org/functions/fnc_leave.sqf new file mode 100644 index 0000000..1f6a532 --- /dev/null +++ b/addons/org/functions/fnc_leave.sqf @@ -0,0 +1,50 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_leave + * Author: J. Schmidt + * + * Description: + * Removes a player from an organization + * + * Arguments: + * 0: _ownerUID - Organization owner's UID + * 1: _orgName - Organization name + * 2: _playerUID - Player's UID who is leaving + * 3: _playerName - Player's name who is leaving + * + * Return Value: + * Success + */ + +params [["_ownerUID", "", [""]], ["_orgName", "", [""]], ["_playerUID", "", [""]], ["_playerName", "", [""]]]; + +if (_ownerUID == "" || _orgName == "" || _playerUID == "" || _playerName == "") exitWith { TRACE_4("Invalid parameters for leaving organization",_ownerUID,_orgName,_playerUID,_playerName); false }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _ownerUID, _orgName]; +private _org = _store call ["getByKey", [_key]]; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found", _key); false }; + +private _members = _org get "members"; +private _logs = _org get "logs"; + +if (isNil { _members get _playerUID }) exitWith { TRACE_2("Player not in this organization",_playerUID,_orgName); false }; + +private _memberData = _members get _playerUID; + +if (_memberData get "rank" == "owner") exitWith { TRACE_2("Owner cannot leave organization, must transfer ownership first",_playerUID,_orgName); false }; + +_logs pushBack [_dateTime, "LEAVE", _playerName, _playerUID]; +_org set ["logs", _logs]; + +_members deleteAt _playerUID; +_org set ["members", _members]; + +_store call ["post", [_ownerUID, _orgName]]; + +true \ No newline at end of file diff --git a/addons/org/functions/fnc_listInvites.sqf b/addons/org/functions/fnc_listInvites.sqf new file mode 100644 index 0000000..421388d --- /dev/null +++ b/addons/org/functions/fnc_listInvites.sqf @@ -0,0 +1,36 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_listPlayerInvites + * Author: J. Schmidt + * + * Description: + * Lists all organization invites for the current player + * + * Arguments: + * 0: _playerUID - Player UID + * + * Return Value: + * Array of organization invites + */ + +params [["_playerUID", "", [""]]]; + +if (_playerUID == "") exitWith { TRACE_1("Invalid player UID",_playerUID); [] }; + +private _playerInvites = GETVAR(profileNamespace,FORGE_ORG_INVITES,createHashMap); +private _invitesList = []; + +{ + private _inviteKey = _x; + private _invite = _playerInvites get _inviteKey; + + _invitesList pushBack [ + _inviteKey, + _invite get "orgName", + _invite get "ownerUID", + _invite get "timestamp" + ]; +} forEach (keys _playerInvites); + +_invitesList \ No newline at end of file diff --git a/addons/org/functions/fnc_removeAsset.sqf b/addons/org/functions/fnc_removeAsset.sqf new file mode 100644 index 0000000..027c96d --- /dev/null +++ b/addons/org/functions/fnc_removeAsset.sqf @@ -0,0 +1,52 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_removeAsset + * Author: J. Schmidt + * + * Description: + * Removes an asset from an organization's inventory + * + * Arguments: + * 0: _uid - Player UID + * 1: _name - Organization name + * 2: _assetType - Type of asset (vehicle, building, etc.) + * 3: _assetId - Unique identifier of the asset + * + * Return Value: + * Updated assets collection + */ + +params [["_uid", "", [""]], ["_name", "", [""]], ["_assetType", "", [""]], ["_assetId", "", [""]]]; + +if (_uid isEqualTo "" || _name isEqualTo "" || _assetType isEqualTo "" || _assetId isEqualTo "") exitWith { TRACE_4("Invalid parameters for removing asset",_uid,_name,_assetType,_assetId); createHashMap }; + +private _store = call FUNC(verifyOrgStore); +private _key = format ["%1_%2", _uid, _name]; +private _org = _store call ["getByKey", [_key]]; + +private _timestamp = systemTimeUTC apply { if (_x < 10) then { "0" + str _x } else { str _x }}; +private _dateTime = format ["%1-%2-%3_%4:%5:%6.%7", _timestamp#0, _timestamp#1, _timestamp#2, _timestamp#3, _timestamp#4, _timestamp#5, _timestamp#6]; + +if (isNil "_org") exitWith { TRACE_1("Organization not found",_name); createHashMap }; + +private _assets = _org get "assets"; +private _logs = _org get "logs"; +private _typeAssets = _assets getOrDefault [_assetType, []]; +private _index = _typeAssets findIf { (_x getOrDefault ["id", ""]) == _assetId }; + +if (_index != -1) then { + private _assetToRemove = _typeAssets select _index; + private _assetName = _assetToRemove getOrDefault ["name", "Unknown Asset"]; + + _typeAssets deleteAt _index; + + _logs pushBack [_dateTime, "ASSET_REMOVED", _assetType, _assetName]; + _org set ["logs", _logs]; +}; + +_org set ["assets", _assets]; + +_store call ["post", [_uid, _name]]; + +_assets \ No newline at end of file diff --git a/addons/org/functions/fnc_verifyOrgStore.sqf b/addons/org/functions/fnc_verifyOrgStore.sqf new file mode 100644 index 0000000..2ccd549 --- /dev/null +++ b/addons/org/functions/fnc_verifyOrgStore.sqf @@ -0,0 +1,22 @@ +#include "..\script_component.hpp" + +/* + * Function: forge_client_org_fnc_verifyOrgStore + * Author: J. Schmidt + * + * Description: + * Ensures the store is initialized and returns the store object + * + * Arguments: + * None + * + * Return Value: + * Store object + */ + +private _store = GETMVAR(FORGE_ORG_STORE_REG,nil); +if (isNil "_store") then { + _store = [] call FUNC(initOrgStore); +}; + +_store \ No newline at end of file diff --git a/addons/org/script_component.hpp b/addons/org/script_component.hpp new file mode 100644 index 0000000..c44062d --- /dev/null +++ b/addons/org/script_component.hpp @@ -0,0 +1,16 @@ +#define COMPONENT org +#define COMPONENT_BEAUTIFIED Org +#include "\z\forge_client\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE + +#ifdef DEBUG_ENABLED_ORG + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_ORG + #define DEBUG_SETTINGS DEBUG_SETTINGS_ORG +#endif + +#include "\z\forge_client\addons\main\script_macros.hpp" \ No newline at end of file diff --git a/addons/store/functions/fnc_buyItem.sqf b/addons/store/functions/fnc_buyItem.sqf index f9b9dee..d86846b 100644 --- a/addons/store/functions/fnc_buyItem.sqf +++ b/addons/store/functions/fnc_buyItem.sqf @@ -30,6 +30,6 @@ switch (_configType) do { // player setVariable ["FORGE_Locker", _locker, true]; SETPVAR(player,FORGE_Locker,_locker); -[_className, _itemType] call EFUNC(armory,addArmoryItem); +[_className, _itemType] call EFUNC(arsenal,addArmoryItem); [format ["You have purchased %1 for $%2.", _displayName, _price], "info", 3, "right"] call EFUNC(misc,notify); \ No newline at end of file