refactor(game): extract EntityController from GameHandler (step 1.3)

Moves entity lifecycle, name/creature/game-object caches, transport GUID
tracking, and the entire update-object pipeline out of GameHandler into a
new EntityController class (friend-class pattern, same as CombatHandler
et al.).

What moved:
- applyUpdateObjectBlock() — 1,520-line core of all entity creation,
  field updates, and movement application
- processOutOfRangeObjects() / finalizeUpdateObjectBatch()
- handleUpdateObject() / handleCompressedUpdateObject() / handleDestroyObject()
- handleNameQueryResponse() / handleCreatureQueryResponse()
- handleGameObjectQueryResponse() / handleGameObjectPageText()
- handlePageTextQueryResponse()
- enqueueUpdateObjectWork() / processPendingUpdateObjectWork()
- playerNameCache, playerClassRaceCache_, pendingNameQueries
- creatureInfoCache, pendingCreatureQueries
- gameObjectInfoCache_, pendingGameObjectQueries_
- transportGuids_, serverUpdatedTransportGuids_
- EntityManager (accessed by other handlers via getEntityManager())

8 opcodes re-registered by EntityController::registerOpcodes():
  SMSG_UPDATE_OBJECT, SMSG_COMPRESSED_UPDATE_OBJECT, SMSG_DESTROY_OBJECT,
  SMSG_NAME_QUERY_RESPONSE, SMSG_CREATURE_QUERY_RESPONSE,
  SMSG_GAMEOBJECT_QUERY_RESPONSE, SMSG_GAMEOBJECT_PAGETEXT,
  SMSG_PAGE_TEXT_QUERY_RESPONSE

Other handler files (combat, movement, social, spell, inventory, quest,
chat) updated to access EntityManager via getEntityManager() and the
name cache via getPlayerNameCache() — no logic changes.

Also included:
- .clang-tidy: add modernize-use-nodiscard,
  modernize-use-designated-initializers; set -std=c++20 in ExtraArgs
- test.sh: prepend clang's own resource include dir before GCC's to
  silence xmmintrin.h / ia32intrin.h conflicts during clang-tidy runs

Line counts:
  entity_controller.hpp  147 lines  (new)
  entity_controller.cpp  2172 lines (new)
  game_handler.cpp       8095 lines (was 10143, −2048)

Build: 0 errors, 0 warnings.
This commit is contained in:
Paul 2026-03-29 08:21:27 +03:00
parent 4f2a4e5520
commit f5757aca83
15 changed files with 2497 additions and 2260 deletions

View file

@ -16,6 +16,8 @@ Checks: >
modernize-deprecated-headers, modernize-deprecated-headers,
modernize-make-unique, modernize-make-unique,
modernize-make-shared, modernize-make-shared,
modernize-use-nodiscard,
modernize-use-designated-initializers,
readability-braces-around-statements, readability-braces-around-statements,
readability-container-size-empty, readability-container-size-empty,
readability-delete-null-pointer, readability-delete-null-pointer,
@ -35,6 +37,7 @@ WarningsAsErrors: ''
# Suppress the noise from GCC-only LTO flags in compile_commands.json. # Suppress the noise from GCC-only LTO flags in compile_commands.json.
# clang doesn't support -fno-fat-lto-objects; this silences the harmless warning. # clang doesn't support -fno-fat-lto-objects; this silences the harmless warning.
ExtraArgs: ExtraArgs:
- -std=c++20
- -Wno-ignored-optimization-argument - -Wno-ignored-optimization-argument
HeaderFilterRegex: '^.*/include/.*\.hpp$' HeaderFilterRegex: '^.*/include/.*\.hpp$'

View file

@ -457,6 +457,7 @@ set(WOWEE_SOURCES
src/game/inventory_handler.cpp src/game/inventory_handler.cpp
src/game/social_handler.cpp src/game/social_handler.cpp
src/game/quest_handler.cpp src/game/quest_handler.cpp
src/game/entity_controller.cpp
src/game/warden_handler.cpp src/game/warden_handler.cpp
src/game/warden_crypto.cpp src/game/warden_crypto.cpp
src/game/warden_module.cpp src/game/warden_module.cpp

View file

@ -0,0 +1,147 @@
#pragma once
#include "game/world_packets.hpp"
#include "game/entity.hpp"
#include "game/opcode_table.hpp"
#include "network/packet.hpp"
#include <chrono>
#include <deque>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
namespace wowee {
namespace game {
class GameHandler;
class EntityController {
public:
using PacketHandler = std::function<void(network::Packet&)>;
using DispatchTable = std::unordered_map<LogicalOpcode, PacketHandler>;
explicit EntityController(GameHandler& owner);
void registerOpcodes(DispatchTable& table);
// --- Entity Manager access ---
EntityManager& getEntityManager() { return entityManager; }
const EntityManager& getEntityManager() const { return entityManager; }
// --- Name / info cache queries ---
void queryPlayerName(uint64_t guid);
void queryCreatureInfo(uint32_t entry, uint64_t guid);
void queryGameObjectInfo(uint32_t entry, uint64_t guid);
std::string getCachedPlayerName(uint64_t guid) const;
std::string getCachedCreatureName(uint32_t entry) const;
void invalidatePlayerName(uint64_t guid) { playerNameCache.erase(guid); }
// Read-only cache access for other handlers
const std::unordered_map<uint64_t, std::string>& getPlayerNameCache() const { return playerNameCache; }
const std::unordered_map<uint32_t, CreatureQueryResponseData>& getCreatureInfoCache() const { return creatureInfoCache; }
std::string getCachedCreatureSubName(uint32_t entry) const {
auto it = creatureInfoCache.find(entry);
return (it != creatureInfoCache.end()) ? it->second.subName : "";
}
int getCreatureRank(uint32_t entry) const {
auto it = creatureInfoCache.find(entry);
return (it != creatureInfoCache.end()) ? static_cast<int>(it->second.rank) : -1;
}
uint32_t getCreatureType(uint32_t entry) const {
auto it = creatureInfoCache.find(entry);
return (it != creatureInfoCache.end()) ? it->second.creatureType : 0;
}
uint32_t getCreatureFamily(uint32_t entry) const {
auto it = creatureInfoCache.find(entry);
return (it != creatureInfoCache.end()) ? it->second.family : 0;
}
const GameObjectQueryResponseData* getCachedGameObjectInfo(uint32_t entry) const {
auto it = gameObjectInfoCache_.find(entry);
return (it != gameObjectInfoCache_.end()) ? &it->second : nullptr;
}
// Name lookup (checks cache then entity manager)
const std::string& lookupName(uint64_t guid) const {
static const std::string kEmpty;
auto it = playerNameCache.find(guid);
if (it != playerNameCache.end()) return it->second;
auto entity = entityManager.getEntity(guid);
if (entity) {
if (auto* unit = dynamic_cast<const Unit*>(entity.get())) {
if (!unit->getName().empty()) return unit->getName();
}
}
return kEmpty;
}
uint8_t lookupPlayerClass(uint64_t guid) const {
auto it = playerClassRaceCache_.find(guid);
return it != playerClassRaceCache_.end() ? it->second.classId : 0;
}
uint8_t lookupPlayerRace(uint64_t guid) const {
auto it = playerClassRaceCache_.find(guid);
return it != playerClassRaceCache_.end() ? it->second.raceId : 0;
}
// --- Transport GUID tracking ---
bool isTransportGuid(uint64_t guid) const { return transportGuids_.count(guid) > 0; }
bool hasServerTransportUpdate(uint64_t guid) const { return serverUpdatedTransportGuids_.count(guid) > 0; }
// --- Update object work queue ---
void enqueueUpdateObjectWork(UpdateObjectData&& data);
void processPendingUpdateObjectWork(const std::chrono::steady_clock::time_point& start,
float budgetMs);
bool hasPendingUpdateObjectWork() const { return !pendingUpdateObjectWork_.empty(); }
// --- Reset all state (called on disconnect / character switch) ---
void clearAll();
private:
GameHandler& owner_;
// --- Entity tracking ---
EntityManager entityManager; // Manages all entities in view
// ---- Name caches ----
std::unordered_map<uint64_t, std::string> playerNameCache;
// Class/race cache from SMSG_NAME_QUERY_RESPONSE (guid → {classId, raceId})
struct PlayerClassRace { uint8_t classId = 0; uint8_t raceId = 0; };
std::unordered_map<uint64_t, PlayerClassRace> playerClassRaceCache_;
std::unordered_set<uint64_t> pendingNameQueries;
std::unordered_map<uint32_t, CreatureQueryResponseData> creatureInfoCache;
std::unordered_set<uint32_t> pendingCreatureQueries;
std::unordered_map<uint32_t, GameObjectQueryResponseData> gameObjectInfoCache_;
std::unordered_set<uint32_t> pendingGameObjectQueries_;
// --- Update Object work queue ---
struct PendingUpdateObjectWork {
UpdateObjectData data;
size_t nextBlockIndex = 0;
bool outOfRangeProcessed = false;
bool newItemCreated = false;
};
std::deque<PendingUpdateObjectWork> pendingUpdateObjectWork_;
// --- Transport GUID tracking ---
std::unordered_set<uint64_t> transportGuids_; // GUIDs of known transport GameObjects
std::unordered_set<uint64_t> serverUpdatedTransportGuids_;
// --- Packet handlers ---
void handleUpdateObject(network::Packet& packet);
void handleCompressedUpdateObject(network::Packet& packet);
void handleDestroyObject(network::Packet& packet);
void handleNameQueryResponse(network::Packet& packet);
void handleCreatureQueryResponse(network::Packet& packet);
void handleGameObjectQueryResponse(network::Packet& packet);
void handleGameObjectPageText(network::Packet& packet);
void handlePageTextQueryResponse(network::Packet& packet);
// --- Entity lifecycle ---
void processOutOfRangeObjects(const std::vector<uint64_t>& guids);
void applyUpdateObjectBlock(const UpdateBlock& block, bool& newItemCreated);
void finalizeUpdateObjectBatch(bool newItemCreated);
};
} // namespace game
} // namespace wowee

View file

@ -12,6 +12,7 @@
#include "game/spell_handler.hpp" #include "game/spell_handler.hpp"
#include "game/quest_handler.hpp" #include "game/quest_handler.hpp"
#include "game/movement_handler.hpp" #include "game/movement_handler.hpp"
#include "game/entity_controller.hpp"
#include "network/packet.hpp" #include "network/packet.hpp"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <memory> #include <memory>
@ -243,8 +244,8 @@ public:
/** /**
* Get entity manager (for accessing entities in view) * Get entity manager (for accessing entities in view)
*/ */
EntityManager& getEntityManager() { return entityManager; } EntityManager& getEntityManager() { return entityController_->getEntityManager(); }
const EntityManager& getEntityManager() const { return entityManager; } const EntityManager& getEntityManager() const { return entityController_->getEntityManager(); }
/** /**
* Send a chat message * Send a chat message
@ -622,36 +623,38 @@ public:
void resetCastState(); // force-clear all cast/craft/queue state without sending packets void resetCastState(); // force-clear all cast/craft/queue state without sending packets
void clearUnitCaches(); // clear per-unit cast states and aura caches void clearUnitCaches(); // clear per-unit cast states and aura caches
// ---- Phase 1: Name queries ---- // ---- Phase 1: Name queries (delegated to EntityController) ----
void queryPlayerName(uint64_t guid); void queryPlayerName(uint64_t guid);
void queryCreatureInfo(uint32_t entry, uint64_t guid); void queryCreatureInfo(uint32_t entry, uint64_t guid);
void queryGameObjectInfo(uint32_t entry, uint64_t guid); void queryGameObjectInfo(uint32_t entry, uint64_t guid);
const GameObjectQueryResponseData* getCachedGameObjectInfo(uint32_t entry) const { const GameObjectQueryResponseData* getCachedGameObjectInfo(uint32_t entry) const {
auto it = gameObjectInfoCache_.find(entry); return entityController_->getCachedGameObjectInfo(entry);
return (it != gameObjectInfoCache_.end()) ? &it->second : nullptr;
} }
std::string getCachedPlayerName(uint64_t guid) const; std::string getCachedPlayerName(uint64_t guid) const;
std::string getCachedCreatureName(uint32_t entry) const; std::string getCachedCreatureName(uint32_t entry) const;
// Read-only cache access forwarded from EntityController
const std::unordered_map<uint64_t, std::string>& getPlayerNameCache() const {
return entityController_->getPlayerNameCache();
}
const std::unordered_map<uint32_t, CreatureQueryResponseData>& getCreatureInfoCache() const {
return entityController_->getCreatureInfoCache();
}
// Returns the creature subname/title (e.g. "<Warchief of the Horde>"), empty if not cached // Returns the creature subname/title (e.g. "<Warchief of the Horde>"), empty if not cached
std::string getCachedCreatureSubName(uint32_t entry) const { std::string getCachedCreatureSubName(uint32_t entry) const {
auto it = creatureInfoCache.find(entry); return entityController_->getCachedCreatureSubName(entry);
return (it != creatureInfoCache.end()) ? it->second.subName : "";
} }
// Returns the creature rank (0=Normal,1=Elite,2=RareElite,3=Boss,4=Rare) // Returns the creature rank (0=Normal,1=Elite,2=RareElite,3=Boss,4=Rare)
// or -1 if not cached yet // or -1 if not cached yet
int getCreatureRank(uint32_t entry) const { int getCreatureRank(uint32_t entry) const {
auto it = creatureInfoCache.find(entry); return entityController_->getCreatureRank(entry);
return (it != creatureInfoCache.end()) ? static_cast<int>(it->second.rank) : -1;
} }
// Returns creature type (1=Beast,2=Dragonkin,...,7=Humanoid,...) or 0 if not cached // Returns creature type (1=Beast,2=Dragonkin,...,7=Humanoid,...) or 0 if not cached
uint32_t getCreatureType(uint32_t entry) const { uint32_t getCreatureType(uint32_t entry) const {
auto it = creatureInfoCache.find(entry); return entityController_->getCreatureType(entry);
return (it != creatureInfoCache.end()) ? it->second.creatureType : 0;
} }
// Returns creature family (e.g. pet family for beasts) or 0 // Returns creature family (e.g. pet family for beasts) or 0
uint32_t getCreatureFamily(uint32_t entry) const { uint32_t getCreatureFamily(uint32_t entry) const {
auto it = creatureInfoCache.find(entry); return entityController_->getCreatureFamily(entry);
return (it != creatureInfoCache.end()) ? it->second.family : 0;
} }
// ---- Phase 2: Combat (delegated to CombatHandler) ---- // ---- Phase 2: Combat (delegated to CombatHandler) ----
@ -1111,8 +1114,8 @@ public:
glm::vec3 getPlayerTransportOffset() const { return playerTransportOffset_; } glm::vec3 getPlayerTransportOffset() const { return playerTransportOffset_; }
// Check if a GUID is a known transport // Check if a GUID is a known transport
bool isTransportGuid(uint64_t guid) const { return transportGuids_.count(guid) > 0; } bool isTransportGuid(uint64_t guid) const { return entityController_->isTransportGuid(guid); }
bool hasServerTransportUpdate(uint64_t guid) const { return serverUpdatedTransportGuids_.count(guid) > 0; } bool hasServerTransportUpdate(uint64_t guid) const { return entityController_->hasServerTransportUpdate(guid); }
glm::vec3 getComposedWorldPosition(); // Compose transport transform * local offset glm::vec3 getComposedWorldPosition(); // Compose transport transform * local offset
TransportManager* getTransportManager() { return transportManager_.get(); } TransportManager* getTransportManager() { return transportManager_.get(); }
void setPlayerOnTransport(uint64_t transportGuid, const glm::vec3& localOffset) { void setPlayerOnTransport(uint64_t transportGuid, const glm::vec3& localOffset) {
@ -1152,27 +1155,16 @@ public:
// Look up class/race for a player GUID from name query cache. Returns 0 if unknown. // Look up class/race for a player GUID from name query cache. Returns 0 if unknown.
uint8_t lookupPlayerClass(uint64_t guid) const { uint8_t lookupPlayerClass(uint64_t guid) const {
auto it = playerClassRaceCache_.find(guid); return entityController_->lookupPlayerClass(guid);
return it != playerClassRaceCache_.end() ? it->second.classId : 0;
} }
uint8_t lookupPlayerRace(uint64_t guid) const { uint8_t lookupPlayerRace(uint64_t guid) const {
auto it = playerClassRaceCache_.find(guid); return entityController_->lookupPlayerRace(guid);
return it != playerClassRaceCache_.end() ? it->second.raceId : 0;
} }
// Look up a display name for any guid: checks playerNameCache then entity manager. // Look up a display name for any guid: checks playerNameCache then entity manager.
// Returns empty string if unknown. Used by chat display to resolve names at render time. // Returns empty string if unknown. Used by chat display to resolve names at render time.
const std::string& lookupName(uint64_t guid) const { const std::string& lookupName(uint64_t guid) const {
static const std::string kEmpty; return entityController_->lookupName(guid);
auto it = playerNameCache.find(guid);
if (it != playerNameCache.end()) return it->second;
auto entity = entityManager.getEntity(guid);
if (entity) {
if (auto* unit = dynamic_cast<const Unit*>(entity.get())) {
if (!unit->getName().empty()) return unit->getName();
}
}
return kEmpty;
} }
uint8_t getPlayerClass() const { uint8_t getPlayerClass() const {
@ -2106,6 +2098,7 @@ private:
friend class SocialHandler; friend class SocialHandler;
friend class QuestHandler; friend class QuestHandler;
friend class WardenHandler; friend class WardenHandler;
friend class EntityController;
// Dead: autoTargetAttacker moved to CombatHandler // Dead: autoTargetAttacker moved to CombatHandler
@ -2121,12 +2114,6 @@ private:
void enqueueIncomingPacket(const network::Packet& packet); void enqueueIncomingPacket(const network::Packet& packet);
void enqueueIncomingPacketFront(network::Packet&& packet); void enqueueIncomingPacketFront(network::Packet&& packet);
void processQueuedIncomingPackets(); void processQueuedIncomingPackets();
void enqueueUpdateObjectWork(UpdateObjectData&& data);
void processPendingUpdateObjectWork(const std::chrono::steady_clock::time_point& start,
float budgetMs);
void processOutOfRangeObjects(const std::vector<uint64_t>& guids);
void applyUpdateObjectBlock(const UpdateBlock& block, bool& newItemCreated);
void finalizeUpdateObjectBatch(bool newItemCreated);
/** /**
* Handle SMSG_AUTH_CHALLENGE from server * Handle SMSG_AUTH_CHALLENGE from server
@ -2186,27 +2173,7 @@ private:
*/ */
void handlePong(network::Packet& packet); void handlePong(network::Packet& packet);
/** // ---- Phase 1 handlers (entity queries delegated to EntityController) ----
* Handle SMSG_UPDATE_OBJECT from server
*/
void handleUpdateObject(network::Packet& packet);
/**
* Handle SMSG_COMPRESSED_UPDATE_OBJECT from server
*/
void handleCompressedUpdateObject(network::Packet& packet);
/**
* Handle SMSG_DESTROY_OBJECT from server
*/
void handleDestroyObject(network::Packet& packet);
// ---- Phase 1 handlers ----
void handleNameQueryResponse(network::Packet& packet);
void handleCreatureQueryResponse(network::Packet& packet);
void handleGameObjectQueryResponse(network::Packet& packet);
void handleGameObjectPageText(network::Packet& packet);
void handlePageTextQueryResponse(network::Packet& packet);
void handleItemQueryResponse(network::Packet& packet); void handleItemQueryResponse(network::Packet& packet);
void queryItemInfo(uint32_t entry, uint64_t guid); void queryItemInfo(uint32_t entry, uint64_t guid);
void rebuildOnlineInventory(); void rebuildOnlineInventory();
@ -2356,13 +2323,6 @@ private:
// Network // Network
std::unique_ptr<network::WorldSocket> socket; std::unique_ptr<network::WorldSocket> socket;
std::deque<network::Packet> pendingIncomingPackets_; std::deque<network::Packet> pendingIncomingPackets_;
struct PendingUpdateObjectWork {
UpdateObjectData data;
size_t nextBlockIndex = 0;
bool outOfRangeProcessed = false;
bool newItemCreated = false;
};
std::deque<PendingUpdateObjectWork> pendingUpdateObjectWork_;
// State // State
WorldState state = WorldState::DISCONNECTED; WorldState state = WorldState::DISCONNECTED;
@ -2396,8 +2356,8 @@ private:
// Inventory // Inventory
Inventory inventory; Inventory inventory;
// Entity tracking // Entity tracking (delegated to EntityController)
EntityManager entityManager; // Manages all entities in view std::unique_ptr<EntityController> entityController_;
// Chat (state lives in ChatHandler; callbacks remain here for cross-domain access) // Chat (state lives in ChatHandler; callbacks remain here for cross-domain access)
ChatBubbleCallback chatBubbleCallback_; ChatBubbleCallback chatBubbleCallback_;
@ -2444,16 +2404,7 @@ private:
uint32_t homeBindZoneId_ = 0; uint32_t homeBindZoneId_ = 0;
glm::vec3 homeBindPos_{0.0f}; glm::vec3 homeBindPos_{0.0f};
// ---- Phase 1: Name caches ---- // ---- Phase 1: Name caches (moved to EntityController) ----
std::unordered_map<uint64_t, std::string> playerNameCache;
// Class/race cache from SMSG_NAME_QUERY_RESPONSE (guid → {classId, raceId})
struct PlayerClassRace { uint8_t classId = 0; uint8_t raceId = 0; };
std::unordered_map<uint64_t, PlayerClassRace> playerClassRaceCache_;
std::unordered_set<uint64_t> pendingNameQueries;
std::unordered_map<uint32_t, CreatureQueryResponseData> creatureInfoCache;
std::unordered_set<uint32_t> pendingCreatureQueries;
std::unordered_map<uint32_t, GameObjectQueryResponseData> gameObjectInfoCache_;
std::unordered_set<uint32_t> pendingGameObjectQueries_;
// ---- Friend/contact list cache ---- // ---- Friend/contact list cache ----
std::unordered_map<std::string, uint64_t> friendsCache; // name -> guid std::unordered_map<std::string, uint64_t> friendsCache; // name -> guid
@ -2586,8 +2537,7 @@ private:
bool hasLocalOrientation = false; bool hasLocalOrientation = false;
}; };
std::unordered_map<uint64_t, TransportAttachment> transportAttachments_; std::unordered_map<uint64_t, TransportAttachment> transportAttachments_;
std::unordered_set<uint64_t> transportGuids_; // GUIDs of known transport GameObjects // Transport GUID tracking moved to EntityController
std::unordered_set<uint64_t> serverUpdatedTransportGuids_;
uint64_t playerTransportGuid_ = 0; // Transport the player is riding (0 = none) uint64_t playerTransportGuid_ = 0; // Transport the player is riding (0 = none)
glm::vec3 playerTransportOffset_ = glm::vec3(0.0f); // Player offset on transport glm::vec3 playerTransportOffset_ = glm::vec3(0.0f); // Player offset on transport
uint64_t playerTransportStickyGuid_ = 0; // Last transport player was on (temporary retention) uint64_t playerTransportStickyGuid_ = 0; // Last transport player was on (temporary retention)

View file

@ -257,6 +257,7 @@ private:
friend class GameHandler; friend class GameHandler;
friend class InventoryHandler; friend class InventoryHandler;
friend class CombatHandler; friend class CombatHandler;
friend class EntityController;
GameHandler& owner_; GameHandler& owner_;

View file

@ -138,8 +138,8 @@ void ChatHandler::sendChatMessage(ChatType type, const std::string& message, con
echo.language = language; echo.language = language;
echo.message = message; echo.message = message;
auto nameIt = owner_.playerNameCache.find(owner_.playerGuid); auto nameIt = owner_.getPlayerNameCache().find(owner_.playerGuid);
if (nameIt != owner_.playerNameCache.end()) { if (nameIt != owner_.getPlayerNameCache().end()) {
echo.senderName = nameIt->second; echo.senderName = nameIt->second;
} }
@ -179,11 +179,11 @@ void ChatHandler::handleMessageChat(network::Packet& packet) {
// Resolve sender name from entity/cache if not already set by parser // Resolve sender name from entity/cache if not already set by parser
if (data.senderName.empty() && data.senderGuid != 0) { if (data.senderName.empty() && data.senderGuid != 0) {
auto nameIt = owner_.playerNameCache.find(data.senderGuid); auto nameIt = owner_.getPlayerNameCache().find(data.senderGuid);
if (nameIt != owner_.playerNameCache.end()) { if (nameIt != owner_.getPlayerNameCache().end()) {
data.senderName = nameIt->second; data.senderName = nameIt->second;
} else { } else {
auto entity = owner_.entityManager.getEntity(data.senderGuid); auto entity = owner_.getEntityManager().getEntity(data.senderGuid);
if (entity) { if (entity) {
if (entity->getType() == ObjectType::PLAYER) { if (entity->getType() == ObjectType::PLAYER) {
auto player = std::dynamic_pointer_cast<Player>(entity); auto player = std::dynamic_pointer_cast<Player>(entity);
@ -356,11 +356,11 @@ void ChatHandler::handleTextEmote(network::Packet& packet) {
} }
std::string senderName; std::string senderName;
auto nameIt = owner_.playerNameCache.find(data.senderGuid); auto nameIt = owner_.getPlayerNameCache().find(data.senderGuid);
if (nameIt != owner_.playerNameCache.end()) { if (nameIt != owner_.getPlayerNameCache().end()) {
senderName = nameIt->second; senderName = nameIt->second;
} else { } else {
auto entity = owner_.entityManager.getEntity(data.senderGuid); auto entity = owner_.getEntityManager().getEntity(data.senderGuid);
if (entity) { if (entity) {
auto unit = std::dynamic_pointer_cast<Unit>(entity); auto unit = std::dynamic_pointer_cast<Unit>(entity);
if (unit) senderName = unit->getName(); if (unit) senderName = unit->getName();
@ -685,7 +685,7 @@ void ChatHandler::handleChannelList(network::Packet& packet) {
uint64_t memberGuid = packet.readUInt64(); uint64_t memberGuid = packet.readUInt64();
uint8_t memberFlags = packet.readUInt8(); uint8_t memberFlags = packet.readUInt8();
std::string name; std::string name;
auto entity = owner_.entityManager.getEntity(memberGuid); auto entity = owner_.getEntityManager().getEntity(memberGuid);
if (entity) { if (entity) {
auto player = std::dynamic_pointer_cast<Player>(entity); auto player = std::dynamic_pointer_cast<Player>(entity);
if (player && !player->getName().empty()) name = player->getName(); if (player && !player->getName().empty()) name = player->getName();

View file

@ -64,7 +64,7 @@ void CombatHandler::registerOpcodes(DispatchTable& table) {
}; };
table[Opcode::SMSG_ATTACKSWING_BADFACING] = [this](network::Packet& /*packet*/) { table[Opcode::SMSG_ATTACKSWING_BADFACING] = [this](network::Packet& /*packet*/) {
if (autoAttackRequested_ && autoAttackTarget_ != 0) { if (autoAttackRequested_ && autoAttackTarget_ != 0) {
auto targetEntity = owner_.entityManager.getEntity(autoAttackTarget_); auto targetEntity = owner_.getEntityManager().getEntity(autoAttackTarget_);
if (targetEntity) { if (targetEntity) {
float toTargetX = targetEntity->getX() - owner_.movementInfo.x; float toTargetX = targetEntity->getX() - owner_.movementInfo.x;
float toTargetY = targetEntity->getY() - owner_.movementInfo.y; float toTargetY = targetEntity->getY() - owner_.movementInfo.y;
@ -96,7 +96,7 @@ void CombatHandler::registerOpcodes(DispatchTable& table) {
uint64_t guid = packet.readUInt64(); uint64_t guid = packet.readUInt64();
uint32_t reaction = packet.readUInt32(); uint32_t reaction = packet.readUInt32();
if (reaction == 2 && owner_.npcAggroCallback_) { if (reaction == 2 && owner_.npcAggroCallback_) {
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
if (entity) if (entity)
owner_.npcAggroCallback_(guid, glm::vec3(entity->getX(), entity->getY(), entity->getZ())); owner_.npcAggroCallback_(guid, glm::vec3(entity->getX(), entity->getY(), entity->getZ()));
} }
@ -204,7 +204,7 @@ void CombatHandler::startAutoAttack(uint64_t targetGuid) {
// Client-side melee range gate to avoid starting "swing forever" loops when // Client-side melee range gate to avoid starting "swing forever" loops when
// target is already clearly out of range. // target is already clearly out of range.
if (auto target = owner_.entityManager.getEntity(targetGuid)) { if (auto target = owner_.getEntityManager().getEntity(targetGuid)) {
float dx = owner_.movementInfo.x - target->getLatestX(); float dx = owner_.movementInfo.x - target->getLatestX();
float dy = owner_.movementInfo.y - target->getLatestY(); float dy = owner_.movementInfo.y - target->getLatestY();
float dz = owner_.movementInfo.z - target->getLatestZ(); float dz = owner_.movementInfo.z - target->getLatestZ();
@ -368,7 +368,7 @@ void CombatHandler::updateCombatText(float deltaTime) {
void CombatHandler::autoTargetAttacker(uint64_t attackerGuid) { void CombatHandler::autoTargetAttacker(uint64_t attackerGuid) {
if (attackerGuid == 0 || attackerGuid == owner_.playerGuid) return; if (attackerGuid == 0 || attackerGuid == owner_.playerGuid) return;
if (owner_.targetGuid != 0) return; if (owner_.targetGuid != 0) return;
if (!owner_.entityManager.hasEntity(attackerGuid)) return; if (!owner_.getEntityManager().hasEntity(attackerGuid)) return;
owner_.setTarget(attackerGuid); owner_.setTarget(attackerGuid);
} }
@ -389,7 +389,7 @@ void CombatHandler::handleAttackStart(network::Packet& packet) {
// Play aggro sound when NPC attacks player // Play aggro sound when NPC attacks player
if (owner_.npcAggroCallback_) { if (owner_.npcAggroCallback_) {
auto entity = owner_.entityManager.getEntity(data.attackerGuid); auto entity = owner_.getEntityManager().getEntity(data.attackerGuid);
if (entity && entity->getType() == ObjectType::UNIT) { if (entity && entity->getType() == ObjectType::UNIT) {
glm::vec3 pos(entity->getX(), entity->getY(), entity->getZ()); glm::vec3 pos(entity->getX(), entity->getY(), entity->getZ());
owner_.npcAggroCallback_(data.attackerGuid, pos); owner_.npcAggroCallback_(data.attackerGuid, pos);
@ -400,8 +400,8 @@ void CombatHandler::handleAttackStart(network::Packet& packet) {
// Force both participants to face each other at combat start. // Force both participants to face each other at combat start.
// Uses atan2(-dy, dx): canonical orientation convention where the West/Y // Uses atan2(-dy, dx): canonical orientation convention where the West/Y
// component is negated (renderYaw = orientation + 90°, model-forward = render+X). // component is negated (renderYaw = orientation + 90°, model-forward = render+X).
auto attackerEnt = owner_.entityManager.getEntity(data.attackerGuid); auto attackerEnt = owner_.getEntityManager().getEntity(data.attackerGuid);
auto victimEnt = owner_.entityManager.getEntity(data.victimGuid); auto victimEnt = owner_.getEntityManager().getEntity(data.victimGuid);
if (attackerEnt && victimEnt) { if (attackerEnt && victimEnt) {
float dx = victimEnt->getX() - attackerEnt->getX(); float dx = victimEnt->getX() - attackerEnt->getX();
float dy = victimEnt->getY() - attackerEnt->getY(); float dy = victimEnt->getY() - attackerEnt->getY();
@ -589,7 +589,7 @@ void CombatHandler::updateAutoAttack(float deltaTime) {
// Leave combat if auto-attack target is too far away (leash range) // Leave combat if auto-attack target is too far away (leash range)
// and keep melee intent tightly synced while stationary. // and keep melee intent tightly synced while stationary.
if (autoAttackRequested_ && autoAttackTarget_ != 0) { if (autoAttackRequested_ && autoAttackTarget_ != 0) {
auto targetEntity = owner_.entityManager.getEntity(autoAttackTarget_); auto targetEntity = owner_.getEntityManager().getEntity(autoAttackTarget_);
if (targetEntity) { if (targetEntity) {
const float targetX = targetEntity->getLatestX(); const float targetX = targetEntity->getLatestX();
const float targetY = targetEntity->getLatestY(); const float targetY = targetEntity->getLatestY();
@ -669,7 +669,7 @@ void CombatHandler::updateAutoAttack(float deltaTime) {
// Keep active melee attackers visually facing the player as positions change. // Keep active melee attackers visually facing the player as positions change.
if (!hostileAttackers_.empty()) { if (!hostileAttackers_.empty()) {
for (uint64_t attackerGuid : hostileAttackers_) { for (uint64_t attackerGuid : hostileAttackers_) {
auto attacker = owner_.entityManager.getEntity(attackerGuid); auto attacker = owner_.getEntityManager().getEntity(attackerGuid);
if (!attacker) continue; if (!attacker) continue;
float dx = owner_.movementInfo.x - attacker->getX(); float dx = owner_.movementInfo.x - attacker->getX();
float dy = owner_.movementInfo.y - attacker->getY(); float dy = owner_.movementInfo.y - attacker->getY();
@ -1098,14 +1098,14 @@ void CombatHandler::clearTarget() {
std::shared_ptr<Entity> CombatHandler::getTarget() const { std::shared_ptr<Entity> CombatHandler::getTarget() const {
if (owner_.targetGuid == 0) return nullptr; if (owner_.targetGuid == 0) return nullptr;
return owner_.entityManager.getEntity(owner_.targetGuid); return owner_.getEntityManager().getEntity(owner_.targetGuid);
} }
void CombatHandler::setFocus(uint64_t guid) { void CombatHandler::setFocus(uint64_t guid) {
owner_.focusGuid = guid; owner_.focusGuid = guid;
owner_.fireAddonEvent("PLAYER_FOCUS_CHANGED", {}); owner_.fireAddonEvent("PLAYER_FOCUS_CHANGED", {});
if (guid != 0) { if (guid != 0) {
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
if (entity) { if (entity) {
std::string name; std::string name;
auto unit = std::dynamic_pointer_cast<Unit>(entity); auto unit = std::dynamic_pointer_cast<Unit>(entity);
@ -1131,7 +1131,7 @@ void CombatHandler::clearFocus() {
std::shared_ptr<Entity> CombatHandler::getFocus() const { std::shared_ptr<Entity> CombatHandler::getFocus() const {
if (owner_.focusGuid == 0) return nullptr; if (owner_.focusGuid == 0) return nullptr;
return owner_.entityManager.getEntity(owner_.focusGuid); return owner_.getEntityManager().getEntity(owner_.focusGuid);
} }
void CombatHandler::setMouseoverGuid(uint64_t guid) { void CombatHandler::setMouseoverGuid(uint64_t guid) {
@ -1156,7 +1156,7 @@ void CombatHandler::targetLastTarget() {
void CombatHandler::targetEnemy(bool reverse) { void CombatHandler::targetEnemy(bool reverse) {
// Get list of hostile entities // Get list of hostile entities
std::vector<uint64_t> hostiles; std::vector<uint64_t> hostiles;
auto& entities = owner_.entityManager.getEntities(); auto& entities = owner_.getEntityManager().getEntities();
for (const auto& [guid, entity] : entities) { for (const auto& [guid, entity] : entities) {
if (entity->getType() == ObjectType::UNIT) { if (entity->getType() == ObjectType::UNIT) {
@ -1200,7 +1200,7 @@ void CombatHandler::targetEnemy(bool reverse) {
void CombatHandler::targetFriend(bool reverse) { void CombatHandler::targetFriend(bool reverse) {
// Get list of friendly entities (players) // Get list of friendly entities (players)
std::vector<uint64_t> friendlies; std::vector<uint64_t> friendlies;
auto& entities = owner_.entityManager.getEntities(); auto& entities = owner_.getEntityManager().getEntities();
for (const auto& [guid, entity] : entities) { for (const auto& [guid, entity] : entities) {
if (entity->getType() == ObjectType::PLAYER && guid != owner_.playerGuid) { if (entity->getType() == ObjectType::PLAYER && guid != owner_.playerGuid) {
@ -1266,7 +1266,7 @@ void CombatHandler::tabTarget(float playerX, float playerY, float playerZ) {
struct EntityDist { uint64_t guid; float distance; }; struct EntityDist { uint64_t guid; float distance; };
std::vector<EntityDist> sortable; std::vector<EntityDist> sortable;
for (const auto& [guid, entity] : owner_.entityManager.getEntities()) { for (const auto& [guid, entity] : owner_.getEntityManager().getEntities()) {
auto t = entity->getType(); auto t = entity->getType();
if (t != ObjectType::UNIT && t != ObjectType::PLAYER) continue; if (t != ObjectType::UNIT && t != ObjectType::PLAYER) continue;
if (guid == owner_.playerGuid) continue; if (guid == owner_.playerGuid) continue;
@ -1297,7 +1297,7 @@ void CombatHandler::tabTarget(float playerX, float playerY, float playerZ) {
while (tries-- > 0) { while (tries-- > 0) {
owner_.tabCycleIndex = (owner_.tabCycleIndex + 1) % static_cast<int>(owner_.tabCycleList.size()); owner_.tabCycleIndex = (owner_.tabCycleIndex + 1) % static_cast<int>(owner_.tabCycleList.size());
uint64_t guid = owner_.tabCycleList[owner_.tabCycleIndex]; uint64_t guid = owner_.tabCycleList[owner_.tabCycleIndex];
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
if (isValidTabTarget(entity)) { if (isValidTabTarget(entity)) {
setTarget(guid); setTarget(guid);
return; return;
@ -1373,7 +1373,7 @@ void CombatHandler::togglePvp() {
auto packet = TogglePvpPacket::build(); auto packet = TogglePvpPacket::build();
owner_.socket->send(packet); owner_.socket->send(packet);
auto entity = owner_.entityManager.getEntity(owner_.playerGuid); auto entity = owner_.getEntityManager().getEntity(owner_.playerGuid);
bool currentlyPvp = false; bool currentlyPvp = false;
if (entity) { if (entity) {
currentlyPvp = (entity->getField(59) & 0x00001000) != 0; currentlyPvp = (entity->getField(59) & 0x00001000) != 0;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -810,8 +810,8 @@ void InventoryHandler::handleLootRoll(network::Packet& packet) {
// Resolve player name // Resolve player name
std::string playerName; std::string playerName;
auto nit = owner_.playerNameCache.find(playerGuid); auto nit = owner_.getPlayerNameCache().find(playerGuid);
if (nit != owner_.playerNameCache.end()) playerName = nit->second; if (nit != owner_.getPlayerNameCache().end()) playerName = nit->second;
if (playerName.empty()) playerName = "Player"; if (playerName.empty()) playerName = "Player";
if (pendingLootRollActive_ && if (pendingLootRollActive_ &&
@ -848,8 +848,8 @@ void InventoryHandler::handleLootRollWon(network::Packet& packet) {
uint8_t rollType = packet.readUInt8(); uint8_t rollType = packet.readUInt8();
std::string winnerName; std::string winnerName;
auto nit = owner_.playerNameCache.find(winnerGuid); auto nit = owner_.getPlayerNameCache().find(winnerGuid);
if (nit != owner_.playerNameCache.end()) winnerName = nit->second; if (nit != owner_.getPlayerNameCache().end()) winnerName = nit->second;
if (winnerName.empty()) winnerName = "Player"; if (winnerName.empty()) winnerName = "Player";
owner_.ensureItemInfo(itemId); owner_.ensureItemInfo(itemId);
@ -1374,7 +1374,7 @@ void InventoryHandler::handleListInventory(network::Packet& packet) {
// Play vendor sound // Play vendor sound
if (owner_.npcVendorCallback_ && currentVendorItems_.vendorGuid != 0) { if (owner_.npcVendorCallback_ && currentVendorItems_.vendorGuid != 0) {
auto entity = owner_.entityManager.getEntity(currentVendorItems_.vendorGuid); auto entity = owner_.getEntityManager().getEntity(currentVendorItems_.vendorGuid);
if (entity && entity->getType() == ObjectType::UNIT) { if (entity && entity->getType() == ObjectType::UNIT) {
glm::vec3 pos(entity->getX(), entity->getY(), entity->getZ()); glm::vec3 pos(entity->getX(), entity->getY(), entity->getZ());
owner_.npcVendorCallback_(currentVendorItems_.vendorGuid, pos); owner_.npcVendorCallback_(currentVendorItems_.vendorGuid, pos);
@ -2076,8 +2076,8 @@ void InventoryHandler::handleTradeStatus(network::Packet& packet) {
tradePeerGuid_ = packet.readUInt64(); tradePeerGuid_ = packet.readUInt64();
tradeStatus_ = TradeStatus::PendingIncoming; tradeStatus_ = TradeStatus::PendingIncoming;
// Resolve name // Resolve name
auto nit = owner_.playerNameCache.find(tradePeerGuid_); auto nit = owner_.getPlayerNameCache().find(tradePeerGuid_);
if (nit != owner_.playerNameCache.end()) tradePeerName_ = nit->second; if (nit != owner_.getPlayerNameCache().end()) tradePeerName_ = nit->second;
else tradePeerName_ = "Unknown"; else tradePeerName_ = "Unknown";
owner_.addSystemChatMessage(tradePeerName_ + " wants to trade with you."); owner_.addSystemChatMessage(tradePeerName_ + " wants to trade with you.");
if (owner_.addonEventCallback_) owner_.addonEventCallback_("TRADE_REQUEST", {tradePeerName_}); if (owner_.addonEventCallback_) owner_.addonEventCallback_("TRADE_REQUEST", {tradePeerName_});
@ -3098,7 +3098,7 @@ void InventoryHandler::maybeDetectVisibleItemLayout() {
" mismatches=", bestMismatches, " score=", bestScore, ")"); " mismatches=", bestMismatches, " score=", bestScore, ")");
// Backfill existing player entities already in view. // Backfill existing player entities already in view.
for (const auto& [guid, ent] : owner_.entityManager.getEntities()) { for (const auto& [guid, ent] : owner_.getEntityManager().getEntities()) {
if (!ent || ent->getType() != ObjectType::PLAYER) continue; if (!ent || ent->getType() != ObjectType::PLAYER) continue;
if (guid == owner_.playerGuid) continue; if (guid == owner_.playerGuid) continue;
updateOtherPlayerVisibleItems(guid, ent->getFields()); updateOtherPlayerVisibleItems(guid, ent->getFields());

View file

@ -1180,7 +1180,7 @@ void MovementHandler::handleOtherPlayerMovement(network::Packet& packet) {
} }
} }
auto entity = owner_.entityManager.getEntity(moverGuid); auto entity = owner_.getEntityManager().getEntity(moverGuid);
if (!entity) { if (!entity) {
return; return;
} }
@ -1539,7 +1539,7 @@ void MovementHandler::handleMonsterMove(network::Packet& packet) {
} }
} }
auto entity = owner_.entityManager.getEntity(data.guid); auto entity = owner_.getEntityManager().getEntity(data.guid);
if (!entity) { if (!entity) {
return; return;
} }
@ -1552,7 +1552,7 @@ void MovementHandler::handleMonsterMove(network::Packet& packet) {
if (data.moveType == 4) { if (data.moveType == 4) {
orientation = core::coords::serverToCanonicalYaw(data.facingAngle); orientation = core::coords::serverToCanonicalYaw(data.facingAngle);
} else if (data.moveType == 3) { } else if (data.moveType == 3) {
auto target = owner_.entityManager.getEntity(data.facingTarget); auto target = owner_.getEntityManager().getEntity(data.facingTarget);
if (target) { if (target) {
float dx = target->getX() - entity->getX(); float dx = target->getX() - entity->getX();
float dy = target->getY() - entity->getY(); float dy = target->getY() - entity->getY();
@ -1613,7 +1613,7 @@ void MovementHandler::handleMonsterMove(network::Packet& packet) {
posCanonical.x, posCanonical.y, posCanonical.z, 0); posCanonical.x, posCanonical.y, posCanonical.z, 0);
} }
} else if (data.moveType == 3 && data.facingTarget != 0) { } else if (data.moveType == 3 && data.facingTarget != 0) {
auto target = owner_.entityManager.getEntity(data.facingTarget); auto target = owner_.getEntityManager().getEntity(data.facingTarget);
if (target) { if (target) {
float dx = target->getX() - entity->getX(); float dx = target->getX() - entity->getX();
float dy = target->getY() - entity->getY(); float dy = target->getY() - entity->getY();
@ -1635,7 +1635,7 @@ void MovementHandler::handleMonsterMoveTransport(network::Packet& packet) {
float localY = packet.readFloat(); float localY = packet.readFloat();
float localZ = packet.readFloat(); float localZ = packet.readFloat();
auto entity = owner_.entityManager.getEntity(moverGuid); auto entity = owner_.getEntityManager().getEntity(moverGuid);
if (!entity) return; if (!entity) return;
if (packet.getReadPos() + 5 > packet.getSize()) { if (packet.getReadPos() + 5 > packet.getSize()) {
@ -1674,7 +1674,7 @@ void MovementHandler::handleMonsterMoveTransport(network::Packet& packet) {
} else if (moveType == 3) { } else if (moveType == 3) {
if (packet.getReadPos() + 8 > packet.getSize()) return; if (packet.getReadPos() + 8 > packet.getSize()) return;
uint64_t tgtGuid = packet.readUInt64(); uint64_t tgtGuid = packet.readUInt64();
if (auto tgt = owner_.entityManager.getEntity(tgtGuid)) { if (auto tgt = owner_.getEntityManager().getEntity(tgtGuid)) {
float dx = tgt->getX() - entity->getX(); float dx = tgt->getX() - entity->getX();
float dy = tgt->getY() - entity->getY(); float dy = tgt->getY() - entity->getY();
if (std::abs(dx) > 0.01f || std::abs(dy) > 0.01f) if (std::abs(dx) > 0.01f || std::abs(dy) > 0.01f)
@ -1922,7 +1922,7 @@ void MovementHandler::handleNewWorld(network::Packet& packet) {
owner_.mountCallback_(0); owner_.mountCallback_(0);
} }
for (const auto& [guid, entity] : owner_.entityManager.getEntities()) { for (const auto& [guid, entity] : owner_.getEntityManager().getEntities()) {
if (guid == owner_.playerGuid) continue; if (guid == owner_.playerGuid) continue;
if (entity->getType() == ObjectType::UNIT && owner_.creatureDespawnCallback_) { if (entity->getType() == ObjectType::UNIT && owner_.creatureDespawnCallback_) {
owner_.creatureDespawnCallback_(guid); owner_.creatureDespawnCallback_(guid);
@ -1938,7 +1938,7 @@ void MovementHandler::handleNewWorld(network::Packet& packet) {
owner_.unitCastStates_.clear(); owner_.unitCastStates_.clear();
owner_.unitAurasCache_.clear(); owner_.unitAurasCache_.clear();
owner_.clearCombatText(); owner_.clearCombatText();
owner_.entityManager.clear(); owner_.getEntityManager().clear();
owner_.clearHostileAttackers(); owner_.clearHostileAttackers();
owner_.worldStates_.clear(); owner_.worldStates_.clear();
owner_.gossipPois_.clear(); owner_.gossipPois_.clear();
@ -2278,7 +2278,7 @@ void MovementHandler::startClientTaxiPath(const std::vector<uint32_t>& pathNodes
movementInfo.orientation = initialOrientation; movementInfo.orientation = initialOrientation;
sanitizeMovementForTaxi(); sanitizeMovementForTaxi();
auto playerEntity = owner_.entityManager.getEntity(owner_.playerGuid); auto playerEntity = owner_.getEntityManager().getEntity(owner_.playerGuid);
if (playerEntity) { if (playerEntity) {
playerEntity->setPosition(start.x, start.y, start.z, initialOrientation); playerEntity->setPosition(start.x, start.y, start.z, initialOrientation);
} }
@ -2293,7 +2293,7 @@ void MovementHandler::startClientTaxiPath(const std::vector<uint32_t>& pathNodes
void MovementHandler::updateClientTaxi(float deltaTime) { void MovementHandler::updateClientTaxi(float deltaTime) {
if (!taxiClientActive_ || taxiClientPath_.size() < 2) return; if (!taxiClientActive_ || taxiClientPath_.size() < 2) return;
auto playerEntity = owner_.entityManager.getEntity(owner_.playerGuid); auto playerEntity = owner_.getEntityManager().getEntity(owner_.playerGuid);
auto finishTaxiFlight = [&]() { auto finishTaxiFlight = [&]() {
if (!taxiClientPath_.empty()) { if (!taxiClientPath_.empty()) {
@ -2820,7 +2820,7 @@ void MovementHandler::updateAttachedTransportChildren(float /*deltaTime*/) {
stale.reserve(8); stale.reserve(8);
for (const auto& [childGuid, attachment] : owner_.transportAttachments_) { for (const auto& [childGuid, attachment] : owner_.transportAttachments_) {
auto entity = owner_.entityManager.getEntity(childGuid); auto entity = owner_.getEntityManager().getEntity(childGuid);
if (!entity) { if (!entity) {
stale.push_back(childGuid); stale.push_back(childGuid);
continue; continue;

View file

@ -504,7 +504,7 @@ void QuestHandler::registerOpcodes(DispatchTable& table) {
} }
// Re-query all nearby quest giver NPCs so markers refresh // Re-query all nearby quest giver NPCs so markers refresh
if (owner_.socket) { if (owner_.socket) {
for (const auto& [guid, entity] : owner_.entityManager.getEntities()) { for (const auto& [guid, entity] : owner_.getEntityManager().getEntities()) {
if (entity->getType() != ObjectType::UNIT) continue; if (entity->getType() != ObjectType::UNIT) continue;
auto unit = std::static_pointer_cast<Unit>(entity); auto unit = std::static_pointer_cast<Unit>(entity);
if (unit->getNpcFlags() & 0x02) { if (unit->getNpcFlags() & 0x02) {
@ -1557,7 +1557,7 @@ void QuestHandler::handleGossipMessage(network::Packet& packet) {
// Play NPC greeting voice // Play NPC greeting voice
if (owner_.npcGreetingCallback_ && currentGossip_.npcGuid != 0) { if (owner_.npcGreetingCallback_ && currentGossip_.npcGuid != 0) {
auto entity = owner_.entityManager.getEntity(currentGossip_.npcGuid); auto entity = owner_.getEntityManager().getEntity(currentGossip_.npcGuid);
if (entity) { if (entity) {
glm::vec3 npcPos(entity->getX(), entity->getY(), entity->getZ()); glm::vec3 npcPos(entity->getX(), entity->getY(), entity->getZ());
owner_.npcGreetingCallback_(currentGossip_.npcGuid, npcPos); owner_.npcGreetingCallback_(currentGossip_.npcGuid, npcPos);
@ -1654,7 +1654,7 @@ void QuestHandler::handleGossipComplete(network::Packet& packet) {
// Play farewell sound before closing // Play farewell sound before closing
if (owner_.npcFarewellCallback_ && currentGossip_.npcGuid != 0) { if (owner_.npcFarewellCallback_ && currentGossip_.npcGuid != 0) {
auto entity = owner_.entityManager.getEntity(currentGossip_.npcGuid); auto entity = owner_.getEntityManager().getEntity(currentGossip_.npcGuid);
if (entity && entity->getType() == ObjectType::UNIT) { if (entity && entity->getType() == ObjectType::UNIT) {
glm::vec3 pos(entity->getX(), entity->getY(), entity->getZ()); glm::vec3 pos(entity->getX(), entity->getY(), entity->getZ());
owner_.npcFarewellCallback_(currentGossip_.npcGuid, pos); owner_.npcFarewellCallback_(currentGossip_.npcGuid, pos);
@ -1865,13 +1865,13 @@ void QuestHandler::handleQuestConfirmAccept(network::Packet& packet) {
} }
sharedQuestSharerName_.clear(); sharedQuestSharerName_.clear();
auto entity = owner_.entityManager.getEntity(sharedQuestSharerGuid_); auto entity = owner_.getEntityManager().getEntity(sharedQuestSharerGuid_);
if (auto* unit = dynamic_cast<Unit*>(entity.get())) { if (auto* unit = dynamic_cast<Unit*>(entity.get())) {
sharedQuestSharerName_ = unit->getName(); sharedQuestSharerName_ = unit->getName();
} }
if (sharedQuestSharerName_.empty()) { if (sharedQuestSharerName_.empty()) {
auto nit = owner_.playerNameCache.find(sharedQuestSharerGuid_); auto nit = owner_.getPlayerNameCache().find(sharedQuestSharerGuid_);
if (nit != owner_.playerNameCache.end()) if (nit != owner_.getPlayerNameCache().end())
sharedQuestSharerName_ = nit->second; sharedQuestSharerName_ = nit->second;
} }
if (sharedQuestSharerName_.empty()) { if (sharedQuestSharerName_.empty()) {

View file

@ -154,7 +154,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
readyCheckResults_.clear(); readyCheckResults_.clear();
if (packet.getSize() - packet.getReadPos() >= 8) { if (packet.getSize() - packet.getReadPos() >= 8) {
uint64_t initiatorGuid = packet.readUInt64(); uint64_t initiatorGuid = packet.readUInt64();
auto entity = owner_.entityManager.getEntity(initiatorGuid); auto entity = owner_.getEntityManager().getEntity(initiatorGuid);
if (auto* unit = dynamic_cast<Unit*>(entity.get())) if (auto* unit = dynamic_cast<Unit*>(entity.get()))
readyCheckInitiator_ = unit->getName(); readyCheckInitiator_ = unit->getName();
} }
@ -174,11 +174,11 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
uint64_t respGuid = packet.readUInt64(); uint64_t respGuid = packet.readUInt64();
uint8_t isReady = packet.readUInt8(); uint8_t isReady = packet.readUInt8();
if (isReady) ++readyCheckReadyCount_; else ++readyCheckNotReadyCount_; if (isReady) ++readyCheckReadyCount_; else ++readyCheckNotReadyCount_;
auto nit = owner_.playerNameCache.find(respGuid); auto nit = owner_.getPlayerNameCache().find(respGuid);
std::string rname; std::string rname;
if (nit != owner_.playerNameCache.end()) rname = nit->second; if (nit != owner_.getPlayerNameCache().end()) rname = nit->second;
else { else {
auto ent = owner_.entityManager.getEntity(respGuid); auto ent = owner_.getEntityManager().getEntity(respGuid);
if (ent) rname = std::static_pointer_cast<game::Unit>(ent)->getName(); if (ent) rname = std::static_pointer_cast<game::Unit>(ent)->getName();
} }
if (!rname.empty()) { if (!rname.empty()) {
@ -231,9 +231,9 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
uint64_t killerGuid = packet.readUInt64(); uint64_t killerGuid = packet.readUInt64();
uint64_t victimGuid = packet.readUInt64(); uint64_t victimGuid = packet.readUInt64();
auto nameFor = [this](uint64_t g) -> std::string { auto nameFor = [this](uint64_t g) -> std::string {
auto nit = owner_.playerNameCache.find(g); auto nit = owner_.getPlayerNameCache().find(g);
if (nit != owner_.playerNameCache.end()) return nit->second; if (nit != owner_.getPlayerNameCache().end()) return nit->second;
auto ent = owner_.entityManager.getEntity(g); auto ent = owner_.getEntityManager().getEntity(g);
if (ent && (ent->getType() == game::ObjectType::UNIT || if (ent && (ent->getType() == game::ObjectType::UNIT ||
ent->getType() == game::ObjectType::PLAYER)) ent->getType() == game::ObjectType::PLAYER))
return std::static_pointer_cast<game::Unit>(ent)->getName(); return std::static_pointer_cast<game::Unit>(ent)->getName();
@ -303,16 +303,16 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
table[Opcode::SMSG_BATTLEGROUND_PLAYER_JOINED] = [this](network::Packet& packet) { table[Opcode::SMSG_BATTLEGROUND_PLAYER_JOINED] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 8) { if (packet.getSize() - packet.getReadPos() >= 8) {
uint64_t guid = packet.readUInt64(); uint64_t guid = packet.readUInt64();
auto it = owner_.playerNameCache.find(guid); auto it = owner_.getPlayerNameCache().find(guid);
if (it != owner_.playerNameCache.end() && !it->second.empty()) if (it != owner_.getPlayerNameCache().end() && !it->second.empty())
owner_.addSystemChatMessage(it->second + " has entered the battleground."); owner_.addSystemChatMessage(it->second + " has entered the battleground.");
} }
}; };
table[Opcode::SMSG_BATTLEGROUND_PLAYER_LEFT] = [this](network::Packet& packet) { table[Opcode::SMSG_BATTLEGROUND_PLAYER_LEFT] = [this](network::Packet& packet) {
if (packet.getSize() - packet.getReadPos() >= 8) { if (packet.getSize() - packet.getReadPos() >= 8) {
uint64_t guid = packet.readUInt64(); uint64_t guid = packet.readUInt64();
auto it = owner_.playerNameCache.find(guid); auto it = owner_.getPlayerNameCache().find(guid);
if (it != owner_.playerNameCache.end() && !it->second.empty()) if (it != owner_.getPlayerNameCache().end() && !it->second.empty())
owner_.addSystemChatMessage(it->second + " has left the battleground."); owner_.addSystemChatMessage(it->second + " has left the battleground.");
} }
}; };
@ -455,7 +455,7 @@ void SocialHandler::registerOpcodes(DispatchTable& table) {
if (roles & 0x08) roleName += "DPS "; if (roles & 0x08) roleName += "DPS ";
if (roleName.empty()) roleName = "None"; if (roleName.empty()) roleName = "None";
std::string pName = "A player"; std::string pName = "A player";
if (auto e = owner_.entityManager.getEntity(roleGuid)) if (auto e = owner_.getEntityManager().getEntity(roleGuid))
if (auto u = std::dynamic_pointer_cast<Unit>(e)) if (auto u = std::dynamic_pointer_cast<Unit>(e))
pName = u->getName(); pName = u->getName();
if (ready) owner_.addSystemChatMessage(pName + " has chosen: " + roleName); if (ready) owner_.addSystemChatMessage(pName + " has chosen: " + roleName);
@ -507,7 +507,7 @@ bool SocialHandler::isInGuild() const {
} }
uint32_t SocialHandler::getEntityGuildId(uint64_t guid) const { uint32_t SocialHandler::getEntityGuildId(uint64_t guid) const {
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
if (!entity || entity->getType() != ObjectType::PLAYER) return 0; if (!entity || entity->getType() != ObjectType::PLAYER) return 0;
const uint16_t ufUnitEnd = fieldIndex(UF::UNIT_END); const uint16_t ufUnitEnd = fieldIndex(UF::UNIT_END);
if (ufUnitEnd == 0xFFFF) return 0; if (ufUnitEnd == 0xFFFF) return 0;
@ -613,7 +613,7 @@ void SocialHandler::handleInspectResults(network::Packet& packet) {
size_t bytesLeft = packet.getSize() - packet.getReadPos(); size_t bytesLeft = packet.getSize() - packet.getReadPos();
if (bytesLeft < 6) { if (bytesLeft < 6) {
LOG_WARNING("SMSG_TALENTS_INFO: too short after guid, ", bytesLeft, " bytes"); LOG_WARNING("SMSG_TALENTS_INFO: too short after guid, ", bytesLeft, " bytes");
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
std::string name = "Target"; std::string name = "Target";
if (entity) { if (entity) {
auto player = std::dynamic_pointer_cast<Player>(entity); auto player = std::dynamic_pointer_cast<Player>(entity);
@ -627,7 +627,7 @@ void SocialHandler::handleInspectResults(network::Packet& packet) {
uint8_t talentGroupCount = packet.readUInt8(); uint8_t talentGroupCount = packet.readUInt8();
uint8_t activeTalentGroup = packet.readUInt8(); uint8_t activeTalentGroup = packet.readUInt8();
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
std::string playerName = "Target"; std::string playerName = "Target";
if (entity) { if (entity) {
auto player = std::dynamic_pointer_cast<Player>(entity); auto player = std::dynamic_pointer_cast<Player>(entity);
@ -1028,12 +1028,12 @@ void SocialHandler::handleDuelRequested(network::Packet& packet) {
duelChallengerGuid_ = packet.readUInt64(); duelChallengerGuid_ = packet.readUInt64();
duelFlagGuid_ = packet.readUInt64(); duelFlagGuid_ = packet.readUInt64();
duelChallengerName_.clear(); duelChallengerName_.clear();
auto entity = owner_.entityManager.getEntity(duelChallengerGuid_); auto entity = owner_.getEntityManager().getEntity(duelChallengerGuid_);
if (auto* unit = dynamic_cast<Unit*>(entity.get())) if (auto* unit = dynamic_cast<Unit*>(entity.get()))
duelChallengerName_ = unit->getName(); duelChallengerName_ = unit->getName();
if (duelChallengerName_.empty()) { if (duelChallengerName_.empty()) {
auto nit = owner_.playerNameCache.find(duelChallengerGuid_); auto nit = owner_.getPlayerNameCache().find(duelChallengerGuid_);
if (nit != owner_.playerNameCache.end()) duelChallengerName_ = nit->second; if (nit != owner_.getPlayerNameCache().end()) duelChallengerName_ = nit->second;
} }
if (duelChallengerName_.empty()) { if (duelChallengerName_.empty()) {
char tmp[32]; char tmp[32];
@ -1745,9 +1745,9 @@ void SocialHandler::handleFriendList(network::Packet& packet) {
classId = packet.readUInt32(); classId = packet.readUInt32();
} }
owner_.friendGuids_.insert(guid); owner_.friendGuids_.insert(guid);
auto nit = owner_.playerNameCache.find(guid); auto nit = owner_.getPlayerNameCache().find(guid);
std::string name; std::string name;
if (nit != owner_.playerNameCache.end()) { if (nit != owner_.getPlayerNameCache().end()) {
name = nit->second; name = nit->second;
owner_.friendsCache[name] = guid; owner_.friendsCache[name] = guid;
} else { } else {
@ -1780,15 +1780,15 @@ void SocialHandler::handleContactList(network::Packet& packet) {
areaId = packet.readUInt32(); level = packet.readUInt32(); classId = packet.readUInt32(); areaId = packet.readUInt32(); level = packet.readUInt32(); classId = packet.readUInt32();
} }
owner_.friendGuids_.insert(guid); owner_.friendGuids_.insert(guid);
auto nit = owner_.playerNameCache.find(guid); auto nit = owner_.getPlayerNameCache().find(guid);
if (nit != owner_.playerNameCache.end()) owner_.friendsCache[nit->second] = guid; if (nit != owner_.getPlayerNameCache().end()) owner_.friendsCache[nit->second] = guid;
else owner_.queryPlayerName(guid); else owner_.queryPlayerName(guid);
} }
ContactEntry entry; ContactEntry entry;
entry.guid = guid; entry.flags = flags; entry.note = std::move(note); entry.guid = guid; entry.flags = flags; entry.note = std::move(note);
entry.status = status; entry.areaId = areaId; entry.level = level; entry.classId = classId; entry.status = status; entry.areaId = areaId; entry.level = level; entry.classId = classId;
auto nit = owner_.playerNameCache.find(guid); auto nit = owner_.getPlayerNameCache().find(guid);
if (nit != owner_.playerNameCache.end()) entry.name = nit->second; if (nit != owner_.getPlayerNameCache().end()) entry.name = nit->second;
owner_.contacts_.push_back(std::move(entry)); owner_.contacts_.push_back(std::move(entry));
} }
if (owner_.addonEventCallback_) { if (owner_.addonEventCallback_) {
@ -1810,8 +1810,8 @@ void SocialHandler::handleFriendStatus(network::Packet& packet) {
if (cit != owner_.contacts_.end() && !cit->name.empty()) { if (cit != owner_.contacts_.end() && !cit->name.empty()) {
playerName = cit->name; playerName = cit->name;
} else { } else {
auto it = owner_.playerNameCache.find(data.guid); auto it = owner_.getPlayerNameCache().find(data.guid);
if (it != owner_.playerNameCache.end()) playerName = it->second; if (it != owner_.getPlayerNameCache().end()) playerName = it->second;
} }
if (data.status == 1 || data.status == 2) owner_.friendsCache[playerName] = data.guid; if (data.status == 1 || data.status == 2) owner_.friendsCache[playerName] = data.guid;
@ -1850,8 +1850,8 @@ void SocialHandler::handleRandomRoll(network::Packet& packet) {
if (!RandomRollParser::parse(packet, data)) return; if (!RandomRollParser::parse(packet, data)) return;
std::string rollerName = (data.rollerGuid == owner_.playerGuid) ? "You" : "Someone"; std::string rollerName = (data.rollerGuid == owner_.playerGuid) ? "You" : "Someone";
if (data.rollerGuid != owner_.playerGuid) { if (data.rollerGuid != owner_.playerGuid) {
auto it = owner_.playerNameCache.find(data.rollerGuid); auto it = owner_.getPlayerNameCache().find(data.rollerGuid);
if (it != owner_.playerNameCache.end()) rollerName = it->second; if (it != owner_.getPlayerNameCache().end()) rollerName = it->second;
} }
std::string msg = rollerName + ((data.rollerGuid == owner_.playerGuid) ? " roll " : " rolls "); std::string msg = rollerName + ((data.rollerGuid == owner_.playerGuid) ? " roll " : " rolls ");
msg += std::to_string(data.result) + " (" + std::to_string(data.minRoll) + "-" + std::to_string(data.maxRoll) + ")"; msg += std::to_string(data.result) + " (" + std::to_string(data.minRoll) + "-" + std::to_string(data.maxRoll) + ")";
@ -2394,7 +2394,7 @@ void SocialHandler::handlePvpLogData(network::Packet& packet) {
ps.guid = packet.readUInt64(); ps.team = packet.readUInt8(); ps.guid = packet.readUInt64(); ps.team = packet.readUInt8();
ps.killingBlows = packet.readUInt32(); ps.honorableKills = packet.readUInt32(); ps.killingBlows = packet.readUInt32(); ps.honorableKills = packet.readUInt32();
ps.deaths = packet.readUInt32(); ps.bonusHonor = packet.readUInt32(); ps.deaths = packet.readUInt32(); ps.bonusHonor = packet.readUInt32();
{ auto ent = owner_.entityManager.getEntity(ps.guid); { auto ent = owner_.getEntityManager().getEntity(ps.guid);
if (ent && (ent->getType() == game::ObjectType::PLAYER || ent->getType() == game::ObjectType::UNIT)) if (ent && (ent->getType() == game::ObjectType::PLAYER || ent->getType() == game::ObjectType::UNIT))
{ auto u = std::static_pointer_cast<game::Unit>(ent); if (!u->getName().empty()) ps.name = u->getName(); } } { auto u = std::static_pointer_cast<game::Unit>(ent); if (!u->getName().empty()) ps.name = u->getName(); } }
if (remaining() < 4) { bgScoreboard_.players.push_back(std::move(ps)); break; } if (remaining() < 4) { bgScoreboard_.players.push_back(std::move(ps)); break; }

View file

@ -248,7 +248,7 @@ void SpellHandler::castSpell(uint32_t spellId, uint64_t targetGuid) {
owner_.addSystemChatMessage("You have no target."); owner_.addSystemChatMessage("You have no target.");
return; return;
} }
auto entity = owner_.entityManager.getEntity(target); auto entity = owner_.getEntityManager().getEntity(target);
if (!entity) { if (!entity) {
owner_.addSystemChatMessage("You have no target."); owner_.addSystemChatMessage("You have no target.");
return; return;
@ -284,7 +284,7 @@ void SpellHandler::castSpell(uint32_t spellId, uint64_t targetGuid) {
isMeleeAbility = true; isMeleeAbility = true;
} }
if (isMeleeAbility && target != 0) { if (isMeleeAbility && target != 0) {
auto entity = owner_.entityManager.getEntity(target); auto entity = owner_.getEntityManager().getEntity(target);
if (entity) { if (entity) {
float dx = entity->getX() - owner_.movementInfo.x; float dx = entity->getX() - owner_.movementInfo.x;
float dy = entity->getY() - owner_.movementInfo.y; float dy = entity->getY() - owner_.movementInfo.y;
@ -305,7 +305,7 @@ void SpellHandler::castSpell(uint32_t spellId, uint64_t targetGuid) {
// Send both SET_FACING and a HEARTBEAT so the server has the updated orientation // Send both SET_FACING and a HEARTBEAT so the server has the updated orientation
// before it processes the cast packet. // before it processes the cast packet.
if (target != 0) { if (target != 0) {
auto entity = owner_.entityManager.getEntity(target); auto entity = owner_.getEntityManager().getEntity(target);
if (entity) { if (entity) {
float dx = entity->getX() - owner_.movementInfo.x; float dx = entity->getX() - owner_.movementInfo.x;
float dy = entity->getY() - owner_.movementInfo.y; float dy = entity->getY() - owner_.movementInfo.y;
@ -819,7 +819,7 @@ void SpellHandler::handleCastFailed(network::Packet& packet) {
// Show failure reason // Show failure reason
int powerType = -1; int powerType = -1;
auto playerEntity = owner_.entityManager.getEntity(owner_.playerGuid); auto playerEntity = owner_.getEntityManager().getEntity(owner_.playerGuid);
if (auto playerUnit = std::dynamic_pointer_cast<Unit>(playerEntity)) { if (auto playerUnit = std::dynamic_pointer_cast<Unit>(playerEntity)) {
powerType = playerUnit->getPowerType(); powerType = playerUnit->getPowerType();
} }
@ -1418,13 +1418,13 @@ void SpellHandler::handleAchievementEarned(network::Packet& packet) {
} }
} else { } else {
std::string senderName; std::string senderName;
auto entity = owner_.entityManager.getEntity(guid); auto entity = owner_.getEntityManager().getEntity(guid);
if (auto* unit = dynamic_cast<Unit*>(entity.get())) { if (auto* unit = dynamic_cast<Unit*>(entity.get())) {
senderName = unit->getName(); senderName = unit->getName();
} }
if (senderName.empty()) { if (senderName.empty()) {
auto nit = owner_.playerNameCache.find(guid); auto nit = owner_.getPlayerNameCache().find(guid);
if (nit != owner_.playerNameCache.end()) if (nit != owner_.getPlayerNameCache().end())
senderName = nit->second; senderName = nit->second;
} }
if (senderName.empty()) { if (senderName.empty()) {
@ -2073,7 +2073,7 @@ void SpellHandler::handleCastResult(network::Packet& packet) {
owner_.craftQueueSpellId_ = 0; owner_.craftQueueRemaining_ = 0; owner_.craftQueueSpellId_ = 0; owner_.craftQueueRemaining_ = 0;
owner_.queuedSpellId_ = 0; owner_.queuedSpellTarget_ = 0; owner_.queuedSpellId_ = 0; owner_.queuedSpellTarget_ = 0;
int playerPowerType = -1; int playerPowerType = -1;
if (auto pe = owner_.entityManager.getEntity(owner_.playerGuid)) { if (auto pe = owner_.getEntityManager().getEntity(owner_.playerGuid)) {
if (auto pu = std::dynamic_pointer_cast<Unit>(pe)) if (auto pu = std::dynamic_pointer_cast<Unit>(pe))
playerPowerType = static_cast<int>(pu->getPowerType()); playerPowerType = static_cast<int>(pu->getPowerType());
} }
@ -2151,7 +2151,7 @@ void SpellHandler::handlePlaySpellVisual(network::Packet& packet) {
if (casterGuid == owner_.playerGuid) { if (casterGuid == owner_.playerGuid) {
spawnPos = renderer->getCharacterPosition(); spawnPos = renderer->getCharacterPosition();
} else { } else {
auto entity = owner_.entityManager.getEntity(casterGuid); auto entity = owner_.getEntityManager().getEntity(casterGuid);
if (!entity) return; if (!entity) return;
glm::vec3 canonical(entity->getLatestX(), entity->getLatestY(), entity->getLatestZ()); glm::vec3 canonical(entity->getLatestX(), entity->getLatestY(), entity->getLatestZ());
spawnPos = core::coords::canonicalToRender(canonical); spawnPos = core::coords::canonicalToRender(canonical);
@ -2308,7 +2308,7 @@ void SpellHandler::handleSpellFailure(network::Packet& packet) {
if (failGuid == owner_.playerGuid && failReason != 0) { if (failGuid == owner_.playerGuid && failReason != 0) {
// Show interruption/failure reason in chat and error overlay for player // Show interruption/failure reason in chat and error overlay for player
int pt = -1; int pt = -1;
if (auto pe = owner_.entityManager.getEntity(owner_.playerGuid)) if (auto pe = owner_.getEntityManager().getEntity(owner_.playerGuid))
if (auto pu = std::dynamic_pointer_cast<Unit>(pe)) if (auto pu = std::dynamic_pointer_cast<Unit>(pe))
pt = static_cast<int>(pu->getPowerType()); pt = static_cast<int>(pu->getPowerType());
const char* reason = getSpellCastResultString(failReason, pt); const char* reason = getSpellCastResultString(failReason, pt);

11
test.sh
View file

@ -75,8 +75,19 @@ echo "Linting ${#SOURCE_FILES[@]} source files..."
EXTRA_TIDY_ARGS=() # for direct clang-tidy: --extra-arg=... EXTRA_TIDY_ARGS=() # for direct clang-tidy: --extra-arg=...
EXTRA_RUN_ARGS=() # for run-clang-tidy: -extra-arg=... EXTRA_RUN_ARGS=() # for run-clang-tidy: -extra-arg=...
if command -v gcc >/dev/null 2>&1; then if command -v gcc >/dev/null 2>&1; then
# Prepend clang's own resource include dir first so clang uses its own
# versions of xmmintrin.h, ia32intrin.h, etc. rather than GCC's.
clang_resource_inc="$($CLANG_TIDY -print-resource-dir 2>/dev/null || true)/include"
if [[ -d "$clang_resource_inc" ]]; then
EXTRA_TIDY_ARGS+=("--extra-arg=-isystem${clang_resource_inc}")
EXTRA_RUN_ARGS+=("-extra-arg=-isystem${clang_resource_inc}")
fi
while IFS= read -r inc_path; do while IFS= read -r inc_path; do
[[ -d "$inc_path" ]] || continue [[ -d "$inc_path" ]] || continue
# Skip the GCC compiler built-in include dir — clang's resource dir above
# provides compatible replacements for xmmintrin.h, ia32intrin.h, etc.
[[ "$inc_path" == */gcc/* ]] && continue
EXTRA_TIDY_ARGS+=("--extra-arg=-isystem${inc_path}") EXTRA_TIDY_ARGS+=("--extra-arg=-isystem${inc_path}")
EXTRA_RUN_ARGS+=("-extra-arg=-isystem${inc_path}") EXTRA_RUN_ARGS+=("-extra-arg=-isystem${inc_path}")
done < <( done < <(