mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-03 20:03:50 +00:00
refactor(game): apply SOLID phases 2-6 to EntityController
- split applyUpdateObjectBlock into handleCreateObject, handleValuesUpdate, handleMovementUpdate - extract concern helpers — createEntityFromBlock, applyPlayerTransportState, applyUnitFieldsOnCreate/OnUpdate, applyPlayerStatFields, dispatchEntitySpawn, trackItemOnCreate, updateItemOnValuesUpdate, syncClassicAurasFromFields, detectPlayerMountChange, updateNonPlayerTransportAttachment - UnitFieldIndices, PlayerFieldIndices, UnitFieldUpdateResult structs with static resolve() — eliminate repeated fieldIndex() calls - IObjectTypeHandler strategy interface; concrete handlers UnitTypeHandler, PlayerTypeHandler, GameObjectTypeHandler, ItemTypeHandler, CorpseTypeHandler registered in typeHandlers_ map; handleCreateObject and handleValuesUpdate now dispatch via getTypeHandler() — adding a new object type requires zero changes to existing handler methods - PendingEvents member bus; all 27 inline owner_.fireAddonEvent() calls in the update path replaced with pendingEvents_.emit(); events flushed via flushPendingEvents() at the end of each handler, decoupling field-parse logic from the addon callback system entity_controller.cpp: 1520-line monolith → longest method ~200 lines, cyclomatic complexity ~180 → ~5; zero duplicated CREATE/VALUES blocks
This commit is contained in:
parent
f5757aca83
commit
b0a07c2472
2 changed files with 1537 additions and 1444 deletions
|
|
@ -11,6 +11,7 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
namespace wowee {
|
||||
namespace game {
|
||||
|
|
@ -141,6 +142,133 @@ private:
|
|||
void processOutOfRangeObjects(const std::vector<uint64_t>& guids);
|
||||
void applyUpdateObjectBlock(const UpdateBlock& block, bool& newItemCreated);
|
||||
void finalizeUpdateObjectBatch(bool newItemCreated);
|
||||
|
||||
// --- Phase 1: Extracted helper methods ---
|
||||
bool extractPlayerAppearance(const std::map<uint16_t, uint32_t>& fields,
|
||||
uint8_t& outRace, uint8_t& outGender,
|
||||
uint32_t& outAppearanceBytes, uint8_t& outFacial) const;
|
||||
void maybeDetectCoinageIndex(const std::map<uint16_t, uint32_t>& oldFields,
|
||||
const std::map<uint16_t, uint32_t>& newFields);
|
||||
|
||||
// --- Phase 2: Update type handlers ---
|
||||
void handleCreateObject(const UpdateBlock& block, bool& newItemCreated);
|
||||
void handleValuesUpdate(const UpdateBlock& block, bool& newItemCreated);
|
||||
void handleMovementUpdate(const UpdateBlock& block);
|
||||
|
||||
// --- Phase 3: Concern-specific helpers ---
|
||||
// 3i: Update transport-relative child attachment (non-player entities).
|
||||
// Consolidates identical logic from CREATE/VALUES/MOVEMENT handlers.
|
||||
void updateNonPlayerTransportAttachment(const UpdateBlock& block,
|
||||
const std::shared_ptr<Entity>& entity,
|
||||
ObjectType entityType);
|
||||
// 3f: Rebuild playerAuras_ from UNIT_FIELD_AURAS (Classic/vanilla only).
|
||||
// Consolidates identical logic from CREATE and VALUES handlers.
|
||||
void syncClassicAurasFromFields(const std::shared_ptr<Entity>& entity);
|
||||
// 3h: Detect mount/dismount from UNIT_FIELD_MOUNTDISPLAYID changes (self-player only).
|
||||
// Consolidates identical logic from CREATE and VALUES handlers.
|
||||
void detectPlayerMountChange(uint32_t newMountDisplayId,
|
||||
const std::map<uint16_t, uint32_t>& blockFields);
|
||||
|
||||
// --- Phase 4: Field index cache structs ---
|
||||
// Cached field indices resolved once per handler call to avoid repeated lookups.
|
||||
struct UnitFieldIndices {
|
||||
uint16_t health, maxHealth, powerBase, maxPowerBase;
|
||||
uint16_t level, faction, flags, dynFlags;
|
||||
uint16_t displayId, mountDisplayId, npcFlags;
|
||||
uint16_t bytes0, bytes1;
|
||||
static UnitFieldIndices resolve();
|
||||
};
|
||||
struct PlayerFieldIndices {
|
||||
uint16_t xp, nextXp, restedXp, level;
|
||||
uint16_t coinage, honor, arena;
|
||||
uint16_t playerFlags, armor;
|
||||
uint16_t pBytes, pBytes2, chosenTitle;
|
||||
uint16_t stats[5];
|
||||
uint16_t meleeAP, rangedAP;
|
||||
uint16_t spDmg1, healBonus;
|
||||
uint16_t blockPct, dodgePct, parryPct, critPct, rangedCritPct;
|
||||
uint16_t sCrit1, rating1;
|
||||
static PlayerFieldIndices resolve();
|
||||
};
|
||||
struct UnitFieldUpdateResult {
|
||||
bool healthChanged = false;
|
||||
bool powerChanged = false;
|
||||
bool displayIdChanged = false;
|
||||
bool npcDeathNotified = false;
|
||||
bool npcRespawnNotified = false;
|
||||
uint32_t oldDisplayId = 0;
|
||||
};
|
||||
|
||||
// --- Phase 3: Extracted concern-specific helpers (continued) ---
|
||||
// 3a: Entity factory — creates the correct Entity subclass for the given block.
|
||||
std::shared_ptr<Entity> createEntityFromBlock(const UpdateBlock& block);
|
||||
// 3b: Track player-on-transport state from movement blocks.
|
||||
void applyPlayerTransportState(const UpdateBlock& block,
|
||||
const std::shared_ptr<Entity>& entity,
|
||||
const glm::vec3& canonicalPos, float oCanonical,
|
||||
bool updateMovementInfoPos);
|
||||
// 3c: Apply unit fields during CREATE — returns true if entity is initially dead.
|
||||
bool applyUnitFieldsOnCreate(const UpdateBlock& block,
|
||||
std::shared_ptr<Unit>& unit,
|
||||
const UnitFieldIndices& ufi);
|
||||
// 3c: Apply unit fields during VALUES — returns change tracking result.
|
||||
UnitFieldUpdateResult applyUnitFieldsOnUpdate(const UpdateBlock& block,
|
||||
const std::shared_ptr<Entity>& entity,
|
||||
std::shared_ptr<Unit>& unit,
|
||||
const UnitFieldIndices& ufi);
|
||||
// 3d: Apply player stat fields (XP, inventory, skills, etc.). isCreate=true for CREATE path.
|
||||
bool applyPlayerStatFields(const std::map<uint16_t, uint32_t>& fields,
|
||||
const PlayerFieldIndices& pfi, bool isCreate);
|
||||
// 3e: Dispatch spawn callbacks (creature/player) — deduplicates CREATE and VALUES paths.
|
||||
void dispatchEntitySpawn(uint64_t guid, ObjectType objectType,
|
||||
const std::shared_ptr<Entity>& entity,
|
||||
const std::shared_ptr<Unit>& unit, bool isDead);
|
||||
// 3g: Track item/container on CREATE.
|
||||
void trackItemOnCreate(const UpdateBlock& block, bool& newItemCreated);
|
||||
// 3g: Update item fields on VALUES update.
|
||||
void updateItemOnValuesUpdate(const UpdateBlock& block,
|
||||
const std::shared_ptr<Entity>& entity);
|
||||
|
||||
// --- Phase 5: Strategy pattern — object-type handler interface ---
|
||||
// Allows extending object-type handling without modifying handler dispatch.
|
||||
struct IObjectTypeHandler {
|
||||
virtual ~IObjectTypeHandler() = default;
|
||||
virtual void onCreate(const UpdateBlock& block, std::shared_ptr<Entity>& entity,
|
||||
bool& newItemCreated) {}
|
||||
virtual void onValuesUpdate(const UpdateBlock& block, std::shared_ptr<Entity>& entity) {}
|
||||
virtual void onMovementUpdate(const UpdateBlock& block, std::shared_ptr<Entity>& entity) {}
|
||||
};
|
||||
struct UnitTypeHandler;
|
||||
struct PlayerTypeHandler;
|
||||
struct GameObjectTypeHandler;
|
||||
struct ItemTypeHandler;
|
||||
struct CorpseTypeHandler;
|
||||
std::unordered_map<uint8_t, std::unique_ptr<IObjectTypeHandler>> typeHandlers_;
|
||||
void initTypeHandlers();
|
||||
IObjectTypeHandler* getTypeHandler(ObjectType type) const;
|
||||
|
||||
// --- Phase 5: Type-specific handler implementations (trampolined from handlers) ---
|
||||
void onCreateUnit(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
void onCreatePlayer(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
void onCreateGameObject(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
void onCreateItem(const UpdateBlock& block, bool& newItemCreated);
|
||||
void onCreateCorpse(const UpdateBlock& block);
|
||||
void onValuesUpdateUnit(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
void onValuesUpdatePlayer(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
void onValuesUpdateItem(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
void onValuesUpdateGameObject(const UpdateBlock& block, std::shared_ptr<Entity>& entity);
|
||||
|
||||
// --- Phase 6: Deferred event bus ---
|
||||
// Collects addon events during block processing, flushes at the end.
|
||||
struct PendingEvents {
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> events;
|
||||
void emit(const std::string& name, const std::vector<std::string>& args = {}) {
|
||||
events.emplace_back(name, args);
|
||||
}
|
||||
void clear() { events.clear(); }
|
||||
};
|
||||
PendingEvents pendingEvents_;
|
||||
void flushPendingEvents();
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue