Tweaks and implemented workaround to MIST bug

This commit is contained in:
Pax1601
2023-07-12 17:01:03 +02:00
parent b78cd27e4e
commit a949a9bf22
27 changed files with 453 additions and 135 deletions

View File

@@ -163,7 +163,7 @@ public:
priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW;
};
virtual string getString(lua_State* L);
virtual unsigned int getLoad() { return 100 * !immediate; }
virtual unsigned int getLoad() { return immediate? 1: 100; }
private:
const string coalition;
@@ -172,7 +172,29 @@ private:
const bool immediate;
};
/* Spawn air unit command */
/* Spawn navy unit command */
class SpawnNavyUnits : public Command
{
public:
SpawnNavyUnits(string coalition, vector<string> unitTypes, vector<Coords> locations, bool immediate) :
coalition(coalition),
unitTypes(unitTypes),
locations(locations),
immediate(immediate)
{
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual string getString(lua_State* L);
virtual unsigned int getLoad() { return immediate ? 1 : 100; }
private:
const string coalition;
const vector<string> unitTypes;
const vector<Coords> locations;
const bool immediate;
};
/* Spawn aircraft command */
class SpawnAircrafts : public Command
{
public:
@@ -187,7 +209,34 @@ public:
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual string getString(lua_State* L);
virtual unsigned int getLoad() { return 100 * !immediate; }
virtual unsigned int getLoad() { return immediate ? 1 : 100; }
private:
const string coalition;
const vector<string> unitTypes;
const vector<Coords> locations;
const vector<string> loadouts;
const string airbaseName;
const bool immediate;
};
/* Spawn helicopter command */
class SpawnHelicopters : public Command
{
public:
SpawnHelicopters(string coalition, vector<string> unitTypes, vector<Coords> locations, vector<string> loadouts, string airbaseName, bool immediate) :
coalition(coalition),
unitTypes(unitTypes),
locations(locations),
loadouts(loadouts),
airbaseName(airbaseName),
immediate(immediate)
{
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual string getString(lua_State* L);
virtual unsigned int getLoad() { return immediate ? 1 : 100; }
private:
const string coalition;
@@ -220,18 +269,21 @@ private:
class Delete : public Command
{
public:
Delete(unsigned int ID, bool explosion) :
Delete(unsigned int ID, bool explosion, bool immediate ) :
ID(ID),
explosion(explosion)
explosion(explosion),
immediate(immediate)
{
priority = CommandPriority::HIGH;
immediate = immediate;
};
virtual string getString(lua_State* L);
virtual unsigned int getLoad() { return 20; }
virtual unsigned int getLoad() { return immediate? 1: 20; }
private:
const unsigned int ID;
const bool explosion;
const bool immediate;
};
/* SetTask command */

View File

@@ -10,6 +10,7 @@ public:
~Scheduler();
void appendCommand(Command* command);
int getCurrentLoad();
void execute(lua_State* L);
void handleRequest(string key, json::value value);

View File

@@ -21,7 +21,7 @@ public:
void updateMissionData(json::value missionData);
void runAILoop();
string getUnitData(stringstream &ss, unsigned long long time);
void deleteUnit(unsigned int ID, bool explosion);
void deleteUnit(unsigned int ID, bool explosion, bool immediate);
void acquireControl(unsigned int ID);
private:

View File

@@ -60,6 +60,30 @@ string SpawnGroundUnits::getString(lua_State* L)
return commandSS.str();
}
/* Spawn ground units command */
string SpawnNavyUnits::getString(lua_State* L)
{
if (unitTypes.size() != locations.size()) return "";
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < unitTypes.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "unitType = " << "\"" << unitTypes[i] << "\"" << ", "
<< "lat = " << locations[i].lat << ", "
<< "lng = " << locations[i].lng << "},";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.spawnUnits, {"
<< "category = " << "\"" << "NavyUnit" << "\"" << ", "
<< "coalition = " << "\"" << coalition << "\"" << ", "
<< "units = " << "{" << unitsSS.str() << "}" << "}";
return commandSS.str();
}
/* Spawn aircrafts command */
string SpawnAircrafts::getString(lua_State* L)
{
@@ -86,6 +110,34 @@ string SpawnAircrafts::getString(lua_State* L)
return commandSS.str();
}
/* Spawn helicopters command */
string SpawnHelicopters::getString(lua_State* L)
{
if (unitTypes.size() != locations.size() || unitTypes.size() != loadouts.size()) return "";
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < unitTypes.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "unitType = " << "\"" << unitTypes[i] << "\"" << ", "
<< "lat = " << locations[i].lat << ", "
<< "lng = " << locations[i].lng << ", "
<< "alt = " << locations[i].alt << ", "
<< "loadout = \"" << loadouts[i] << "\"" << "},";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.spawnUnits, {"
<< "category = " << "\"" << "Helicopter" << "\"" << ", "
<< "coalition = " << "\"" << coalition << "\"" << ", "
<< "airbaseName = \"" << airbaseName << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}";
return commandSS.str();
}
/* Clone unit command */
string Clone::getString(lua_State* L)
{

View File

@@ -9,7 +9,8 @@
#include <chrono>
using namespace std::chrono;
auto before = std::chrono::system_clock::now();
auto lastUpdate = std::chrono::system_clock::now();
auto lastExecution = std::chrono::system_clock::now();
/* Singleton objects */
UnitsManager* unitsManager = nullptr;
@@ -72,27 +73,33 @@ extern "C" DllExport int coreFrame(lua_State* L)
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<double> duration = std::chrono::system_clock::now() - before;
if (duration.count() > UPDATE_TIME_INTERVAL * (60.0 / frameRate))
const std::chrono::duration<double> updateDuration = std::chrono::system_clock::now() - lastUpdate;
double updateTimeInterval = max(UPDATE_TIME_INTERVAL, UPDATE_TIME_INTERVAL * (60.0 / frameRate));
if (updateDuration.count() > updateTimeInterval)
{
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
if (duration.count() > 0)
frameRate = frameCounter / duration.count();
if (updateDuration.count() > 0)
frameRate = frameCounter / updateDuration.count();
frameCounter = 0;
if (unitsManager != nullptr) {
unitsManager->updateExportData(L, duration.count());
unitsManager->updateExportData(L, updateDuration.count());
unitsManager->runAILoop();
}
before = std::chrono::system_clock::now();
lastUpdate = std::chrono::system_clock::now();
}
if (scheduler != nullptr)
scheduler->execute(L);
const std::chrono::duration<double> executionDuration = std::chrono::system_clock::now() - lastExecution;
double executionTimeInterval = max(EXECUTION_TIME_INTERVAL, EXECUTION_TIME_INTERVAL * (60.0 / frameRate));
if (executionDuration.count() > executionTimeInterval) {
if (scheduler != nullptr)
scheduler->execute(L);
lastExecution = std::chrono::system_clock::now();
}
return(0);
}
@@ -104,28 +111,19 @@ extern "C" DllExport int coreMissionData(lua_State * L)
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "missionData");
json::value missionData = luaTableToJSON(L, -1);
try
{
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "missionData");
json::value missionData = luaTableToJSON(L, -1);
if (missionData.has_object_field(L"unitsData"))
unitsManager->updateMissionData(missionData[L"unitsData"]);
if (missionData.has_object_field(L"airbases"))
airbases = missionData[L"airbases"];
if (missionData.has_object_field(L"bullseyes"))
bullseyes = missionData[L"bullseyes"];
if (missionData.has_object_field(L"mission"))
mission = missionData[L"mission"];
if (missionData.has_object_field(L"unitsData")) {
unitsManager->updateMissionData(missionData[L"unitsData"]);
}
catch (exception const& e)
{
log(e.what());
}
if (missionData.has_object_field(L"airbases"))
airbases = missionData[L"airbases"];
if (missionData.has_object_field(L"bullseyes"))
bullseyes = missionData[L"bullseyes"];
if (missionData.has_object_field(L"mission"))
mission = missionData[L"mission"];
return(0);
}

View File

@@ -23,6 +23,15 @@ void Scheduler::appendCommand(Command* command)
commands.push_back(command);
}
int Scheduler::getCurrentLoad()
{
int currentLoad = 0;
for (auto command : commands) {
currentLoad += command->getLoad();
}
return currentLoad;
}
void Scheduler::execute(lua_State* L)
{
/* Decrease the active computation load. New commands can be sent only if the load has reached 0.
@@ -42,7 +51,7 @@ void Scheduler::execute(lua_State* L)
if (dostring_in(L, "server", (commandString)))
log("Error executing command " + commandString);
else
log("Command '" + commandString + "' executed correctly, current load " + to_string(load));
log("Command '" + commandString + "' executed correctly, current load " + to_string(getCurrentLoad()));
load = command->getLoad();
commands.remove(command);
return;
@@ -92,25 +101,6 @@ void Scheduler::handleRequest(string key, json::value value)
Coords loc; loc.lat = lat; loc.lng = lng;
command = dynamic_cast<Command*>(new Smoke(color, loc));
}
else if (key.compare("spawnGroundUnits") == 0)
{
bool immediate = value[L"immediate"].as_bool();
string coalition = to_string(value[L"coalition"]);
vector<string> unitTypes;
vector<Coords> locations;
for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double();
Coords location; location.lat = lat; location.lng = lng;
log("Spawning " + coalition + " ground unit of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
unitTypes.push_back(unitType);
locations.push_back(location);
}
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, unitTypes, locations, immediate));
}
else if (key.compare("spawnAircrafts") == 0)
{
bool immediate = value[L"immediate"].as_bool();
@@ -127,15 +117,78 @@ void Scheduler::handleRequest(string key, json::value value)
double alt = unit[L"altitude"].as_double();
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
string loadout = to_string(unit[L"loadout"]);
log("Spawning " + coalition + " air unit unit of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
log("Spawning " + coalition + " aircraft of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
unitTypes.push_back(unitType);
locations.push_back(location);
loadouts.push_back(loadout);
}
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, unitTypes, locations, loadouts, airbaseName, immediate));
}
else if (key.compare("spawnHelicopters") == 0)
{
bool immediate = value[L"immediate"].as_bool();
string coalition = to_string(value[L"coalition"]);
string airbaseName = to_string(value[L"airbaseName"]);
vector<string> unitTypes;
vector<Coords> locations;
vector<string> loadouts;
for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double();
double alt = unit[L"altitude"].as_double();
Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
string loadout = to_string(unit[L"loadout"]);
log("Spawning " + coalition + " helicopter of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
unitTypes.push_back(unitType);
locations.push_back(location);
loadouts.push_back(loadout);
}
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, unitTypes, locations, loadouts, airbaseName, immediate));
}
else if (key.compare("spawnGroundUnits") == 0)
{
bool immediate = value[L"immediate"].as_bool();
string coalition = to_string(value[L"coalition"]);
vector<string> unitTypes;
vector<Coords> locations;
for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double();
Coords location; location.lat = lat; location.lng = lng;
log("Spawning " + coalition + " GroundUnit of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
unitTypes.push_back(unitType);
locations.push_back(location);
}
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, unitTypes, locations, immediate));
}
else if (key.compare("spawnNavyUnits") == 0)
{
bool immediate = value[L"immediate"].as_bool();
string coalition = to_string(value[L"coalition"]);
vector<string> unitTypes;
vector<Coords> locations;
for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double();
Coords location; location.lat = lat; location.lng = lng;
log("Spawning " + coalition + " NavyUnit of type " + unitType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
unitTypes.push_back(unitType);
locations.push_back(location);
}
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, unitTypes, locations, immediate));
}
else if (key.compare("attackUnit") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
@@ -287,7 +340,8 @@ void Scheduler::handleRequest(string key, json::value value)
{
unsigned int ID = value[L"ID"].as_integer();
bool explosion = value[L"explosion"].as_bool();
unitsManager->deleteUnit(ID, explosion);
bool immediate = value[L"immediate"].as_bool();
unitsManager->deleteUnit(ID, explosion, immediate);
}
else if (key.compare("refuel") == 0)
{
@@ -414,7 +468,7 @@ void Scheduler::handleRequest(string key, json::value value)
if (command != nullptr)
{
appendCommand(command);
log("New command appended correctly to stack. Current server load: " + to_string(load));
log("New command appended correctly to stack. Current server load: " + to_string(getCurrentLoad()));
}
}

View File

@@ -164,11 +164,11 @@ string UnitsManager::getUnitData(stringstream &ss, unsigned long long time)
return to_base64(ss.str());
}
void UnitsManager::deleteUnit(unsigned int ID, bool explosion)
void UnitsManager::deleteUnit(unsigned int ID, bool explosion, bool immediate)
{
if (getUnit(ID) != nullptr)
{
Command* command = dynamic_cast<Command*>(new Delete(ID, explosion));
Command* command = dynamic_cast<Command*>(new Delete(ID, explosion, immediate));
scheduler->appendCommand(command);
}
}

View File

@@ -1,6 +1,6 @@
#pragma once
#define VERSION "v0.2.1"
#define VERSION "v0.4.0-alpha"
#define LOG_NAME "Olympus_log.txt"
#define REST_ADDRESS "http://localhost:30000"
#define REST_URI "olympus"
@@ -10,4 +10,5 @@
#define BULLSEYE_URI "bullseyes"
#define MISSION_URI "mission"
#define UPDATE_TIME_INTERVAL 0.25
#define UPDATE_TIME_INTERVAL 0.25
#define EXECUTION_TIME_INTERVAL 0.05