diff --git a/src/core/include/aircraft.h b/src/core/include/aircraft.h index 7fd3f615..87c48a5f 100644 --- a/src/core/include/aircraft.h +++ b/src/core/include/aircraft.h @@ -4,10 +4,10 @@ class Aircraft : public AirUnit { public: - Aircraft(json::value json, int ID); + Aircraft(json::value json, unsigned int ID); - virtual wstring getCategory() { return L"Aircraft"; }; + virtual string getCategory() { return "Aircraft"; }; - virtual void changeSpeed(wstring change); - virtual void changeAltitude(wstring change); + virtual void changeSpeed(string change); + virtual void changeAltitude(string change); }; \ No newline at end of file diff --git a/src/core/include/airunit.h b/src/core/include/airunit.h index cabd7b9e..7c72c88d 100644 --- a/src/core/include/airunit.h +++ b/src/core/include/airunit.h @@ -5,18 +5,18 @@ #include "luatools.h" #include "Unit.h" -#define AIR_DEST_DIST_THR 2000 +#define AIR_DEST_DIST_THR 2000 // Meters class AirUnit : public Unit { public: - AirUnit(json::value json, int ID); + AirUnit(json::value json, unsigned int ID); - virtual void setState(int newState); + virtual void setState(unsigned char newState); - virtual wstring getCategory() = 0; - virtual void changeSpeed(wstring change) = 0; - virtual void changeAltitude(wstring change) = 0; + virtual string getCategory() = 0; + virtual void changeSpeed(string change) = 0; + virtual void changeAltitude(string change) = 0; protected: virtual void AIloop(); diff --git a/src/core/include/commands.h b/src/core/include/commands.h index 1cd8aae4..091eac61 100644 --- a/src/core/include/commands.h +++ b/src/core/include/commands.h @@ -54,6 +54,15 @@ namespace ReactionToThreat { }; } +namespace EmissionCountermeasure { + enum ReactionsToThreat { + SILENT = 0, + ATTACK = 1, + DEFEND = 2, + FREE = 3 + }; +} + namespace RadarUse { enum RadarUses { NEVER = 0, @@ -85,19 +94,19 @@ namespace ECMUse { class Command { public: - int getPriority() { return priority; } - virtual wstring getString(lua_State* L) = 0; - virtual int getLoad() = 0; + unsigned int getPriority() { return priority; } + virtual string getString(lua_State* L) = 0; + virtual unsigned int getLoad() = 0; protected: - int priority = CommandPriority::LOW; + unsigned int priority = CommandPriority::LOW; }; /* Simple low priority move command (from user click) */ class Move : public Command { public: - Move(wstring groupName, Coords destination, double speed, wstring speedType, double altitude, wstring altitudeType, wstring taskOptions, wstring category): + Move(string groupName, Coords destination, double speed, string speedType, double altitude, string altitudeType, string taskOptions, string category): groupName(groupName), destination(destination), speed(speed), @@ -109,35 +118,35 @@ public: { priority = CommandPriority::HIGH; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 5; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 5; } private: - const wstring groupName; + const string groupName; const Coords destination; const double speed; - const wstring speedType; + const string speedType; const double altitude; - const wstring altitudeType; - const wstring taskOptions; - const wstring category; + const string altitudeType; + const string taskOptions; + const string category; }; /* Smoke command */ class Smoke : public Command { public: - Smoke(wstring color, Coords location) : + Smoke(string color, Coords location) : color(color), location(location) { priority = CommandPriority::LOW; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 5; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 5; } private: - const wstring color; + const string color; const Coords location; }; @@ -145,7 +154,7 @@ private: class SpawnGroundUnit : public Command { public: - SpawnGroundUnit(wstring coalition, wstring unitType, Coords location, bool immediate) : + SpawnGroundUnit(string coalition, string unitType, Coords location, bool immediate) : coalition(coalition), unitType(unitType), location(location), @@ -153,12 +162,12 @@ public: { priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 100 * !immediate; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 100 * !immediate; } private: - const wstring coalition; - const wstring unitType; + const string coalition; + const string unitType; const Coords location; const bool immediate; }; @@ -167,7 +176,7 @@ private: class SpawnAircraft : public Command { public: - SpawnAircraft(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName, bool immediate) : + SpawnAircraft(string coalition, string unitType, Coords location, string payloadName, string airbaseName, bool immediate) : coalition(coalition), unitType(unitType), location(location), @@ -177,15 +186,15 @@ public: { priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 100 * !immediate; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 100 * !immediate; } private: - const wstring coalition; - const wstring unitType; + const string coalition; + const string unitType; const Coords location; - const wstring payloadName; - const wstring airbaseName; + const string payloadName; + const string airbaseName; const bool immediate; }; @@ -193,17 +202,17 @@ private: class Clone : public Command { public: - Clone(int ID, Coords location) : + Clone(unsigned int ID, Coords location) : ID(ID), location(location) { priority = CommandPriority::LOW; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 100; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 100; } private: - const int ID; + const unsigned int ID; const Coords location; }; @@ -211,17 +220,17 @@ private: class Delete : public Command { public: - Delete(int ID, bool explosion) : + Delete(unsigned int ID, bool explosion) : ID(ID), explosion(explosion) { priority = CommandPriority::HIGH; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 20; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 20; } private: - const int ID; + const unsigned int ID; const bool explosion; }; @@ -229,59 +238,59 @@ private: class SetTask : public Command { public: - SetTask(wstring groupName, wstring task) : + SetTask(string groupName, string task) : groupName(groupName), task(task) { priority = CommandPriority::MEDIUM; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 2; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 2; } private: - const wstring groupName; - const wstring task; + const string groupName; + const string task; }; /* Reset task command */ class ResetTask : public Command { public: - ResetTask(wstring groupName) : + ResetTask(string groupName) : groupName(groupName) { priority = CommandPriority::HIGH; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 2; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 2; } private: - const wstring groupName; + const string groupName; }; /* Set command */ class SetCommand : public Command { public: - SetCommand(wstring groupName, wstring command) : + SetCommand(string groupName, string command) : groupName(groupName), command(command) { priority = CommandPriority::HIGH; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 2; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 2; } private: - const wstring groupName; - const wstring command; + const string groupName; + const string command; }; /* Set option command */ class SetOption : public Command { public: - SetOption(wstring groupName, int optionID, int optionValue) : + SetOption(string groupName, unsigned int optionID, unsigned int optionValue) : groupName(groupName), optionID(optionID), optionValue(optionValue), @@ -291,7 +300,7 @@ public: priority = CommandPriority::HIGH; }; - SetOption(wstring groupName, int optionID, bool optionBool) : + SetOption(string groupName, unsigned int optionID, bool optionBool) : groupName(groupName), optionID(optionID), optionValue(0), @@ -300,13 +309,13 @@ public: { priority = CommandPriority::HIGH; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 2; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 2; } private: - const wstring groupName; - const int optionID; - const int optionValue; + const string groupName; + const unsigned int optionID; + const unsigned int optionValue; const bool optionBool; const bool isBoolean; }; @@ -315,17 +324,17 @@ private: class SetOnOff : public Command { public: - SetOnOff(wstring groupName, bool onOff) : + SetOnOff(string groupName, bool onOff) : groupName(groupName), onOff(onOff) { priority = CommandPriority::HIGH; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 2; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 2; } private: - const wstring groupName; + const string groupName; const bool onOff; }; @@ -333,16 +342,16 @@ private: class Explosion : public Command { public: - Explosion(int intensity, Coords location) : + Explosion(unsigned int intensity, Coords location) : location(location), intensity(intensity) { priority = CommandPriority::MEDIUM; }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 10; } + virtual string getString(lua_State* L); + virtual unsigned int getLoad() { return 10; } private: const Coords location; - const int intensity; + const unsigned int intensity; }; diff --git a/src/core/include/groundunit.h b/src/core/include/groundunit.h index 6b5930b0..fcb8da22 100644 --- a/src/core/include/groundunit.h +++ b/src/core/include/groundunit.h @@ -6,12 +6,12 @@ class GroundUnit : public Unit { public: - GroundUnit(json::value json, int ID); - virtual wstring getCategory() { return L"GroundUnit"; }; + GroundUnit(json::value json, unsigned int ID); + virtual string getCategory() { return "GroundUnit"; }; - virtual void setState(int newState); + virtual void setState(unsigned char newState); - virtual void changeSpeed(wstring change); + virtual void changeSpeed(string change); virtual void setOnOff(bool newOnOff); virtual void setFollowRoads(bool newFollowRoads); diff --git a/src/core/include/helicopter.h b/src/core/include/helicopter.h index 097990b3..94f3d09b 100644 --- a/src/core/include/helicopter.h +++ b/src/core/include/helicopter.h @@ -4,10 +4,10 @@ class Helicopter : public AirUnit { public: - Helicopter(json::value json, int ID); + Helicopter(json::value json, unsigned int ID); - virtual wstring getCategory() { return L"Helicopter"; }; + virtual string getCategory() { return "Helicopter"; }; - virtual void changeSpeed(wstring change); - virtual void changeAltitude(wstring change); + virtual void changeSpeed(string change); + virtual void changeAltitude(string change); }; \ No newline at end of file diff --git a/src/core/include/navyunit.h b/src/core/include/navyunit.h index a27b5a31..d1c6e31e 100644 --- a/src/core/include/navyunit.h +++ b/src/core/include/navyunit.h @@ -4,10 +4,10 @@ class NavyUnit : public Unit { public: - NavyUnit(json::value json, int ID); + NavyUnit(json::value json, unsigned int ID); virtual void AIloop(); - virtual wstring getCategory() { return L"NavyUnit"; }; - virtual void changeSpeed(wstring change); + virtual string getCategory() { return "NavyUnit"; }; + virtual void changeSpeed(string change); }; \ No newline at end of file diff --git a/src/core/include/scheduler.h b/src/core/include/scheduler.h index d5ebfcf6..0b931e1c 100644 --- a/src/core/include/scheduler.h +++ b/src/core/include/scheduler.h @@ -11,10 +11,10 @@ public: void appendCommand(Command* command); void execute(lua_State* L); - void handleRequest(wstring key, json::value value); + void handleRequest(string key, json::value value); private: list commands; - int load; + unsigned int load; }; diff --git a/src/core/include/server.h b/src/core/include/server.h index cb735442..6880f7b4 100644 --- a/src/core/include/server.h +++ b/src/core/include/server.h @@ -15,8 +15,6 @@ public: void start(lua_State* L); void stop(lua_State* L); - json::value& getUpdateJson() { return updateJson; } - json::value& getRefreshJson() { return refreshJson; } private: std::thread* serverThread; @@ -29,9 +27,7 @@ private: void task(); atomic runListener; - json::value updateJson; - json::value refreshJson; - wstring password = L""; + string password = ""; }; diff --git a/src/core/include/unit.h b/src/core/include/unit.h index 196e89b1..2fc60171 100644 --- a/src/core/include/unit.h +++ b/src/core/include/unit.h @@ -5,6 +5,7 @@ #include "luatools.h" #include "measure.h" #include "logger.h" +#include "commands.h" #define TASK_CHECK_INIT_VALUE 10 @@ -32,16 +33,16 @@ namespace Options { struct TACAN { bool isOn = false; - int channel = 40; - wstring XY = L"X"; - wstring callsign = L"TKR"; + unsigned char channel = 40; + char XY = 'X'; + char callsign[4]; }; struct Radio { - int frequency = 124000000; // MHz - int callsign = 1; - int callsignNumber = 1; + unsigned int frequency = 124000000; // MHz + unsigned char callsign = 1; + unsigned char callsignNumber = 1; }; struct GeneralSettings @@ -54,116 +55,145 @@ namespace Options { }; } +namespace DataTypes { + struct Ammo { + unsigned short quantity = 0; + string name; + unsigned char guidance = 0; + unsigned char category = 0; + unsigned char missileCategory = 0; + }; + + struct Contact { + unsigned int ID = 0; + unsigned char detectionMethod = 0; + }; + + struct DataPacket { + unsigned int ID; + unsigned int bitmask; + Coords position; + double speed; + double heading; + unsigned short fuel; + double desiredSpeed; + double desiredAltitude; + unsigned int targetID; + Coords targetPosition; + unsigned char state; + unsigned char ROE; + unsigned char reactionToThreat; + unsigned char emissionsCountermeasures; + Options::TACAN TACAN; + Options::Radio Radio; + }; +} + class Unit { public: - Unit(json::value json, int ID); + Unit(json::value json, unsigned int ID); ~Unit(); /********** Public methods **********/ void initialize(json::value json); void setDefaults(bool force = false); - int getID() { return ID; } + unsigned int getID() { return ID; } void runAILoop(); void updateExportData(json::value json, double dt = 0); void updateMissionData(json::value json); - json::value getData(long long time, bool getAll = false); - virtual wstring getCategory() { return L"No category"; }; + DataTypes::DataPacket getDataPacket(); + string getData(bool refresh); + virtual string getCategory() { return "No category"; }; /********** Base data **********/ - void setControlled(bool newControlled) { controlled = newControlled; addMeasure(L"controlled", json::value(newControlled)); } - void setName(wstring newName) { name = newName; addMeasure(L"name", json::value(newName));} - void setUnitName(wstring newUnitName) { unitName = newUnitName; addMeasure(L"unitName", json::value(newUnitName));} - void setGroupName(wstring newGroupName) { groupName = newGroupName; addMeasure(L"groupName", json::value(newGroupName));} - void setAlive(bool newAlive) { alive = newAlive; addMeasure(L"alive", json::value(newAlive));} - void setType(json::value newType) { type = newType; addMeasure(L"type", newType);} - void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));} + 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; } bool getControlled() { return controlled; } - wstring getName() { return name; } - wstring getUnitName() { return unitName; } - wstring getGroupName() { return groupName; } + string getName() { return name; } + string getUnitName() { return unitName; } + string getGroupName() { return groupName; } bool getAlive() { return alive; } - json::value getType() { return type; } - int getCountry() { return country; } + unsigned int getCountry() { return country; } + bool getHuman() { return human; } /********** Flight data **********/ - void setLatitude(double newLatitude) {latitude = newLatitude; addMeasure(L"latitude", json::value(newLatitude));} - void setLongitude(double newLongitude) {longitude = newLongitude; addMeasure(L"longitude", json::value(newLongitude));} - void setAltitude(double newAltitude) {altitude = newAltitude; addMeasure(L"altitude", json::value(newAltitude));} - void setHeading(double newHeading) {heading = newHeading; addMeasure(L"heading", json::value(newHeading));} - void setSpeed(double newSpeed) {speed = newSpeed; addMeasure(L"speed", json::value(newSpeed));} + void setPosition(Coords newPosition) { position = newPosition; } + void setHeading(double newHeading) {heading = newHeading; } + void setSpeed(double newSpeed) {speed = newSpeed; } - double getLatitude() { return latitude; } - double getLongitude() { return longitude; } - double getAltitude() { return altitude; } + Coords getPosition() { return position; } double getHeading() { return heading; } double getSpeed() { return speed; } /********** Mission data **********/ - void setFuel(double newFuel) { fuel = newFuel; addMeasure(L"fuel", json::value(newFuel));} - void setAmmo(json::value newAmmo) { ammo = newAmmo; addMeasure(L"ammo", json::value(newAmmo));} - void setContacts(json::value newContacts) {contacts = newContacts; addMeasure(L"contacts", json::value(newContacts));} + void setFuel(short newFuel) { fuel = newFuel; } + void setAmmo(vector newAmmo) { ammo = newAmmo; } + void setContacts(vector newContacts) {contacts = newContacts; } void setHasTask(bool newHasTask); - void setCoalitionID(int newCoalitionID); - void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));} + void setCoalitionID(unsigned int newCoalitionID); double getFuel() { return fuel; } - json::value getAmmo() { return ammo; } - json::value getTargets() { return contacts; } + vector getAmmo() { return ammo; } + vector getTargets() { return contacts; } bool getHasTask() { return hasTask; } - wstring getCoalition() { return coalition; } - int getCoalitionID(); - json::value getFlags() { return flags; } + string getCoalition() { return coalition; } + unsigned int getCoalitionID(); /********** Formation data **********/ - void setLeaderID(int newLeaderID) { leaderID = newLeaderID; addMeasure(L"leaderID", json::value(newLeaderID)); } + void setLeaderID(unsigned int newLeaderID) { leaderID = newLeaderID; } void setFormationOffset(Offset formationOffset); - int getLeaderID() { return leaderID; } + unsigned int getLeaderID() { return leaderID; } Offset getFormationoffset() { return formationOffset; } /********** Task data **********/ - void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask; addMeasure(L"currentTask", json::value(newCurrentTask)); } + void setCurrentTask(string newCurrentTask) { currentTask = newCurrentTask; } void setDesiredSpeed(double newDesiredSpeed); void setDesiredAltitude(double newDesiredAltitude); - void setDesiredSpeedType(wstring newDesiredSpeedType); - void setDesiredAltitudeType(wstring newDesiredAltitudeType); - void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix + void setDesiredSpeedType(string newDesiredSpeedType); + void setDesiredAltitudeType(string newDesiredAltitudeType); + void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; } void setActivePath(list newActivePath); - void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));} - void setTargetLocation(Coords newTargetLocation); + 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; addMeasure(L"onOff", json::value(newOnOff));}; - virtual void setFollowRoads(bool newFollowRoads) { followRoads = newFollowRoads; addMeasure(L"followRoads", json::value(newFollowRoads)); }; + virtual void setOnOff(bool newOnOff) { onOff = newOnOff; }; + virtual void setFollowRoads(bool newFollowRoads) { followRoads = newFollowRoads; }; - wstring getCurrentTask() { return currentTask; } + string getCurrentTask() { return currentTask; } virtual double getDesiredSpeed() { return desiredSpeed; }; virtual double getDesiredAltitude() { return desiredAltitude; }; - virtual wstring getDesiredSpeedType() { return desiredSpeedType; }; - virtual wstring getDesiredAltitudeType() { return desiredAltitudeType; }; + virtual bool getDesiredSpeedType() { return desiredSpeedType; }; + virtual bool getDesiredAltitudeType() { return desiredAltitudeType; }; Coords getActiveDestination() { return activeDestination; } list getActivePath() { return activePath; } - int getTargetID() { return targetID; } - Coords getTargetLocation() { return targetLocation; } + unsigned int getTargetID() { return targetID; } + Coords getTargetPosition() { return targetPosition; } bool getIsTanker() { return isTanker; } bool getIsAWACS() { return isAWACS; } bool getOnOff() { return onOff; }; bool getFollowRoads() { return followRoads; }; /********** Options data **********/ - void setROE(wstring newROE, bool force = false); - void setReactionToThreat(wstring newReactionToThreat, bool force = false); - void setEmissionsCountermeasures(wstring newEmissionsCountermeasures, bool force = false); + 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); - wstring getROE() { return ROE; } - wstring getReactionToThreat() { return reactionToThreat; } - wstring getEmissionsCountermeasures() { return emissionsCountermeasures; }; + unsigned char getROE() { return ROE; } + unsigned char getReactionToThreat() { return reactionToThreat; } + unsigned char getEmissionsCountermeasures() { return emissionsCountermeasures; }; Options::TACAN getTACAN() { return TACAN; } Options::Radio getRadio() { return radio; } Options::GeneralSettings getGeneralSettings() { return generalSettings; } @@ -171,10 +201,10 @@ public: /********** Control functions **********/ void landAt(Coords loc); - virtual void changeSpeed(wstring change) {}; - virtual void changeAltitude(wstring change) {}; + virtual void changeSpeed(string change) {}; + virtual void changeAltitude(string change) {}; void resetActiveDestination(); - virtual void setState(int newState) { state = newState; }; + virtual void setState(unsigned char newState) { state = newState; }; void resetTask(); void clearActivePath(); void pushActivePathFront(Coords newActivePathFront); @@ -182,81 +212,77 @@ public: void popActivePathFront(); protected: - int ID; + unsigned int ID; - map measures; - int taskCheckCounter = 0; + map measures; + unsigned int taskCheckCounter = 0; /********** Base data **********/ bool controlled = false; - wstring name = L"undefined"; - wstring unitName = L"undefined"; - wstring groupName = L"undefined"; + string name = "undefined"; + string unitName = "undefined"; + string groupName = "undefined"; bool alive = true; - json::value type = json::value::null(); - int country = NULL; + bool human = false; + unsigned int country = NULL; /********** Flight data **********/ - double latitude = NULL; - double longitude = NULL; - double altitude = NULL; + Coords position = Coords(NULL); double speed = NULL; double heading = NULL; /********** Mission data **********/ - double fuel = 0; + unsigned short fuel = 0; double initialFuel = 0; // Used internally to detect refueling completed - json::value ammo = json::value::null(); - json::value contacts = json::value::null(); + vector ammo; + vector contacts; bool hasTask = false; - wstring coalition = L""; - json::value flags = json::value::null(); + string coalition = ""; /********** Formation data **********/ - int leaderID = NULL; + unsigned int leaderID = NULL; Offset formationOffset = Offset(NULL); /********** Task data **********/ - wstring currentTask = L""; + string currentTask = ""; double desiredSpeed = 0; double desiredAltitude = 0; - wstring desiredSpeedType = L"GS"; - wstring desiredAltitudeType = L"AGL"; + bool desiredSpeedType = 0; + bool desiredAltitudeType = 0; list activePath; Coords activeDestination = Coords(NULL); - int targetID = NULL; - Coords targetLocation = Coords(NULL); + unsigned int targetID = NULL; + Coords targetPosition = Coords(NULL); bool isTanker = false; bool isAWACS = false; bool onOff = true; bool followRoads = false; /********** Options data **********/ - wstring ROE = L"Designated"; - wstring reactionToThreat = L"Evade"; - wstring emissionsCountermeasures = L"Defend"; + unsigned char ROE = ROE::OPEN_FIRE_WEAPON_FREE; + unsigned char reactionToThreat = ReactionToThreat::EVADE_FIRE; + unsigned char emissionsCountermeasures = EmissionCountermeasure::DEFEND; Options::TACAN TACAN; Options::Radio radio; Options::GeneralSettings generalSettings; bool EPLRS = false; /********** State machine **********/ - int state = State::NONE; + unsigned char state = State::NONE; /********** Other **********/ Coords oldPosition = Coords(0); // Used to approximate speed /********** Functions **********/ - wstring getTargetName(); - wstring getLeaderName(); + string getTargetName(); + string getLeaderName(); bool isTargetAlive(); bool isLeaderAlive(); virtual void AIloop() = 0; - void addMeasure(wstring key, json::value value); bool isDestinationReached(double threshold); bool setActiveDestination(); bool updateActivePath(bool looping); - void goToDestination(wstring enrouteTask = L"nil"); + void goToDestination(string enrouteTask = "nil"); bool checkTaskFailed(); void resetTaskFailedCounter(); }; diff --git a/src/core/include/unitsmanager.h b/src/core/include/unitsmanager.h index 0a0e138b..b2233183 100644 --- a/src/core/include/unitsmanager.h +++ b/src/core/include/unitsmanager.h @@ -10,23 +10,22 @@ public: UnitsManager(lua_State* L); ~UnitsManager(); - map& getUnits() { return units; }; - Unit* getUnit(int ID); + map& getUnits() { return units; }; + Unit* getUnit(unsigned int ID); bool isUnitInGroup(Unit* unit); bool isUnitGroupLeader(Unit* unit); - Unit* getGroupLeader(int ID); + Unit* getGroupLeader(unsigned int ID); Unit* getGroupLeader(Unit* unit); - vector getGroupMembers(wstring groupName); + vector getGroupMembers(string groupName); void updateExportData(lua_State* L, double dt = 0); void updateMissionData(json::value missionData); void runAILoop(); - void getUnitData(json::value& answer, long long time); - void appendUnitData(int ID, json::value& answer, long long time); - void deleteUnit(int ID, bool explosion); - void acquireControl(int ID); + string getUnitData(bool refresh); + void deleteUnit(unsigned int ID, bool explosion); + void acquireControl(unsigned int ID); private: - map units; + map units; json::value missionDB; }; diff --git a/src/core/include/weapon.h b/src/core/include/weapon.h index a1097bcb..1597ffec 100644 --- a/src/core/include/weapon.h +++ b/src/core/include/weapon.h @@ -4,9 +4,9 @@ class Weapon : public Unit { public: - Weapon(json::value json, int ID); + Weapon(json::value json, unsigned int ID); - virtual wstring getCategory() = 0; + virtual string getCategory() = 0; protected: /* Weapons are not controllable and have no AIloop */ @@ -16,15 +16,15 @@ protected: class Missile : public Weapon { public: - Missile(json::value json, int ID); + Missile(json::value json, unsigned int ID); - virtual wstring getCategory() { return L"Missile"; }; + virtual string getCategory() { return "Missile"; }; }; class Bomb : public Weapon { public: - Bomb(json::value json, int ID); + Bomb(json::value json, unsigned int ID); - virtual wstring getCategory() { return L"Bomb"; }; + virtual string getCategory() { return "Bomb"; }; }; \ No newline at end of file diff --git a/src/core/src/aircraft.cpp b/src/core/src/aircraft.cpp index 1284f903..c1cca92e 100644 --- a/src/core/src/aircraft.cpp +++ b/src/core/src/aircraft.cpp @@ -13,10 +13,9 @@ extern Scheduler* scheduler; extern UnitsManager* unitsManager; /* Aircraft */ -Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID) +Aircraft::Aircraft(json::value json, unsigned int ID) : AirUnit(json, ID) { log("New Aircraft created with ID: " + to_string(ID)); - addMeasure(L"category", json::value(getCategory())); double desiredSpeed = knotsToMs(300); double desiredAltitude = ftToM(20000); @@ -24,13 +23,13 @@ Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID) setDesiredAltitude(desiredAltitude); }; -void Aircraft::changeSpeed(wstring change) +void Aircraft::changeSpeed(string change) { - if (change.compare(L"stop") == 0) + if (change.compare("stop") == 0) setState(State::IDLE); - else if (change.compare(L"slow") == 0) + else if (change.compare("slow") == 0) setDesiredSpeed(getDesiredSpeed() - knotsToMs(25)); - else if (change.compare(L"fast") == 0) + else if (change.compare("fast") == 0) setDesiredSpeed(getDesiredSpeed() + knotsToMs(25)); if (getDesiredSpeed() < knotsToMs(50)) @@ -42,16 +41,16 @@ void Aircraft::changeSpeed(wstring change) goToDestination(); /* Send the command to reach the destination */ } -void Aircraft::changeAltitude(wstring change) +void Aircraft::changeAltitude(string change) { - if (change.compare(L"descend") == 0) + if (change.compare("descend") == 0) { if (getDesiredAltitude() > 5000) setDesiredAltitude(getDesiredAltitude() - ftToM(2500)); else if (getDesiredAltitude() > 0) setDesiredAltitude(getDesiredAltitude() - ftToM(500)); } - else if (change.compare(L"climb") == 0) + else if (change.compare("climb") == 0) { if (getDesiredAltitude() > 5000) setDesiredAltitude(getDesiredAltitude() + ftToM(2500)); diff --git a/src/core/src/airunit.cpp b/src/core/src/airunit.cpp index 06c0808a..375a996d 100644 --- a/src/core/src/airunit.cpp +++ b/src/core/src/airunit.cpp @@ -13,12 +13,12 @@ extern Scheduler* scheduler; extern UnitsManager* unitsManager; /* Air unit */ -AirUnit::AirUnit(json::value json, int ID) : Unit(json, ID) +AirUnit::AirUnit(json::value json, unsigned int ID) : Unit(json, ID) { }; -void AirUnit::setState(int newState) +void AirUnit::setState(unsigned char newState) { /************ Perform any action required when LEAVING a state ************/ if (newState != state) { @@ -46,7 +46,7 @@ void AirUnit::setState(int newState) case State::BOMB_POINT: case State::CARPET_BOMB: case State::BOMB_BUILDING: { - setTargetLocation(Coords(NULL)); + setTargetPosition(Coords(NULL)); break; } default: @@ -59,12 +59,10 @@ void AirUnit::setState(int newState) case State::IDLE: { clearActivePath(); resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Idle")); break; } case State::REACH_DESTINATION: { resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Reach destination")); break; } case State::ATTACK: { @@ -74,42 +72,35 @@ void AirUnit::setState(int newState) clearActivePath(); pushActivePathFront(targetPosition); resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Attack")); } break; } case State::FOLLOW: { clearActivePath(); resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Follow")); break; } case State::LAND: { resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Land")); break; } case State::REFUEL: { initialFuel = fuel; clearActivePath(); resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Refuel")); break; } case State::BOMB_POINT: { - addMeasure(L"currentState", json::value(L"Bombing point")); clearActivePath(); resetActiveDestination(); break; } case State::CARPET_BOMB: { - addMeasure(L"currentState", json::value(L"Carpet bombing")); clearActivePath(); resetActiveDestination(); break; } case State::BOMB_BUILDING: { - addMeasure(L"currentState", json::value(L"Bombing building")); clearActivePath(); resetActiveDestination(); break; @@ -120,7 +111,7 @@ void AirUnit::setState(int newState) resetTask(); - log(unitName + L" setting state from " + to_wstring(state) + L" to " + to_wstring(newState)); + log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState)); state = newState; } @@ -129,11 +120,11 @@ void AirUnit::AIloop() /* State machine */ switch (state) { case State::IDLE: { - currentTask = L"Idle"; + currentTask = "Idle"; if (!getHasTask()) { - std::wostringstream taskSS; + std::ostringstream taskSS; if (isTanker) { taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' } }"; } @@ -150,23 +141,23 @@ void AirUnit::AIloop() break; } case State::REACH_DESTINATION: { - wstring enrouteTask = L""; + string enrouteTask = ""; bool looping = false; if (isTanker) { - enrouteTask = L"{ id = 'Tanker' }"; - currentTask = L"Tanker"; + enrouteTask = "{ id = 'Tanker' }"; + currentTask = "Tanker"; } else if (isAWACS) { - enrouteTask = L"{ id = 'AWACS' }"; - currentTask = L"AWACS"; + enrouteTask = "{ id = 'AWACS' }"; + currentTask = "AWACS"; } else { - enrouteTask = L"nil"; - currentTask = L"Reaching destination"; + enrouteTask = "nil"; + currentTask = "Reaching destination"; } if (activeDestination == NULL || !getHasTask()) @@ -187,8 +178,8 @@ void AirUnit::AIloop() break; } case State::LAND: { - wstring enrouteTask = L"{ id = 'Land' }"; - currentTask = L"Landing"; + string enrouteTask = "{ id = 'Land' }"; + currentTask = "Landing"; if (activeDestination == NULL) { @@ -206,13 +197,13 @@ void AirUnit::AIloop() /* Attack state is an "enroute" task, meaning the unit will keep trying to attack even if a new destination is set. This is useful to manoeuvre the unit so that it can detect and engage the target. */ - std::wostringstream enrouteTaskSS; + std::ostringstream enrouteTaskSS; enrouteTaskSS << "{" << "id = 'EngageUnit'" << "," << "targetID = " << targetID << "," << "}"; - wstring enrouteTask = enrouteTaskSS.str(); - currentTask = L"Attacking " + getTargetName(); + string enrouteTask = enrouteTaskSS.str(); + currentTask = "Attacking " + getTargetName(); if (!getHasTask()) { @@ -232,13 +223,13 @@ void AirUnit::AIloop() break; } - currentTask = L"Following " + getTargetName(); + currentTask = "Following " + getTargetName(); Unit* leader = unitsManager->getUnit(leaderID); if (!getHasTask()) { if (leader != nullptr && leader->getAlive() && formationOffset != NULL) { - std::wostringstream taskSS; + std::ostringstream taskSS; taskSS << "{" << "id = 'FollowUnit'" << ", " << "leaderID = " << leader->getID() << "," @@ -256,11 +247,11 @@ void AirUnit::AIloop() break; } case State::REFUEL: { - currentTask = L"Refueling"; + currentTask = "Refueling"; if (!getHasTask()) { if (fuel <= initialFuel) { - std::wostringstream taskSS; + std::ostringstream taskSS; taskSS << "{" << "id = 'Refuel'" << "}"; @@ -274,22 +265,22 @@ void AirUnit::AIloop() } } case State::BOMB_POINT: { - currentTask = L"Bombing point"; + currentTask = "Bombing point"; if (!getHasTask()) { - std::wostringstream taskSS; - taskSS << "{id = 'Bombing', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << "}"; + std::ostringstream taskSS; + taskSS << "{id = 'Bombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}"; Command* command = dynamic_cast(new SetTask(groupName, taskSS.str())); scheduler->appendCommand(command); setHasTask(true); } } case State::CARPET_BOMB: { - currentTask = L"Carpet bombing"; + currentTask = "Carpet bombing"; if (!getHasTask()) { - std::wostringstream taskSS; - taskSS << "{id = 'CarpetBombing', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << "}"; + std::ostringstream taskSS; + taskSS << "{id = 'CarpetBombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}"; Command* command = dynamic_cast(new SetTask(groupName, taskSS.str())); scheduler->appendCommand(command); setHasTask(true); @@ -297,11 +288,11 @@ void AirUnit::AIloop() break; } case State::BOMB_BUILDING: { - currentTask = L"Bombing building"; + currentTask = "Bombing building"; if (!getHasTask()) { - std::wostringstream taskSS; - taskSS << "{id = 'AttackMapObject', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << "}"; + std::ostringstream taskSS; + taskSS << "{id = 'AttackMapObject', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}"; Command* command = dynamic_cast(new SetTask(groupName, taskSS.str())); scheduler->appendCommand(command); setHasTask(true); @@ -311,6 +302,4 @@ void AirUnit::AIloop() default: break; } - - addMeasure(L"currentTask", json::value(currentTask)); } \ No newline at end of file diff --git a/src/core/src/commands.cpp b/src/core/src/commands.cpp index 87f33218..fbd6da60 100644 --- a/src/core/src/commands.cpp +++ b/src/core/src/commands.cpp @@ -7,10 +7,10 @@ extern UnitsManager* unitsManager; /* Move command */ -wstring Move::getString(lua_State* L) +string Move::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.move, " << "\"" << groupName << "\"" << ", " @@ -26,9 +26,9 @@ wstring Move::getString(lua_State* L) } /* Smoke command */ -wstring Smoke::getString(lua_State* L) +string Smoke::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.smoke, " << "\"" << color << "\"" << ", " @@ -38,9 +38,9 @@ wstring Smoke::getString(lua_State* L) } /* Spawn ground command */ -wstring SpawnGroundUnit::getString(lua_State* L) +string SpawnGroundUnit::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.spawnGroundUnit, " << "\"" << coalition << "\"" << ", " @@ -51,16 +51,16 @@ wstring SpawnGroundUnit::getString(lua_State* L) } /* Spawn air command */ -wstring SpawnAircraft::getString(lua_State* L) +string SpawnAircraft::getString(lua_State* L) { - std::wostringstream optionsSS; + std::ostringstream optionsSS; optionsSS.precision(10); optionsSS << "{" << "payloadName = \"" << payloadName << "\", " << "airbaseName = \"" << airbaseName << "\", " << "}"; - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.spawnAircraft, " << "\"" << coalition << "\"" << ", " @@ -73,12 +73,12 @@ wstring SpawnAircraft::getString(lua_State* L) } /* Clone unit command */ -wstring Clone::getString(lua_State* L) +string Clone::getString(lua_State* L) { Unit* unit = unitsManager->getUnit(ID); if (unit != nullptr) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.clone, " << ID << ", " @@ -89,14 +89,14 @@ wstring Clone::getString(lua_State* L) } else { - return L""; + return ""; } } /* Delete unit command */ -wstring Delete::getString(lua_State* L) +string Delete::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.delete, " << ID << ", " @@ -105,9 +105,9 @@ wstring Delete::getString(lua_State* L) } /* Set task command */ -wstring SetTask::getString(lua_State* L) +string SetTask::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.setTask, " << "\"" << groupName << "\"" << ", " @@ -117,9 +117,9 @@ wstring SetTask::getString(lua_State* L) } /* Reset task command */ -wstring ResetTask::getString(lua_State* L) +string ResetTask::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.resetTask, " << "\"" << groupName << "\""; @@ -128,9 +128,9 @@ wstring ResetTask::getString(lua_State* L) } /* Set command command */ -wstring SetCommand::getString(lua_State* L) +string SetCommand::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.setCommand, " << "\"" << groupName << "\"" << ", " @@ -140,9 +140,9 @@ wstring SetCommand::getString(lua_State* L) } /* Set option command */ -wstring SetOption::getString(lua_State* L) +string SetOption::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); if (!isBoolean) { @@ -160,9 +160,9 @@ wstring SetOption::getString(lua_State* L) } /* Set onOff command */ -wstring SetOnOff::getString(lua_State* L) +string SetOnOff::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.setOnOff, " @@ -173,9 +173,9 @@ wstring SetOnOff::getString(lua_State* L) } /* Explosion command */ -wstring Explosion::getString(lua_State* L) +string Explosion::getString(lua_State* L) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS.precision(10); commandSS << "Olympus.explosion, " << intensity << ", " diff --git a/src/core/src/core.cpp b/src/core/src/core.cpp index aab6d0ac..7a17691b 100644 --- a/src/core/src/core.cpp +++ b/src/core/src/core.cpp @@ -10,19 +10,24 @@ using namespace std::chrono; auto before = std::chrono::system_clock::now(); + +/* Singleton objects */ UnitsManager* unitsManager = nullptr; Server* server = nullptr; Scheduler* scheduler = nullptr; + +/* Data jsons */ json::value airbases; json::value bullseyes; json::value mission; + mutex mutexLock; -bool initialized = false; string sessionHash; -int lastUpdateIndex = 0; -int frameCounter = 0; + +bool initialized = false; + +unsigned int frameCounter = 0; double frameRate = 30; -long long lastUpdateTime = 0; /* Called when DCS simulation stops. All singleton instances are deleted. */ extern "C" DllExport int coreDeinit(lua_State* L) @@ -64,48 +69,29 @@ extern "C" DllExport int coreFrame(lua_State* L) if (!initialized) return (0); - /* Lock for thread safety */ - lock_guard guard(mutexLock); - frameCounter++; + /* Slow down the update rate if the frameRate is very low since it means DCS is struggling to keep up */ const std::chrono::duration duration = std::chrono::system_clock::now() - before; - - if (unitsManager != nullptr) { - // TODO put in a function - vector IDs; - for (auto iter = unitsManager->getUnits().begin(); iter != unitsManager->getUnits().end(); ++iter) - IDs.push_back(iter->first); - - int updateChunk = 20; - int finalUpdateIndex = lastUpdateIndex + updateChunk; - - /* Get all the new data (with some margin) */ - while (lastUpdateIndex < unitsManager->getUnits().size() && lastUpdateIndex <= finalUpdateIndex) - unitsManager->appendUnitData(IDs[lastUpdateIndex++], server->getUpdateJson(), lastUpdateTime - 1000); - } - - if (duration.count() > UPDATE_TIME_INTERVAL && lastUpdateIndex == unitsManager->getUnits().size()) + if (duration.count() > UPDATE_TIME_INTERVAL * (60.0 / frameRate)) { + /* Lock for thread safety */ + lock_guard guard(mutexLock); + milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); - lastUpdateTime = ms.count(); frameRate = frameCounter / duration.count(); frameCounter = 0; - if (unitsManager != nullptr) + if (unitsManager != nullptr) { unitsManager->updateExportData(L, duration.count()); + unitsManager->runAILoop(); + } before = std::chrono::system_clock::now(); - - /* Restart the update counter */ - lastUpdateIndex = 0; } if (scheduler != nullptr) scheduler->execute(L); - if (duration.count() > UPDATE_TIME_INTERVAL && unitsManager != nullptr) - unitsManager->runAILoop(); - return(0); } diff --git a/src/core/src/groundunit.cpp b/src/core/src/groundunit.cpp index 58b8fd50..f28e8a18 100644 --- a/src/core/src/groundunit.cpp +++ b/src/core/src/groundunit.cpp @@ -13,16 +13,15 @@ extern Scheduler* scheduler; extern UnitsManager* unitsManager; /* Ground unit */ -GroundUnit::GroundUnit(json::value json, int ID) : Unit(json, ID) +GroundUnit::GroundUnit(json::value json, unsigned int ID) : Unit(json, ID) { log("New Ground Unit created with ID: " + to_string(ID)); - addMeasure(L"category", json::value(getCategory())); double desiredSpeed = 10; setDesiredSpeed(desiredSpeed); }; -void GroundUnit::setState(int newState) +void GroundUnit::setState(unsigned char newState) { /************ Perform any action required when LEAVING a state ************/ if (newState != state) { @@ -34,7 +33,7 @@ void GroundUnit::setState(int newState) break; } case State::FIRE_AT_AREA: { - setTargetLocation(Coords(NULL)); + setTargetPosition(Coords(NULL)); break; } default: @@ -47,16 +46,13 @@ void GroundUnit::setState(int newState) case State::IDLE: { clearActivePath(); resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Idle")); break; } case State::REACH_DESTINATION: { resetActiveDestination(); - addMeasure(L"currentState", json::value(L"Reach destination")); break; } case State::FIRE_AT_AREA: { - addMeasure(L"currentState", json::value(L"Firing at area")); clearActivePath(); resetActiveDestination(); break; @@ -67,7 +63,7 @@ void GroundUnit::setState(int newState) resetTask(); - log(unitName + L" setting state from " + to_wstring(state) + L" to " + to_wstring(newState)); + log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState)); state = newState; } @@ -75,16 +71,16 @@ void GroundUnit::AIloop() { switch (state) { case State::IDLE: { - currentTask = L"Idle"; + currentTask = "Idle"; if (getHasTask()) resetTask(); break; } case State::REACH_DESTINATION: { - wstring enrouteTask = L""; + string enrouteTask = ""; bool looping = false; - std::wostringstream taskSS; + std::ostringstream taskSS; taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads() ? "true" : "false") << " }"; enrouteTask = taskSS.str(); @@ -106,11 +102,11 @@ void GroundUnit::AIloop() break; } case State::FIRE_AT_AREA: { - currentTask = L"Firing at area"; + currentTask = "Firing at area"; if (!getHasTask()) { - std::wostringstream taskSS; - taskSS << "{id = 'FireAtPoint', lat = " << targetLocation.lat << ", lng = " << targetLocation.lng << ", radius = 1000}"; + std::ostringstream taskSS; + taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1000}"; Command* command = dynamic_cast(new SetTask(groupName, taskSS.str())); scheduler->appendCommand(command); setHasTask(true); @@ -119,17 +115,15 @@ void GroundUnit::AIloop() default: break; } - - addMeasure(L"currentTask", json::value(currentTask)); } -void GroundUnit::changeSpeed(wstring change) +void GroundUnit::changeSpeed(string change) { - if (change.compare(L"stop") == 0) + if (change.compare("stop") == 0) setState(State::IDLE); - else if (change.compare(L"slow") == 0) + else if (change.compare("slow") == 0) setDesiredSpeed(getDesiredSpeed() - knotsToMs(5)); - else if (change.compare(L"fast") == 0) + else if (change.compare("fast") == 0) setDesiredSpeed(getDesiredSpeed() + knotsToMs(5)); if (getDesiredSpeed() < 0) diff --git a/src/core/src/helicopter.cpp b/src/core/src/helicopter.cpp index d728f4c5..5215a484 100644 --- a/src/core/src/helicopter.cpp +++ b/src/core/src/helicopter.cpp @@ -13,10 +13,9 @@ extern Scheduler* scheduler; extern UnitsManager* unitsManager; /* Helicopter */ -Helicopter::Helicopter(json::value json, int ID) : AirUnit(json, ID) +Helicopter::Helicopter(json::value json, unsigned int ID) : AirUnit(json, ID) { log("New Helicopter created with ID: " + to_string(ID)); - addMeasure(L"category", json::value(getCategory())); double desiredSpeed = knotsToMs(100); double desiredAltitude = ftToM(5000); @@ -24,16 +23,16 @@ Helicopter::Helicopter(json::value json, int ID) : AirUnit(json, ID) setDesiredAltitude(desiredAltitude); }; -void Helicopter::changeSpeed(wstring change) +void Helicopter::changeSpeed(string change) { - if (change.compare(L"stop") == 0) + if (change.compare("stop") == 0) { /* Air units can't hold a position, so we can only set them to hold. At the moment, this will erase any other command. TODO: helicopters should be able to hover in place */ clearActivePath(); } - else if (change.compare(L"slow") == 0) + else if (change.compare("slow") == 0) desiredSpeed -= knotsToMs(10); - else if (change.compare(L"fast") == 0) + else if (change.compare("fast") == 0) desiredSpeed += knotsToMs(10); if (desiredSpeed < 0) desiredSpeed = 0; @@ -41,16 +40,16 @@ void Helicopter::changeSpeed(wstring change) goToDestination(); /* Send the command to reach the destination */ } -void Helicopter::changeAltitude(wstring change) +void Helicopter::changeAltitude(string change) { - if (change.compare(L"descend") == 0) + if (change.compare("descend") == 0) { if (desiredAltitude > 100) desiredAltitude -= ftToM(100); else if (desiredAltitude > 0) desiredAltitude -= ftToM(10); } - else if (change.compare(L"climb") == 0) + else if (change.compare("climb") == 0) { if (desiredAltitude > 100) desiredAltitude += ftToM(100); diff --git a/src/core/src/navyunit.cpp b/src/core/src/navyunit.cpp index dc96f7a1..b3746803 100644 --- a/src/core/src/navyunit.cpp +++ b/src/core/src/navyunit.cpp @@ -13,10 +13,9 @@ extern Scheduler* scheduler; extern UnitsManager* unitsManager; /* Navy Unit */ -NavyUnit::NavyUnit(json::value json, int ID) : Unit(json, ID) +NavyUnit::NavyUnit(json::value json, unsigned int ID) : Unit(json, ID) { log("New Navy Unit created with ID: " + to_string(ID)); - addMeasure(L"category", json::value(getCategory())); double desiredSpeed = 10; setDesiredSpeed(desiredSpeed); @@ -27,17 +26,17 @@ void NavyUnit::AIloop() /* TODO */ } -void NavyUnit::changeSpeed(wstring change) +void NavyUnit::changeSpeed(string change) { - if (change.compare(L"stop") == 0) + if (change.compare("stop") == 0) { } - else if (change.compare(L"slow") == 0) + else if (change.compare("slow") == 0) { } - else if (change.compare(L"fast") == 0) + else if (change.compare("fast") == 0) { } diff --git a/src/core/src/scheduler.cpp b/src/core/src/scheduler.cpp index 76d3ffcd..e070414a 100644 --- a/src/core/src/scheduler.cpp +++ b/src/core/src/scheduler.cpp @@ -32,16 +32,16 @@ void Scheduler::execute(lua_State* L) return; } - int priority = CommandPriority::IMMEDIATE; + unsigned int priority = CommandPriority::IMMEDIATE; while (priority >= CommandPriority::LOW) { for (auto command : commands) { if (command->getPriority() == priority) { - wstring commandString = L"Olympus.protectedCall(" + command->getString(L) + L")"; - if (dostring_in(L, "server", to_string(commandString))) - log(L"Error executing command " + commandString); + string commandString = "Olympus.protectedCall(" + command->getString(L) + ")"; + if (dostring_in(L, "server", (commandString))) + log("Error executing command " + commandString); load = command->getLoad(); commands.remove(command); return; @@ -51,81 +51,81 @@ void Scheduler::execute(lua_State* L) } } -void Scheduler::handleRequest(wstring key, json::value value) +void Scheduler::handleRequest(string key, json::value value) { Command* command = nullptr; - log(L"Received request with ID: " + key); - if (key.compare(L"setPath") == 0) + log("Received request with ID: " + key); + if (key.compare("setPath") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) { - wstring unitName = unit->getUnitName(); + string unitName = unit->getUnitName(); json::value path = value[L"path"]; list newPath; - for (int i = 1; i <= path.as_object().size(); i++) + for (unsigned int i = 1; i <= path.as_object().size(); i++) { - wstring WP = to_wstring(i); - double lat = path[WP][L"lat"].as_double(); - double lng = path[WP][L"lng"].as_double(); - log(unitName + L" set path destination " + WP + L" (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + 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(); + log(unitName + " set path destination " + WP + " (" + to_string(lat) + ", " + to_string(lng) + ")"); Coords dest; dest.lat = lat; dest.lng = lng; newPath.push_back(dest); } unit->setActivePath(newPath); unit->setState(State::REACH_DESTINATION); - log(unitName + L" new path set successfully"); + log(unitName + " new path set successfully"); } } - else if (key.compare(L"smoke") == 0) + else if (key.compare("smoke") == 0) { - wstring color = value[L"color"].as_string(); + string color = to_string(value[L"color"]); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); - log(L"Adding " + color + L" smoke at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + log("Adding " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")"); Coords loc; loc.lat = lat; loc.lng = lng; command = dynamic_cast(new Smoke(color, loc)); } - else if (key.compare(L"spawnGround") == 0) + else if (key.compare("spawnGround") == 0) { bool immediate = value[L"immediate"].as_bool(); - wstring coalition = value[L"coalition"].as_string(); - wstring type = value[L"type"].as_string(); + string coalition = to_string(value[L"coalition"]); + string type = to_string(value[L"type"]); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); - log(L"Spawning " + coalition + L" ground unit of type " + type + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + log("Spawning " + coalition + " ground unit of type " + type + " at (" + to_string(lat) + ", " + to_string(lng) + ")"); Coords loc; loc.lat = lat; loc.lng = lng; command = dynamic_cast(new SpawnGroundUnit(coalition, type, loc, immediate)); } - else if (key.compare(L"spawnAir") == 0) + else if (key.compare("spawnAir") == 0) { bool immediate = value[L"immediate"].as_bool(); - wstring coalition = value[L"coalition"].as_string(); - wstring type = value[L"type"].as_string(); + string coalition = to_string(value[L"coalition"]); + string type = to_string(value[L"type"]); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); double altitude = value[L"altitude"].as_double(); Coords loc; loc.lat = lat; loc.lng = lng; loc.alt = altitude; - wstring payloadName = value[L"payloadName"].as_string(); - wstring airbaseName = value[L"airbaseName"].as_string(); - log(L"Spawning " + coalition + L" air unit of type " + type + L" with payload " + payloadName + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L" " + airbaseName + L")"); + string payloadName = to_string(value[L"payloadName"]); + string airbaseName = to_string(value[L"airbaseName"]); + log("Spawning " + coalition + " air unit of type " + type + " with payload " + payloadName + " at (" + to_string(lat) + ", " + to_string(lng) + " " + airbaseName + ")"); command = dynamic_cast(new SpawnAircraft(coalition, type, loc, payloadName, airbaseName, immediate)); } - else if (key.compare(L"attackUnit") == 0) + else if (key.compare("attackUnit") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); - int targetID = value[L"targetID"].as_integer(); + unsigned int targetID = value[L"targetID"].as_integer(); Unit* unit = unitsManager->getGroupLeader(ID); Unit* target = unitsManager->getUnit(targetID); - wstring unitName; - wstring targetName; + string unitName; + string targetName; if (unit != nullptr) unitName = unit->getUnitName(); @@ -137,24 +137,24 @@ void Scheduler::handleRequest(wstring key, json::value value) else return; - log(L"Unit " + unitName + L" attacking unit " + targetName); + log("Unit " + unitName + " attacking unit " + targetName); unit->setTargetID(targetID); unit->setState(State::ATTACK); } - else if (key.compare(L"followUnit") == 0) + else if (key.compare("followUnit") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); - int leaderID = value[L"targetID"].as_integer(); - int offsetX = value[L"offsetX"].as_integer(); - int offsetY = value[L"offsetY"].as_integer(); - int offsetZ = value[L"offsetZ"].as_integer(); + unsigned int leaderID = value[L"targetID"].as_integer(); + unsigned int offsetX = value[L"offsetX"].as_integer(); + unsigned int offsetY = value[L"offsetY"].as_integer(); + unsigned int offsetZ = value[L"offsetZ"].as_integer(); Unit* unit = unitsManager->getGroupLeader(ID); Unit* leader = unitsManager->getUnit(leaderID); - wstring unitName; - wstring leaderName; + string unitName; + string leaderName; if (unit != nullptr) unitName = unit->getUnitName(); @@ -166,95 +166,95 @@ void Scheduler::handleRequest(wstring key, json::value value) else return; - log(L"Unit " + unitName + L" following unit " + leaderName); + log("Unit " + unitName + " following unit " + leaderName); unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ)); unit->setLeaderID(leaderID); unit->setState(State::FOLLOW); } - else if (key.compare(L"changeSpeed") == 0) + else if (key.compare("changeSpeed") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) - unit->changeSpeed(value[L"change"].as_string()); + unit->changeSpeed(to_string(value[L"change"])); } - else if (key.compare(L"changeAltitude") == 0) + else if (key.compare("changeAltitude") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) - unit->changeAltitude(value[L"change"].as_string()); + unit->changeAltitude(to_string(value[L"change"])); } - else if (key.compare(L"setSpeed") == 0) + else if (key.compare("setSpeed") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) unit->setDesiredSpeed(value[L"speed"].as_double()); } - else if (key.compare(L"setSpeedType") == 0) + else if (key.compare("setSpeedType") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) - unit->setDesiredSpeedType(value[L"speedType"].as_string()); + unit->setDesiredSpeedType(to_string(value[L"speedType"])); } - else if (key.compare(L"setAltitude") == 0) + else if (key.compare("setAltitude") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) unit->setDesiredAltitude(value[L"altitude"].as_double()); } - else if (key.compare(L"setAltitudeType") == 0) + else if (key.compare("setAltitudeType") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) - unit->setDesiredAltitudeType(value[L"altitudeType"].as_string()); + unit->setDesiredAltitudeType(to_string(value[L"altitudeType"])); } - else if (key.compare(L"cloneUnit") == 0) + else if (key.compare("cloneUnit") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); Coords loc; loc.lat = lat; loc.lng = lng; command = dynamic_cast(new Clone(ID, loc)); - log(L"Cloning unit " + to_wstring(ID)); + log("Cloning unit " + to_string(ID)); } - else if (key.compare(L"setROE") == 0) + else if (key.compare("setROE") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); - wstring ROE = value[L"ROE"].as_string(); + unsigned char ROE = value[L"ROE"].as_number().is_uint32(); unit->setROE(ROE); } - else if (key.compare(L"setReactionToThreat") == 0) + else if (key.compare("setReactionToThreat") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); - wstring reactionToThreat = value[L"reactionToThreat"].as_string(); + unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().is_uint32(); unit->setReactionToThreat(reactionToThreat); } - else if (key.compare(L"setEmissionsCountermeasures") == 0) + else if (key.compare("setEmissionsCountermeasures") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); - wstring emissionsCountermeasures = value[L"emissionsCountermeasures"].as_string(); + unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().is_uint32(); unit->setEmissionsCountermeasures(emissionsCountermeasures); } - else if (key.compare(L"landAt") == 0) + else if (key.compare("landAt") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); double lat = value[L"location"][L"lat"].as_double(); @@ -262,22 +262,22 @@ void Scheduler::handleRequest(wstring key, json::value value) Coords loc; loc.lat = lat; loc.lng = lng; unit->landAt(loc); } - else if (key.compare(L"deleteUnit") == 0) + else if (key.compare("deleteUnit") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); bool explosion = value[L"explosion"].as_bool(); unitsManager->deleteUnit(ID, explosion); } - else if (key.compare(L"refuel") == 0) + else if (key.compare("refuel") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::REFUEL); } - else if (key.compare(L"setAdvancedOptions") == 0) + else if (key.compare("setAdvancedOptions") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); Unit* unit = unitsManager->getGroupLeader(ID); if (unit != nullptr) @@ -287,18 +287,21 @@ void Scheduler::handleRequest(wstring key, json::value value) unit->setIsAWACS(value[L"isAWACS"].as_bool()); /* TACAN Options */ - auto TACAN = value[L"TACAN"]; - unit->setTACAN({ TACAN[L"isOn"].as_bool(), - TACAN[L"channel"].as_number().to_int32(), - TACAN[L"XY"].as_string(), - TACAN[L"callsign"].as_string() - }); + Options::TACAN TACAN; + TACAN.isOn = value[L"TACAN"][L"isOn"].as_bool(); + TACAN.channel = static_cast(value[L"TACAN"][L"channel"].as_number().to_uint32()); + TACAN.XY = to_string(value[L"TACAN"][L"XY"]).at(0); + string callsign = to_string(value[L"TACAN"][L"callsign"]); + if (callsign.length() > 3) + callsign = callsign.substr(0, 3); + strcpy_s(TACAN.callsign, 4, callsign.c_str()); + unit->setTACAN(TACAN); /* Radio Options */ auto radio = value[L"radio"]; - unit->setRadio({ radio[L"frequency"].as_number().to_int32(), - radio[L"callsign"].as_number().to_int32(), - radio[L"callsignNumber"].as_number().to_int32() + unit->setRadio({ radio[L"frequency"].as_number().to_uint32(), + static_cast(radio[L"callsign"].as_number().to_uint32()), + static_cast(radio[L"callsignNumber"].as_number().to_uint32()) }); /* General Settings */ @@ -313,78 +316,78 @@ void Scheduler::handleRequest(wstring key, json::value value) unit->resetActiveDestination(); } } - else if (key.compare(L"setFollowRoads") == 0) + else if (key.compare("setFollowRoads") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); bool followRoads = value[L"followRoads"].as_bool(); Unit* unit = unitsManager->getGroupLeader(ID); unit->setFollowRoads(followRoads); } - else if (key.compare(L"setOnOff") == 0) + else if (key.compare("setOnOff") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); bool onOff = value[L"onOff"].as_bool(); Unit* unit = unitsManager->getGroupLeader(ID); unit->setOnOff(onOff); } - else if (key.compare(L"explosion") == 0) + else if (key.compare("explosion") == 0) { - int intensity = value[L"intensity"].as_integer(); + unsigned int intensity = value[L"intensity"].as_integer(); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); - log(L"Adding " + to_wstring(intensity) + L" explosion at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + log("Adding " + to_string(intensity) + " explosion at (" + to_string(lat) + ", " + to_string(lng) + ")"); Coords loc; loc.lat = lat; loc.lng = lng; command = dynamic_cast(new Explosion(intensity, loc)); } - else if (key.compare(L"bombPoint") == 0) + else if (key.compare("bombPoint") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); Coords loc; loc.lat = lat; loc.lng = lng; Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::BOMB_POINT); - unit->setTargetLocation(loc); + unit->setTargetPosition(loc); } - else if (key.compare(L"carpetBomb") == 0) + else if (key.compare("carpetBomb") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); Coords loc; loc.lat = lat; loc.lng = lng; Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::CARPET_BOMB); - unit->setTargetLocation(loc); + unit->setTargetPosition(loc); } - else if (key.compare(L"bombBuilding") == 0) + else if (key.compare("bombBuilding") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); Coords loc; loc.lat = lat; loc.lng = lng; Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::BOMB_BUILDING); - unit->setTargetLocation(loc); + unit->setTargetPosition(loc); } - else if (key.compare(L"fireAtArea") == 0) + else if (key.compare("fireAtArea") == 0) { - int ID = value[L"ID"].as_integer(); + unsigned int ID = value[L"ID"].as_integer(); unitsManager->acquireControl(ID); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); Coords loc; loc.lat = lat; loc.lng = lng; Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::FIRE_AT_AREA); - unit->setTargetLocation(loc); + unit->setTargetPosition(loc); } else { - log(L"Unknown command: " + key); + log("Unknown command: " + key); } if (command != nullptr) diff --git a/src/core/src/scriptloader.cpp b/src/core/src/scriptloader.cpp index 0509463e..12ed68c8 100644 --- a/src/core/src/scriptloader.cpp +++ b/src/core/src/scriptloader.cpp @@ -13,10 +13,12 @@ bool executeLuaScript(lua_State* L, string path) if (dostring_in(L, "server", str.c_str()) != 0) { log("Error registering " + path); + return false; } else { log(path + " registered successfully"); + return true; } } diff --git a/src/core/src/server.cpp b/src/core/src/server.cpp index 621f0e43..e8c71e5d 100644 --- a/src/core/src/server.cpp +++ b/src/core/src/server.cpp @@ -36,8 +36,7 @@ Server::Server(lua_State* L): serverThread(nullptr), runListener(true) { - refreshJson = json::value::object(); - updateJson = json::value::object(); + } void Server::start(lua_State* L) @@ -71,8 +70,8 @@ void Server::handle_get(http_request request) lock_guard guard(mutexLock); http_response response(status_codes::OK); - string authorization = to_base64("admin:" + to_string(password)); - if (password == L"" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second == L"Basic " + to_wstring(authorization))) + string authorization = to_base64("admin:" + password); + if (password == "" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second == L"Basic " + to_wstring(authorization))) { std::exception_ptr eptr; try { @@ -81,7 +80,8 @@ void Server::handle_get(http_request request) if (path.size() > 0) { - if (path[0] == UNITS_URI) + string URI = to_string(path[0]); + if (URI.compare(UNITS_URI) == 0) { map query = request.relative_uri().split_query(request.relative_uri().query()); long long time = 0; @@ -94,22 +94,21 @@ void Server::handle_get(http_request request) time = 0; } } - if (time == 0) - unitsManager->getUnitData(answer, 0); - else - answer[L"units"] = updateJson; + + // TODO would be nice to optimize this + answer[L"units"] = json::value(to_wstring(unitsManager->getUnitData(time == 0))); } - else if (path[0] == LOGS_URI) + 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 (path[0] == AIRBASES_URI) + else if (URI.compare(AIRBASES_URI) == 0) answer[L"airbases"] = airbases; - else if (path[0] == BULLSEYE_URI) + else if (URI.compare(BULLSEYE_URI) == 0) answer[L"bullseyes"] = bullseyes; - else if (path[0] == MISSION_URI) + else if (URI.compare(MISSION_URI) == 0) answer[L"mission"] = mission; milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); @@ -139,8 +138,8 @@ void Server::handle_get(http_request request) void Server::handle_request(http_request request, function action) { http_response response(status_codes::OK); - string authorization = to_base64("admin:" + to_string(password)); - if (password == L"" || (request.headers().has(L"Authorization") && request.headers().find(L"Authorization")->second == L"Basic " + to_wstring(authorization))) + 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)))) { auto answer = json::value::object(); request.extract_json().then([&answer, &action](pplx::task task) @@ -148,11 +147,8 @@ void Server::handle_request(http_request request, functionhandleRequest(key, value); + scheduler->handleRequest(to_string(key), value); } catch (...) { eptr = std::current_exception(); // capture @@ -200,8 +196,8 @@ void Server::handle_put(http_request request) void Server::task() { - wstring address = wstring(REST_ADDRESS); - wstring modLocation; + string address = REST_ADDRESS; + string modLocation; char* buf = nullptr; size_t sz = 0; if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr) @@ -210,31 +206,31 @@ void Server::task() std::stringstream ss; ss << ifstream.rdbuf(); std::error_code errorCode; - json::value config = json::value::parse(to_wstring(ss.str()), errorCode); + json::value config = json::value::parse(ss.str(), errorCode); if (config.is_object() && config.has_object_field(L"server") && config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port")) { - address = L"http://" + config[L"server"][L"address"].as_string() + L":" + to_wstring(config[L"server"][L"port"].as_number().to_int32()); - log(L"Starting server on " + address); + address = "http://" + to_string(config[L"server"][L"address"]) + ":" + to_string(config[L"server"][L"port"].as_number().to_int32()); + log("Starting server on " + address); } else - log(L"Error reading configuration file. Starting server on " + address); + log("Error reading configuration file. Starting server on " + address); if (config.is_object() && config.has_object_field(L"authentication") && config[L"authentication"].has_string_field(L"password")) { - password = config[L"authentication"][L"password"].as_string(); + password = to_string(config[L"authentication"][L"password"]); } else - log(L"Error reading configuration file. No password set."); + log("Error reading configuration file. No password set."); free(buf); } else { - log(L"DCSOLYMPUS_PATH environment variable is missing, starting server on " + address); + log("DCSOLYMPUS_PATH environment variable is missing, starting server on " + address); } - http_listener listener(address + L"/" + wstring(REST_URI)); + http_listener listener(to_wstring(address + "/" + REST_URI)); std::function handle_options = std::bind(&Server::handle_options, this, std::placeholders::_1); std::function handle_get = std::bind(&Server::handle_get, this, std::placeholders::_1); diff --git a/src/core/src/unit.cpp b/src/core/src/unit.cpp index cf7ba257..1fdda23a 100644 --- a/src/core/src/unit.cpp +++ b/src/core/src/unit.cpp @@ -6,6 +6,9 @@ #include "defines.h" #include "unitsmanager.h" +#include "base64.hpp" +using namespace base64; + #include using namespace std::chrono; @@ -32,7 +35,7 @@ bool operator==(const Options::GeneralSettings& lhs, const Options::GeneralSetti lhs.prohibitAirWpn == rhs.prohibitAirWpn && lhs.prohibitJettison == rhs.prohibitJettison; } -Unit::Unit(json::value json, int ID) : +Unit::Unit(json::value json, unsigned int ID) : ID(ID) { log("Creating unit with ID: " + to_string(ID)); @@ -55,18 +58,19 @@ void Unit::setDefaults(bool force) const bool isUnitAlive = getAlive(); const bool isUnitLeader = unitsManager->isUnitGroupLeader(this); const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this); - const bool isUnitHuman = getFlags()[L"Human"].as_bool(); - if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman) { + + if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !human) { /* Set the default IDLE state */ setState(State::IDLE); /* Set desired altitude to be equal to current altitude so the unit does not climb/descend after spawn */ - setDesiredAltitude(altitude); + setDesiredAltitude(position.alt); /* Set the default options (these are all defaults so will only affect the export data, no DCS command will be sent) */ - setROE(L"Designated", force); - setReactionToThreat(L"Evade", force); - setEmissionsCountermeasures(L"Defend", force); + setROE(ROE::OPEN_FIRE_WEAPON_FREE, force); + setReactionToThreat(ReactionToThreat::EVADE_FIRE, force); + setEmissionsCountermeasures(EmissionCountermeasure::DEFEND, force); + strcpy_s(TACAN.callsign, 4, "TKR"); setTACAN(TACAN, force); setRadio(radio, force); setEPLRS(EPLRS, force); @@ -76,28 +80,13 @@ void Unit::setDefaults(bool force) } } -void Unit::addMeasure(wstring key, json::value value) -{ - milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); - if (measures.find(key) == measures.end()) - measures[key] = new Measure(value, ms.count()); - else - { - if (measures[key]->getValue() != value) - { - measures[key]->setValue(value); - measures[key]->setTime(ms.count()); - } - } -} - void Unit::runAILoop() { /* If the unit is alive, controlled and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */ if (!getControlled()) return; if (!unitsManager->isUnitGroupLeader(this)) return; - if (getFlags()[L"Human"].as_bool()) return; + if (human) return; - // Keep running the AI loop even if the unit is dead if it is the leader of a group which has other members in it + /* Keep running the AI loop even if the unit is dead if it is the leader of a group which has other members in it */ const bool isUnitAlive = getAlive(); const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this); if (!(isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits)) return; @@ -114,146 +103,182 @@ void Unit::updateExportData(json::value json, double dt) if (oldPosition != NULL) { double dist = 0; - Geodesic::WGS84().Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist); + Geodesic::WGS84().Inverse(getPosition().lat, getPosition().lng, oldPosition.lat, oldPosition.lng, dist); if (dt > 0) setSpeed(getSpeed() * 0.95 + (dist / dt) * 0.05); } - oldPosition = Coords(latitude, longitude, altitude); + oldPosition = position; if (json.has_string_field(L"Name")) - setName(json[L"Name"].as_string()); + setName(to_string(json[L"Name"])); if (json.has_string_field(L"UnitName")) - setUnitName(json[L"UnitName"].as_string()); + setUnitName(to_string(json[L"UnitName"])); if (json.has_string_field(L"GroupName")) - setGroupName(json[L"GroupName"].as_string()); - if (json.has_object_field(L"Type")) - setType(json[L"Type"]); + 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")) { - setLatitude(json[L"LatLongAlt"][L"Lat"].as_number().to_double()); - setLongitude(json[L"LatLongAlt"][L"Long"].as_number().to_double()); - setAltitude(json[L"LatLongAlt"][L"Alt"].as_number().to_double()); + 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")) - setFlags(json[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(L"Olympus") != wstring::npos) + if (getUnitName().find("Olympus") != string::npos) setControlled(true); } void Unit::updateMissionData(json::value json) { if (json.has_number_field(L"fuel")) - setFuel(int(json[L"fuel"].as_number().to_double() * 100)); - if (json.has_object_field(L"ammo")) - setAmmo(json[L"ammo"]); - if (json.has_object_field(L"contacts")) - setContacts(json[L"contacts"]); + setFuel(short(json[L"fuel"].as_number().to_double() * 100)); + + if (json.has_object_field(L"ammo")) { + vector ammo; + for (auto const& el : json[L"ammo"].as_object()) { + DataTypes::Ammo ammoItem; + auto ammoJson = el.second; + ammoItem.quantity = ammoJson[L"count"].as_number().to_uint32(); + ammoItem.name = to_string(ammoJson[L"desc"][L"displayName"]); + ammoItem.guidance = ammoJson[L"desc"][L"guidance"].as_number().to_uint32(); + ammoItem.category = ammoJson[L"desc"][L"category"].as_number().to_uint32(); + ammoItem.missileCategory = ammoJson[L"desc"][L"missileCategory"].as_number().to_uint32(); + ammo.push_back(ammoItem); + } + setAmmo(ammo); + } + + if (json.has_object_field(L"contacts")) { + vector contacts; + for (auto const& el : json[L"ammo"].as_object()) { + DataTypes::Contact contactItem; + auto contactJson = el.second; + contactItem.ID = contactJson[L"object"][L"id_"].as_number().to_uint32(); + + string detectionMethod = to_string(contactJson[L"detectionMethod"]); + if (detectionMethod.compare("VISUAL")) contactItem.detectionMethod = 1; + else if (detectionMethod.compare("OPTIC")) contactItem.detectionMethod = 2; + else if (detectionMethod.compare("RADAR")) contactItem.detectionMethod = 4; + else if (detectionMethod.compare("IRST")) contactItem.detectionMethod = 8; + else if (detectionMethod.compare("RWR")) contactItem.detectionMethod = 16; + else if (detectionMethod.compare("DLINK")) contactItem.detectionMethod = 32; + contacts.push_back(contactItem); + } + setContacts(contacts); + } + if (json.has_boolean_field(L"hasTask")) setHasTask(json[L"hasTask"].as_bool()); } -json::value Unit::getData(long long time, bool getAll) +DataTypes::DataPacket Unit::getDataPacket() { - auto json = json::value::object(); + unsigned int bitmask = 0; + bitmask |= alive << 0; + bitmask |= human << 1; + bitmask |= controlled << 2; + bitmask |= hasTask << 3; + bitmask |= desiredAltitudeType << 16; + bitmask |= desiredSpeedType << 17; + bitmask |= isTanker << 18; + bitmask |= isAWACS << 19; + bitmask |= onOff << 19; + bitmask |= followRoads << 19; + bitmask |= EPLRS << 20; + bitmask |= generalSettings.prohibitAA << 21; + bitmask |= generalSettings.prohibitAfterburner << 22; + bitmask |= generalSettings.prohibitAG << 23; + bitmask |= generalSettings.prohibitAirWpn << 24; + bitmask |= generalSettings.prohibitJettison << 25; - /* If the unit is in a group, task & option data is given by the group leader */ - if (unitsManager->isUnitInGroup(this) && !unitsManager->isUnitGroupLeader(this)) - json = unitsManager->getGroupLeader(this)->getData(time, true); + DataTypes::DataPacket datapacket{ + ID, + bitmask, + position, + speed, + heading, + fuel, + desiredSpeed, + desiredAltitude, + targetID, + targetPosition, + state, + ROE, + reactionToThreat, + emissionsCountermeasures, + TACAN, + radio + }; + + return datapacket; +} + +string Unit::getData(bool refresh) +{ + /* Prepare the data in a stringstream */ + stringstream ss; + + /* Reserve data for: + 1) DataPacket; + 2) Length of active path; + 3) Active path; + */ + char* data = (char*)malloc(sizeof(DataTypes::DataPacket) + sizeof(unsigned short) + activePath.size() * sizeof(Coords)); + unsigned int offset = 0; + + /* Prepare the data packet and copy it to memory */ + DataTypes::DataPacket dataPacket; + /* If the unit is in a group, get the datapacket from the group leader and only replace the position, speed and heading */ + if (unitsManager->isUnitInGroup(this) && !unitsManager->isUnitGroupLeader(this)) { + dataPacket = unitsManager->getGroupLeader(this)->getDataPacket(); + dataPacket.position = position; + dataPacket.speed = speed; + dataPacket.heading = heading; + } + else + dataPacket = getDataPacket(); - /********** Base data **********/ - json[L"baseData"] = json::value::object(); - for (auto key : { L"controlled", L"name", L"unitName", L"groupName", L"alive", L"category"}) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"baseData"][key] = measures[key]->getValue(); - } - if (json[L"baseData"].size() == 0) - json.erase(L"baseData"); + memcpy(data + offset, &dataPacket, sizeof(dataPacket)); + offset += sizeof(dataPacket); - if (alive || getAll) { - /********** Flight data **********/ - json[L"flightData"] = json::value::object(); - for (auto key : { L"latitude", L"longitude", L"altitude", L"speed", L"heading" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"flightData"][key] = measures[key]->getValue(); - } - if (json[L"flightData"].size() == 0) - json.erase(L"flightData"); + /* Prepare the path memory and copy it to memory */ + std::vector path; + for (const Coords& c : activePath) + path.push_back(c); + unsigned short pathLength = activePath.size(); - /********** Mission data **********/ - json[L"missionData"] = json::value::object(); - for (auto key : { L"fuel", L"ammo", L"contacts", L"hasTask", L"coalition", L"flags" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"missionData"][key] = measures[key]->getValue(); - } - if (json[L"missionData"].size() == 0) - json.erase(L"missionData"); + memcpy(data + offset, &pathLength, sizeof(unsigned short)); + offset += sizeof(unsigned short); + memcpy(data + offset, &path, activePath.size() * sizeof(Coords)); + offset += sizeof(unsigned short); - /********** Formation data **********/ - json[L"formationData"] = json::value::object(); - for (auto key : { L"leaderID" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"formationData"][key] = measures[key]->getValue(); - } - if (json[L"formationData"].size() == 0) - json.erase(L"formationData"); + ss << to_base64(data, offset); - /* If the unit is in a group, task & option data is given by the group leader */ - if (unitsManager->isUnitGroupLeader(this)) { - /********** Task data **********/ - json[L"taskData"] = json::value::object(); - for (auto key : { L"currentState", L"currentTask", L"desiredSpeed", L"desiredAltitude", L"desiredSpeedType", L"desiredAltitudeType", L"activePath", L"isTanker", L"isAWACS", L"onOff", L"followRoads", L"targetID", L"targetLocation" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"taskData"][key] = measures[key]->getValue(); - } - if (json[L"taskData"].size() == 0) - json.erase(L"taskData"); - - /********** Options data **********/ - json[L"optionsData"] = json::value::object(); - for (auto key : { L"ROE", L"reactionToThreat", L"emissionsCountermeasures", L"TACAN", L"radio", L"generalSettings" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"optionsData"][key] = measures[key]->getValue(); - } - if (json[L"optionsData"].size() == 0) - json.erase(L"optionsData"); - } + if (refresh) { + ss << name; + ss << unitName; + ss << groupName; + ss << getCategory(); + ss << coalition; } - return json; + return ss.str(); } void Unit::setActivePath(list newPath) { activePath = newPath; resetActiveDestination(); - - auto path = json::value::object(); - if (activePath.size() > 0) { - int count = 1; - for (auto& destination : activePath) - { - auto json = json::value::object(); - json[L"lat"] = destination.lat; - json[L"lng"] = destination.lng; - json[L"alt"] = destination.alt; - path[to_wstring(count++)] = json; - } - } - addMeasure(L"activePath", path); } void Unit::clearActivePath() @@ -283,28 +308,27 @@ void Unit::popActivePathFront() setActivePath(path); } -void Unit::setCoalitionID(int newCoalitionID) +void Unit::setCoalitionID(unsigned int newCoalitionID) { if (newCoalitionID == 0) - coalition = L"neutral"; + coalition = "neutral"; else if (newCoalitionID == 1) - coalition = L"red"; + coalition = "red"; else - coalition = L"blue"; - addMeasure(L"coalition", json::value(coalition)); + coalition = "blue"; } -int Unit::getCoalitionID() +unsigned int Unit::getCoalitionID() { - if (coalition == L"neutral") + if (coalition == "neutral") return 0; - else if (coalition == L"red") + else if (coalition == "red") return 1; else return 2; } -wstring Unit::getTargetName() +string Unit::getTargetName() { if (isTargetAlive()) { @@ -312,7 +336,7 @@ wstring Unit::getTargetName() if (target != nullptr) return target->getUnitName(); } - return L""; + return ""; } bool Unit::isTargetAlive() @@ -327,7 +351,7 @@ bool Unit::isTargetAlive() return false; } -wstring Unit::getLeaderName() +string Unit::getLeaderName() { if (isLeaderAlive()) { @@ -335,7 +359,7 @@ wstring Unit::getLeaderName() if (leader != nullptr) return leader->getUnitName(); } - return L""; + return ""; } bool Unit::isLeaderAlive() @@ -369,84 +393,52 @@ void Unit::setFormationOffset(Offset newFormationOffset) resetTask(); } -void Unit::setROE(wstring newROE, bool force) { - addMeasure(L"ROE", json::value(newROE)); - +void Unit::setROE(unsigned char newROE, bool force) +{ if (ROE != newROE || force) { ROE = newROE; - - int ROEEnum; - if (ROE.compare(L"Free") == 0) - ROEEnum = ROE::WEAPON_FREE; - else if (ROE.compare(L"Designated free") == 0) - ROEEnum = ROE::OPEN_FIRE_WEAPON_FREE; - else if (ROE.compare(L"Designated") == 0) - ROEEnum = ROE::OPEN_FIRE; - else if (ROE.compare(L"Return") == 0) - ROEEnum = ROE::RETURN_FIRE; - else if (ROE.compare(L"Hold") == 0) - ROEEnum = ROE::WEAPON_HOLD; - else - return; - - Command* command = dynamic_cast(new SetOption(groupName, SetCommandType::ROE, ROEEnum)); + Command* command = dynamic_cast(new SetOption(groupName, SetCommandType::ROE, ROE)); scheduler->appendCommand(command); } } -void Unit::setReactionToThreat(wstring newReactionToThreat, bool force) { - addMeasure(L"reactionToThreat", json::value(newReactionToThreat)); - +void Unit::setReactionToThreat(unsigned char newReactionToThreat, bool force) +{ if (reactionToThreat != newReactionToThreat || force) { reactionToThreat = newReactionToThreat; - int reactionToThreatEnum; - if (reactionToThreat.compare(L"None") == 0) - reactionToThreatEnum = ReactionToThreat::NO_REACTION; - else if (reactionToThreat.compare(L"Passive") == 0) - reactionToThreatEnum = ReactionToThreat::PASSIVE_DEFENCE; - else if (reactionToThreat.compare(L"Evade") == 0) - reactionToThreatEnum = ReactionToThreat::EVADE_FIRE; - else if (reactionToThreat.compare(L"Escape") == 0) - reactionToThreatEnum = ReactionToThreat::BYPASS_AND_ESCAPE; - else if (reactionToThreat.compare(L"Abort") == 0) - reactionToThreatEnum = ReactionToThreat::ALLOW_ABORT_MISSION; - else - return; - - Command* command = dynamic_cast(new SetOption(groupName, SetCommandType::REACTION_ON_THREAT, reactionToThreatEnum)); + Command* command = dynamic_cast(new SetOption(groupName, SetCommandType::REACTION_ON_THREAT, reactionToThreat)); scheduler->appendCommand(command); } } -void Unit::setEmissionsCountermeasures(wstring newEmissionsCountermeasures, bool force) { - addMeasure(L"emissionsCountermeasures", json::value(newEmissionsCountermeasures)); - +void Unit::setEmissionsCountermeasures(unsigned char newEmissionsCountermeasures, bool force) +{ if (emissionsCountermeasures != newEmissionsCountermeasures || force) { emissionsCountermeasures = newEmissionsCountermeasures; - int radarEnum; - int flareEnum; - int ECMEnum; - if (emissionsCountermeasures.compare(L"Silent") == 0) + unsigned int radarEnum; + unsigned int flareEnum; + unsigned int ECMEnum; + if (emissionsCountermeasures == EmissionCountermeasure::SILENT) { radarEnum = RadarUse::NEVER; flareEnum = FlareUse::NEVER; ECMEnum = ECMUse::NEVER_USE; } - else if (emissionsCountermeasures.compare(L"Attack") == 0) + else if (emissionsCountermeasures == EmissionCountermeasure::ATTACK) { radarEnum = RadarUse::FOR_ATTACK_ONLY; flareEnum = FlareUse::AGAINST_FIRED_MISSILE; ECMEnum = ECMUse::USE_IF_ONLY_LOCK_BY_RADAR; } - else if (emissionsCountermeasures.compare(L"Defend") == 0) + else if (emissionsCountermeasures == EmissionCountermeasure::DEFEND) { radarEnum = RadarUse::FOR_SEARCH_IF_REQUIRED; flareEnum = FlareUse::WHEN_FLYING_IN_SAM_WEZ; ECMEnum = ECMUse::USE_IF_DETECTED_LOCK_BY_RADAR; } - else if (emissionsCountermeasures.compare(L"Free") == 0) + else if (emissionsCountermeasures == EmissionCountermeasure::FREE) { radarEnum = RadarUse::FOR_CONTINUOUS_SEARCH; flareEnum = FlareUse::WHEN_FLYING_NEAR_ENEMIES; @@ -468,42 +460,37 @@ void Unit::setEmissionsCountermeasures(wstring newEmissionsCountermeasures, bool } } -void Unit::landAt(Coords loc) { +void Unit::landAt(Coords loc) +{ clearActivePath(); pushActivePathBack(loc); setState(State::LAND); } -void Unit::setIsTanker(bool newIsTanker) { +void Unit::setIsTanker(bool newIsTanker) +{ isTanker = newIsTanker; resetTask(); - addMeasure(L"isTanker", json::value(newIsTanker)); } -void Unit::setIsAWACS(bool newIsAWACS) { +void Unit::setIsAWACS(bool newIsAWACS) +{ isAWACS = newIsAWACS; resetTask(); - addMeasure(L"isAWACS", json::value(newIsAWACS)); setEPLRS(isAWACS); } -void Unit::setTACAN(Options::TACAN newTACAN, bool force) { - auto json = json::value(); - json[L"isOn"] = json::value(newTACAN.isOn); - json[L"channel"] = json::value(newTACAN.channel); - json[L"XY"] = json::value(newTACAN.XY); - json[L"callsign"] = json::value(newTACAN.callsign); - addMeasure(L"TACAN", json); - +void Unit::setTACAN(Options::TACAN newTACAN, bool force) +{ if (TACAN != newTACAN || force) { TACAN = newTACAN; if (TACAN.isOn) { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS << "{" << "id = 'ActivateBeacon'," << "params = {" - << "type = " << ((TACAN.XY.compare(L"X") == 0) ? 4 : 5) << "," + << "type = " << ((TACAN.XY == 'X' == 0) ? 4 : 5) << "," << "system = 3," << "name = \"Olympus_TACAN\"," << "callsign = \"" << TACAN.callsign << "\", " @@ -514,7 +501,7 @@ void Unit::setTACAN(Options::TACAN newTACAN, bool force) { scheduler->appendCommand(command); } else { - std::wostringstream commandSS; + std::ostringstream commandSS; commandSS << "{" << "id = 'DeactivateBeacon'," << "params = {" @@ -526,19 +513,13 @@ void Unit::setTACAN(Options::TACAN newTACAN, bool force) { } } -void Unit::setRadio(Options::Radio newRadio, bool force) { - - auto json = json::value(); - json[L"frequency"] = json::value(newRadio.frequency); - json[L"callsign"] = json::value(newRadio.callsign); - json[L"callsignNumber"] = json::value(newRadio.callsignNumber); - addMeasure(L"radio", json); - +void Unit::setRadio(Options::Radio newRadio, bool force) +{ if (radio != newRadio || force) { radio = newRadio; - std::wostringstream commandSS; + std::ostringstream commandSS; Command* command; commandSS << "{" @@ -552,7 +533,7 @@ void Unit::setRadio(Options::Radio newRadio, bool force) { scheduler->appendCommand(command); // Clear the stringstream - commandSS.str(wstring()); + commandSS.str(string("")); commandSS << "{" << "id = 'SetCallsign'," @@ -568,12 +549,12 @@ void Unit::setRadio(Options::Radio newRadio, bool force) { void Unit::setEPLRS(bool newEPLRS, bool force) { - //addMeasure(L"EPLRS", json::value(newEPLRS)); + //addMeasure("EPLRS", json::value(newEPLRS)); // //if (EPLRS != newEPLRS || force) { // EPLRS = newEPLRS; // - // std::wostringstream commandSS; + // std::ostringstream commandSS; // commandSS << "{" // << "id = 'EPLRS'," // << "params = {" @@ -585,16 +566,8 @@ void Unit::setEPLRS(bool newEPLRS, bool force) //} } -void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool force) { - - auto json = json::value(); - json[L"prohibitJettison"] = json::value(newGeneralSettings.prohibitJettison); - json[L"prohibitAA"] = json::value(newGeneralSettings.prohibitAA); - json[L"prohibitAG"] = json::value(newGeneralSettings.prohibitAG); - json[L"prohibitAfterburner"] = json::value(newGeneralSettings.prohibitAfterburner); - json[L"prohibitAirWpn"] = json::value(newGeneralSettings.prohibitAirWpn); - addMeasure(L"generalSettings", json); - +void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool force) +{ if (generalSettings != newGeneralSettings) { generalSettings = newGeneralSettings; @@ -613,47 +586,47 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool } } -void Unit::setDesiredSpeed(double newDesiredSpeed) { +void Unit::setDesiredSpeed(double newDesiredSpeed) +{ desiredSpeed = newDesiredSpeed; - addMeasure(L"desiredSpeed", json::value(newDesiredSpeed)); if (state == State::IDLE) resetTask(); else goToDestination(); /* Send the command to reach the destination */ } -void Unit::setDesiredAltitude(double newDesiredAltitude) { +void Unit::setDesiredAltitude(double newDesiredAltitude) +{ desiredAltitude = newDesiredAltitude; - addMeasure(L"desiredAltitude", json::value(newDesiredAltitude)); if (state == State::IDLE) resetTask(); else goToDestination(); /* Send the command to reach the destination */ } -void Unit::setDesiredSpeedType(wstring newDesiredSpeedType) { - desiredSpeedType = newDesiredSpeedType; - addMeasure(L"desiredSpeedType", json::value(newDesiredSpeedType)); +void Unit::setDesiredSpeedType(string newDesiredSpeedType) +{ + desiredSpeedType = newDesiredSpeedType.compare("GS") == 0; if (state == State::IDLE) resetTask(); else goToDestination(); /* Send the command to reach the destination */ } -void Unit::setDesiredAltitudeType(wstring newDesiredAltitudeType) { - desiredAltitudeType = newDesiredAltitudeType; - addMeasure(L"desiredAltitudeType", json::value(newDesiredAltitudeType)); +void Unit::setDesiredAltitudeType(string newDesiredAltitudeType) +{ + desiredAltitudeType = newDesiredAltitudeType.compare("AGL") == 0; if (state == State::IDLE) resetTask(); else goToDestination(); /* Send the command to reach the destination */ } -void Unit::goToDestination(wstring enrouteTask) +void Unit::goToDestination(string enrouteTask) { if (activeDestination != NULL) { - Command* command = dynamic_cast(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType(), getDesiredAltitude(), getDesiredAltitudeType(), enrouteTask, getCategory())); + Command* command = dynamic_cast(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType()? "GS": "CAS", getDesiredAltitude(), getDesiredAltitudeType()? "AGL" : "ASL", enrouteTask, getCategory())); scheduler->appendCommand(command); setHasTask(true); } @@ -667,16 +640,17 @@ bool Unit::isDestinationReached(double threshold) for (auto const& p: unitsManager->getGroupMembers(groupName)) { double dist = 0; - Geodesic::WGS84().Inverse(p->getLatitude(), p->getLongitude(), activeDestination.lat, activeDestination.lng, dist); + Geodesic::WGS84().Inverse(p->getPosition().lat, p->getPosition().lng, activeDestination.lat, activeDestination.lng, dist); if (dist < threshold) { - log(unitName + L" destination reached"); + log(unitName + " destination reached"); return true; } else { return false; } - } + } + return false; } else return true; @@ -687,13 +661,13 @@ bool Unit::setActiveDestination() if (activePath.size() > 0) { activeDestination = activePath.front(); - log(unitName + L" active destination set to queue front"); + log(unitName + " active destination set to queue front"); return true; } else { activeDestination = Coords(0); - log(unitName + L" active destination set to NULL"); + log(unitName + " active destination set to NULL"); return false; } } @@ -706,7 +680,7 @@ bool Unit::updateActivePath(bool looping) if (looping) pushActivePathBack(activePath.front()); popActivePathFront(); - log(unitName + L" active path front popped"); + log(unitName + " active path front popped"); return true; } else { @@ -714,15 +688,13 @@ bool Unit::updateActivePath(bool looping) } } -void Unit::setTargetLocation(Coords newTargetLocation) { - targetLocation = newTargetLocation; - auto json = json::value(); - json[L"latitude"] = json::value(newTargetLocation.lat); - json[L"longitude"] = json::value(newTargetLocation.lng); - addMeasure(L"targetLocation", json::value(json)); +void Unit::setTargetPosition(Coords newTargetPosition) +{ + targetPosition = newTargetPosition; } -bool Unit::checkTaskFailed() { +bool Unit::checkTaskFailed() +{ if (getHasTask()) return false; else { @@ -736,7 +708,7 @@ void Unit::resetTaskFailedCounter() { taskCheckCounter = TASK_CHECK_INIT_VALUE; } -void Unit::setHasTask(bool newHasTask) { +void Unit::setHasTask(bool newHasTask) +{ hasTask = newHasTask; - addMeasure(L"hasTask", json::value(newHasTask)); } \ No newline at end of file diff --git a/src/core/src/unitsmanager.cpp b/src/core/src/unitsmanager.cpp index 4d9ed681..1c6b33aa 100644 --- a/src/core/src/unitsmanager.cpp +++ b/src/core/src/unitsmanager.cpp @@ -22,7 +22,7 @@ UnitsManager::~UnitsManager() } -Unit* UnitsManager::getUnit(int ID) +Unit* UnitsManager::getUnit(unsigned int ID) { if (units.find(ID) == units.end()) { return nullptr; @@ -35,7 +35,7 @@ Unit* UnitsManager::getUnit(int ID) bool UnitsManager::isUnitInGroup(Unit* unit) { if (unit != nullptr) { - wstring groupName = unit->getGroupName(); + string groupName = unit->getGroupName(); for (auto const& p : units) { if (p.second->getGroupName().compare(groupName) == 0 && p.second != unit) @@ -57,7 +57,7 @@ bool UnitsManager::isUnitGroupLeader(Unit* unit) Unit* UnitsManager::getGroupLeader(Unit* unit) { if (unit != nullptr) { - wstring groupName = unit->getGroupName(); + string groupName = unit->getGroupName(); /* Find the first unit that has the same groupName */ for (auto const& p : units) @@ -69,7 +69,7 @@ Unit* UnitsManager::getGroupLeader(Unit* unit) return nullptr; } -vector UnitsManager::getGroupMembers(wstring groupName) +vector UnitsManager::getGroupMembers(string groupName) { vector members; for (auto const& p : units) @@ -80,7 +80,7 @@ vector UnitsManager::getGroupMembers(wstring groupName) return members; } -Unit* UnitsManager::getGroupLeader(int ID) +Unit* UnitsManager::getGroupLeader(unsigned int ID) { Unit* unit = getUnit(ID); return getGroupLeader(unit); @@ -88,12 +88,12 @@ Unit* UnitsManager::getGroupLeader(int ID) void UnitsManager::updateExportData(lua_State* L, double dt) { - map unitJSONs = getAllUnits(L); + map unitJSONs = getAllUnits(L); /* Update all units, create them if needed TODO: move code to get constructor in dedicated function */ for (auto const& p : unitJSONs) { - int ID = p.first; + unsigned int ID = p.first; if (units.count(ID) == 0) { json::value type = static_cast(p.second)[L"Type"]; @@ -139,7 +139,7 @@ void UnitsManager::updateMissionData(json::value missionData) /* Update all units */ for (auto const& p : units) { - int ID = p.first; + unsigned int ID = p.first; if (missionData.has_field(to_wstring(ID))) p.second->updateMissionData(missionData[to_wstring(ID)]); } @@ -151,29 +151,15 @@ void UnitsManager::runAILoop() { unit.second->runAILoop(); } -void UnitsManager::getUnitData(json::value& answer, long long time) +string UnitsManager::getUnitData(bool refresh) { - auto unitsJson = json::value::object(); + stringstream ss; for (auto const& p : units) - { - auto unitJson = p.second->getData(time); - if (unitJson.size() > 0) - unitsJson[to_wstring(p.first)] = unitJson; - } - answer[L"units"] = unitsJson; + ss << p.second->getData(refresh); + return ss.str(); } -void UnitsManager::appendUnitData(int ID, json::value& answer, long long time) -{ - Unit* unit = getUnit(ID); - if (unit != nullptr) { - auto unitJson = unit->getData(time); - if (unitJson.size() > 0) - answer[to_wstring(ID)] = unitJson; - } -} - -void UnitsManager::deleteUnit(int ID, bool explosion) +void UnitsManager::deleteUnit(unsigned int ID, bool explosion) { if (getUnit(ID) != nullptr) { @@ -182,7 +168,7 @@ void UnitsManager::deleteUnit(int ID, bool explosion) } } -void UnitsManager::acquireControl(int ID) { +void UnitsManager::acquireControl(unsigned int ID) { Unit* unit = getUnit(ID); if (unit != nullptr) { for (auto const& groupMember : getGroupMembers(unit->getGroupName())) { diff --git a/src/core/src/weapon.cpp b/src/core/src/weapon.cpp index 7705b710..3308c1e8 100644 --- a/src/core/src/weapon.cpp +++ b/src/core/src/weapon.cpp @@ -13,21 +13,19 @@ extern Scheduler* scheduler; extern UnitsManager* unitsManager; /* Weapon */ -Weapon::Weapon(json::value json, int ID) : Unit(json, ID) +Weapon::Weapon(json::value json, unsigned int ID) : Unit(json, ID) { }; /* Missile */ -Missile::Missile(json::value json, int ID) : Weapon(json, ID) +Missile::Missile(json::value json, unsigned int ID) : Weapon(json, ID) { log("New Missile created with ID: " + to_string(ID)); - addMeasure(L"category", json::value(getCategory())); }; /* Bomb */ -Bomb::Bomb(json::value json, int ID) : Weapon(json, ID) +Bomb::Bomb(json::value json, unsigned int ID) : Weapon(json, ID) { log("New Bomb created with ID: " + to_string(ID)); - addMeasure(L"category", json::value(getCategory())); }; \ No newline at end of file diff --git a/src/dcstools/include/dcstools.h b/src/dcstools/include/dcstools.h index db8ff519..5547f686 100644 --- a/src/dcstools/include/dcstools.h +++ b/src/dcstools/include/dcstools.h @@ -5,8 +5,8 @@ void DllExport LogInfo(lua_State* L, string message); void DllExport LogWarning(lua_State* L, string message); void DllExport LogError(lua_State* L, string message); -void DllExport Log(lua_State* L, string message, int level); +void DllExport Log(lua_State* L, string message, unsigned int level); int DllExport dostring_in(lua_State* L, string target, string command); -map DllExport getAllUnits(lua_State* L); -int DllExport TACANChannelToFrequency(int channel, wstring XY); +map DllExport getAllUnits(lua_State* L); +unsigned int DllExport TACANChannelToFrequency(unsigned int channel, char XY); diff --git a/src/dcstools/src/dcstools.cpp b/src/dcstools/src/dcstools.cpp index 64184a98..515d9e7e 100644 --- a/src/dcstools/src/dcstools.cpp +++ b/src/dcstools/src/dcstools.cpp @@ -42,7 +42,7 @@ void LogError(lua_State* L, string message) Log(L, message, errorLevel); } -void Log(lua_State* L, string message, int level) +void Log(lua_State* L, string message, unsigned int level) { STACK_INIT; @@ -56,10 +56,10 @@ void Log(lua_State* L, string message, int level) STACK_CLEAN; } -map getAllUnits(lua_State* L) +map getAllUnits(lua_State* L) { - int res = 0; - map units; + unsigned int res = 0; + map units; STACK_INIT; @@ -83,7 +83,8 @@ map getAllUnits(lua_State* L) lua_pushnil(L); while (lua_next(L, 2) != 0) { - int ID = lua_tonumber(L, -2); + unsigned int ID = lua_tonumber(L, -2); + // TODO more efficient method can be used, converting all the lua data to a json object may be overkill units[ID] = luaTableToJSON(L, -1); STACK_POP(1) } @@ -103,8 +104,8 @@ int dostring_in(lua_State* L, string target, string command) return lua_pcall(L, 2, 0, 0); } -int TACANChannelToFrequency(int channel, wstring XY) +unsigned int TACANChannelToFrequency(unsigned int channel, char XY) { - int basef = (XY == L"X" && channel > 63) || (XY == L"Y" && channel < 64) ? 1087: 961; + unsigned int basef = (XY == 'X' && channel > 63) || (XY == 'Y' && channel < 64) ? 1087 : 961; return (basef + channel) * 1000000; } \ No newline at end of file diff --git a/src/logger/include/interface.h b/src/logger/include/interface.h index f5dbe800..bc65f27d 100644 --- a/src/logger/include/interface.h +++ b/src/logger/include/interface.h @@ -3,4 +3,4 @@ void DllExport log(const std::string& sMessage); void DllExport log(const std::wstring& sMessage); -void DllExport getLogsJSON(json::value& json, int logsNumber = NULL); +void DllExport getLogsJSON(json::value& json, unsigned int logsNumber = NULL); diff --git a/src/logger/include/logger.h b/src/logger/include/logger.h index 20e17d71..6de74ec8 100644 --- a/src/logger/include/logger.h +++ b/src/logger/include/logger.h @@ -7,7 +7,7 @@ class Logger public: void log(const string& sMessage); void log(const wstring& sMessage); - void toJSON(json::value& json, int logsNumber = NULL); + void toJSON(json::value& json, unsigned int logsNumber = NULL); static Logger* GetLogger(); diff --git a/src/logger/src/interface.cpp b/src/logger/src/interface.cpp index 77c743b5..dd1200e0 100644 --- a/src/logger/src/interface.cpp +++ b/src/logger/src/interface.cpp @@ -14,7 +14,7 @@ void log(const wstring& message) LOGGER->log(message); } -void getLogsJSON(json::value& json, int logsNumber) +void getLogsJSON(json::value& json, unsigned int logsNumber) { LOGGER->toJSON(json, logsNumber); } \ No newline at end of file diff --git a/src/logger/src/logger.cpp b/src/logger/src/logger.cpp index 4c9810d3..cb3174ed 100644 --- a/src/logger/src/logger.cpp +++ b/src/logger/src/logger.cpp @@ -32,10 +32,10 @@ void Logger::Close() m_Logfile.close(); } -void Logger::toJSON(json::value& json, int logsNumber) +void Logger::toJSON(json::value& json, unsigned int logsNumber) { lock_guard guard(mutexLock); - int i = 0; + unsigned int i = 0; for (auto itr = m_logs.end(); itr != m_logs.begin(); --itr) { json[to_wstring(m_logs.size() - 1 - i)] = json::value::string(to_wstring(*itr)); diff --git a/src/shared/include/defines.h b/src/shared/include/defines.h index 9289e51d..de0a36ba 100644 --- a/src/shared/include/defines.h +++ b/src/shared/include/defines.h @@ -2,12 +2,12 @@ #define VERSION "v0.2.1" #define LOG_NAME "Olympus_log.txt" -#define REST_ADDRESS L"http://localhost:30000" -#define REST_URI L"olympus" -#define UNITS_URI L"units" -#define LOGS_URI L"logs" -#define AIRBASES_URI L"airbases" -#define BULLSEYE_URI L"bullseyes" -#define MISSION_URI L"mission" +#define REST_ADDRESS "http://localhost:30000" +#define REST_URI "olympus" +#define UNITS_URI "units" +#define LOGS_URI "logs" +#define AIRBASES_URI "airbases" +#define BULLSEYE_URI "bullseyes" +#define MISSION_URI "mission" #define UPDATE_TIME_INTERVAL 0.25 \ No newline at end of file diff --git a/src/shared/include/framework.h b/src/shared/include/framework.h index c1b6de88..60157cb4 100644 --- a/src/shared/include/framework.h +++ b/src/shared/include/framework.h @@ -20,6 +20,7 @@ #include #include #include +#include #include using namespace std; diff --git a/src/utils/include/utils.h b/src/utils/include/utils.h index 4534a8de..3ab1a636 100644 --- a/src/utils/include/utils.h +++ b/src/utils/include/utils.h @@ -16,18 +16,19 @@ struct Offset { // Get current date/time, format is YYYY-MM-DD.HH:mm:ss const DllExport std::string CurrentDateTime(); std::wstring DllExport to_wstring(const std::string& str); +std::string DllExport to_string(json::value& value); std::string DllExport to_string(const std::wstring& wstr); std::string DllExport random_string(size_t length); bool DllExport operator== (const Coords& a, const Coords& b); bool DllExport operator!= (const Coords& a, const Coords& b); -bool DllExport operator== (const Coords& a, const int& b); -bool DllExport operator!= (const Coords& a, const int& b); +bool DllExport operator== (const Coords& a, const double& b); +bool DllExport operator!= (const Coords& a, const double& b); bool DllExport operator== (const Offset& a, const Offset& b); bool DllExport operator!= (const Offset& a, const Offset& b); -bool DllExport operator== (const Offset& a, const int& b); -bool DllExport operator!= (const Offset& a, const int& b); +bool DllExport operator== (const Offset& a, const double& b); +bool DllExport operator!= (const Offset& a, const double& b); double DllExport knotsToMs(const double knots); double DllExport msToKnots(const double ms); diff --git a/src/utils/src/utils.cpp b/src/utils/src/utils.cpp index 9d91fbe7..62299d2d 100644 --- a/src/utils/src/utils.cpp +++ b/src/utils/src/utils.cpp @@ -14,12 +14,16 @@ const std::string CurrentDateTime() std::wstring to_wstring(const std::string& str) { - int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); + unsigned int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (unsigned int)str.size(), NULL, 0); std::wstring wstrTo(size_needed, 0); - MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); + MultiByteToWideChar(CP_UTF8, 0, &str[0], (unsigned int)str.size(), &wstrTo[0], size_needed); return wstrTo; } +std::string to_string(json::value value) { + return to_string(value.as_string()); +} + std::string to_string(const std::wstring& wstr) { if (wstr.empty()) @@ -27,14 +31,14 @@ std::string to_string(const std::wstring& wstr) return ""; } - const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (int)wstr.size(), nullptr, 0, nullptr, nullptr); + const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (unsigned int)wstr.size(), nullptr, 0, nullptr, nullptr); if (size_needed <= 0) { throw std::runtime_error("WideCharToMultiByte() failed: " + std::to_string(size_needed)); } std::string result(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (int)wstr.size(), &result.at(0), size_needed, nullptr, nullptr); + WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (unsigned int)wstr.size(), &result.at(0), size_needed, nullptr, nullptr); return result; } @@ -56,13 +60,13 @@ std::string random_string(size_t length) bool operator== (const Coords& a, const Coords& b) { return a.lat == b.lat && a.lng == b.lng && a.alt == b.alt; } bool operator!= (const Coords& a, const Coords& b) { return !(a == b); } -bool operator== (const Coords& a, const int& b) { return a.lat == b && a.lng == b && a.alt == b; } -bool operator!= (const Coords& a, const int& b) { return !(a == b); } +bool operator== (const Coords& a, const double& b) { return a.lat == b && a.lng == b && a.alt == b; } +bool operator!= (const Coords& a, const double& b) { return !(a == b); } bool operator== (const Offset& a, const Offset& b) { return a.x == b.x && a.y == b.y && a.z == b.z; } bool operator!= (const Offset& a, const Offset& b) { return !(a == b); } -bool operator== (const Offset& a, const int& b) { return a.x == b && a.y == b && a.z == b; } -bool operator!= (const Offset& a, const int& b) { return !(a == b); } +bool operator== (const Offset& a, const double& b) { return a.x == b && a.y == b && a.z == b; } +bool operator!= (const Offset& a, const double& b) { return !(a == b); } double knotsToMs(const double knots) { @@ -79,4 +83,4 @@ double ftToM(const double ft) { double mToFt(const double m) { return m / 0.3048; -} \ No newline at end of file +} diff --git a/third-party/base64/include/base64.hpp b/third-party/base64/include/base64.hpp index adcf1c04..5590e7a8 100644 --- a/third-party/base64/include/base64.hpp +++ b/third-party/base64/include/base64.hpp @@ -6,76 +6,81 @@ namespace base64 { -inline std::string get_base64_chars() { - static std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - return base64_chars; -} + inline std::string get_base64_chars() { + static std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + return base64_chars; + } + inline std::string to_base64(std::string const& data) { + return to_base64(data.c_str(), data.length()); + } -inline std::string to_base64(std::string const &data) { - int counter = 0; - uint32_t bit_stream = 0; - const std::string base64_chars = get_base64_chars(); - std::string encoded; - int offset = 0; - for (unsigned char c : data) { - auto num_val = static_cast(c); - offset = 16 - counter % 3 * 8; - bit_stream += num_val << offset; - if (offset == 16) { - encoded += base64_chars.at(bit_stream >> 18 & 0x3f); - } - if (offset == 8) { - encoded += base64_chars.at(bit_stream >> 12 & 0x3f); - } - if (offset == 0 && counter != 3) { - encoded += base64_chars.at(bit_stream >> 6 & 0x3f); - encoded += base64_chars.at(bit_stream & 0x3f); - bit_stream = 0; - } - counter++; - } - if (offset == 16) { - encoded += base64_chars.at(bit_stream >> 12 & 0x3f); - encoded += "=="; - } - if (offset == 8) { - encoded += base64_chars.at(bit_stream >> 6 & 0x3f); - encoded += '='; - } - return encoded; -} - -inline std::string from_base64(std::string const &data) { - int counter = 0; - uint32_t bit_stream = 0; - std::string decoded; - int offset = 0; - const std::string base64_chars = get_base64_chars(); - for (unsigned char c : data) { - auto num_val = base64_chars.find(c); - if (num_val != std::string::npos) { - offset = 18 - counter % 4 * 6; - bit_stream += num_val << offset; - if (offset == 12) { - decoded += static_cast(bit_stream >> 16 & 0xff); - } - if (offset == 6) { - decoded += static_cast(bit_stream >> 8 & 0xff); - } - if (offset == 0 && counter != 4) { - decoded += static_cast(bit_stream & 0xff); - bit_stream = 0; - } - } else if (c != '=') { - return std::string(); - } - counter++; - } - return decoded; -} + inline std::string to_base64(const char* data, size_t size) { + int counter = 0; + uint32_t bit_stream = 0; + const std::string base64_chars = get_base64_chars(); + std::string encoded; + encoded.reserve(ceil(4.0 / 3.0 * size)); + int offset = 0; + for (unsigned int idx = 0; idx < size; idx++) { + unsigned char c = data[idx]; + auto num_val = static_cast(c); + offset = 16 - counter % 3 * 8; + bit_stream += num_val << offset; + if (offset == 16) { + encoded += base64_chars.at(bit_stream >> 18 & 0x3f); + } + if (offset == 8) { + encoded += base64_chars.at(bit_stream >> 12 & 0x3f); + } + if (offset == 0 && counter != 3) { + encoded += base64_chars.at(bit_stream >> 6 & 0x3f); + encoded += base64_chars.at(bit_stream & 0x3f); + bit_stream = 0; + } + counter++; + } + if (offset == 16) { + encoded += base64_chars.at(bit_stream >> 12 & 0x3f); + encoded += "=="; + } + if (offset == 8) { + encoded += base64_chars.at(bit_stream >> 6 & 0x3f); + encoded += '='; + } + return encoded; + } + inline std::string from_base64(std::string const& data) { + int counter = 0; + uint32_t bit_stream = 0; + std::string decoded; + int offset = 0; + const std::string base64_chars = get_base64_chars(); + for (unsigned char c : data) { + auto num_val = base64_chars.find(c); + if (num_val != std::string::npos) { + offset = 18 - counter % 4 * 6; + bit_stream += num_val << offset; + if (offset == 12) { + decoded += static_cast(bit_stream >> 16 & 0xff); + } + if (offset == 6) { + decoded += static_cast(bit_stream >> 8 & 0xff); + } + if (offset == 0 && counter != 4) { + decoded += static_cast(bit_stream & 0xff); + bit_stream = 0; + } + } + else if (c != '=') { + return std::string(); + } + counter++; + } + return decoded; + } } #endif // BASE_64_HPP \ No newline at end of file