client/addons/org/functions/fnc_initOrgStore.sqf
Jacob Schmidt 31402b40db
All checks were successful
Build / Build (push) Successful in 27s
Refactor: Organization Store CRUD Operations and Function Simplification
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.
2025-03-30 17:15:02 -05:00

565 lines
21 KiB
Plaintext

#include "..\script_component.hpp"
/*
* Function: forge_client_org_fnc_initOrgStore
* Author: J. Schmidt
*
* Description:
* Initializes player organization data interface for CRUD operations
* This interfaces with ArmaDragonflyClient database for persistence
*
* Arguments:
* None
*
* Return Value:
* Organization interface <OBJECT>
*/
private _orgStoreInterface = createHashMapObject [[
["#type", "IOrganizationStore"],
["#create", {
_self set ["currentOrganization", nil];
_self set ["memberUID", getPlayerUID player];
_self set ["isLoaded", false];
_self call ["loadFromDatabase", []];
true
}],
["loadFromDatabase", {
private _playerUID = _self get "memberUID";
private _orgID = format ["%1_org", _playerUID];
["hgetallid", _orgID, "", -1, [], QFUNC(handleOrgLoad), false, netId player] remoteExecCall ["dragonfly_db_fnc_addTask", 2, false];
_self set ["isLoaded", false];
}],
["saveToDatabase", {
private _orgData = _self get "currentOrganization";
if (isNil "_orgData") exitWith { ERROR_MSG("No organization data to save"); false };
private _processedData = createHashMapFromArray [];
{
private _key = _x;
private _value = _orgData get _key;
if (_key in ["name", "owner"] && _value isEqualType "") then {
_value = (_value splitString " ") joinString "_";
};
// 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],
["logs", []],
["created", _dateTime],
["lastModified", _dateTime]
];
// Create owner member entry
private _memberMap = createHashMap;
_memberMap set ["uid", _uid];
_memberMap set ["name", name player];
_memberMap set ["role", "owner"];
_memberMap set ["joinDate", _dateTime];
// Add to members hashMap
private _members = _orgData get "members";
_members set [_uid, _memberMap];
_orgData set ["members", _members];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
_orgData
}],
["getCurrentOrg", {
if (!(_self get "isLoaded")) then {
waitUntil { _self get "isLoaded" };
};
_self get "currentOrganization"
}],
["getOrgID", {
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); "" };
_orgData get "id"
}],
["syncWithDatabase", {
private _orgData = _self get "currentOrganization";
if (isNil "_orgData") exitWith { ERROR_MSG("No organization data to sync"); false };
_orgData set ["lastModified", call EFUNC(misc,getSystemTime)];
_self set ["currentOrganization", _orgData];
_self call ["saveToDatabase", []];
true
}],
["updateFunds", {
params [["_amount", 0, [0]]];
private _orgData = _self call ["getCurrentOrg", []];
if (isNil "_orgData") exitWith { ERROR_MSG("No organization found"); false };
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
}]
]];
SETMVAR(FORGE_ORG_STORE_REG,_orgStoreInterface);
GETMVAR(FORGE_ORG_STORE_REG,nil)