Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions addons/aar/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class CfgFunctions
class reportVehiclePositions {};
class sendEvent {};
class sendJson {};
class sendUnitPosition {};
class sendVehiclePosition {};
class serializeJson {};
class serializeMission {};
class serializePlayer {};
Expand Down
9 changes: 2 additions & 7 deletions addons/aar/functions/fn_init.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@ addMissionEventHandler ["MPEnded", { [] call anrop_aar_fnc_eventMissionEnded }];

// Periodically send unit positions
if (anrop_aar_position_reporting > 0) then {
[] spawn {
anrop_aar_position_reporting call anrop_aar_fnc_reportUnitPositions;
};

[] spawn {
anrop_aar_position_reporting call anrop_aar_fnc_reportVehiclePositions;
};
[anrop_aar_fnc_reportUnitPositions, anrop_aar_position_reporting, []] call CBA_fnc_addPerFrameHandler;
[anrop_aar_fnc_reportVehiclePositions, anrop_aar_position_reporting, []] call CBA_fnc_addPerFrameHandler;
};
43 changes: 5 additions & 38 deletions addons/aar/functions/fn_reportUnitPositions.sqf
Original file line number Diff line number Diff line change
@@ -1,39 +1,6 @@
private "_unitCacheKey";
_unitCacheKey = "anrop_aar_unit_cache";
private _allUnits = allUnits;
_allUnits append allDead;

while { true } do {
private _reportUnit = {
params ["_reportedUnit"];

private _name = _reportedUnit call anrop_aar_fnc_getUnitName;
private _uid = "";
if (isPlayer _reportedUnit) then {
_uid = getPlayerUID _reportedUnit;
};
private _player = [_name, _uid] call anrop_aar_fnc_serializePlayer;
private _unit = _reportedUnit call anrop_aar_fnc_serializeUnit;

private _arr = ["object",
["type", ["string", "UnitPosition"]],
["player", _player],
["unit", _unit]
];

private _cached = _reportedUnit getVariable [_unitCacheKey, ""];

private _serialized = _arr call anrop_aar_fnc_serializeJson;
if (_serialized != _cached) then {
_reportedUnit setVariable [_unitCacheKey, _serialized];
_serialized call anrop_aar_fnc_sendJson;
};
};

private _allUnits = allUnits;
_allUnits append allDead;

{
[_x] call _reportUnit;
} forEach _allUnits;

sleep _this;
};
{
[_x] call anrop_aar_fnc_sendUnitPosition;
} forEach _allUnits;
32 changes: 3 additions & 29 deletions addons/aar/functions/fn_reportVehiclePositions.sqf
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
private "_vehicleCacheKey";
_vehicleCacheKey = "anrop_aar_vehicle_cache";

while { true } do {
private _reportVehicle = {
params ["_reportedVehicle"];

private _vehicle = _reportedVehicle call anrop_aar_fnc_serializeVehicle;

private "_arr";
_arr = ["object",
["type", ["string", "VehiclePosition"]],
["vehicle", _vehicle]
];

private _cached = _reportedVehicle getVariable [_vehicleCacheKey, ""];;

private _serialized = _arr call anrop_aar_fnc_serializeJson;
if (_serialized != _cached) then {
_reportedVehicle setVariable [_vehicleCacheKey, _serialized];
_serialized call anrop_aar_fnc_sendJson;
};
};

{
_x call _reportVehicle
} forEach vehicles;
sleep _this;
};
{
[_x] call anrop_aar_fnc_sendVehiclePosition;
} forEach vehicles;
21 changes: 21 additions & 0 deletions addons/aar/functions/fn_sendUnitPosition.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
params ["_unit"];

private _id = netId _unit;
private _lifeState = lifeState _unit;
private _name = _unit call anrop_aar_fnc_getUnitName;
private _dir = direction _unit;
(getPosASL _unit) params ["_posX", "_posY", "_posZ"];
private _side = side _unit;

private _uid = "";
if (isPlayer _unit) then {
_uid = getPlayerUID _unit;
};

private _vehicleId = "";
if (vehicle _unit != _unit) then {
_vehicleId = netId vehicle _unit;
};

anrop_aar_extension callExtension ["unitPosition", [_id, _lifeState, _name, _dir, _posX, _posY, _posZ, _side, _uid, _vehicleId]];

10 changes: 10 additions & 0 deletions addons/aar/functions/fn_sendVehiclePosition.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
params ["_vehicle"];

private _id = netId _vehicle;
private _name = getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "displayName");
private _dir = direction _vehicle;
(getPosASL _vehicle) params ["_posX", "_posY", "_posZ"];
private _side = str side _vehicle;
private _simulation = getText (configFile >> "CfgVehicles" >> typeOf _vehicle >> "simulation");

anrop_aar_extension callExtension ["vehiclePosition", [_id, _name, _dir, _posX, _posY, _posZ, _side, _simulation]];
112 changes: 112 additions & 0 deletions src/lib/ArgsProcessor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "ArgsProcessor.hpp"
#include "Utils.hpp"

ArgsProcessor::ArgsProcessor(Organizer *organizer) {
this->organizer = organizer;
}

ArgsProcessor::argsProcessed ArgsProcessor::processUnitPosition(const char **argv, int argc) {
std::string id(*argv++);
std::string lifeState(*argv++);
std::string name(*argv++);
auto dir = atof(*argv++);
auto posX = atof(*argv++);
auto posY = atof(*argv++);
auto posZ = atof(*argv++);
std::string side(*argv++);
std::string uid(*argv++);
std::string vehicleId(*argv++);

Utils::unquoteArmaString(&id);
Utils::unquoteArmaString(&lifeState);
Utils::unquoteArmaString(&name);
Utils::unquoteArmaString(&side);
Utils::unquoteArmaString(&uid);
Utils::unquoteArmaString(&vehicleId);

nlohmann::json j;
j["type"] = "UnitPosition";
j["player"]["name"] = name;
j["player"]["uid"] = uid;
j["unit"]["id"] = id;
j["unit"]["life_state"] = lifeState;
j["unit"]["name"] = name;
j["unit"]["position"]["dir"] = dir;
j["unit"]["position"]["x"] = posX;
j["unit"]["position"]["y"] = posY;
j["unit"]["position"]["z"] = posZ;
j["unit"]["side"] = side;

if (!vehicleId.empty()) {
j["unit"]["vehicle_id"] = vehicleId;
}

auto json_str = j.dump();

auto cacheLookup = unitsCache.find(id);
if (cacheLookup != unitsCache.end()) {
auto cached = cacheLookup->second;

if (json_str.compare(cached) == 0) {
return ArgsProcessor::EVENT_CACHED;
}
}

unitsCache[id] = json_str;

EventManager::event_added result = this->organizer->addEvent(json_str);

if (result == EventManager::EVENT_OK) {
return ArgsProcessor::EVENT_OK;
} else {
return ArgsProcessor::EVENT_ERROR;
}
}

ArgsProcessor::argsProcessed ArgsProcessor::processVehiclePosition(const char **argv, int argc) {
std::string id(*argv++);
std::string name(*argv++);
auto dir = atof(*argv++);
auto posX = atof(*argv++);
auto posY = atof(*argv++);
auto posZ = atof(*argv++);
std::string side(*argv++);
std::string simulation(*argv++);

Utils::unquoteArmaString(&id);
Utils::unquoteArmaString(&name);
Utils::unquoteArmaString(&side);
Utils::unquoteArmaString(&simulation);

nlohmann::json j;
j["type"] = "VehiclePosition";
j["vehicle"]["id"] = id;
j["vehicle"]["name"] = name;
j["vehicle"]["position"]["dir"] = dir;
j["vehicle"]["position"]["x"] = posX;
j["vehicle"]["position"]["y"] = posY;
j["vehicle"]["position"]["z"] = posZ;
j["vehicle"]["side"] = side;
j["vehicle"]["simulation"] = simulation;

auto json_str = j.dump();

auto cacheLookup = vehicleCache.find(id);
if (cacheLookup != vehicleCache.end()) {
auto cached = cacheLookup->second;

if (json_str.compare(cached) == 0) {
return ArgsProcessor::EVENT_CACHED;
}
}

vehicleCache[id] = json_str;

EventManager::event_added result = this->organizer->addEvent(json_str);

if (result == EventManager::EVENT_OK) {
return ArgsProcessor::EVENT_OK;
} else {
return ArgsProcessor::EVENT_ERROR;
}
}
17 changes: 17 additions & 0 deletions src/lib/ArgsProcessor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "Organizer.hpp"

class ArgsProcessor {
public:
enum argsProcessed {EVENT_OK, EVENT_ERROR, EVENT_CACHED};

ArgsProcessor(Organizer *organizer);

ArgsProcessor::argsProcessed processUnitPosition(const char **argv, int argc);
ArgsProcessor::argsProcessed processVehiclePosition(const char **argv, int argc);
private:
Organizer *organizer;
std::map<std::string, std::string> unitsCache;
std::map<std::string, std::string> vehicleCache;
};
31 changes: 31 additions & 0 deletions src/lib/Utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "Utils.hpp"

void Utils::unquoteArmaString(std::string *s) {
if (s->size() > 0) {
if (s->front() == '"')
s->erase(0, 1);
}

if (s->size() > 0) {
if (s->back() == '"') {
s->erase(s->size() - 1);
}
}

if (s->size() > 0) {
bool lastQuote = false;
for (std::string::iterator it = s->begin(); it != s->end(); it++) {
if (*it == '"') {
if (!lastQuote) {
lastQuote = true;
} else {
s->erase(it);
it--;
lastQuote = false;
}
} else {
lastQuote = false;
}
}
}
};
8 changes: 8 additions & 0 deletions src/lib/Utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <string>

class Utils {
public:
static void unquoteArmaString(std::string *s);
};
38 changes: 38 additions & 0 deletions src/lib/main.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
#include <iostream>
#include <nlohmann/json.hpp>

#include "Config.hpp"
#include "ArgsProcessor.hpp"
#include "Organizer.hpp"
#include "Utils.hpp"

using namespace std;

Config config;
Organizer organizer;
ArgsProcessor eventProcessor(&organizer);

extern "C" {
#ifdef WIN32
__declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
__declspec (dllexport) int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **argv, int argc);
#else
void RVExtension(char *output, int outputSize, const char *function);
int RVExtensionArgs(char *output, int outputSize, const char *function, const char **argv, int argc);
#endif
}

Expand Down Expand Up @@ -68,3 +74,35 @@ void RVExtension(char *output, int outputSize, const char *function)
}
}
}

#ifdef WIN32
int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **argv, int argc)
#else
int RVExtensionArgs(char *output, int outputSize, const char *function, const char **argv, int argc)
#endif
{
std::string s_function(function);
if (s_function == "unitPosition") {
auto status = eventProcessor.processUnitPosition(argv, argc);

if (status == ArgsProcessor::EVENT_OK) {
strncpy(output, "OK", outputSize);
} else if (status == ArgsProcessor::EVENT_CACHED) {
strncpy(output, "CACHED", outputSize);
} else if (status == ArgsProcessor::EVENT_ERROR) {
strncpy(output, "ERROR", outputSize);
}
} else if (s_function == "vehiclePosition") {
auto status = eventProcessor.processVehiclePosition(argv, argc);

if (status == ArgsProcessor::EVENT_OK) {
strncpy(output, "OK", outputSize);
} else if (status == ArgsProcessor::EVENT_CACHED) {
strncpy(output, "CACHED", outputSize);
} else if (status == ArgsProcessor::EVENT_ERROR) {
strncpy(output, "ERROR", outputSize);
}
}

return 0;
}