Refactor: Organization Store CRUD Operations and Function Simplification
All checks were successful
Build / Build (push) Successful in 27s

This commit refactors the organization store to utilize the new CRUD (Create, Read, Update, Delete) operations and simplifies several organization-related functions.

*   **Organization Store CRUD Operations:** Implements a new interface for the organization store, providing methods for creating, reading, updating, and deleting organization data. This includes methods for adding and removing assets, managing funds and reputation, and handling member operations. The store now interfaces with the ArmaDragonflyClient database for persistence.
*   **Function Simplification:** Simplifies several organization functions by leveraging the new CRUD operations within the organization store. This reduces code duplication and improves readability. Specifically:
    *   `fnc_addAsset.sqf`: Simplified to use the `addAsset` method.
    *   `fnc_removeAsset.sqf`: Simplified to use the `removeAsset` method.
    *   `fnc_create.sqf`: Simplified to use the `createOrg` method.
    *   `fnc_leave.sqf`: Simplified to use the `leaveOrg` method.
    *   `fnc_disband.sqf`: Simplified to use the `deleteOrg` method.
    *   `fnc_addFunds.sqf`: Simplified to use the `updateFunds` method.
    *   `fnc_addReputation.sqf`: Simplified to use the `updateReputation` method.
    *   `fnc_verifyOrgStore.sqf`: Improved to ensure the store is initialized.
*   **XEH Updates:** Updated `XEH_PREP.hpp` files to reflect the changes in function calls.
*   **Locker Fix:** Fixed an issue in `fnc_equipGear.sqf` where the `isNull` check was incorrect for certain gear types.
This commit is contained in:
Jacob Schmidt 2025-03-30 17:15:02 -05:00
parent fc236ad4e6
commit 31402b40db
36 changed files with 22702 additions and 509 deletions

24
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,24 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Start Arma 3 Server",
"type": "process",
"command": "wscript.exe",
"args": [
"D:\\SteamLibrary\\steamapps\\common\\Arma 3\\start_serverhub_hidden.vbs"
],
"presentation": {
"reveal": "silent",
"panel": "shared",
"showReuseMessage": false,
"clear": true
},
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@ -29,7 +29,7 @@ switch (_itemType) do {
};
};
case "facewear": {
if (isNull (goggles player)) then {
if (goggles player == "") then {
player addGoggles _item;
playSound "FD_Finish_F";
} else {
@ -40,7 +40,7 @@ switch (_itemType) do {
};
};
case "headgear": {
if (isNull (headgear player)) then {
if (headgear player == "") then {
player addHeadgear _item;
playSound "FD_Finish_F";
} else {
@ -51,7 +51,7 @@ switch (_itemType) do {
};
};
case "hmd": {
if (isNull (hmd player)) then {
if (hmd player == "") then {
player linkItem _item;
playSound "FD_Finish_F";
} else {
@ -84,7 +84,7 @@ switch (_itemType) do {
};
};
case "uniform": {
if (isNull (uniform player)) then {
if (uniform player == "") then {
player forceAddUniform _item;
playSound "FD_Finish_F";
} else {
@ -95,7 +95,7 @@ switch (_itemType) do {
};
};
case "vest": {
if (isNull (vest player)) then {
if (vest player == "") then {
player addVest _item;
playSound "FD_Finish_F";
} else {

View File

@ -1,5 +1,6 @@
PREP(cargoToPairs);
PREP(formatNumber);
PREP(getSystemTime);
PREP(isAssignableBinocular);
PREP(isWeaponType);
PREP(notify);

View File

@ -0,0 +1,6 @@
#include "..\script_component.hpp"
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];
_dateTime

View File

@ -1,13 +1,11 @@
PREP(acceptInvite);
PREP(addAsset);
PREP(addFunds);
PREP(addMember);
PREP(addReputation);
PREP(create);
PREP(disband);
PREP(handleOrgLoad);
PREP(initOrgStore);
PREP(invite);
PREP(join);
PREP(leave);
PREP(listInvites);
PREP(removeAsset);
PREP(verifyOrgStore);

View File

@ -1,31 +0,0 @@
#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 <STRING>
* 1: _playerName - Player Name <STRING>
* 2: _inviteKey - Invite key from the player's invites <STRING>
*
* Return Value:
* Success <BOOL>
*/
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);

View File

@ -8,42 +8,24 @@
* Adds an asset to an organization's inventory
*
* Arguments:
* 0: _uid - Player UID <STRING>
* 1: _name - Organization name <STRING>
* 2: _assetType - Type of asset (vehicle, building, etc.) <STRING>
* 3: _assetData - Asset data <HASHMAP>
* 0: _assetType - Type of asset (vehicle, building, etc.) <STRING>
* 1: _className - Class name of the asset <STRING>
*
* Return Value:
* Updated assets collection <HASHMAP>
* Success <BOOLEAN>
*/
params [["_uid", "", [""]], ["_name", "", [""]], ["_assetType", "", [""]], ["_assetData", createHashMap, [createHashMap]]];
params [["_assetType", "", [""]], ["_className", "", [""]]];
if (_uid == "" || _name == "" || _assetType == "") exitWith { TRACE_3("Invalid parameters for adding asset",_uid,_name,_assetType); nil };
if (_assetType == "" || _className == "") exitWith { TRACE_2("Invalid parameters for adding asset",_assetType,_className); nil };
private _store = call FUNC(verifyOrgStore);
private _key = format ["%1_%2", _uid, _name];
private _org = _store call ["getByKey", [_key]];
private _assetId = _store call ["addAsset", [_assetType, _className]];
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 (_assetId != "") then {
TRACE_2("Asset added successfully",_assetType,_className);
} else {
TRACE_2("Failed to add asset",_assetType,_className);
};
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
_assetId

View File

@ -8,37 +8,21 @@
* Adds funds to an organization's account
*
* Arguments:
* 0: _uid - Player UID <STRING>
* 1: _name - Organization name <STRING>
* 2: _amount - Amount to add (can be negative for withdrawals) <NUMBER>
* 0: _amount - Amount to add (can be negative for withdrawals) <NUMBER>
*
* Return Value:
* New funds amount <NUMBER>
*/
params [["_uid", "", [""]], ["_name", "", [""]], ["_amount", 0, [0]]];
if (_uid == "" || _name == "") exitWith { TRACE_2("Invalid parameters for adding funds",_uid,_name); nil };
params [["_amount", 0, [0]]];
private _store = call FUNC(verifyOrgStore);
private _key = format ["%1_%2", _uid, _name];
private _org = _store call ["getByKey", [_key]];
private _result = _store call ["updateFunds", [_amount]];
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 (_result) then {
TRACE_1("Funds updated successfully",_amount);
} else {
TRACE_1("Failed to update funds",_amount);
};
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
_result

View File

@ -0,0 +1,31 @@
#include "..\script_component.hpp"
/*
* Function: forge_client_org_fnc_addMember
* Author: J. Schmidt
*
* Description:
* Adds a member to an organization
*
* Arguments:
* 0: _uid - Target player UID <STRING>
* 1: _name - Target player name <STRING>
*
* Return Value:
* Success <BOOL>
*/
params [["_uid", "", [""]], ["_name", "", [""]]];
if (_uid == "" || _name == "") exitWith { TRACE_2("Invalid parameters for organization invitation",_uid,_name); false };
private _store = call FUNC(verifyOrgStore);
private _result = _store call ["addMember", [_uid, _name]];
if (_result) then {
TRACE_2("Member added successfully",_uid,_name);
} else {
TRACE_2("Failed to add member",_uid,_name);
};
_result

View File

@ -8,37 +8,21 @@
* Adds reputation to an organization
*
* Arguments:
* 0: _uid - Player UID <STRING>
* 1: _name - Organization name <STRING>
* 2: _amount - Amount of reputation to add (can be negative) <NUMBER>
* 0: _amount - Amount of reputation to add (can be negative) <NUMBER>
*
* Return Value:
* New reputation amount <NUMBER>
*/
params [["_uid", "", [""]], ["_name", "", [""]], ["_amount", 0, [0]]];
if (_uid == "" || _name == "") exitWith { TRACE_2("Invalid parameters for adding reputation",_uid,_name); nil };
params [["_amount", 0, [0]]];
private _store = call FUNC(verifyOrgStore);
private _key = format ["%1_%2", _uid, _name];
private _org = _store call ["getByKey", [_key]];
private _result = _store call ["updateReputation", [_amount]];
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 (_result) then {
TRACE_1("Reputation updated successfully",_amount);
} else {
TRACE_1("Failed to update reputation",_amount);
};
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
_result

View File

@ -9,35 +9,41 @@
*
* Arguments:
* 0: _ownerUID - Player UID <STRING>
* 1: _ownerName - Player name <STRING>
* 1: _ownerName - Player name <STRING> (unused, gets name from player object)
* 2: _name - Organization name <STRING>
* 3: _initialFunds - Initial funds for the org <NUMBER> (Optional, default: 0)
* 4: _initialReputation - Initial reputation for the org <NUMBER> (Optional, default: 0)
*
* Return Value:
* Success <BOOL>
* Organization data <HASHMAP> or nil on failure
*/
params [["_ownerUID", "", [""]], ["_ownerName", "", [""]], ["_name", "", [""]]];
params [
["_ownerUID", "", [""]],
["_name", "", [""]],
["_initialFunds", 0, [0]],
["_initialReputation", 0, [0]]
];
if (_ownerUID == "" || _ownerName == "" || _name == "") exitWith { TRACE_3("Invalid parameters for organization creation",_ownerUID,_ownerName,_name); false };
if (_ownerUID == "" || _name == "") exitWith {
TRACE_2("Invalid parameters for organization creation",_ownerUID,_name);
nil
};
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", []]);
// The createOrg method in the store already handles:
// - Checking if player already has an organization
// - Creating the organization with basic data
// - Adding the owner as a member
// - Saving to database
private _orgData = _store call ["createOrg", [_ownerUID, _name, _initialFunds, _initialReputation]];
if (_playerAlreadyInOrg) exitWith { TRACE_1("Player already in an organization",_ownerUID); false };
if (isNil "_orgData") then {
TRACE_2("Failed to create organization",_name,_ownerUID);
} else {
TRACE_2("Organization created successfully",_name,_ownerUID);
};
_store call ["post", [_ownerUID, _name, 0, 0]];
[_name, _ownerUID, _ownerName, "owner"] call FUNC(join);
TRACE_2("Organization created successfully",_name,_ownerUID);
true
// Return the organization data
_orgData

View File

@ -8,26 +8,19 @@
* Disbands an organization if requested by the owner
*
* Arguments:
* 0: _uid - UID of the player attempting to disband <STRING>
* 1: _name - Organization name <STRING>
* None
*
* Return Value:
* Success <BOOL>
*/
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]];
private _result = _store call ["deleteOrg", []];
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 };
if (_result) then {
TRACE_1("Organization disbanded successfully",_result);
} else {
TRACE_1("Failed to disband organization",_result);
};
_store call ["delete", [_key]];
TRACE_1("Organization disbanded successfully",_name);
true
_result

View File

@ -0,0 +1,230 @@
#include "..\script_component.hpp"
/*
* Function: forge_client_org_fnc_handleOrgLoad
* Author: J. Schmidt
*
* Description:
* Handles organization data loaded from database
*
* Arguments:
* 0: Result <ARRAY> - Redis HGETALL result
*
* Return Value:
* None
*/
diag_log text format ["[FORGE Organization] Organization data received: '%1'", _this];
private _data = _this;
private _playerNetId = netId player;
private _store = call FUNC(verifyOrgStore);
if (isNil "_data" || {!(_data isEqualType [])} || {count _data < 2} || {_data isEqualTo [""]}) exitWith {
diag_log text "[FORGE Organization] Empty or invalid organization data received";
if !(isNil "_store") then {
_store set ["currentOrganization", nil];
_store set ["isLoaded", true];
};
};
// Create organization data hashMap
private _orgData = createHashMap;
// Process the data array
for "_i" from 0 to (count _data - 1) step 2 do {
private _key = _data select _i;
private _value = _data select (_i + 1);
// Unwrap single-item arrays
if (_value isEqualType []) then {
switch (_key) do {
case "assets": {
// Convert to hashMap by assetType
private _flattenedAssets = [];
// Handle multi-level nesting and ensure it's flattened first
if (count _value > 0 && {_value select 0 isEqualType []}) then {
{
if (_x isEqualType []) then {
_flattenedAssets append _x;
} else {
_flattenedAssets pushBack _x;
};
} forEach _value;
} else {
_flattenedAssets = _value;
};
// Create hashMap from flattened assets
private _assetsMap = createHashMap;
{
if (_x isEqualType [] && count _x >= 2) then {
private _type = _x select 0;
private _class = _x select 1;
// Create a hashMap for this asset
private _assetMap = createHashMap;
// Try to get ID or generate one
private _assetId = "";
private _idIndex = _x findIf {_x == "id"};
if (_idIndex != -1 && _idIndex + 1 < count _x) then {
_assetId = _x select (_idIndex + 1);
} else {
_assetId = format ["%1_%2", _class, diag_tickTime];
};
_assetMap set ["id", _assetId];
_assetMap set ["className", _class];
// Add any extra properties (key-value pairs)
for "_j" from 2 to (count _x - 1) step 2 do {
if (_j + 1 < count _x) then {
private _propName = _x select _j;
private _propValue = _x select (_j + 1);
if (_propName != "className") then {
_assetMap set [_propName, _propValue];
};
};
};
// Add this asset to its type array
private _typeArray = _assetsMap getOrDefault [_type, []];
_typeArray pushBack _assetMap;
_assetsMap set [_type, _typeArray];
};
} forEach _flattenedAssets;
_value = _assetsMap;
};
case "members": {
// Convert to hashMap by memberUID
private _flattenedMembers = [];
// Handle multi-level nesting and ensure it's flattened first
if (count _value > 0 && {_value select 0 isEqualType []}) then {
{
if (_x isEqualType []) then {
_flattenedMembers append _x;
} else {
_flattenedMembers pushBack _x;
};
} forEach _value;
} else {
_flattenedMembers = _value;
};
// Create member hashMap
private _membersMap = createHashMap;
{
if (_x isEqualType [] && count _x >= 3) then {
private _uid = _x select 0;
private _name = _x select 1;
private _role = _x select 2;
private _joinDate = if (count _x > 3) then {_x select 3} else {""};
// Replace underscores with spaces in name
if (_name isEqualType "") then {
_name = (_name splitString "_") joinString " ";
};
// Create member hashMap
private _memberMap = createHashMap;
_memberMap set ["uid", _uid];
_memberMap set ["name", _name];
_memberMap set ["role", _role];
_memberMap set ["joinDate", _joinDate];
// Add extra properties if any (for future expansion)
for "_j" from 4 to (count _x - 1) step 2 do {
if (_j + 1 < count _x) then {
private _propName = _x select _j;
private _propValue = _x select (_j + 1);
_memberMap set [_propName, _propValue];
};
};
_membersMap set [_uid, _memberMap];
};
} forEach _flattenedMembers;
_value = _membersMap;
};
case "logs": {
// Flatten arrays but don't process contents
private _flattenedArray = [];
// Handle multi-level nesting
if (count _value > 0 && {_value select 0 isEqualType []}) then {
{
if (_x isEqualType []) then {
_flattenedArray append _x;
} else {
_flattenedArray pushBack _x;
};
} forEach _value;
_value = _flattenedArray;
};
};
default {
if (count _value == 1) then {
_value = _value select 0;
};
};
};
};
// Process string values
if (_value isEqualType "" && _key in ["name", "owner"]) then {
_value = (_value splitString "_") joinString " ";
};
// Convert numeric values
if (_key in ["funds", "reputation"] && _value isEqualType "") then {
_value = parseNumber _value;
};
// Store in hashMap
_orgData set [_key, _value];
};
// Ensure we have all required fields in the hashMap
private _requiredFields = ["id", "name", "owner", "funds", "reputation", "assets", "members", "logs", "created", "lastModified"];
{
if (isNil {_orgData get _x}) then {
switch (_x) do {
case "funds";
case "reputation": {
_orgData set [_x, 0];
};
case "assets";
case "members": {
_orgData set [_x, createHashMap];
};
case "logs": {
_orgData set [_x, []];
};
case "created";
case "lastModified": {
_orgData set [_x, ""];
};
default {
_orgData set [_x, ""];
};
};
};
} forEach _requiredFields;
// Update the organization store with the complete hashMap
_store set ["currentOrganization", _orgData];
_store set ["isLoaded", true];
// Log successful load
if (!isNil { _orgData get "name" }) then {
diag_log text format ["[FORGE Organization] Organization successfully loaded: %1", _orgData get "name"];
};

View File

@ -5,7 +5,8 @@
* Author: J. Schmidt
*
* Description:
* Initializes player organization data using the database interface
* Initializes player organization data interface for CRUD operations
* This interfaces with ArmaDragonflyClient database for persistence
*
* Arguments:
* None
@ -17,114 +18,544 @@
private _orgStoreInterface = createHashMapObject [[
["#type", "IOrganizationStore"],
["#create", {
private _store = GETMVAR(FORGE_STORE_REG,nil);
_self set ["currentOrganization", nil];
_self set ["memberUID", getPlayerUID player];
_self set ["isLoaded", false];
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];
};
_self call ["loadFromDatabase", []];
true
}],
["post", {
params [["_uid", "", [""]], ["_name", "", [""]], ["_initialFunds", 0, [0]], ["_initialReputation", 0, [0]]];
["loadFromDatabase", {
private _playerUID = _self get "memberUID";
private _orgID = format ["%1_org", _playerUID];
if (_uid == "" || _name == "") exitWith { ERROR_MSG("Owner UID and, or name cannot be empty"); nil };
["hgetallid", _orgID, "", -1, [], QFUNC(handleOrgLoad), false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];
private _store = GETMVAR(FORGE_STORE_REG,nil);
private _key = format ["%1_%2", _uid, _name];
_self set ["isLoaded", false];
}],
["saveToDatabase", {
private _orgData = _self get "currentOrganization";
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 "_orgData") exitWith { ERROR_MSG("No organization data to save"); false };
private _orgRegistry = GETVAR(profileNamespace,FORGE_ORG_REG,createHashMap);
private _processedData = createHashMapFromArray [];
{
private _key = _x;
private _value = _orgData get _key;
private _existingOrgKey = _store call ["get", ["organizationNameIndex", _key]];
private _existingOrg = nil;
private _orgData = nil;
if !(isNil "_existingOrgKey") then {
_existingOrg = _store call ["get", ["organizations", _existingOrgKey]];
if (_key in ["name", "owner"] && _value isEqualType "") then {
_value = (_value splitString " ") joinString "_";
};
if !(isNil "_existingOrg") then {
_orgData = _existingOrg;
} else {
_orgData = createHashMapFromArray [
// Convert members hashMap back to array format for storage
if (_key == "members" && _value isEqualType createHashMap) then {
private _flattenedMembers = [];
{
private _uid = _x;
private _memberMap = _value get _uid;
if (!isNil "_memberMap") then {
private _name = _memberMap get "name";
// Replace spaces with underscores for storage
if (_name isEqualType "") then {
_name = (_name splitString " ") joinString "_";
};
private _role = _memberMap get "role";
private _joinDate = _memberMap get "joinDate";
private _memberArray = [_uid, _name, _role, _joinDate];
// Add any additional properties
{
if !(_x in ["uid", "name", "role", "joinDate"]) then {
_memberArray pushBack _x;
_memberArray pushBack (_memberMap get _x);
};
} forEach (keys _memberMap);
_flattenedMembers pushBack _memberArray;
};
} forEach (keys _value);
_value = _flattenedMembers;
};
// Convert assets hashMap back to flat array for storage
if (_key == "assets" && _value isEqualType createHashMap) then {
private _flattenedAssets = [];
{
private _type = _x;
private _typeAssets = _value get _type;
{
private _assetMap = _x;
private _id = _assetMap get "id";
private _className = _assetMap get "className";
private _flatAsset = [_type, _className, "id", _id];
// Add all other properties as key-value pairs
{
if (_x != "className" && _x != "id") then {
_flatAsset pushBack _x;
_flatAsset pushBack (_assetMap get _x);
};
} forEach (keys _assetMap);
_flattenedAssets pushBack _flatAsset;
} forEach _typeAssets;
} forEach (keys _value);
_value = _flattenedAssets;
};
_processedData set [_key, _value];
} forEach (keys _orgData);
private _data = [
_processedData get "id",
"id", [_processedData get "id"],
"name", [_processedData get "name"],
"owner", [_processedData get "owner"],
"funds", [_processedData get "funds"],
"reputation", [_processedData get "reputation"],
"assets", [_processedData get "assets"],
"members", [_processedData get "members"],
"logs", [_processedData get "logs"],
"created", [_processedData get "created"],
"lastModified", [_processedData get "lastModified"]
];
["hsetidbulk", "", "", -1, _data, "", false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];
true
}],
["generateOrgID", {
params [["_uid", "", [""]]];
if (_uid == "") exitWith { ERROR_MSG("Owner UID cannot be empty"); "" };
private _orgID =format ["%1_org", _uid];
_orgID
}],
["createOrg", {
params [["_uid", "", [""]], ["_name", "", [""]], ["_initialFunds", 0, [0]], ["_initialReputation", 0, [0]]];
if (_uid == "" || _name == "") exitWith { ERROR_MSG("Owner UID and name cannot be empty"); nil };
if (!isNil {_self get "currentOrganization"}) exitWith { ERROR_MSG("Player is already part of an organization"); nil };
private _dateTime = call EFUNC(misc,getSystemTime);
private _orgID = _self call ["generateOrgID", [_uid]];
private _orgData = createHashMapFromArray [
["id", _orgID],
["name", _name],
["owner", _uid],
["funds", _initialFunds],
["reputation", _initialReputation],
["assets", createHashMap],
["members", createHashMap],
["invites", createHashMap],
["logs", []],
["created", _dateTime]
["created", _dateTime],
["lastModified", _dateTime]
];
_orgRegistry set [_key, _orgData];
// Create owner member entry
private _memberMap = createHashMap;
_memberMap set ["uid", _uid];
_memberMap set ["name", name player];
_memberMap set ["role", "owner"];
_memberMap set ["joinDate", _dateTime];
SETVAR(profileNamespace,FORGE_ORG_REG,_orgRegistry);
saveProfileNamespace;
};
// Add to members hashMap
private _members = _orgData get "members";
_members set [_uid, _memberMap];
_orgData set ["members", _members];
_store call ["set", ["organizationNameIndex", _key, _name]];
_store call ["set", ["organizations", _key, _orgData]];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
_orgData
}],
["get", {
private _store = GETMVAR(FORGE_STORE_REG,nil);
private _orgStore = _store call ["getStore", ["organizations"]];
["getCurrentOrg", {
if (!(_self get "isLoaded")) then {
waitUntil { _self get "isLoaded" };
};
if (isNil "_orgStore") exitWith { createHashMap };
_orgStore
_self get "currentOrganization"
}],
["getByKey", {
params [["_key", "", [""]]];
["getOrgID", {
private _orgData = _self call ["getCurrentOrg", []];
if (_key == "") exitWith { ERROR_MSG("Key cannot be empty"); nil };
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); "" };
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
_orgData get "id"
}],
["delete", {
params [["_key", "", [""]]];
["syncWithDatabase", {
private _orgData = _self get "currentOrganization";
if (_key == "") exitWith { ERROR_MSG("Key cannot be empty"); false };
if (isNil "_orgData") exitWith { ERROR_MSG("No organization data to sync"); false };
private _store = GETMVAR(FORGE_STORE_REG,nil);
private _key = _store call ["get", ["organizationNameIndex", _key, nil]];
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
_store call ["delete", ["organizationNameIndex", _key]];
true
}],
["updateFunds", {
params [["_amount", 0, [0]]];
if (isNil "_key") exitWith { ERROR_MSG_1("Key for organization not found: %1",_key); false };
private _orgData = _self call ["getCurrentOrg", []];
_store call ["delete", ["organizations", _key]];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _orgRegistry = GETVAR(profileNamespace,FORGE_ORG_REG,createHashMap);
_orgRegistry deleteAt _key;
SETVAR(profileNamespace,FORGE_ORG_REG,_orgRegistry);
saveProfileNamespace;
private _funds = _orgData get "funds";
private _dateTime = call EFUNC(misc,getSystemTime);
private _newFunds = _funds + _amount;
_orgData set ["funds", _newFunds];
_orgData set ["lastModified", _dateTime];
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "FUNDS_UPDATED", _amount, _newFunds];
_orgData set ["logs", _logs];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
true
}],
["getFunds", {
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); nil };
_orgData get "funds"
}],
["updateReputation", {
params [["_amount", 0, [0]]];
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _reputation = _orgData get "reputation";
private _newReputation = _reputation + _amount;
_orgData set ["reputation", _newReputation];
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
private _dateTime = call EFUNC(misc,getSystemTime);
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "REPUTATION_UPDATED", _amount, _newReputation];
_orgData set ["logs", _logs];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
true
}],
["getReputation", {
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); nil };
_orgData get "reputation"
}],
["addAsset", {
params [["_assetType", "", [""]], ["_className", "", [""]], ["_properties", createHashMap, [createHashMap]]];
if (_assetType == "" || _className == "") exitWith { ERROR_MSG("Asset type and className cannot be empty"); false };
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _assets = _orgData get "assets";
if !(_assets isEqualType createHashMap) then {
_assets = createHashMap;
};
// Get or create the asset type array
private _typeAssets = _assets getOrDefault [_assetType, []];
// Generate a unique ID for this asset
private _assetId = format ["%1_%2", _className, call EFUNC(misc,getSystemTime)];
// Create the asset hashMap
private _assetMap = createHashMap;
_assetMap set ["id", _assetId];
_assetMap set ["className", _className];
// Add all provided properties
{
if (_x != "className" && _x != "id") then {
_assetMap set [_x, _properties get _x];
};
} forEach (keys _properties);
// Add as a new asset
_typeAssets pushBack _assetMap;
_assets set [_assetType, _typeAssets];
_orgData set ["assets", _assets];
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
private _dateTime = call EFUNC(misc,getSystemTime);
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "ASSET_ADDED", _assetType, _className, _assetId];
_orgData set ["logs", _logs];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
_assetId // Return the generated ID
}],
["getAssets", {
params [["_assetType", "", [""]], ["_idOrClassName", "", [""]], ["_findById", false, [false]]];
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); nil };
private _assets = _orgData get "assets";
if !(_assets isEqualType createHashMap) then {
_assets = createHashMap;
};
// Get specific asset by ID or className
if (_assetType != "" && _idOrClassName != "") then {
private _typeAssets = _assets getOrDefault [_assetType, []];
private _index = -1;
if (_findById) then {
_index = _typeAssets findIf {(_x get "id") == _idOrClassName};
} else {
// Get first matching className (for backward compatibility)
_index = _typeAssets findIf {(_x get "className") == _idOrClassName};
};
if (_index != -1) then {
_typeAssets select _index
} else {
nil
}
} else {
if (_assetType != "") then {
_assets getOrDefault [_assetType, []]
} else {
private _allAssets = [];
{
private _type = _x;
private _typeAssets = _assets get _type;
{
private _assetMap = _x;
private _id = _assetMap get "id";
private _className = _assetMap get "className";
private _flatAsset = [_type, _className, "id", _id];
// Add all other properties as key-value pairs
{
if (_x != "className" && _x != "id") then {
_flatAsset pushBack _x;
_flatAsset pushBack (_assetMap get _x);
};
} forEach (keys _assetMap);
_allAssets pushBack _flatAsset;
} forEach _typeAssets;
} forEach (keys _assets);
_allAssets
}
}
}],
["removeAsset", {
params [["_assetType", "", [""]], ["_assetId", "", [""]]];
if (_assetType == "" || _assetId == "") exitWith { ERROR_MSG("Asset type and asset ID cannot be empty"); false };
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _assets = _orgData get "assets";
if !(_assets isEqualType createHashMap) then {
_assets = createHashMap;
};
private _typeAssets = _assets getOrDefault [_assetType, []];
private _index = _typeAssets findIf {(_x get "id") == _assetId};
if (_index != -1) then {
private _asset = _typeAssets select _index;
private _className = _asset get "className";
_typeAssets deleteAt _index;
_assets set [_assetType, _typeAssets];
_orgData set ["assets", _assets];
private _dateTime = call EFUNC(misc,getSystemTime);
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "ASSET_REMOVED", _assetType, _className, _assetId];
_orgData set ["logs", _logs];
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
true
} else {
ERROR_MSG_2("Asset with ID %1 not found in type %2",_assetId,_assetType);
false
};
}],
["addMember", {
params [["_uid", "", [""]], ["_name", "", [""]], ["_role", "member", [""]]];
if (_uid == "" || _name == "") exitWith { ERROR_MSG("Member UID and name cannot be empty"); false };
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _playerUID = _self get "memberUID";
if ((_orgData get "owner") != _playerUID) exitWith { ERROR_MSG("Only the owner can add members"); false };
private _members = _orgData get "members";
if !(_members isEqualType createHashMap) then {
_members = createHashMap;
};
// Check if member already exists
if (!isNil {_members get _uid}) exitWith { ERROR_MSG_1("Member already in this organization: %1",_uid); true };
// Create member hashMap
private _memberMap = createHashMap;
private _joinDate = call EFUNC(misc,getSystemTime);
_memberMap set ["uid", _uid];
_memberMap set ["name", _name];
_memberMap set ["role", _role];
_memberMap set ["joinDate", _joinDate];
// Add to members hashMap
_members set [_uid, _memberMap];
_orgData set ["members", _members];
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
private _dateTime = call EFUNC(misc,getSystemTime);
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "MEMBER_ADDED", _uid, _name, _role];
_orgData set ["logs", _logs];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
true
}],
["removeMember", {
params [["_uid", "", [""]]];
if (_uid == "") exitWith { ERROR_MSG("Member UID cannot be empty"); false };
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _playerUID = _self get "memberUID";
if ((_orgData get "owner") != _playerUID) exitWith { ERROR_MSG("Only the owner can remove members"); false };
private _members = _orgData get "members";
if !(_members isEqualType createHashMap) then {
_members = createHashMap;
};
// Get member and check if they exist
private _memberMap = _members get _uid;
if (isNil "_memberMap") exitWith { ERROR_MSG_1("Member not in organization: %1",_uid); false };
// Check if trying to remove the owner
if ((_memberMap get "role") == "owner") exitWith { ERROR_MSG("Cannot remove the organization owner"); false };
// Get name for logging
private _name = _memberMap get "name";
// Remove from hashMap
_members deleteAt _uid;
_orgData set ["members", _members];
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
private _dateTime = call EFUNC(misc,getSystemTime);
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "MEMBER_REMOVED", _uid, _name];
_orgData set ["logs", _logs];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
true
}],
["getMembers", {
params [["_uid", "", [""]]];
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); nil };
private _members = _orgData get "members";
if !(_members isEqualType createHashMap) then {
_members = createHashMap;
};
// Get specific member by UID
if (_uid != "") then {
_members get _uid
} else {
// Get all members
private _allMembers = [];
{
_allMembers pushBack (_members get _x);
} forEach (keys _members);
_allMembers
}
}],
["deleteOrg", {
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _playerUID = _self get "memberUID";
if ((_orgData get "owner") != _playerUID) exitWith { ERROR_MSG("Only the owner can delete the organization"); false };
private _orgID = _orgData get "id";
["del", _orgID, "", -1, [], "", false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];
_self set ["currentOrganization", nil];
_self set ["isLoaded", true];
true
}],
["leaveOrg", {
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
private _playerUID = _self get "memberUID";
if ((_orgData get "owner") == _playerUID) exitWith { ERROR_MSG("Organization owner cannot leave, must delete instead"); false };
private _members = _orgData get "members";
if !(_members isEqualType createHashMap) then {
_members = createHashMap;
};
// Get member data
private _memberMap = _members get _playerUID;
if (!isNil "_memberMap") then {
private _dateTime = call EFUNC(misc,getSystemTime);
private _memberName = _memberMap get "name";
private _logs = _orgData get "logs";
_logs pushBack [_dateTime, "MEMBER_LEFT", _playerUID, _memberName];
_orgData set ["logs", _logs];
_self call ["saveToDatabase", []];
};
_self set ["currentOrganization", nil];
_self set ["isLoaded", true];
true
}]

View File

@ -1,76 +0,0 @@
#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 <STRING>
* 1: _name - Organization name <STRING>
* 2: _targetUID - Target player's UID <STRING>
* 3: _targetName - Target player's name <STRING>
*
* Return Value:
* Success <BOOL>
*/
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

View File

@ -1,86 +0,0 @@
#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 <STRING>
* 1: _name - Organization name <STRING>
* 2: _targetUID - Target player's UID <STRING>
* 3: _targetName - Target player's name <STRING>
* 4: _targetRank - Player's rank in organization (default: "member") <STRING>
*
* Return Value:
* Success <BOOL>
*/
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
};
};

View File

@ -8,43 +8,19 @@
* Removes a player from an organization
*
* Arguments:
* 0: _ownerUID - Organization owner's UID <STRING>
* 1: _orgName - Organization name <STRING>
* 2: _playerUID - Player's UID who is leaving <STRING>
* 3: _playerName - Player's name who is leaving <STRING>
* None
*
* Return Value:
* Success <BOOL>
*/
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 _result = _store call ["leaveOrg", []];
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 (_result) then {
TRACE_1("Left organization successfully",_result);
} else {
TRACE_1("Failed to leave organization",_result);
};
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
_result

View File

@ -1,36 +0,0 @@
#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 <STRING>
*
* Return Value:
* Array of organization invites <ARRAY>
*/
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

View File

@ -8,45 +8,24 @@
* Removes an asset from an organization's inventory
*
* Arguments:
* 0: _uid - Player UID <STRING>
* 1: _name - Organization name <STRING>
* 2: _assetType - Type of asset (vehicle, building, etc.) <STRING>
* 3: _assetId - Unique identifier of the asset <STRING>
* 0: _assetType - Type of asset (vehicle, building, etc.) <STRING>
* 1: _assetId - Unique identifier of the asset <STRING>
*
* Return Value:
* Updated assets collection <HASHMAP>
* Success <BOOLEAN>
*/
params [["_uid", "", [""]], ["_name", "", [""]], ["_assetType", "", [""]], ["_assetId", "", [""]]];
params [["_assetType", "", [""]], ["_assetId", "", [""]]];
if (_uid isEqualTo "" || _name isEqualTo "" || _assetType isEqualTo "" || _assetId isEqualTo "") exitWith { TRACE_4("Invalid parameters for removing asset",_uid,_name,_assetType,_assetId); createHashMap };
if (_assetType isEqualTo "" || _assetId isEqualTo "") exitWith { TRACE_2("Invalid parameters for removing asset",_assetType,_assetId); createHashMap };
private _store = call FUNC(verifyOrgStore);
private _key = format ["%1_%2", _uid, _name];
private _org = _store call ["getByKey", [_key]];
private _result = _store call ["removeAsset", [_assetType, _assetId]];
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];
if (_result) then {
TRACE_1("Asset removed successfully",_assetId);
} else {
TRACE_1("Failed to remove asset",_assetId);
};
_org set ["assets", _assets];
_store call ["post", [_uid, _name]];
_assets
_result

View File

@ -15,8 +15,7 @@
*/
private _store = GETMVAR(FORGE_ORG_STORE_REG,nil);
if (isNil "_store") then {
_store = [] call FUNC(initOrgStore);
};
if (isNil "_store") then { _store = [] call FUNC(initOrgStore); };
_store

View File

@ -0,0 +1,8 @@
GetCurrentOrg: [["assets",[["vehicle",[[["id","B_MRAP_01_F_2025-03-30_21:42:43.261"],["className","B_MRAP_01_F"]]]]]],["created","2025-03-30_21:42:23.900"],["lastModified","2025-03-30_21:42:43.261"],["name","Blackwater Corp"],["logs",[["2025-03-30_21:42:43.261","ASSET_ADDED","vehicle","B_MRAP_01_F","B_MRAP_01_F_2025-03-30_21:42:43.261"],["2025-03-30_21:47:05.667","ASSET_ADDED","vehicle","B_MRAP_01_F","B_MRAP_01_F_2025-03-30_21:47:05.667"]]],["id","76561198027566824_org"],["funds",5000],["reputation",500],["owner","76561198027566824"],["members",[["76561198027566824",[["name","Jacob Schmidt"],["uid","76561198027566824"],["role","owner"],["joinDate","2025-03-30_21:42:23.900"]]]]]]
GetAssets: [["vehicle","B_MRAP_01_F","id","B_MRAP_01_F_2025-03-30_21:42:43.261"]]
GetAssets(Vehicle): [[["id","B_MRAP_01_F_2025-03-30_21:42:43.261"],["className","B_MRAP_01_F"]]]
GetAssets(Vehicle,ID): [["id","B_MRAP_01_F_2025-03-30_21:42:43.261"],["className","B_MRAP_01_F"]]
GetFunds: 5000
GetReputation: 500
GetMembers: [[["name","Jacob Schmidt"],["uid","76561198027566824"],["role","owner"],["joinDate","2025-03-30_21:42:23.900"]]]
GetMembers(UID): [["name","Jacob Schmidt"],["uid","76561198027566824"],["role","owner"],["joinDate","2025-03-30_21:42:23.900"]]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff