mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Tweaks and implemented workaround to MIST bug
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -10,6 +10,7 @@ public:
|
||||
~Scheduler();
|
||||
|
||||
void appendCommand(Command* command);
|
||||
int getCurrentLoad();
|
||||
void execute(lua_State* L);
|
||||
void handleRequest(string key, json::value value);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user