mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added new method for handling data
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
#include "logger.h"
|
||||
|
||||
namespace CommandPriority {
|
||||
enum CommandPriorities { LOW, MEDIUM, HIGH };
|
||||
enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE };
|
||||
};
|
||||
|
||||
namespace SetCommandType {
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
location(location),
|
||||
immediate(immediate)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 100 * !immediate; }
|
||||
@@ -175,7 +175,7 @@ public:
|
||||
airbaseName(airbaseName),
|
||||
immediate(immediate)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 100 * !immediate; }
|
||||
|
||||
@@ -15,6 +15,8 @@ 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;
|
||||
@@ -27,6 +29,8 @@ private:
|
||||
void task();
|
||||
|
||||
atomic<bool> runListener;
|
||||
json::value updateJson;
|
||||
json::value refreshJson;
|
||||
|
||||
wstring password = L"";
|
||||
};
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
void setDefaults(bool force = false);
|
||||
int getID() { return ID; }
|
||||
void runAILoop();
|
||||
void updateExportData(json::value json);
|
||||
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"; };
|
||||
|
||||
@@ -10,16 +10,18 @@ public:
|
||||
UnitsManager(lua_State* L);
|
||||
~UnitsManager();
|
||||
|
||||
map<int, Unit*>& getUnits() { return units; };
|
||||
Unit* getUnit(int ID);
|
||||
bool isUnitInGroup(Unit* unit);
|
||||
bool isUnitGroupLeader(Unit* unit);
|
||||
Unit* getGroupLeader(int ID);
|
||||
Unit* getGroupLeader(Unit* unit);
|
||||
vector<Unit*> getGroupMembers(wstring groupName);
|
||||
void updateExportData(lua_State* L);
|
||||
void updateExportData(lua_State* L, double dt = 0);
|
||||
void updateMissionData(json::value missionData);
|
||||
void runAILoop();
|
||||
void getData(json::value& answer, long long time);
|
||||
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);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "scheduler.h"
|
||||
#include "scriptLoader.h"
|
||||
#include "luatools.h"
|
||||
#include <chrono>
|
||||
using namespace std::chrono;
|
||||
|
||||
auto before = std::chrono::system_clock::now();
|
||||
UnitsManager* unitsManager = nullptr;
|
||||
@@ -17,6 +19,10 @@ json::value mission;
|
||||
mutex mutexLock;
|
||||
bool initialized = false;
|
||||
string sessionHash;
|
||||
int lastUpdateIndex = 0;
|
||||
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)
|
||||
@@ -61,21 +67,44 @@ extern "C" DllExport int coreFrame(lua_State* L)
|
||||
/* Lock for thread safety */
|
||||
lock_guard<mutex> guard(mutexLock);
|
||||
|
||||
frameCounter++;
|
||||
|
||||
const std::chrono::duration<double> duration = std::chrono::system_clock::now() - before;
|
||||
|
||||
/* TODO make intervals editable */
|
||||
if (duration.count() > UPDATE_TIME_INTERVAL)
|
||||
if (unitsManager != nullptr) {
|
||||
// TODO put in a function
|
||||
vector<int> 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())
|
||||
{
|
||||
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||
lastUpdateTime = ms.count();
|
||||
frameRate = frameCounter / duration.count();
|
||||
frameCounter = 0;
|
||||
|
||||
if (unitsManager != nullptr)
|
||||
{
|
||||
unitsManager->updateExportData(L);
|
||||
unitsManager->runAILoop();
|
||||
}
|
||||
unitsManager->updateExportData(L, duration.count());
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ void Scheduler::execute(lua_State* L)
|
||||
return;
|
||||
}
|
||||
|
||||
int priority = CommandPriority::HIGH;
|
||||
int priority = CommandPriority::IMMEDIATE;
|
||||
while (priority >= CommandPriority::LOW)
|
||||
{
|
||||
for (auto command : commands)
|
||||
|
||||
@@ -36,7 +36,8 @@ Server::Server(lua_State* L):
|
||||
serverThread(nullptr),
|
||||
runListener(true)
|
||||
{
|
||||
|
||||
refreshJson = json::value::object();
|
||||
updateJson = json::value::object();
|
||||
}
|
||||
|
||||
void Server::start(lua_State* L)
|
||||
@@ -93,7 +94,10 @@ void Server::handle_get(http_request request)
|
||||
time = 0;
|
||||
}
|
||||
}
|
||||
unitsManager->getData(answer, time);
|
||||
if (time == 0)
|
||||
unitsManager->getUnitData(answer, 0);
|
||||
else
|
||||
answer[L"units"] = updateJson;
|
||||
}
|
||||
else if (path[0] == LOGS_URI)
|
||||
{
|
||||
|
||||
@@ -92,31 +92,31 @@ void Unit::addMeasure(wstring key, json::value value)
|
||||
}
|
||||
|
||||
void Unit::runAILoop() {
|
||||
/* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
|
||||
const bool isUnitControlledByOlympus = getControlled();
|
||||
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 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;
|
||||
|
||||
// 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
|
||||
if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman)
|
||||
{
|
||||
if (checkTaskFailed() && state != State::IDLE && State::LAND)
|
||||
setState(State::IDLE);
|
||||
const bool isUnitAlive = getAlive();
|
||||
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
|
||||
if (!(isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits)) return;
|
||||
|
||||
if (checkTaskFailed() && state != State::IDLE && State::LAND)
|
||||
setState(State::IDLE);
|
||||
|
||||
AIloop();
|
||||
}
|
||||
AIloop();
|
||||
}
|
||||
|
||||
void Unit::updateExportData(json::value json)
|
||||
void Unit::updateExportData(json::value json, double dt)
|
||||
{
|
||||
/* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */
|
||||
if (oldPosition != NULL)
|
||||
{
|
||||
double dist = 0;
|
||||
Geodesic::WGS84().Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist);
|
||||
setSpeed(getSpeed() * 0.95 + (dist / UPDATE_TIME_INTERVAL) * 0.05);
|
||||
if (dt > 0)
|
||||
setSpeed(getSpeed() * 0.95 + (dist / dt) * 0.05);
|
||||
}
|
||||
oldPosition = Coords(latitude, longitude, altitude);
|
||||
|
||||
@@ -160,7 +160,7 @@ void Unit::updateMissionData(json::value json)
|
||||
setHasTask(json[L"hasTask"].as_bool());
|
||||
}
|
||||
|
||||
json::value Unit::getData(long long time, bool sendAll)
|
||||
json::value Unit::getData(long long time, bool getAll)
|
||||
{
|
||||
auto json = json::value::object();
|
||||
|
||||
@@ -178,7 +178,7 @@ json::value Unit::getData(long long time, bool sendAll)
|
||||
if (json[L"baseData"].size() == 0)
|
||||
json.erase(L"baseData");
|
||||
|
||||
if (alive || sendAll) {
|
||||
if (alive || getAll) {
|
||||
/********** Flight data **********/
|
||||
json[L"flightData"] = json::value::object();
|
||||
for (auto key : { L"latitude", L"longitude", L"altitude", L"speed", L"heading" })
|
||||
|
||||
@@ -59,18 +59,11 @@ Unit* UnitsManager::getGroupLeader(Unit* unit)
|
||||
if (unit != nullptr) {
|
||||
wstring groupName = unit->getGroupName();
|
||||
|
||||
/* Get the unit IDs in order */
|
||||
std::vector<int> keys;
|
||||
for (auto const& p : units)
|
||||
keys.push_back(p.first);
|
||||
sort(keys.begin(), keys.end());
|
||||
|
||||
/* Find the first unit that has the same groupName */
|
||||
for (auto const& tempID : keys)
|
||||
for (auto const& p : units)
|
||||
{
|
||||
Unit* tempUnit = getUnit(tempID);
|
||||
if (tempUnit != nullptr && tempUnit->getGroupName().compare(groupName) == 0)
|
||||
return tempUnit;
|
||||
if (p.second->getGroupName().compare(groupName) == 0)
|
||||
return p.second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@@ -93,7 +86,7 @@ Unit* UnitsManager::getGroupLeader(int ID)
|
||||
return getGroupLeader(unit);
|
||||
}
|
||||
|
||||
void UnitsManager::updateExportData(lua_State* L)
|
||||
void UnitsManager::updateExportData(lua_State* L, double dt)
|
||||
{
|
||||
map<int, json::value> unitJSONs = getAllUnits(L);
|
||||
|
||||
@@ -132,15 +125,13 @@ void UnitsManager::updateExportData(lua_State* L)
|
||||
else {
|
||||
/* Update the unit if present*/
|
||||
if (units.count(ID) != 0)
|
||||
units[ID]->updateExportData(p.second);
|
||||
units[ID]->updateExportData(p.second, dt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the units that are not present in the JSON as dead (probably have been destroyed) */
|
||||
for (auto const& unit : units)
|
||||
{
|
||||
unit.second->setAlive(unitJSONs.find(unit.first) != unitJSONs.end());
|
||||
}
|
||||
}
|
||||
|
||||
void UnitsManager::updateMissionData(json::value missionData)
|
||||
@@ -150,32 +141,38 @@ void UnitsManager::updateMissionData(json::value missionData)
|
||||
{
|
||||
int ID = p.first;
|
||||
if (missionData.has_field(to_wstring(ID)))
|
||||
{
|
||||
p.second->updateMissionData(missionData[to_wstring(ID)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitsManager::runAILoop() {
|
||||
/* Run the AI Loop on all units */
|
||||
for (auto const& unit : units)
|
||||
{
|
||||
unit.second->runAILoop();
|
||||
}
|
||||
}
|
||||
|
||||
void UnitsManager::getData(json::value& answer, long long time)
|
||||
void UnitsManager::getUnitData(json::value& answer, long long time)
|
||||
{
|
||||
auto unitsJson = json::value::object();
|
||||
for (auto const& p : units)
|
||||
{
|
||||
auto unitJson = p.second->getData(time);
|
||||
if (unitJson.size() > 0)
|
||||
unitsJson[to_wstring(p.first)] = p.second->getData(time);
|
||||
unitsJson[to_wstring(p.first)] = unitJson;
|
||||
}
|
||||
answer[L"units"] = unitsJson;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (getUnit(ID) != nullptr)
|
||||
|
||||
Reference in New Issue
Block a user