#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 */ 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)