Refactor: Organization Store CRUD Operations and Function Simplification
All checks were successful
Build / Build (push) Successful in 27s
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:
parent
fc236ad4e6
commit
31402b40db
24
.vscode/tasks.json
vendored
Normal file
24
.vscode/tasks.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -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 {
|
||||
|
@ -1,5 +1,6 @@
|
||||
PREP(cargoToPairs);
|
||||
PREP(formatNumber);
|
||||
PREP(getSystemTime);
|
||||
PREP(isAssignableBinocular);
|
||||
PREP(isWeaponType);
|
||||
PREP(notify);
|
||||
|
6
addons/misc/functions/fnc_getSystemTime.sqf
Normal file
6
addons/misc/functions/fnc_getSystemTime.sqf
Normal 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
|
@ -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);
|
@ -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);
|
@ -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
|
@ -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
|
31
addons/org/functions/fnc_addMember.sqf
Normal file
31
addons/org/functions/fnc_addMember.sqf
Normal 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
|
@ -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
|
@ -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", []]);
|
||||
|
||||
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);
|
||||
// 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 (isNil "_orgData") then {
|
||||
TRACE_2("Failed to create organization",_name,_ownerUID);
|
||||
} else {
|
||||
TRACE_2("Organization created successfully",_name,_ownerUID);
|
||||
};
|
||||
|
||||
true
|
||||
// Return the organization data
|
||||
_orgData
|
@ -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
|
230
addons/org/functions/fnc_handleOrgLoad.sqf
Normal file
230
addons/org/functions/fnc_handleOrgLoad.sqf
Normal 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"];
|
||||
};
|
@ -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
|
||||
}]
|
||||
|
@ -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
|
@ -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
|
||||
};
|
||||
};
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
8
addons/org/functions/output.rpt
Normal file
8
addons/org/functions/output.rpt
Normal 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"]]
|
1432
serverhub/arma3serverprofiling_x64_2025-03-30_13-18-31.rpt
Normal file
1432
serverhub/arma3serverprofiling_x64_2025-03-30_13-18-31.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1357
serverhub/arma3serverprofiling_x64_2025-03-30_13-46-47.rpt
Normal file
1357
serverhub/arma3serverprofiling_x64_2025-03-30_13-46-47.rpt
Normal file
File diff suppressed because it is too large
Load Diff
2933
serverhub/arma3serverprofiling_x64_2025-03-30_14-00-25.rpt
Normal file
2933
serverhub/arma3serverprofiling_x64_2025-03-30_14-00-25.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1357
serverhub/arma3serverprofiling_x64_2025-03-30_14-09-03.rpt
Normal file
1357
serverhub/arma3serverprofiling_x64_2025-03-30_14-09-03.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1353
serverhub/arma3serverprofiling_x64_2025-03-30_14-26-55.rpt
Normal file
1353
serverhub/arma3serverprofiling_x64_2025-03-30_14-26-55.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1355
serverhub/arma3serverprofiling_x64_2025-03-30_14-31-52.rpt
Normal file
1355
serverhub/arma3serverprofiling_x64_2025-03-30_14-31-52.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1354
serverhub/arma3serverprofiling_x64_2025-03-30_14-54-34.rpt
Normal file
1354
serverhub/arma3serverprofiling_x64_2025-03-30_14-54-34.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1374
serverhub/arma3serverprofiling_x64_2025-03-30_15-08-11.rpt
Normal file
1374
serverhub/arma3serverprofiling_x64_2025-03-30_15-08-11.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1050
serverhub/arma3serverprofiling_x64_2025-03-30_15-44-16.rpt
Normal file
1050
serverhub/arma3serverprofiling_x64_2025-03-30_15-44-16.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1371
serverhub/arma3serverprofiling_x64_2025-03-30_15-45-33.rpt
Normal file
1371
serverhub/arma3serverprofiling_x64_2025-03-30_15-45-33.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1374
serverhub/arma3serverprofiling_x64_2025-03-30_15-54-00.rpt
Normal file
1374
serverhub/arma3serverprofiling_x64_2025-03-30_15-54-00.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1373
serverhub/arma3serverprofiling_x64_2025-03-30_16-01-48.rpt
Normal file
1373
serverhub/arma3serverprofiling_x64_2025-03-30_16-01-48.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1375
serverhub/arma3serverprofiling_x64_2025-03-30_16-19-18.rpt
Normal file
1375
serverhub/arma3serverprofiling_x64_2025-03-30_16-19-18.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1371
serverhub/arma3serverprofiling_x64_2025-03-30_16-34-25.rpt
Normal file
1371
serverhub/arma3serverprofiling_x64_2025-03-30_16-34-25.rpt
Normal file
File diff suppressed because it is too large
Load Diff
1361
serverhub/arma3serverprofiling_x64_2025-03-30_16-39-45.rpt
Normal file
1361
serverhub/arma3serverprofiling_x64_2025-03-30_16-39-45.rpt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user