129 lines
4.5 KiB
C++
129 lines
4.5 KiB
C++
#include <atomic>
|
|
#include <chrono>
|
|
#include <filesystem>
|
|
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <Windows.h>
|
|
|
|
#include <imgui.h>
|
|
#include "Config.h"
|
|
#include "Logger.h"
|
|
#include "Overlay/GameOverlay.h"
|
|
#include "Overlay/OverlayWindow.h"
|
|
#include "Runtime/DayZRuntimeService.h"
|
|
#include "Web/WebRadarServer.h"
|
|
|
|
// Shared stop flag so the console Ctrl+C / close handler can reach it.
|
|
static std::atomic<bool>* g_stopFlag = nullptr;
|
|
|
|
static BOOL WINAPI ConsoleCtrlHandler(DWORD signal) {
|
|
if (signal == CTRL_C_EVENT || signal == CTRL_CLOSE_EVENT ||
|
|
signal == CTRL_BREAK_EVENT)
|
|
{
|
|
if (g_stopFlag) g_stopFlag->store(true);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int main() {
|
|
std::filesystem::create_directories("logs");
|
|
AppLogger::Init();
|
|
auto log = AppLogger::Get();
|
|
log->info("DayZ Memory Reader - Starting");
|
|
|
|
RuntimeConfig rtCfg = RuntimeConfig::Load("config/config.cfg");
|
|
DayZRuntimeService service(rtCfg);
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Config — loaded from config/overlay.json (defaults if missing).
|
|
// -------------------------------------------------------------------------
|
|
static const std::string kCfgPath = "config/overlay.json";
|
|
OverlayConfig cfg = OverlayConfig::Load(kCfgPath);
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Web radar server — settings come from config.
|
|
// -------------------------------------------------------------------------
|
|
WebRadarConfig webCfg;
|
|
webCfg.bindAddress = cfg.webBindAddress;
|
|
webCfg.port = cfg.webPort;
|
|
webCfg.password = cfg.webPassword;
|
|
|
|
WebRadarServer webRadar(webCfg);
|
|
webRadar.Start();
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Runtime service callback: log stats + push snapshot to web radar.
|
|
// -------------------------------------------------------------------------
|
|
|
|
service.SetUpdateCallback([&log, &webRadar](const RuntimeUpdate& update) {
|
|
// Always push to the web radar (even when not yet attached) so the
|
|
// browser client sees connection/status changes immediately.
|
|
webRadar.PushSnapshot(update);
|
|
|
|
if (!update.areBaseObjectsReady) {
|
|
// Status messages are already de-duplicated inside WaitForSession.
|
|
return;
|
|
}
|
|
|
|
// Periodic heartbeat at most once every 10 seconds. Kept terse — the
|
|
// interesting per-event detail (admins detected, skeletons lost) is logged
|
|
// as it happens by the runtime service, not polled here.
|
|
using Clock = std::chrono::steady_clock;
|
|
static auto nextLog = Clock::time_point{};
|
|
auto now = Clock::now();
|
|
if (now < nextLog) return;
|
|
nextLog = now + std::chrono::seconds(10);
|
|
|
|
// Skeleton coverage: how many in-range players currently have valid bones.
|
|
size_t skelOk = 0, admins = 0;
|
|
for (const auto& p : update.players) {
|
|
if (p.skeleton.valid) ++skelOk;
|
|
if (p.isAdmin) ++admins;
|
|
}
|
|
|
|
log->info("[Live] Players={} (bones {}/{}, admins {}) Zombies={} Vehicles={} Server='{}'",
|
|
update.players.size(),
|
|
skelOk, update.players.size(), admins,
|
|
update.zombies.size(),
|
|
update.carsAndBoats.size(),
|
|
update.serverName.value_or("?"));
|
|
});
|
|
|
|
service.Start();
|
|
|
|
// Overlay polls GetLatestUpdate() each frame; no extra callback needed.
|
|
std::atomic<bool> stopFlag{false};
|
|
g_stopFlag = &stopFlag;
|
|
|
|
GameOverlay overlay(service, cfg, kCfgPath);
|
|
overlay.SetWebRadarPort(webCfg.port);
|
|
overlay.SetExitCallback([&stopFlag]() { stopFlag.store(true); });
|
|
OverlayWindow window;
|
|
window.SetResolutionOverride(cfg.overlayWidth, cfg.overlayHeight);
|
|
overlay.SetResizeCallback([&window](int w, int h) { window.ResizeTo(w, h); });
|
|
|
|
window.SetDrawCallback([&overlay](float w, float h) {
|
|
overlay.Draw(w, h);
|
|
});
|
|
window.SetInputQueryCallback([&overlay]() {
|
|
return overlay.IsMenuOpen();
|
|
});
|
|
window.SetFontReadyCallback([&overlay](ImFont* close, ImFont* lootFar) {
|
|
overlay.SetLootFonts(close, lootFar);
|
|
});
|
|
|
|
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
|
|
|
|
// Blocks until the overlay window is closed or stopFlag is set externally.
|
|
window.Run(stopFlag);
|
|
|
|
webRadar.Stop();
|
|
service.Stop();
|
|
log->info("Stopped.");
|
|
spdlog::shutdown();
|
|
return 0;
|
|
}
|