Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
131 changes: 108 additions & 23 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,10 @@ void Player::updatePartyTrackerAnalyzer() const {
}

void Player::sendLootStats(const std::shared_ptr<Item> &item, uint8_t count) {
// Batch loot stats to reduce I/O and allocations
batchedTrackerData.lootItems.emplace_back(item, count);

// Calculate value for metrics
uint64_t value = 0;
if (item->getID() == ITEM_GOLD_COIN || item->getID() == ITEM_PLATINUM_COIN || item->getID() == ITEM_CRYSTAL_COIN) {
if (item->getID() == ITEM_PLATINUM_COIN) {
Expand All @@ -1679,47 +1683,128 @@ void Player::sendLootStats(const std::shared_ptr<Item> &item, uint8_t count) {
} else {
value = count;
}
} else if (
const auto &npc = g_game().getNpcByName("The Lootmonger")
) {
} else if (const auto &npc = g_game().getNpcByName("The Lootmonger")) {
const auto &iType = Item::items.getItemType(item->getID());
value = iType.sellPrice * count;
}
g_metrics().addCounter("player_loot", value, { { "player", getName() } });

if (client) {
client->sendLootStats(item, count);
}
batchedTrackerData.lootValue += value;

if (m_party) {
m_party->addPlayerLoot(getPlayer(), item);
// Schedule batch flush if not already pending
if (!trackerBatchPending) {
trackerBatchPending = true;
const auto self = static_self_cast<Player>();
trackerBatchEventId = g_dispatcher().scheduleEvent(
250, [self] {
self->flushBatchedTrackerData();
},
"Player::flushBatchedTrackerData"
);
}
}

void Player::updateSupplyTracker(const std::shared_ptr<Item> &item) {
const auto &iType = Item::items.getItemType(item->getID());
const auto value = iType.buyPrice;
g_metrics().addCounter("player_supply", value, { { "player", getName() } });

if (client) {
client->sendUpdateSupplyTracker(item);
}
// Batch supply tracker to reduce I/O and allocations
batchedTrackerData.supplyItems.push_back(item);

if (m_party) {
m_party->addPlayerSupply(getPlayer(), item);
const auto &iType = Item::items.getItemType(item->getID());
batchedTrackerData.supplyValue += iType.buyPrice;

// Schedule batch flush if not already pending
if (!trackerBatchPending) {
trackerBatchPending = true;
const auto self = static_self_cast<Player>();
trackerBatchEventId = g_dispatcher().scheduleEvent(
250, [self] {
self->flushBatchedTrackerData();
},
"Player::flushBatchedTrackerData"
);
}
}

void Player::updateImpactTracker(CombatType_t type, int32_t amount) const {
if (client) {
client->sendUpdateImpactTracker(type, amount);
// Batch impact tracker to reduce I/O and allocations
const_cast<Player*>(this)->batchedTrackerData.impactData.emplace_back(type, amount);

// Schedule batch flush if not already pending
if (!trackerBatchPending) {
const_cast<Player*>(this)->trackerBatchPending = true;
const auto self = const_cast<Player*>(this)->static_self_cast<Player>();
const_cast<Player*>(this)->trackerBatchEventId = g_dispatcher().scheduleEvent(
250, [self] {
self->flushBatchedTrackerData();
},
"Player::flushBatchedTrackerData"
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you sum the amount, it'll create a bug with the "max-dps" and "all-time high"
But if you don’t sum it, you’ll send all of them separately so it’ll be the same, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sending impact events separately is the right behavior, and it’s what the code already does.

}
}

void Player::updateInputAnalyzer(CombatType_t type, int32_t amount, const std::string &target) const {
if (client) {
client->sendUpdateInputAnalyzer(type, amount, target);
// Batch input analyzer to reduce I/O and allocations
const_cast<Player*>(this)->batchedTrackerData.inputData.emplace_back(type, amount, target);

// Schedule batch flush if not already pending
if (!trackerBatchPending) {
const_cast<Player*>(this)->trackerBatchPending = true;
const auto self = const_cast<Player*>(this)->static_self_cast<Player>();
const_cast<Player*>(this)->trackerBatchEventId = g_dispatcher().scheduleEvent(
250, [self] {
self->flushBatchedTrackerData();
},
"Player::flushBatchedTrackerData"
);
}
}

void Player::flushBatchedTrackerData() {
trackerBatchPending = false;

// Send aggregated loot stats
if (batchedTrackerData.lootValue > 0) {
g_metrics().addCounter("player_loot", batchedTrackerData.lootValue, { { "player", getName() } });

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated info in g_metrics()
g_metrics().addCounter("player_loot", value, { { "player", getName() } });

}

// Send individual loot items to client and party
for (const auto &[item, count] : batchedTrackerData.lootItems) {
if (client) {
client->sendLootStats(item, count);
}
if (m_party) {
m_party->addPlayerLoot(getPlayer(), item);
}
}

// Send aggregated supply stats
if (batchedTrackerData.supplyValue > 0) {
g_metrics().addCounter("player_supply", batchedTrackerData.supplyValue, { { "player", getName() } });
}

// Send individual supply items to client and party
for (const auto &item : batchedTrackerData.supplyItems) {
if (client) {
client->sendUpdateSupplyTracker(item);
}
if (m_party) {
m_party->addPlayerSupply(getPlayer(), item);
}
}

// Send batched impact tracker data
for (const auto &[type, amount] : batchedTrackerData.impactData) {
if (client) {
client->sendUpdateImpactTracker(type, amount);
}
}

// Send batched input analyzer data
for (const auto &[type, amount, target] : batchedTrackerData.inputData) {
if (client) {
client->sendUpdateInputAnalyzer(type, amount, target);
}
}

// Clear batched data
batchedTrackerData = BatchedTrackerData {};
}

void Player::createLeaderTeamFinder(NetworkMessage &msg) const {
Expand Down
16 changes: 16 additions & 0 deletions src/creatures/players/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1379,11 +1379,11 @@
* added to the player or being updated, there is a chance to prevent these actions
******************************************************************************/
struct DeflectCondition {
DeflectCondition(std::string source, ConditionType_t condition, uint8_t chance) :

Check warning on line 1382 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1382 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1382 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1382 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1382 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1382 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

when initialized here [-Wreorder]
source(source), condition(condition), chance(chance) { }
std::string source;
uint8_t chance = 0;

Check warning on line 1385 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

‘uint8_t Player::DeflectCondition::chance’ [-Wreorder]

Check warning on line 1385 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

‘uint8_t Player::DeflectCondition::chance’ [-Wreorder]

Check warning on line 1385 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

‘uint8_t Player::DeflectCondition::chance’ [-Wreorder]

Check warning on line 1385 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘uint8_t Player::DeflectCondition::chance’ [-Wreorder]

Check warning on line 1385 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘uint8_t Player::DeflectCondition::chance’ [-Wreorder]

Check warning on line 1385 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘uint8_t Player::DeflectCondition::chance’ [-Wreorder]
ConditionType_t condition = CONDITION_NONE;

Check warning on line 1386 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

‘Player::DeflectCondition::condition’ will be initialized after [-Wreorder]

Check warning on line 1386 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

‘Player::DeflectCondition::condition’ will be initialized after [-Wreorder]

Check warning on line 1386 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-24.04-linux-debug

‘Player::DeflectCondition::condition’ will be initialized after [-Wreorder]

Check warning on line 1386 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘Player::DeflectCondition::condition’ will be initialized after [-Wreorder]

Check warning on line 1386 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘Player::DeflectCondition::condition’ will be initialized after [-Wreorder]

Check warning on line 1386 in src/creatures/players/player.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘Player::DeflectCondition::condition’ will be initialized after [-Wreorder]
};

const std::vector<DeflectCondition> &getDeflectConditions() const {
Expand Down Expand Up @@ -1752,6 +1752,22 @@
uint64_t m_serene_cooldown = 0;
VirtueMonk_t m_virtue = VIRTUE_NONE;

// Batched tracker updates to reduce I/O and allocations
struct BatchedTrackerData {
uint64_t lootValue = 0;
uint64_t supplyValue = 0;
std::vector<std::pair<CombatType_t, int32_t>> impactData;
std::vector<std::tuple<CombatType_t, int32_t, std::string>> inputData;
std::vector<std::pair<std::shared_ptr<Item>, uint8_t>> lootItems;
std::vector<std::shared_ptr<Item>> supplyItems;
};

BatchedTrackerData batchedTrackerData;
uint64_t trackerBatchEventId = 0;
bool trackerBatchPending = false;

void flushBatchedTrackerData();

friend class Game;
friend class SaveManager;
friend class Npc;
Expand Down
Loading