Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 126 additions & 65 deletions mods/src/patches/parts/sync.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1095,10 +1095,120 @@ static void ship_combat_log_data()
namespace processors
{

static void queue_battle_ids(const std::vector<uint64_t>& battle_ids)
{
std::vector<uint64_t> to_enqueue;
{
using trackers::previously_sent_battlelogs;
using trackers::previously_sent_battlelogs_mtx;

std::scoped_lock lk(previously_sent_battlelogs_mtx);

for (const auto id : battle_ids | std::views::reverse) {
if (eastl::find(previously_sent_battlelogs.begin(), previously_sent_battlelogs.end(), id)
== previously_sent_battlelogs.end()) {
previously_sent_battlelogs.push_back(id);
to_enqueue.push_back(id);
}
}
}

if (!to_enqueue.empty()) {
http::logging::debug("QUEUE", "battle headers",
STR_FORMAT("Queuing {} battles for background processing", to_enqueue.size()));

{
std::scoped_lock lk(workers::combat_log_data_mtx);
for (const auto id : to_enqueue) {
workers::combat_log_data_queue.push(id);
}
}

trackers::save_previously_sent_logs();
workers::combat_log_data_cv.notify_all();
}
}

static void battle_result_headers(std::unique_ptr<std::string>&& bytes)
{
// TODO: Placeholder for future client support; currently unused by the game client.
spdlog::debug("process_battle_result_headers() was called");
if (auto response = Digit::PrimeServer::Models::BattleResultHeadersResponse(); response.ParseFromString(*bytes)) {
http::logging::trace("PROCESS", "battle headers",
STR_FORMAT("Processing {} battle headers", response.headers_size()));

std::vector<uint64_t> battle_ids;
battle_ids.reserve(static_cast<size_t>(response.headers_size()));

for (const auto& header : response.headers()) {
battle_ids.push_back(static_cast<uint64_t>(header.id()));
}

queue_battle_ids(battle_ids);
} else {
spdlog::error("Failed to parse battle result headers");
}
}

struct ShipRecord {
int64_t id;
int64_t hull_id;
int32_t tier;
int32_t level;
double level_percentage;
std::vector<int64_t> components;
};

static void sync_ships(const std::vector<ShipRecord>& ships)
{
using json = nlohmann::json;
using trackers::types::ShipState;

static std::unordered_map<int64_t, ShipState> ship_states;
static std::mutex ship_states_mtx;
static std::atomic_bool is_first_sync{true};

auto ship_array = json::array();
{
std::scoped_lock lk(ship_states_mtx);

for (const auto& ship : ships) {
const ShipState state{ship.tier, ship.level, ship.level_percentage, ship.components};

if (const auto& it = ship_states.find(ship.id); it == ship_states.end() || it->second != state) {
ship_states[ship.id] = state;
ship_array.push_back({{"type", SyncConfig::Type::Ships},
{"psid", ship.id},
{"level", ship.level},
{"level_percentage", ship.level_percentage},
{"tier", ship.tier},
{"hull_id", ship.hull_id},
{"components", ship.components}});
}
}
}

if (!ship_array.empty()) {
const bool first_sync = is_first_sync.exchange(false, std::memory_order_acq_rel);
workers::queue_data(SyncConfig::Type::Ships, ship_array, first_sync);
}
}

static void player_ships(std::unique_ptr<std::string>&& bytes)
{
if (auto response = Digit::PrimeServer::Models::PlayerShipsResponse(); response.ParseFromString(*bytes)) {
http::logging::trace("PROCESS", "ships", STR_FORMAT("Processing {} ships", response.ships_size()));

std::vector<ShipRecord> ships;
ships.reserve(static_cast<size_t>(response.ships_size()));

for (const auto& ship : response.ships() | std::views::values) {
ships.push_back({ship.id(), ship.hullid(), ship.tier(), ship.level(), ship.levelpercentage(),
std::vector<int64_t>(ship.components().begin(), ship.components().end())});
}

sync_ships(ships);
} else {
spdlog::error("Failed to parse player ships");
}
}

static void battle_report(std::unique_ptr<std::string>&& bytes)
Expand Down Expand Up @@ -1927,36 +2037,7 @@ namespace json
battle_ids.push_back(id);
}

std::vector<uint64_t> to_enqueue;
{
using trackers::previously_sent_battlelogs;
using trackers::previously_sent_battlelogs_mtx;

std::scoped_lock lk(previously_sent_battlelogs_mtx);

for (const auto id : battle_ids | std::views::reverse) {
if (eastl::find(previously_sent_battlelogs.begin(), previously_sent_battlelogs.end(), id)
== previously_sent_battlelogs.end()) {
previously_sent_battlelogs.push_back(id);
to_enqueue.push_back(id);
}
}
}

if (!to_enqueue.empty()) {
http::logging::debug("QUEUE", "battle headers",
STR_FORMAT("Queuing {} battles for background processing", to_enqueue.size()));

{
std::scoped_lock lk(workers::combat_log_data_mtx);
for (const auto id : to_enqueue) {
workers::combat_log_data_queue.push(id);
}
}

trackers::save_previously_sent_logs();
workers::combat_log_data_cv.notify_all();
}
queue_battle_ids(battle_ids);
}

static void resources(const nlohmann::json& section)
Expand Down Expand Up @@ -2020,43 +2101,19 @@ namespace json
static void ships(const nlohmann::json& section)
{
using json = nlohmann::json;
using trackers::types::ShipState;

static std::unordered_map<int64_t, ShipState> ship_states;
static std::mutex ship_states_mtx;
static std::atomic_bool is_first_sync{true};

http::logging::trace("PROCESS", "ships", STR_FORMAT("Processing {} ships (JSON)", section.size()));

auto ship_array = json::array();
{
std::scoped_lock lk(ship_states_mtx);

for (const auto& ship : section.get<json::object_t>() | std::views::values) {
const auto id = ship["id"].get<int64_t>();
const auto tier = ship["tier"].get<int32_t>();
const auto level = ship["level"].get<int32_t>();
const auto level_percentage = ship["level_percentage"].get<double_t>();
const auto components = ship["components"].get<std::vector<int64_t>>();
const ShipState state{tier, level, level_percentage, components};

if (const auto& it = ship_states.find(id); it == ship_states.end() || it->second != state) {
ship_states[id] = state;
ship_array.push_back({{"type", SyncConfig::Type::Ships},
{"psid", id},
{"level", level},
{"level_percentage", level_percentage},
{"tier", tier},
{"hull_id", ship["hull_id"].get<int64_t>()},
{"components", components}});
}
}
}
std::vector<ShipRecord> records;
records.reserve(section.size());

if (!ship_array.empty()) {
const bool first_sync = is_first_sync.exchange(false, std::memory_order_acq_rel);
workers::queue_data(SyncConfig::Type::Ships, ship_array, first_sync);
for (const auto& ship : section.get<json::object_t>() | std::views::values) {
records.push_back({ship["id"].get<int64_t>(), ship["hull_id"].get<int64_t>(), ship["tier"].get<int32_t>(),
ship["level"].get<int32_t>(), ship["level_percentage"].get<double_t>(),
ship["components"].get<std::vector<int64_t>>()});
}

sync_ships(records);
}

static void parse(std::unique_ptr<std::string>&& bytes)
Expand Down Expand Up @@ -2382,7 +2439,11 @@ static void HandleEntityGroup(EntityGroup* entity_group)
break;

// ships
// TODO: currently still part of JSON, likely to change in the future
case EntityGroup::Type::Ships:
if (sync_options.ships) {
submit_async(processors::player_ships);
}
break;

// slots
case EntityGroup::Type::EntitySlots:
Expand Down
12 changes: 12 additions & 0 deletions mods/src/prime/EntityGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,18 @@ struct EntityGroup {
ResourceProducers = 240, // 0x000000F0
Starbase = 241, // 0x000000F1

NodeSystem = 242, // 0x000000F2
DockingPoints = 243, // 0x000000F3
PlayerContainer = 244, // 0x000000F4
MarauderQuickScanData = 245, // 0x000000F5
AllianceContainer = 246, // 0x000000F6
QuickScanResults = 247, // 0x000000F7
DeployedFleets = 248, // 0x000000F8
MyDeployedFleets = 249, // 0x000000F9
Fleets = 250, // 0x000000FA
Ships = 251, // 0x000000FB
ResourceHarvesters = 252, // 0x000000FC

PlanetaryBaseData = 1213, // 0x000004BD
PlanetaryResourceProducers = 1214, // 0x000004BE
PlanetaryMapData = 1215, // 0x000004BF
Expand Down
32 changes: 32 additions & 0 deletions mods/src/prime/proto/Digit.PrimeServer.Models.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3577,6 +3577,17 @@ enum Type {
TYPE_STARBASEMODULES = 239;
TYPE_RESOURCEPRODUCERS = 240;
TYPE_STARBASE = 241;
TYPE_NODESYSTEM = 242;
TYPE_DOCKINGPOINTS = 243;
TYPE_PLAYERCONTAINER = 244;
TYPE_MARAUDERQUICKSCANDATA = 245;
TYPE_ALLIANCECONTAINER = 246;
TYPE_QUICKSCANRESULTS = 247;
TYPE_DEPLOYEDFLEETS = 248;
TYPE_MYDEPLOYEDFLEETS = 249;
TYPE_FLEETS = 250;
TYPE_SHIPS = 251;
TYPE_RESOURCEHARVESTERS = 252;
TYPE_OUTPOSTSTATICDATA = 8401;
TYPE_OUTPOSTUPGRADERESPONSE = 8402;
TYPE_OUTPOSTSYNC = 8403;
Expand Down Expand Up @@ -3900,6 +3911,19 @@ message PlayerPartyResponse {
PartyResponse response = 1;
}

message PlayerShipData {
int64 id = 1;
int32 tier = 2;
int64 hullId = 3;
repeated int64 components = 4;
int32 level = 5;
float levelPercentage = 6;
}

message PlayerShipsResponse {
map<int64, PlayerShipData> ships = 1;
}

message PlanetaryBaseSpec {
int64 id = 1;
string buildingName = 2;
Expand Down Expand Up @@ -5583,3 +5607,11 @@ message WaveDefenseChallengeDataResponse {
message ActiveWormholesResponse {
repeated Wormhole wormholes = 1;
}

message JournalHeaderProto {
int64 id = 1;
}

message BattleResultHeadersResponse {
repeated JournalHeaderProto headers = 1;
}
Loading