Files
Daybreak/Daybreak.GWCA/source/GameStateModule.cpp
T
amacocianandGitHub 51d6fb0f42 Fix vanquishing API (#448)
Pass Health/Energy from GWCA
Fix for enemy primary professions
Fix for LiveCharts2 memory leak
Update GWCA

Closes #447
Closes #446
Closes #445
Closes #444
Closes #442
2023-10-29 16:59:05 +00:00

106 lines
3.2 KiB
C++

#include "pch.h"
#include "GameStateModule.h"
#include <GWCA/Managers/GameThreadMgr.h>
#include <GWCA/Managers/AgentMgr.h>
#include <GWCA/GameEntities/Agent.h>
#include <GWCA/Managers/MapMgr.h>
#include <future>
#include <payloads/GameStatePayload.h>
#include <json.hpp>
#include <queue>
#include <algorithm>
namespace Daybreak::Modules::GameStateModule {
std::queue<std::promise<GameStatePayload>*> PromiseQueue;
std::mutex GameThreadMutex;
GW::HookEntry GameThreadHook;
volatile bool initialized = false;
std::list<GW::AgentLiving> GetLivingAgents() {
std::list<GW::AgentLiving> agentList;
const GW::AgentArray* agents_ptr = GW::Agents::GetAgentArray();
GW::AgentArray* agents = GW::Agents::GetAgentArray();
if (!agents) {
return agentList;
}
for (auto* a : *agents) {
const GW::AgentLiving* agent = a ? a->GetAsAgentLiving() : nullptr;
if (agent) {
agentList.push_back(*agent);
}
}
return agentList;
}
std::list<StatePayload> GetStates(
std::list<GW::AgentLiving> agents) {
std::list<StatePayload> states;
for (auto& agent : agents) {
StatePayload state;
state.Id = agent.agent_id;
state.PosX = agent.pos.x;
state.PosY = agent.pos.y;
state.State = agent.type_map;
state.Health = agent.hp * (agent.max_hp > 0 ? agent.max_hp : 1);
state.Energy = agent.energy * (agent.max_energy > 0 ? agent.max_energy : 1);
states.push_back(state);
}
return states;
}
GameStatePayload GetPayload() {
GameStatePayload gamePayload;
if (!GW::Map::GetIsMapLoaded()) {
return gamePayload;
}
auto agents = GetLivingAgents();
if (agents.empty()) {
return gamePayload;
}
auto states = GetStates(agents);
gamePayload.States = states;
return gamePayload;
}
void EnsureInitialized() {
GameThreadMutex.lock();
if (!initialized) {
GW::GameThread::RegisterGameThreadCallback(&GameThreadHook, [&](GW::HookStatus*) {
while (!PromiseQueue.empty()) {
auto promise = PromiseQueue.front();
PromiseQueue.pop();
try {
auto payload = GetPayload();
promise->set_value(payload);
}
catch (...) {
GameStatePayload payload;
promise->set_value(payload);
}
}
});
initialized = true;
}
GameThreadMutex.unlock();
}
void GetGameStateInfo(const httplib::Request&, httplib::Response& res) {
auto callbackEntry = new GW::HookEntry;
auto response = new std::promise<GameStatePayload>;
EnsureInitialized();
PromiseQueue.emplace(response);
json responsePayload = response->get_future().get();
delete callbackEntry;
delete response;
res.set_content(responsePayload.dump(), "text/json");
}
}