mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Fixed update error and added update trigger
This commit is contained in:
8
src/.vscode/settings.json
vendored
8
src/.vscode/settings.json
vendored
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.ejs": "html",
|
||||
"xstring": "cpp",
|
||||
"vector": "cpp",
|
||||
"list": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "logger.h"
|
||||
#include "commands.h"
|
||||
|
||||
#include <chrono>
|
||||
using namespace std::chrono;
|
||||
|
||||
#define TASK_CHECK_INIT_VALUE 10
|
||||
|
||||
namespace State
|
||||
@@ -79,8 +82,10 @@ namespace DataTypes {
|
||||
unsigned short fuel;
|
||||
double desiredSpeed;
|
||||
double desiredAltitude;
|
||||
unsigned int leaderID;
|
||||
unsigned int targetID;
|
||||
Coords targetPosition;
|
||||
unsigned char coalition;
|
||||
unsigned char state;
|
||||
unsigned char ROE;
|
||||
unsigned char reactionToThreat;
|
||||
@@ -90,11 +95,7 @@ namespace DataTypes {
|
||||
unsigned short pathLength;
|
||||
unsigned short ammoLength;
|
||||
unsigned short contactsLength;
|
||||
unsigned char nameLength;
|
||||
unsigned char unitNameLength;
|
||||
unsigned char groupNameLength;
|
||||
unsigned char categoryLength;
|
||||
unsigned char coalitionLength;
|
||||
unsigned char taskLength;
|
||||
};
|
||||
}
|
||||
#pragma pack(pop)
|
||||
@@ -112,18 +113,18 @@ public:
|
||||
void runAILoop();
|
||||
void updateExportData(json::value json, double dt = 0);
|
||||
void updateMissionData(json::value json);
|
||||
unsigned int getUpdateData(char* &data);
|
||||
void getData(stringstream &ss, bool refresh);
|
||||
unsigned int getDataPacket(char* &data);
|
||||
void getData(stringstream &ss, unsigned long long time, bool refresh);
|
||||
virtual string getCategory() { return "No category"; };
|
||||
|
||||
/********** Base data **********/
|
||||
void setControlled(bool newControlled) { controlled = newControlled; }
|
||||
void setName(string newName) { name = newName; }
|
||||
void setUnitName(string newUnitName) { unitName = newUnitName; }
|
||||
void setGroupName(string newGroupName) { groupName = newGroupName; }
|
||||
void setAlive(bool newAlive) { alive = newAlive; }
|
||||
void setCountry(unsigned int newCountry) { country = newCountry; }
|
||||
void setHuman(bool newHuman) { human = newHuman; }
|
||||
void setControlled(bool newValue) { updateValue(controlled, newValue); }
|
||||
void setName(string newValue) { updateValue(name, newValue); }
|
||||
void setUnitName(string newValue) { updateValue(unitName, newValue); }
|
||||
void setGroupName(string newValue) { updateValue(groupName, newValue); }
|
||||
void setAlive(bool newValue) { updateValue(alive, newValue); }
|
||||
void setCountry(unsigned int newValue) { updateValue(country, newValue); }
|
||||
void setHuman(bool newValue) { updateValue(human, newValue); }
|
||||
|
||||
bool getControlled() { return controlled; }
|
||||
string getName() { return name; }
|
||||
@@ -134,51 +135,50 @@ public:
|
||||
bool getHuman() { return human; }
|
||||
|
||||
/********** Flight data **********/
|
||||
void setPosition(Coords newPosition) { position = newPosition; }
|
||||
void setHeading(double newHeading) {heading = newHeading; }
|
||||
void setSpeed(double newSpeed) {speed = newSpeed; }
|
||||
void setPosition(Coords newValue) { updateValue(position, newValue); }
|
||||
void setHeading(double newValue) { updateValue(heading, newValue); }
|
||||
void setSpeed(double newValue) { updateValue(speed, newValue); }
|
||||
|
||||
Coords getPosition() { return position; }
|
||||
double getHeading() { return heading; }
|
||||
double getSpeed() { return speed; }
|
||||
|
||||
/********** Mission data **********/
|
||||
void setFuel(short newFuel) { fuel = newFuel; }
|
||||
void setFuel(unsigned short newValue) { updateValue(fuel, newValue); }
|
||||
void setAmmo(vector<DataTypes::Ammo> newAmmo) { ammo = newAmmo; }
|
||||
void setContacts(vector<DataTypes::Contact> newContacts) {contacts = newContacts; }
|
||||
void setHasTask(bool newHasTask);
|
||||
void setCoalitionID(unsigned int newCoalitionID);
|
||||
void setContacts(vector<DataTypes::Contact> newContacts) { contacts = newContacts; }
|
||||
void setHasTask(bool newValue) { updateValue(hasTask, newValue); }
|
||||
void setCoalition(unsigned char newValue) { updateValue(coalition, newValue);}
|
||||
|
||||
double getFuel() { return fuel; }
|
||||
vector<DataTypes::Ammo> getAmmo() { return ammo; }
|
||||
vector<DataTypes::Contact> getTargets() { return contacts; }
|
||||
bool getHasTask() { return hasTask; }
|
||||
string getCoalition() { return coalition; }
|
||||
unsigned int getCoalitionID();
|
||||
unsigned int getCoalition() { return coalition; }
|
||||
|
||||
/********** Formation data **********/
|
||||
void setLeaderID(unsigned int newLeaderID) { leaderID = newLeaderID; }
|
||||
void setLeaderID(unsigned int newValue) { updateValue(leaderID, newValue); }
|
||||
void setFormationOffset(Offset formationOffset);
|
||||
|
||||
unsigned int getLeaderID() { return leaderID; }
|
||||
Offset getFormationoffset() { return formationOffset; }
|
||||
|
||||
/********** Task data **********/
|
||||
void setCurrentTask(string newCurrentTask) { currentTask = newCurrentTask; }
|
||||
void setDesiredSpeed(double newDesiredSpeed);
|
||||
void setDesiredAltitude(double newDesiredAltitude);
|
||||
void setDesiredSpeedType(string newDesiredSpeedType);
|
||||
void setDesiredAltitudeType(string newDesiredAltitudeType);
|
||||
void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; }
|
||||
void setActivePath(list<Coords> newActivePath);
|
||||
void setTargetID(unsigned int newTargetID) { targetID = newTargetID; }
|
||||
void setTargetPosition(Coords newTargetPosition);
|
||||
void setIsTanker(bool newIsTanker);
|
||||
void setIsAWACS(bool newIsAWACS);
|
||||
virtual void setOnOff(bool newOnOff) { onOff = newOnOff; };
|
||||
virtual void setFollowRoads(bool newFollowRoads) { followRoads = newFollowRoads; };
|
||||
void setTask(string newValue) { updateValue(task, newValue); }
|
||||
void setDesiredSpeed(double newValue);
|
||||
void setDesiredAltitude(double newValue);
|
||||
void setDesiredSpeedType(string newValue);
|
||||
void setDesiredAltitudeType(string newValue);
|
||||
void setActiveDestination(Coords newValue) { updateValue(activeDestination, newValue); }
|
||||
void setActivePath(list<Coords> newValue);
|
||||
void setTargetID(unsigned int newValue) { updateValue(targetID, newValue); }
|
||||
void setTargetPosition(Coords newValue) { updateValue(targetPosition, newValue); }
|
||||
void setIsTanker(bool newValue);
|
||||
void setIsAWACS(bool newValue);
|
||||
virtual void setOnOff(bool newValue) { updateValue(onOff, newValue); };
|
||||
virtual void setFollowRoads(bool newValue) { updateValue(followRoads, newValue); };
|
||||
|
||||
string getCurrentTask() { return currentTask; }
|
||||
string getTask() { return task; }
|
||||
virtual double getDesiredSpeed() { return desiredSpeed; };
|
||||
virtual double getDesiredAltitude() { return desiredAltitude; };
|
||||
virtual bool getDesiredSpeedType() { return desiredSpeedType; };
|
||||
@@ -193,13 +193,13 @@ public:
|
||||
bool getFollowRoads() { return followRoads; };
|
||||
|
||||
/********** Options data **********/
|
||||
void setROE(unsigned char newROE, bool force = false);
|
||||
void setReactionToThreat(unsigned char newReactionToThreat, bool force = false);
|
||||
void setEmissionsCountermeasures(unsigned char newEmissionsCountermeasures, bool force = false);
|
||||
void setTACAN(Options::TACAN newTACAN, bool force = false);
|
||||
void setRadio(Options::Radio newradio, bool force = false);
|
||||
void setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool force = false);
|
||||
void setEPLRS(bool newEPLRS, bool force = false);
|
||||
void setROE(unsigned char newValue, bool force = false);
|
||||
void setReactionToThreat(unsigned char newValue, bool force = false);
|
||||
void setEmissionsCountermeasures(unsigned char newValue, bool force = false);
|
||||
void setTACAN(Options::TACAN newValue, bool force = false);
|
||||
void setRadio(Options::Radio newValue, bool force = false);
|
||||
void setGeneralSettings(Options::GeneralSettings newValue, bool force = false);
|
||||
void setEPLRS(bool newValue, bool force = false);
|
||||
|
||||
unsigned char getROE() { return ROE; }
|
||||
unsigned char getReactionToThreat() { return reactionToThreat; }
|
||||
@@ -220,6 +220,8 @@ public:
|
||||
void pushActivePathFront(Coords newActivePathFront);
|
||||
void pushActivePathBack(Coords newActivePathBack);
|
||||
void popActivePathFront();
|
||||
void triggerUpdate() { lastUpdateTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); }
|
||||
unsigned long long getLastUpdateTime() { return lastUpdateTime; };
|
||||
|
||||
protected:
|
||||
unsigned int ID;
|
||||
@@ -247,18 +249,18 @@ protected:
|
||||
vector<DataTypes::Ammo> ammo;
|
||||
vector<DataTypes::Contact> contacts;
|
||||
bool hasTask = false;
|
||||
string coalition = "";
|
||||
unsigned char coalition;
|
||||
|
||||
/********** Formation data **********/
|
||||
unsigned int leaderID = NULL;
|
||||
Offset formationOffset = Offset(NULL);
|
||||
|
||||
/********** Task data **********/
|
||||
string currentTask = "";
|
||||
string task = "";
|
||||
double desiredSpeed = 0;
|
||||
double desiredAltitude = 0;
|
||||
bool desiredSpeedType = 0;
|
||||
bool desiredAltitudeType = 0;
|
||||
bool desiredSpeedType = 1;
|
||||
bool desiredAltitudeType = 1;
|
||||
list<Coords> activePath;
|
||||
Coords activeDestination = Coords(NULL);
|
||||
unsigned int targetID = NULL;
|
||||
@@ -277,10 +279,14 @@ protected:
|
||||
Options::GeneralSettings generalSettings;
|
||||
bool EPLRS = false;
|
||||
|
||||
/********** Data packet **********/
|
||||
DataTypes::DataPacket dataPacket;
|
||||
|
||||
/********** State machine **********/
|
||||
unsigned char state = State::NONE;
|
||||
|
||||
/********** Other **********/
|
||||
unsigned long long lastUpdateTime = 0;
|
||||
Coords oldPosition = Coords(0); // Used to approximate speed
|
||||
|
||||
/********** Functions **********/
|
||||
@@ -295,4 +301,14 @@ protected:
|
||||
void goToDestination(string enrouteTask = "nil");
|
||||
bool checkTaskFailed();
|
||||
void resetTaskFailedCounter();
|
||||
|
||||
template <typename T>
|
||||
void updateValue(T& value, T& newValue)
|
||||
{
|
||||
if (newValue != value)
|
||||
{
|
||||
triggerUpdate();
|
||||
*(&value) = newValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
void updateExportData(lua_State* L, double dt = 0);
|
||||
void updateMissionData(json::value missionData);
|
||||
void runAILoop();
|
||||
string getUnitData(bool refresh);
|
||||
string getUnitData(stringstream &ss, unsigned long long time, bool refresh);
|
||||
void deleteUnit(unsigned int ID, bool explosion);
|
||||
void acquireControl(unsigned int ID);
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ void AirUnit::AIloop()
|
||||
/* State machine */
|
||||
switch (state) {
|
||||
case State::IDLE: {
|
||||
currentTask = "Idle";
|
||||
setTask("Idle");
|
||||
|
||||
if (!getHasTask())
|
||||
{
|
||||
@@ -147,17 +147,17 @@ void AirUnit::AIloop()
|
||||
if (isTanker)
|
||||
{
|
||||
enrouteTask = "{ id = 'Tanker' }";
|
||||
currentTask = "Tanker";
|
||||
setTask("Tanker");
|
||||
}
|
||||
else if (isAWACS)
|
||||
{
|
||||
enrouteTask = "{ id = 'AWACS' }";
|
||||
currentTask = "AWACS";
|
||||
setTask("AWACS");
|
||||
}
|
||||
else
|
||||
{
|
||||
enrouteTask = "nil";
|
||||
currentTask = "Reaching destination";
|
||||
setTask("Reaching destination");
|
||||
}
|
||||
|
||||
if (activeDestination == NULL || !getHasTask())
|
||||
@@ -179,7 +179,7 @@ void AirUnit::AIloop()
|
||||
}
|
||||
case State::LAND: {
|
||||
string enrouteTask = "{ id = 'Land' }";
|
||||
currentTask = "Landing";
|
||||
setTask("Landing");
|
||||
|
||||
if (activeDestination == NULL)
|
||||
{
|
||||
@@ -203,7 +203,7 @@ void AirUnit::AIloop()
|
||||
<< "targetID = " << targetID << ","
|
||||
<< "}";
|
||||
string enrouteTask = enrouteTaskSS.str();
|
||||
currentTask = "Attacking " + getTargetName();
|
||||
setTask("Attacking " + getTargetName());
|
||||
|
||||
if (!getHasTask())
|
||||
{
|
||||
@@ -223,7 +223,7 @@ void AirUnit::AIloop()
|
||||
break;
|
||||
}
|
||||
|
||||
currentTask = "Following " + getTargetName();
|
||||
setTask("Following " + getTargetName());
|
||||
|
||||
Unit* leader = unitsManager->getUnit(leaderID);
|
||||
if (!getHasTask()) {
|
||||
@@ -247,7 +247,7 @@ void AirUnit::AIloop()
|
||||
break;
|
||||
}
|
||||
case State::REFUEL: {
|
||||
currentTask = "Refueling";
|
||||
setTask("Refueling");
|
||||
|
||||
if (!getHasTask()) {
|
||||
if (fuel <= initialFuel) {
|
||||
@@ -265,7 +265,7 @@ void AirUnit::AIloop()
|
||||
}
|
||||
}
|
||||
case State::BOMB_POINT: {
|
||||
currentTask = "Bombing point";
|
||||
setTask("Bombing point");
|
||||
|
||||
if (!getHasTask()) {
|
||||
std::ostringstream taskSS;
|
||||
@@ -276,7 +276,7 @@ void AirUnit::AIloop()
|
||||
}
|
||||
}
|
||||
case State::CARPET_BOMB: {
|
||||
currentTask = "Carpet bombing";
|
||||
setTask("Carpet bombing");
|
||||
|
||||
if (!getHasTask()) {
|
||||
std::ostringstream taskSS;
|
||||
@@ -288,7 +288,7 @@ void AirUnit::AIloop()
|
||||
break;
|
||||
}
|
||||
case State::BOMB_BUILDING: {
|
||||
currentTask = "Bombing building";
|
||||
setTask("Bombing building");
|
||||
|
||||
if (!getHasTask()) {
|
||||
std::ostringstream taskSS;
|
||||
|
||||
@@ -85,13 +85,14 @@ extern "C" DllExport int coreFrame(lua_State* L)
|
||||
|
||||
if (unitsManager != nullptr) {
|
||||
unitsManager->updateExportData(L, duration.count());
|
||||
//unitsManager->runAILoop();
|
||||
unitsManager->runAILoop();
|
||||
|
||||
}
|
||||
before = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
if (scheduler != nullptr)
|
||||
//scheduler->execute(L);
|
||||
scheduler->execute(L);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ void GroundUnit::AIloop()
|
||||
{
|
||||
switch (state) {
|
||||
case State::IDLE: {
|
||||
currentTask = "Idle";
|
||||
setTask("Idle");
|
||||
if (getHasTask())
|
||||
resetTask();
|
||||
break;
|
||||
@@ -102,7 +102,7 @@ void GroundUnit::AIloop()
|
||||
break;
|
||||
}
|
||||
case State::FIRE_AT_AREA: {
|
||||
currentTask = "Firing at area";
|
||||
setTask("Firing at area");
|
||||
|
||||
if (!getHasTask()) {
|
||||
std::ostringstream taskSS;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
extern UnitsManager* unitsManager;
|
||||
|
||||
Scheduler::Scheduler(lua_State* L):
|
||||
Scheduler::Scheduler(lua_State* L) :
|
||||
load(0)
|
||||
{
|
||||
LogInfo(L, "Scheduler constructor called successfully");
|
||||
@@ -25,16 +25,15 @@ void Scheduler::appendCommand(Command* command)
|
||||
|
||||
void Scheduler::execute(lua_State* L)
|
||||
{
|
||||
/* Decrease the active computation load. New commands can be sent only if the load has reached 0.
|
||||
/* Decrease the active computation load. New commands can be sent only if the load has reached 0.
|
||||
This is needed to avoid server lag. */
|
||||
if (load > 0) {
|
||||
load--;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int priority = CommandPriority::IMMEDIATE;
|
||||
while (priority >= CommandPriority::LOW)
|
||||
{
|
||||
int priority = CommandPriority::IMMEDIATE;
|
||||
while (priority >= CommandPriority::LOW) {
|
||||
for (auto command : commands)
|
||||
{
|
||||
if (command->getPriority() == priority)
|
||||
@@ -42,13 +41,15 @@ void Scheduler::execute(lua_State* L)
|
||||
string commandString = "Olympus.protectedCall(" + command->getString(L) + ")";
|
||||
if (dostring_in(L, "server", (commandString)))
|
||||
log("Error executing command " + commandString);
|
||||
else
|
||||
log("Command '" + commandString + "' executed correctly, current load " + to_string(load));
|
||||
load = command->getLoad();
|
||||
commands.remove(command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
priority--;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void Scheduler::handleRequest(string key, json::value value)
|
||||
@@ -66,11 +67,11 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
string unitName = unit->getUnitName();
|
||||
json::value path = value[L"path"];
|
||||
list<Coords> newPath;
|
||||
for (unsigned int i = 1; i <= path.as_object().size(); i++)
|
||||
for (unsigned int i = 0; i < path.as_array().size(); i++)
|
||||
{
|
||||
string WP = to_string(i);
|
||||
double lat = path[to_wstring(i)][L"lat"].as_double();
|
||||
double lng = path[to_wstring(i)][L"lng"].as_double();
|
||||
double lat = path[i][L"lat"].as_double();
|
||||
double lng = path[i][L"lng"].as_double();
|
||||
log(unitName + " set path destination " + WP + " (" + to_string(lat) + ", " + to_string(lng) + ")");
|
||||
Coords dest; dest.lat = lat; dest.lng = lng;
|
||||
newPath.push_back(dest);
|
||||
@@ -126,7 +127,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
|
||||
string unitName;
|
||||
string targetName;
|
||||
|
||||
|
||||
if (unit != nullptr)
|
||||
unitName = unit->getUnitName();
|
||||
else
|
||||
@@ -197,11 +198,11 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
}
|
||||
else if (key.compare("setSpeedType") == 0)
|
||||
{
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr)
|
||||
unit->setDesiredSpeedType(to_string(value[L"speedType"]));
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr)
|
||||
unit->setDesiredSpeedType(to_string(value[L"speedType"]));
|
||||
}
|
||||
else if (key.compare("setAltitude") == 0)
|
||||
{
|
||||
@@ -233,7 +234,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
unsigned char ROE = value[L"ROE"].as_number().is_uint32();
|
||||
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
|
||||
unit->setROE(ROE);
|
||||
}
|
||||
else if (key.compare("setReactionToThreat") == 0)
|
||||
@@ -241,7 +242,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().is_uint32();
|
||||
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
|
||||
unit->setReactionToThreat(reactionToThreat);
|
||||
}
|
||||
else if (key.compare("setEmissionsCountermeasures") == 0)
|
||||
@@ -249,7 +250,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().is_uint32();
|
||||
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
|
||||
unit->setEmissionsCountermeasures(emissionsCountermeasures);
|
||||
}
|
||||
else if (key.compare("landAt") == 0)
|
||||
@@ -317,7 +318,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
}
|
||||
}
|
||||
else if (key.compare("setFollowRoads") == 0)
|
||||
{
|
||||
{
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
bool followRoads = value[L"followRoads"].as_bool();
|
||||
@@ -325,7 +326,7 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
unit->setFollowRoads(followRoads);
|
||||
}
|
||||
else if (key.compare("setOnOff") == 0)
|
||||
{
|
||||
{
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
bool onOff = value[L"onOff"].as_bool();
|
||||
@@ -389,10 +390,11 @@ void Scheduler::handleRequest(string key, json::value value)
|
||||
{
|
||||
log("Unknown command: " + key);
|
||||
}
|
||||
|
||||
|
||||
if (command != nullptr)
|
||||
{
|
||||
appendCommand(command);
|
||||
log("New command appended correctly to stack. Current server load: " + to_string(load));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,10 +69,11 @@ void Server::handle_get(http_request request)
|
||||
/* Lock for thread safety */
|
||||
lock_guard<mutex> guard(mutexLock);
|
||||
|
||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||
|
||||
http_response response(status_codes::OK);
|
||||
string authorization = to_base64("admin:" + password);
|
||||
log(authorization);
|
||||
if (password == "" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second == L"Basic " + to_wstring(authorization)))
|
||||
if (password.length() == 0 || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second.compare(L"Basic " + to_wstring(authorization)) == 0))
|
||||
{
|
||||
std::exception_ptr eptr;
|
||||
try {
|
||||
@@ -96,28 +97,34 @@ void Server::handle_get(http_request request)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO would be nice to optimize this
|
||||
answer[L"units"] = json::value(to_wstring(unitsManager->getUnitData(time == 0)));
|
||||
}
|
||||
else if (URI.compare(LOGS_URI) == 0)
|
||||
{
|
||||
auto logs = json::value::object();
|
||||
getLogsJSON(logs, 100); // By reference, for thread safety. Get the last 100 log entries
|
||||
answer[L"logs"] = logs;
|
||||
}
|
||||
else if (URI.compare(AIRBASES_URI) == 0)
|
||||
answer[L"airbases"] = airbases;
|
||||
else if (URI.compare(BULLSEYE_URI) == 0)
|
||||
answer[L"bullseyes"] = bullseyes;
|
||||
else if (URI.compare(MISSION_URI) == 0)
|
||||
answer[L"mission"] = mission;
|
||||
bool refresh = (time == 0);
|
||||
unsigned long long updateTime = ms.count();
|
||||
|
||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
||||
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
|
||||
stringstream ss;
|
||||
ss.write((char*)&updateTime, sizeof(updateTime));
|
||||
unitsManager->getUnitData(ss, time, refresh);
|
||||
response.set_body(concurrency::streams::bytestream::open_istream(ss.str()));
|
||||
}
|
||||
else {
|
||||
if (URI.compare(LOGS_URI) == 0)
|
||||
{
|
||||
auto logs = json::value::object();
|
||||
getLogsJSON(logs, 100); // By reference, for thread safety. Get the last 100 log entries
|
||||
answer[L"logs"] = logs;
|
||||
}
|
||||
else if (URI.compare(AIRBASES_URI) == 0)
|
||||
answer[L"airbases"] = airbases;
|
||||
else if (URI.compare(BULLSEYE_URI) == 0)
|
||||
answer[L"bullseyes"] = bullseyes;
|
||||
else if (URI.compare(MISSION_URI) == 0)
|
||||
answer[L"mission"] = mission;
|
||||
|
||||
|
||||
answer[L"time"] = json::value::string(to_wstring(ms.count()));
|
||||
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
|
||||
response.set_body(answer);
|
||||
}
|
||||
}
|
||||
|
||||
response.set_body(answer);
|
||||
}
|
||||
catch (...) {
|
||||
eptr = std::current_exception(); // capture
|
||||
@@ -140,7 +147,7 @@ void Server::handle_request(http_request request, function<void(json::value cons
|
||||
{
|
||||
http_response response(status_codes::OK);
|
||||
string authorization = to_base64("admin:" + password);
|
||||
if (password == "" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second.compare(L"Basic " + to_wstring(authorization))))
|
||||
if (password.length() == 0 || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second.compare(L"Basic " + to_wstring(authorization)) == 0))
|
||||
{
|
||||
auto answer = json::value::object();
|
||||
request.extract_json().then([&answer, &action](pplx::task<json::value> task)
|
||||
|
||||
@@ -45,6 +45,24 @@ Unit::~Unit()
|
||||
|
||||
void Unit::initialize(json::value json)
|
||||
{
|
||||
if (json.has_string_field(L"Name"))
|
||||
setName(to_string(json[L"Name"]));
|
||||
if (json.has_string_field(L"UnitName"))
|
||||
setUnitName(to_string(json[L"UnitName"]));
|
||||
if (json.has_string_field(L"GroupName"))
|
||||
setGroupName(to_string(json[L"GroupName"]));
|
||||
if (json.has_number_field(L"Country"))
|
||||
setCountry(json[L"Country"].as_number().to_int32());
|
||||
if (json.has_number_field(L"CoalitionID"))
|
||||
setCoalition(json[L"CoalitionID"].as_number().to_int32());
|
||||
|
||||
if (json.has_object_field(L"Flags"))
|
||||
setHuman(json[L"Flags"][L"Human"].as_bool());
|
||||
|
||||
/* All units which contain the name "Olympus" are automatically under AI control */
|
||||
if (getUnitName().find("Olympus") != string::npos)
|
||||
setControlled(true);
|
||||
|
||||
updateExportData(json);
|
||||
setDefaults();
|
||||
}
|
||||
@@ -92,6 +110,21 @@ void Unit::runAILoop() {
|
||||
|
||||
void Unit::updateExportData(json::value json, double dt)
|
||||
{
|
||||
Coords newPosition = Coords(NULL);
|
||||
double newHeading = 0;
|
||||
double newSpeed = 0;
|
||||
|
||||
if (json.has_object_field(L"LatLongAlt"))
|
||||
{
|
||||
setPosition({
|
||||
json[L"LatLongAlt"][L"Lat"].as_number().to_double(),
|
||||
json[L"LatLongAlt"][L"Long"].as_number().to_double(),
|
||||
json[L"LatLongAlt"][L"Alt"].as_number().to_double()
|
||||
});
|
||||
}
|
||||
if (json.has_number_field(L"Heading"))
|
||||
setHeading(json[L"Heading"].as_number().to_double());
|
||||
|
||||
/* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */
|
||||
if (oldPosition != NULL)
|
||||
{
|
||||
@@ -100,35 +133,7 @@ void Unit::updateExportData(json::value json, double dt)
|
||||
if (dt > 0)
|
||||
setSpeed(getSpeed() * 0.95 + (dist / dt) * 0.05);
|
||||
}
|
||||
|
||||
if (json.has_string_field(L"Name"))
|
||||
setName(to_string(json[L"Name"]));
|
||||
if (json.has_string_field(L"UnitName"))
|
||||
setUnitName(to_string(json[L"UnitName"]));
|
||||
if (json.has_string_field(L"GroupName"))
|
||||
setGroupName(to_string(json[L"GroupName"]));
|
||||
if (json.has_number_field(L"Country"))
|
||||
setCountry(json[L"Country"].as_number().to_int32());
|
||||
if (json.has_number_field(L"CoalitionID"))
|
||||
setCoalitionID(json[L"CoalitionID"].as_number().to_int32());
|
||||
if (json.has_object_field(L"LatLongAlt"))
|
||||
{
|
||||
Coords position = {
|
||||
json[L"LatLongAlt"][L"Lat"].as_number().to_double(),
|
||||
json[L"LatLongAlt"][L"Long"].as_number().to_double(),
|
||||
json[L"LatLongAlt"][L"Alt"].as_number().to_double()
|
||||
};
|
||||
setPosition(position);
|
||||
}
|
||||
if (json.has_number_field(L"Heading"))
|
||||
setHeading(json[L"Heading"].as_number().to_double());
|
||||
if (json.has_object_field(L"Flags"))
|
||||
setHuman(json[L"Flags"][L"Human"].as_bool());
|
||||
|
||||
/* All units which contain the name "Olympus" are automatically under AI control */
|
||||
if (getUnitName().find("Olympus") != string::npos)
|
||||
setControlled(true);
|
||||
|
||||
|
||||
oldPosition = position;
|
||||
}
|
||||
|
||||
@@ -175,7 +180,7 @@ void Unit::updateMissionData(json::value json)
|
||||
setHasTask(json[L"hasTask"].as_bool());
|
||||
}
|
||||
|
||||
unsigned int Unit::getUpdateData(char* &data)
|
||||
unsigned int Unit::getDataPacket(char* &data)
|
||||
{
|
||||
/* Reserve data for:
|
||||
1) DataPacket;
|
||||
@@ -217,34 +222,31 @@ unsigned int Unit::getUpdateData(char* &data)
|
||||
fuel,
|
||||
desiredSpeed,
|
||||
desiredAltitude,
|
||||
leaderID,
|
||||
targetID,
|
||||
targetPosition,
|
||||
state,
|
||||
ROE,
|
||||
reactionToThreat,
|
||||
emissionsCountermeasures,
|
||||
coalition,
|
||||
TACAN,
|
||||
radio,
|
||||
activePath.size(),
|
||||
ammo.size(),
|
||||
contacts.size(),
|
||||
name.size(),
|
||||
unitName.size(),
|
||||
groupName.size(),
|
||||
getCategory().size(),
|
||||
coalition.size()
|
||||
task.size()
|
||||
};
|
||||
|
||||
memcpy(data + offset, &dataPacket, sizeof(dataPacket));
|
||||
offset += sizeof(dataPacket);
|
||||
|
||||
/* Prepare the path vector and copy it to memory */
|
||||
std::vector<Coords> path;
|
||||
for (const Coords& c : activePath)
|
||||
path.push_back(c);
|
||||
memcpy(data + offset, &path, activePath.size() * sizeof(Coords));
|
||||
offset += activePath.size() * sizeof(Coords);
|
||||
|
||||
for (const Coords& c : activePath) {
|
||||
memcpy(data + offset, &c, sizeof(Coords));
|
||||
offset += sizeof(Coords);
|
||||
}
|
||||
|
||||
/* Copy the ammo vector to memory */
|
||||
memcpy(data + offset, &ammo, ammo.size() * sizeof(DataTypes::Ammo));
|
||||
offset += ammo.size() * sizeof(DataTypes::Ammo);
|
||||
@@ -256,10 +258,12 @@ unsigned int Unit::getUpdateData(char* &data)
|
||||
return offset;
|
||||
}
|
||||
|
||||
void Unit::getData(stringstream &ss, bool refresh)
|
||||
void Unit::getData(stringstream &ss, unsigned long long time, bool refresh)
|
||||
{
|
||||
if (time > lastUpdateTime && !refresh) return;
|
||||
|
||||
char* data;
|
||||
unsigned int size = getUpdateData(data);
|
||||
unsigned int size = getDataPacket(data);
|
||||
|
||||
/* Prepare the data packet and copy it to memory */
|
||||
/* If the unit is in a group, get the update data from the group leader and only replace the position, speed and heading */
|
||||
@@ -271,15 +275,25 @@ void Unit::getData(stringstream &ss, bool refresh)
|
||||
}
|
||||
|
||||
ss.write(data, size);
|
||||
delete data;
|
||||
ss << task;
|
||||
|
||||
if (refresh) {
|
||||
ss << name;
|
||||
ss << unitName;
|
||||
ss << groupName;
|
||||
ss << getCategory();
|
||||
ss << coalition;
|
||||
}
|
||||
unsigned short nameLength = name.length();
|
||||
unsigned short unitNameLength = unitName.length();
|
||||
unsigned short groupNameLength = groupName.length();
|
||||
unsigned short categoryLength = getCategory().length();
|
||||
|
||||
ss.write((char*)&nameLength, sizeof(nameLength));
|
||||
ss.write((char*)&unitNameLength, sizeof(unitNameLength));
|
||||
ss.write((char*)&groupNameLength, sizeof(groupNameLength));
|
||||
ss.write((char*)&categoryLength, sizeof(categoryLength));
|
||||
|
||||
ss << name;
|
||||
ss << unitName;
|
||||
ss << groupName;
|
||||
ss << getCategory();
|
||||
|
||||
|
||||
delete data;
|
||||
}
|
||||
|
||||
void Unit::setActivePath(list<Coords> newPath)
|
||||
@@ -315,26 +329,6 @@ void Unit::popActivePathFront()
|
||||
setActivePath(path);
|
||||
}
|
||||
|
||||
void Unit::setCoalitionID(unsigned int newCoalitionID)
|
||||
{
|
||||
if (newCoalitionID == 0)
|
||||
coalition = "neutral";
|
||||
else if (newCoalitionID == 1)
|
||||
coalition = "red";
|
||||
else
|
||||
coalition = "blue";
|
||||
}
|
||||
|
||||
unsigned int Unit::getCoalitionID()
|
||||
{
|
||||
if (coalition == "neutral")
|
||||
return 0;
|
||||
else if (coalition == "red")
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
string Unit::getTargetName()
|
||||
{
|
||||
if (isTargetAlive())
|
||||
@@ -398,6 +392,8 @@ void Unit::setFormationOffset(Offset newFormationOffset)
|
||||
{
|
||||
formationOffset = newFormationOffset;
|
||||
resetTask();
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
void Unit::setROE(unsigned char newROE, bool force)
|
||||
@@ -406,6 +402,8 @@ void Unit::setROE(unsigned char newROE, bool force)
|
||||
ROE = newROE;
|
||||
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ROE, static_cast<unsigned int>(ROE)));
|
||||
scheduler->appendCommand(command);
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,6 +414,8 @@ void Unit::setReactionToThreat(unsigned char newReactionToThreat, bool force)
|
||||
|
||||
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::REACTION_ON_THREAT, static_cast<unsigned int>(reactionToThreat)));
|
||||
scheduler->appendCommand(command);
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,6 +464,8 @@ void Unit::setEmissionsCountermeasures(unsigned char newEmissionsCountermeasures
|
||||
|
||||
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ECM_USING, ECMEnum));
|
||||
scheduler->appendCommand(command);
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,15 +478,23 @@ void Unit::landAt(Coords loc)
|
||||
|
||||
void Unit::setIsTanker(bool newIsTanker)
|
||||
{
|
||||
isTanker = newIsTanker;
|
||||
resetTask();
|
||||
if (isTanker != newIsTanker) {
|
||||
isTanker = newIsTanker;
|
||||
resetTask();
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setIsAWACS(bool newIsAWACS)
|
||||
{
|
||||
isAWACS = newIsAWACS;
|
||||
resetTask();
|
||||
setEPLRS(isAWACS);
|
||||
if (isAWACS != newIsAWACS) {
|
||||
isAWACS = newIsAWACS;
|
||||
resetTask();
|
||||
setEPLRS(isAWACS);
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setTACAN(Options::TACAN newTACAN, bool force)
|
||||
@@ -517,6 +527,8 @@ void Unit::setTACAN(Options::TACAN newTACAN, bool force)
|
||||
Command* command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,6 +563,8 @@ void Unit::setRadio(Options::Radio newRadio, bool force)
|
||||
<< "}";
|
||||
command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
|
||||
scheduler->appendCommand(command);
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,6 +604,8 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool
|
||||
scheduler->appendCommand(command);
|
||||
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ENGAGE_AIR_WEAPONS, !generalSettings.prohibitAirWpn));
|
||||
scheduler->appendCommand(command);
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,6 +616,8 @@ void Unit::setDesiredSpeed(double newDesiredSpeed)
|
||||
resetTask();
|
||||
else
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
void Unit::setDesiredAltitude(double newDesiredAltitude)
|
||||
@@ -609,6 +627,8 @@ void Unit::setDesiredAltitude(double newDesiredAltitude)
|
||||
resetTask();
|
||||
else
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
void Unit::setDesiredSpeedType(string newDesiredSpeedType)
|
||||
@@ -618,6 +638,8 @@ void Unit::setDesiredSpeedType(string newDesiredSpeedType)
|
||||
resetTask();
|
||||
else
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
|
||||
@@ -627,6 +649,8 @@ void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
|
||||
resetTask();
|
||||
else
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
void Unit::goToDestination(string enrouteTask)
|
||||
@@ -669,12 +693,16 @@ bool Unit::setActiveDestination()
|
||||
{
|
||||
activeDestination = activePath.front();
|
||||
log(unitName + " active destination set to queue front");
|
||||
|
||||
triggerUpdate();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeDestination = Coords(0);
|
||||
log(unitName + " active destination set to NULL");
|
||||
|
||||
triggerUpdate();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -695,11 +723,6 @@ bool Unit::updateActivePath(bool looping)
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::setTargetPosition(Coords newTargetPosition)
|
||||
{
|
||||
targetPosition = newTargetPosition;
|
||||
}
|
||||
|
||||
bool Unit::checkTaskFailed()
|
||||
{
|
||||
if (getHasTask())
|
||||
@@ -714,8 +737,3 @@ bool Unit::checkTaskFailed()
|
||||
void Unit::resetTaskFailedCounter() {
|
||||
taskCheckCounter = TASK_CHECK_INIT_VALUE;
|
||||
}
|
||||
|
||||
void Unit::setHasTask(bool newHasTask)
|
||||
{
|
||||
hasTask = newHasTask;
|
||||
}
|
||||
@@ -154,11 +154,10 @@ void UnitsManager::runAILoop() {
|
||||
unit.second->runAILoop();
|
||||
}
|
||||
|
||||
string UnitsManager::getUnitData(bool refresh)
|
||||
string UnitsManager::getUnitData(stringstream &ss, unsigned long long time, bool refresh)
|
||||
{
|
||||
stringstream ss;
|
||||
for (auto const& p : units)
|
||||
p.second->getData(ss, refresh);
|
||||
p.second->getData(ss, time, refresh);
|
||||
return to_base64(ss.str());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "framework.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct Coords {
|
||||
double lat = 0;
|
||||
double lng = 0;
|
||||
@@ -12,6 +13,7 @@ struct Offset {
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
|
||||
const DllExport std::string CurrentDateTime();
|
||||
|
||||
Reference in New Issue
Block a user