Commit db72487c authored by Razer's avatar Razer
Browse files

Optimized ApmsDB plugin

parent 87ced259
/*
* Desolation Redux
* http://desolationredux.com/
* © 2016 - 2020 Desolation Dev Team
*
* This work is licensed under the Arma Public License Share Alike (APL-SA) + Bohemia monetization rights.
* To view a copy of this license, visit:
* https://www.bistudio.com/community/licenses/arma-public-license-share-alike/
* https://www.bistudio.com/monetization/
*/
/*
GLOBAL:
true
DESCRIPTION:
This function is used to create log messages that are stored to DB.
Custom variables can be set for better understanding for external programs.
PARAMS:
1 - STRING: Readable text header
2 - ARRAY (Optional): Array of variables for the log. (This can be used in external programs)
1 - STRING: Variable name
2 - ANYTHING: Variable data
3 - STRING (Optional): Target who triggered this log.
Can be one of these: ("pUUID","cUUID","clanUUID")
USAGE:
_pUUID = _player getVariable ["pUUID",""];
_success = ["Player spawned vehicle",[["location",_location],["object",_object]],_pUUID] call DB_fnc_log
RETURNS:
TRUE if success FALSE if failed
*/
// timestamp, wuuid, puuid*, cuuid*, ouuid*, logtype, message, data
// Client request for server
if(!isServer) exitWith {_this call DB_fnc_serverRequest};
#include "\ApmsDB\constants.hpp"
params [["_header","",[""]],["_variables",[],[[]]],["_uuid","",[""]]];
// CHECK WORLD UUID
_worldUUID = call DB_fnc_getWorldUUID;
if (_worldUUID == "") then {_worldUUID == "ERROR: NO WORLD UUID SET"};
// CHECK HEADER
if (_header == "") then {
_header = "MESSAGE";
};
// Make sure variable data is in string format
{
_x params [["_varName","",[""]],"_varData"];
if (isNil "_varData" || _varName == "") then {
// Delete invalid data
_variables deleteAt _forEachIndex;
diag_log format ["<ApmsDB>: ERROR: Invalid log variable parameters: %1",_x];
} else {
if !(_x isEqualType "") then {
// Transform data into a string
_variables set [_forEachIndex,str(_x)];
};
};
} forEach _variables;
// TODO: if uuid not set, add to request at all?
// SEND DATA
_request = ["LOG",[
WORLDUUID,_worldUUID,
HEADER,_header,
VARIABLES,_variables,
UUID,_uuid,
]];
private _return = [_request] call DB_fnc_sendRequest;
if (_return isEqualType [] && {(_return select 0) isEqualTo "error"}) exitWith {false};
// ADD RPT LOG
private _message = format ["<ApmsDB>: INFO: %1",_header];
if (_variables != []) then {_message = _message + (format [" | VARIABLES: %1",_variables])};
if (_uuid != "") then {_message = _message + (format [" | UUID: %1",_uuid])};
diag_log _message;
true
\ No newline at end of file
......@@ -13,8 +13,7 @@
params ["_obj"];
if!(_obj getVariable ["APMS_updateRequired",true]) then { // If variable doesent exist dont add this variable
_obj setVariable ["APMS_updateRequired",true,true];
};
_obj setVariable ["APMS_updateRequired",true,2];
false
\ No newline at end of file
......@@ -56,9 +56,7 @@ if(!isNull _object && {_object getVariable ["oUUID",""] != ""}) then {
_events = ["Hit","GetOut"];
_events apply {
_object addEventHandler [_x,{
if!((_this select 0) getVariable ["APMS_updateRequired",false]) then { // Check if update is already required
(_this select 0) setVariable ["APMS_updateRequired",true,true];
};
(_this select 0) setVariable ["APMS_updateRequired",true,2];
}];
};
......
......@@ -54,7 +54,7 @@ _child setVariable ["APMS_priority",_parent_priority + 1];
if !(_offset isEqualType []) then {
_offset = (getPos _child) vectorDiff getPos _parent;
_direction = (getDir _child) - (getDir _parent);
_positionadvanced = [["APMS_vectorUp",str(vectorUp _child)],["APMS_vectorDir",str(vectorDir _child)]];
_positionadvanced = [str(vectorUp _child),str(vectorDir _child)];
};
_child attachTo [_parent,_offset];
......@@ -84,22 +84,9 @@ if(["AutoDetach","DB",true] call BASE_fnc_getCfgData) then {
}];
};
// create compatibility to VectorDirAndUp instead of APMS positionadvanced
if !(_positionadvanced isEqualTo []) then {
// in case we got VectorDirAndUp serialize them before using them
// to make sure the result is the same as after the respawn
if (((_positionadvanced select 0) select 0) isEqualType 0) then {
private _vectorDir = (_positionadvanced select 0);
private _vectorUp = (_positionadvanced select 1);
_positionadvanced = [["APMS_vectorUp",str(_vectorUp)],["APMS_vectorDir",str(_vectorDir)]];
};
};
// apply vectors from the serialized data
if ((count _positionadvanced) > 0) then {
private _hpVectorUp = call compile ((_positionadvanced select 0) select 1);
private _hpVectorDir = call compile ((_positionadvanced select 1) select 1);
_child_uuid setVectorDirAndUp [_hpVectorDir,_hpVectorUp];
if ((count _positionadvanced) > 1) then {
_child setVectorDirAndUp [(parseSimpleArray(_positionadvanced#1)),parseSimpleArray(_positionadvanced#0)];
};
......
......@@ -21,7 +21,7 @@ detach _child;
// reset priority
_child setVariable ["APMS_priority",nil];
// force recalculation of the positionAdvanced
_child setVariable ["APMS_positionAdvanced",[]];
_child setVariable ["APMS_positionAdvanced",nil];
private _serializedData = [_child] call DB_fnc_serializeObject;
// remove parent link in database
......
......@@ -21,9 +21,7 @@
Parameter(s):
0: OBJECT - Target object to which action is attached.
1: ARRAY - Script type and parameters for the command.
0: STRING - Script type (Command).
1: ARRAY (ANY) - Parameters for the command in right order (use "this" to point for the object)
1: STRING - Script to run.
2: BOOL (Optional) - Should the script be executed once on target now?
Returns:
......@@ -31,39 +29,54 @@
Examples:
(This would turn the object's engine on when ever restored from DB)
_index = [_object, ["engineOn",["this",true]] ] call DB_fnc_initScript;
_index = [_object,"this engineOn true"] call DB_fnc_initScript;
(This would clear the weapons from the object's inventory)
_index = [_object ,["clearWeaponCargoGlobal",["this"]] ] call DB_fnc_initScript;
_index = [_object,"clearWeaponCargoGlobal this"] call DB_fnc_initScript;
(This would add one item when executed)
_index = [_object, ["addItem",["this","NVGoggles"],true] ] call DB_fnc_initScript;
(This would add one item when initialized)
_index = [_object,"this addItem 'NVGoggles'",true] call DB_fnc_initScript;
*/
if(isRemoteExecuted && {remoteExecutedOwner != 2}) exitWith {};
params [["_object",objNull,[objNull]], ["_script",[],[]], ["_runNow",false,[false]]];
#include "\ApmsDB\constants.hpp"
params [["_object",objNull,[objNull]],["_script","",[""]],["_runNow",false,[false]]];
private _oID = _object getVariable ["oUUID",""];
if(isNull _object || _script isEqualTo [] || _oID == "") exitWith {-1};
if(isNull _object || _script isEqualTo "" || _oID == "") exitWith {-1};
private _scripts = _object getVariable ["_SVAR_APMS_Scripts_"+(_oID),[]];
private _index = _scripts pushBack _script;
_object setVariable ["_SVAR_APMS_Scripts_"+(_oID),_scripts];
//--- Update Variables
private _variables = [];
(allVariables _object) apply {
if("svar_" in _x) then { // Both (_svar_ and svar_ also somethingsvar_)
private _v = _object getVariable _x; // Variable data
if!(isNil "_v") then {
_variables pushback [_x,_v];
};
};
};
private _request = [PROTOCOL_DBCALL_FUNCTION_QUIET_UPDATE_OBJECT,[
PROTOCOL_DBCALL_ARGUMENT_OBJECTUUID,_oID,
PROTOCOL_DBCALL_ARGUMENT_VARIABLES,_variables
]];
[_request] call DB_fnc_sendRequest;
if(_runNow) then {
_script params [["_type",""],["_params",[]]];
// Replace "this" by object
{
if(_x isEqualTo "this") then {
_params set [_forEachIndex,_object];
};
} forEach _params;
// Replace "this" by object and run
if ((toLower _script) find "this" != -1) then {
_script = [_script,"this",'objectFromNetId ' + str(netid _object)] call BASE_fnc_editString;
};
_params remoteExec [_type,2]; // Server execute
call compile _script;
};
_index
\ No newline at end of file
......@@ -45,7 +45,7 @@ private _objectType = _serializedData select 7;
_object setVariable ["APMS_objectType",_objectType];
_object setVariable ["APMS_priority",_objectPriority];
_object setVariable ["APMS_updateRequired",false,true];
_object setVariable ["APMS_updateRequired",false];
DB_var_Objects pushback _object;
DB_var_ObjectUUIDS pushback _object_uuid;
......
......@@ -23,11 +23,8 @@ diag_log "<ApmsDB>: Spawning DB objects";
{
if(_x select 0 == "") exitWith {}; // Unknown classname
_object = objNull;
[_x] call DB_fnc_unserializeObject;
// _object should now be the actual object
if!(isNull _object) then {
// Check if data succesully restored
if!([_x] call DB_fnc_unserializeObject) then {
["DB_onObjectRestored",[_object,_x]] spawn BASE_fnc_addEventHandler;
};
} forEach _dbSpawnData;
......
......@@ -20,7 +20,7 @@ private _request = [PROTOCOL_DBCALL_FUNCTION_QUIET_UPDATE_OBJECT,_serializedData
[_request] call DB_fnc_sendRequest;
// Reset the updateRequired flag
_object setVariable ["APMS_updateRequired",false,true];
_object setVariable ["APMS_updateRequired",false];
["DB_onObjectUpdated",[_object]] spawn BASE_fnc_addEventHandler;
......
......@@ -13,7 +13,5 @@
params ["_unit", "_container"];
if!(isNull _container) then {
if!(_container getVariable ["APMS_updateRequired",true]) then { // If variable doesent exist dont add this variable
(_container) setVariable ["APMS_updateRequired",true,true];
};
(_container) setVariable ["APMS_updateRequired",true,2];
};
\ No newline at end of file
......@@ -77,7 +77,10 @@ if(count(_temp) > 2) then {
{
if(_x != "") then {
if(count(_temp select 2) > _forEachIndex) then {
_hitpoints pushback [_x,((_temp select 2) select _forEachIndex)];
private _dmg = ((_temp select 2) select _forEachIndex);
if (_dmg > 0) then {
_hitpoints pushback [_x,_dmg];
};
};
};
} forEach (_temp select 0);
......
......@@ -70,8 +70,10 @@ if(count(_temp) > 2) then {
{
if(_x != "") then {
if(count(_temp select 2) > _forEachIndex) then {
private _value = (_temp select 2) select _forEachIndex;
_hitpoints pushback [_x,_value];
private _dmg = (_temp select 2) select _forEachIndex;
if (_dmg > 0) then {
_hitpoints pushback [_x,_dmg];
};
};
};
} forEach (_temp select 0);
......@@ -182,15 +184,15 @@ if(_objectType == 4) then {
private _aiSettings = [_skills,_features];
//--- Update settings variables list
_variables pushBack ["_svar_apmsunit_ai_settings",_aiSettings];
_object setVariable ["_svar_apmsunit_ai_settings",_aiSettings];
_variables pushBack ["_svar_apmsunit_settings",_aiSettings];
_object setVariable ["_svar_apmsunit_settings",_aiSettings];
//--- AI Side/Group setings
private _grpName = _object getVariable "_svar_apmsunit_grpname";
if (isNil "_grpName") then {
private _grpInfo = _object getVariable "_svar_apmsunit_grpinfo";
if (isNil "_grpInfo") then {
// Get group name from group variable if exists
_grpName = (group _object) getVariable "apms_grpname_temp";
_grpName = (group _object) in DB_var_aiGroupList;
if!(isNil "_grpName") exitWith {
_variables pushBack ["_svar_apmsunit_grpname",_grpName];
_object setVariable ["_svar_apmsunit_grpname",_grpName];
......@@ -210,8 +212,8 @@ if(_objectType == 4) then {
_grpName = "group_" + _grpName;
(group _object) setVariable ["apms_grpname_temp",_grpName]; // Set group variable for future
_variables pushBack ["_svar_apmsunit_grpname",_grpName];
_object setVariable ["_svar_apmsunit_grpname",_grpName];
_variables pushBack ["_SVAR_apmsUnit_grpInfo",[_grpName,str(side _object)]];
_object setVariable ["_SVAR_apmsUnit_grpInfo",[_grpName,str(side _object)]];
};
// Increase priority by one to make sure group leader gets spawned first
......@@ -222,12 +224,6 @@ if(_objectType == 4) then {
_priority = 100001 + _groupIndex;
};
private _grpSide = _object getVariable "_svar_apmsunit_grpside";
if (isNil "_grpSide") then {
_variables pushBack ["_svar_apmsunit_grpside",str(side _object)];
_object setVariable ["_svar_apmsunit_grpside",str(side _object)];
};
//--- AI Object Parent
_parent = objectParent _object;
if(!isNull _parent) then {
......@@ -253,18 +249,19 @@ if ((_positionASL select 2) < (_position select 2)) then {
_positionType = 0;
};
private _positionadvanced = [["APMS_vectorUp",str(vectorUp _object)]];
if (_objectType == 2) then { // is house
_positionadvanced = _object getVariable "APMS_positionAdvanced";
if(isNil "_positionadvanced") then {
_positionadvanced = [
["APMS_vectorUp",str(vectorUp _object)], //high precision vectorup
["APMS_vectorDir",str(vectorDir _object)], //high precision vectordir
["APMS_position",_position call DB_fnc_hpFloatArray] //high precision position
];
_object setVariable ["APMS_positionAdvanced",_positionadvanced];
};
};
//--- Advanced Position (Use string to make sure the DB understands the data)
// Elements order: "[[vectorUp],[vectorDir],['position']]"
// Check if there is overrided data (Attached object)
private _positionadvanced = (_object getVariable ["APMS_positionAdvanced",
if (_objectType != 4) then { // not ai
(if (_objectType == 2) then { // Is House
[str(vectorUp _object),str(vectorDir _object),(_position call DB_fnc_hpFloatArray)] // High precision position function = (STRING)
} else {
[str(vectorUp _object)]
});
} else {[]}
]);
[
......@@ -281,17 +278,17 @@ if (_objectType == 2) then { // is house
PROTOCOL_DBCALL_ARGUMENT_FUELCARGO,getFuelCargo _object,
PROTOCOL_DBCALL_ARGUMENT_REPAIRCARGO,getRepairCargo _object,
PROTOCOL_DBCALL_ARGUMENT_ITEMS,_items,
PROTOCOL_DBCALL_ARGUMENT_MAGAZINESTURRET, _magazinesturret,
PROTOCOL_DBCALL_ARGUMENT_VARIABLES, _variables,
PROTOCOL_DBCALL_ARGUMENT_ANIMATIONSTATE, _animStates,
PROTOCOL_DBCALL_ARGUMENT_MAGAZINESTURRET,_magazinesturret,
PROTOCOL_DBCALL_ARGUMENT_VARIABLES,_variables,
PROTOCOL_DBCALL_ARGUMENT_ANIMATIONSTATE,_animStates,
PROTOCOL_DBCALL_ARGUMENT_TEXTURES,getObjectTextures _object,
PROTOCOL_DBCALL_ARGUMENT_DIRECTION,getDir _object,
PROTOCOL_DBCALL_ARGUMENT_POSITIONTYPE, _positionType,
PROTOCOL_DBCALL_ARGUMENT_POSITIONX, _position select 0,
PROTOCOL_DBCALL_ARGUMENT_POSITIONY, _position select 1,
PROTOCOL_DBCALL_ARGUMENT_POSITIONZ, _position select 2,
PROTOCOL_DBCALL_ARGUMENT_POSITIONX,_position select 0,
PROTOCOL_DBCALL_ARGUMENT_POSITIONY,_position select 1,
PROTOCOL_DBCALL_ARGUMENT_POSITIONZ,_position select 2,
PROTOCOL_DBCALL_ARGUMENT_POSITIONADVANCED,_positionadvanced,
PROTOCOL_DBCALL_ARGUMENT_RESERVEDONE, [],
PROTOCOL_DBCALL_ARGUMENT_RESERVEDTWO, [],
PROTOCOL_DBCALL_ARGUMENT_RESERVEDONE,[],
PROTOCOL_DBCALL_ARGUMENT_RESERVEDTWO,[],
PROTOCOL_DBCALL_ARGUMENT_PARENTUUID,_parent getVariable ["oUUID",""]
];
\ No newline at end of file
......@@ -17,16 +17,23 @@ if(_object isEqualType []) then {_data = +_object; _object = objNull;};
if(_data isEqualTo []) exitWith {
diag_log format ["<ApmsDB>: ERROR: Cannot unserialize object (%1). Invalid parameters!",_object];
diag_log str(_x);
false
};
_data params [
private _test = _data params [
"_classname","_priority","_objectType","_accesscode","_locked","_player_uuid","_hitpoints",
"_damage","_fuel","_fuelcargo","_repaircargo","_items","_magazinesturret","_variables",
"_animStates","_textures","_direction","_positiontype","_positionx","_positiony","_positionz",
"_positionadvanced","_reservedone","_reservedtwo","_object_uuid","_parentuuid","_clan_uuid"
];
if !(_test) exitWith {
diag_log format ["<ApmsDB>: CRITICAL ERROR: UNABLE TO RESTORE OBJECT. SOME DATA IS MISSING!"];
diag_log str(_x);
false
};
private _position = [_positionx,_positiony,_positionz];
/* _objectType:
......@@ -49,19 +56,16 @@ if(_object isEqualTo objNull) then {
case 1: { // Simple object
createSimpleObject [_classname,(ATLToASL _position)];
};
case 2: {
_classname createVehicle _position;
};
case 3: {
case 2; // House
case 3: { // Vehicle
_classname createVehicle _position;
};
case 4: {
case 4: { // AI
// Get group info
private _grpname = (_variables select (_variables findIf {_x select 0 == "_svar_apmsunit_grpname"})) select 1;
private _grpside = (_variables select (_variables findIf {_x select 0 == "_svar_apmsunit_grpside"})) select 1;
private _grpinfo = (_variables select (_variables findIf {_x select 0 == "_svar_apmsunit_grpinfo"})) select 1;
private _unitGroup = [_grpname,_grpside] call BASE_fnc_getAiGroup;
_unitGroup setVariable ["apms_grpname_temp",_grpName]; // Set group variable for future use
private _unitGroup = [_grpinfo#0,_grpinfo#1] call BASE_fnc_getAiGroup; // [groupName,groupSide]
_unitGroup setVariable ["apms_grpname_temp",_grpinfo#1]; // Set group variable for future use
_unitGroup createUnit [_classname,_position,[],0,"CAN_COLLIDE"];
};
......@@ -83,18 +87,15 @@ _variables apply {
// Add INIT events (Use oUUID for security reasons)
if(toLower(_name) == "_svar_apms_scripts_" + toLower(_object_uuid)) then {
// Example: ["setDamage",["this",1]];
_data params ["_command","_params"];
// Replace "this" by object
{
if(_x isEqualType "" && {_x == "this"}) then {
_params set [_forEachIndex,_object];
_data apply {
// Replace "this" by object and run
_script = _x;
if ((toLower _script) find "this" != -1) then {
_script = [_script,"this",'objectFromNetId ' + str(netid _object)] call BASE_fnc_editString;
};
} forEach _params;
_params remoteExec [_command,2]; // Server execute
call compile _script;
};
};
} else {
_object setVariable [_name,_data,true]; // GLOBAL VARIABLE
......@@ -115,12 +116,12 @@ if(_clan_uuid != "") then {_object setVariable ["clanUUID",_clan_uuid]};
if!(_accesscode isEqualTo []) then {_object setVariable ["APMS_unlockCode",_accesscode,true]};
//--- APMS Variables
_object setVariable ["APMS_updateRequired",false,true];
_object setVariable ["APMS_updateRequired",false];
_object setVariable ["APMS_objectType",_objectType];
_object setVariable ["APMS_priority",_priority];
//--- Position
_object setDir _direction;
_object setDir _direction; // Apply this before position advanced
if(_positiontype == 1) then {
_object setPosATL _position;
} else {
......@@ -151,28 +152,6 @@ if (_objectType == 2 || {_objectType == 3}) then {
//--- Items
[_object,_items,true] call BASE_fnc_setAllCargo; // (Last param (true/false): Remove existing items)
//--- Advanced Position
private _amountOfPositionInformation = count _positionadvanced;
if (_amountOfPositionInformation > 0) then {
private _hpVectorUp = call compile ((_positionadvanced select 0) select 1);
if (_amountOfPositionInformation > 2) then {
private _hpVectorDir = call compile ((_positionadvanced select 1) select 1);
private _hpPosition = call compile ((_positionadvanced select 2) select 1);
_object setVectorDirAndUp [_hpVectorDir,_hpVectorUp];
if(_positiontype == 1) then {
_object setPosATL _hpPosition;
} else {
_object setPosASL _hpPosition;
};
_object setVariable ["APMS_positionAdvanced",_positionadvanced];
} else {
_object setVectorUp (_hpVectorUp);
};
};
//--- Building
if(_objectType == 2) exitWith {
......@@ -214,29 +193,6 @@ if(_objectType == 4) then { // If AI
private _aiSettings = _object getVariable ["_svar_apmsunit_ai_settings",[[],[]]]; // [["skills"],["features"]]
(_aiSettings select 0) apply {_object setSkill [_x select 0,_x select 1]};
(_aiSettings select 1) apply {_object enableAIFeature [_x select 0,_x select 1]};
// Advanced Position
private _amountOfPositionInformation = count _positionadvanced;
if (_amountOfPositionInformation > 0) then {
private _hpVectorUp = call compile ((_positionadvanced select 0) select 1);
if (_amountOfPositionInformation > 2) then {
private _hpVectorDir = call compile ((_positionadvanced select 1) select 1);
private _hpPosition = call compile ((_positionadvanced select 2) select 1);
_object setVectorDirAndUp [_hpVectorDir,_hpVectorUp];
if(_positiontype == 1) then {
_object setPosATL _hpPosition;
} else {
_object setPosASL _hpPosition;
};
_object setVariable ["APMS_positionAdvanced",_positionadvanced];
} else {
_object setVectorUp (_hpVectorUp);
};
};
};
//--- Set object parent (Attach)
......@@ -282,6 +238,42 @@ if !(_parentuuid isEqualTo "") then {
[_object,_parent,_position,_direction,_positionadvanced,false] call DB_fnc_attachTo;
};
};
} else {
//--- Advanced Position (No attached object)
// Elements order: "[[vectorUp],[vectorDir],['position']]"
if (isNil "_positionadvanced" || {_positionadvanced isEqualTo []}) exitWith {}; // No data
// Add old data type support (added for 0.4.4) --> (Remove for v.0.4.5)
private _modified = false;
{
if (_x isEqualType []) then {