mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 01:23:51 +00:00
Reduce update-object and inventory update overhead
This commit is contained in:
parent
37888c666d
commit
0631b9f5dc
2 changed files with 71 additions and 48 deletions
|
|
@ -4750,48 +4750,46 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
||||||
|
|
||||||
// Process out-of-range objects first
|
// Process out-of-range objects first
|
||||||
for (uint64_t guid : data.outOfRangeGuids) {
|
for (uint64_t guid : data.outOfRangeGuids) {
|
||||||
if (entityManager.hasEntity(guid)) {
|
auto entity = entityManager.getEntity(guid);
|
||||||
const bool isKnownTransport = transportGuids_.count(guid) > 0;
|
if (!entity) continue;
|
||||||
if (isKnownTransport) {
|
|
||||||
// Keep transports alive across out-of-range flapping.
|
|
||||||
// Boats/zeppelins are global movers and removing them here can make
|
|
||||||
// them disappear until a later movement snapshot happens to recreate them.
|
|
||||||
const bool playerAboardNow = (playerTransportGuid_ == guid);
|
|
||||||
const bool stickyAboard = (playerTransportStickyGuid_ == guid && playerTransportStickyTimer_ > 0.0f);
|
|
||||||
const bool movementSaysAboard = (movementInfo.transportGuid == guid);
|
|
||||||
LOG_INFO("Preserving transport on out-of-range: 0x",
|
|
||||||
std::hex, guid, std::dec,
|
|
||||||
" now=", playerAboardNow,
|
|
||||||
" sticky=", stickyAboard,
|
|
||||||
" movement=", movementSaysAboard);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_DEBUG("Entity went out of range: 0x", std::hex, guid, std::dec);
|
const bool isKnownTransport = transportGuids_.count(guid) > 0;
|
||||||
// Trigger despawn callbacks before removing entity
|
if (isKnownTransport) {
|
||||||
auto entity = entityManager.getEntity(guid);
|
// Keep transports alive across out-of-range flapping.
|
||||||
if (entity) {
|
// Boats/zeppelins are global movers and removing them here can make
|
||||||
if (entity->getType() == ObjectType::UNIT && creatureDespawnCallback_) {
|
// them disappear until a later movement snapshot happens to recreate them.
|
||||||
creatureDespawnCallback_(guid);
|
const bool playerAboardNow = (playerTransportGuid_ == guid);
|
||||||
} else if (entity->getType() == ObjectType::PLAYER && playerDespawnCallback_) {
|
const bool stickyAboard = (playerTransportStickyGuid_ == guid && playerTransportStickyTimer_ > 0.0f);
|
||||||
playerDespawnCallback_(guid);
|
const bool movementSaysAboard = (movementInfo.transportGuid == guid);
|
||||||
otherPlayerVisibleItemEntries_.erase(guid);
|
LOG_INFO("Preserving transport on out-of-range: 0x",
|
||||||
otherPlayerVisibleDirty_.erase(guid);
|
std::hex, guid, std::dec,
|
||||||
otherPlayerMoveTimeMs_.erase(guid);
|
" now=", playerAboardNow,
|
||||||
inspectedPlayerItemEntries_.erase(guid);
|
" sticky=", stickyAboard,
|
||||||
pendingAutoInspect_.erase(guid);
|
" movement=", movementSaysAboard);
|
||||||
} else if (entity->getType() == ObjectType::GAMEOBJECT && gameObjectDespawnCallback_) {
|
continue;
|
||||||
gameObjectDespawnCallback_(guid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transportGuids_.erase(guid);
|
|
||||||
serverUpdatedTransportGuids_.erase(guid);
|
|
||||||
clearTransportAttachment(guid);
|
|
||||||
if (playerTransportGuid_ == guid) {
|
|
||||||
clearPlayerTransport();
|
|
||||||
}
|
|
||||||
entityManager.removeEntity(guid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("Entity went out of range: 0x", std::hex, guid, std::dec);
|
||||||
|
// Trigger despawn callbacks before removing entity
|
||||||
|
if (entity->getType() == ObjectType::UNIT && creatureDespawnCallback_) {
|
||||||
|
creatureDespawnCallback_(guid);
|
||||||
|
} else if (entity->getType() == ObjectType::PLAYER && playerDespawnCallback_) {
|
||||||
|
playerDespawnCallback_(guid);
|
||||||
|
otherPlayerVisibleItemEntries_.erase(guid);
|
||||||
|
otherPlayerVisibleDirty_.erase(guid);
|
||||||
|
otherPlayerMoveTimeMs_.erase(guid);
|
||||||
|
inspectedPlayerItemEntries_.erase(guid);
|
||||||
|
pendingAutoInspect_.erase(guid);
|
||||||
|
} else if (entity->getType() == ObjectType::GAMEOBJECT && gameObjectDespawnCallback_) {
|
||||||
|
gameObjectDespawnCallback_(guid);
|
||||||
|
}
|
||||||
|
transportGuids_.erase(guid);
|
||||||
|
serverUpdatedTransportGuids_.erase(guid);
|
||||||
|
clearTransportAttachment(guid);
|
||||||
|
if (playerTransportGuid_ == guid) {
|
||||||
|
clearPlayerTransport();
|
||||||
|
}
|
||||||
|
entityManager.removeEntity(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process update blocks
|
// Process update blocks
|
||||||
|
|
@ -5466,7 +5464,12 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
||||||
}
|
}
|
||||||
// Update XP / inventory slot / skill fields for player entity
|
// Update XP / inventory slot / skill fields for player entity
|
||||||
if (block.guid == playerGuid) {
|
if (block.guid == playerGuid) {
|
||||||
std::map<uint16_t, uint32_t> oldFieldsSnapshot = lastPlayerFields_;
|
const bool needCoinageDetectSnapshot =
|
||||||
|
(pendingMoneyDelta_ != 0 && pendingMoneyDeltaTimer_ > 0.0f);
|
||||||
|
std::map<uint16_t, uint32_t> oldFieldsSnapshot;
|
||||||
|
if (needCoinageDetectSnapshot) {
|
||||||
|
oldFieldsSnapshot = lastPlayerFields_;
|
||||||
|
}
|
||||||
if (block.hasMovement && block.runSpeed > 0.1f && block.runSpeed < 100.0f) {
|
if (block.hasMovement && block.runSpeed > 0.1f && block.runSpeed < 100.0f) {
|
||||||
serverRunSpeed_ = block.runSpeed;
|
serverRunSpeed_ = block.runSpeed;
|
||||||
// Some server dismount paths update run speed without updating mount display field.
|
// Some server dismount paths update run speed without updating mount display field.
|
||||||
|
|
@ -5480,10 +5483,13 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto mergeHint = lastPlayerFields_.end();
|
||||||
for (const auto& [key, val] : block.fields) {
|
for (const auto& [key, val] : block.fields) {
|
||||||
lastPlayerFields_[key] = val;
|
mergeHint = lastPlayerFields_.insert_or_assign(mergeHint, key, val);
|
||||||
|
}
|
||||||
|
if (needCoinageDetectSnapshot) {
|
||||||
|
maybeDetectCoinageIndex(oldFieldsSnapshot, lastPlayerFields_);
|
||||||
}
|
}
|
||||||
maybeDetectCoinageIndex(oldFieldsSnapshot, lastPlayerFields_);
|
|
||||||
maybeDetectVisibleItemLayout();
|
maybeDetectVisibleItemLayout();
|
||||||
detectInventorySlotBases(block.fields);
|
detectInventorySlotBases(block.fields);
|
||||||
bool slotsChanged = false;
|
bool slotsChanged = false;
|
||||||
|
|
@ -5545,17 +5551,33 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
||||||
|
|
||||||
// Update item stack count for online items
|
// Update item stack count for online items
|
||||||
if (entity->getType() == ObjectType::ITEM || entity->getType() == ObjectType::CONTAINER) {
|
if (entity->getType() == ObjectType::ITEM || entity->getType() == ObjectType::CONTAINER) {
|
||||||
|
bool inventoryChanged = false;
|
||||||
|
const uint16_t itemStackField = fieldIndex(UF::ITEM_FIELD_STACK_COUNT);
|
||||||
|
const uint16_t containerNumSlotsField = fieldIndex(UF::CONTAINER_FIELD_NUM_SLOTS);
|
||||||
|
const uint16_t containerSlot1Field = fieldIndex(UF::CONTAINER_FIELD_SLOT_1);
|
||||||
for (const auto& [key, val] : block.fields) {
|
for (const auto& [key, val] : block.fields) {
|
||||||
if (key == fieldIndex(UF::ITEM_FIELD_STACK_COUNT)) {
|
if (key == itemStackField) {
|
||||||
auto it = onlineItems_.find(block.guid);
|
auto it = onlineItems_.find(block.guid);
|
||||||
if (it != onlineItems_.end()) it->second.stackCount = val;
|
if (it != onlineItems_.end() && it->second.stackCount != val) {
|
||||||
|
it->second.stackCount = val;
|
||||||
|
inventoryChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update container slot GUIDs on bag content changes
|
// Update container slot GUIDs on bag content changes
|
||||||
if (entity->getType() == ObjectType::CONTAINER) {
|
if (entity->getType() == ObjectType::CONTAINER) {
|
||||||
|
for (const auto& [key, _] : block.fields) {
|
||||||
|
if ((containerNumSlotsField != 0xFFFF && key == containerNumSlotsField) ||
|
||||||
|
(containerSlot1Field != 0xFFFF && key >= containerSlot1Field && key < containerSlot1Field + 72)) {
|
||||||
|
inventoryChanged = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
extractContainerFields(block.guid, block.fields);
|
extractContainerFields(block.guid, block.fields);
|
||||||
}
|
}
|
||||||
rebuildOnlineInventory();
|
if (inventoryChanged) {
|
||||||
|
rebuildOnlineInventory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (block.hasMovement && entity->getType() == ObjectType::GAMEOBJECT) {
|
if (block.hasMovement && entity->getType() == ObjectType::GAMEOBJECT) {
|
||||||
if (transportGuids_.count(block.guid) && transportMoveCallback_) {
|
if (transportGuids_.count(block.guid) && transportMoveCallback_) {
|
||||||
|
|
|
||||||
|
|
@ -1117,7 +1117,8 @@ bool UpdateObjectParser::parseUpdateFields(network::Packet& packet, UpdateBlock&
|
||||||
highestSetBit = fieldIndex;
|
highestSetBit = fieldIndex;
|
||||||
}
|
}
|
||||||
uint32_t value = packet.readUInt32();
|
uint32_t value = packet.readUInt32();
|
||||||
block.fields[fieldIndex] = value;
|
// fieldIndex is monotonically increasing here, so end() is a good insertion hint.
|
||||||
|
block.fields.emplace_hint(block.fields.end(), fieldIndex, value);
|
||||||
valuesReadCount++;
|
valuesReadCount++;
|
||||||
|
|
||||||
LOG_DEBUG(" Field[", fieldIndex, "] = 0x", std::hex, value, std::dec);
|
LOG_DEBUG(" Field[", fieldIndex, "] = 0x", std::hex, value, std::dec);
|
||||||
|
|
@ -1256,7 +1257,7 @@ bool UpdateObjectParser::parse(network::Packet& packet, UpdateObjectData& data)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.blocks.push_back(block);
|
data.blocks.emplace_back(std::move(block));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue