Files
ThordekkCore/PHASE_7_OBSERVER_INTEGRATION_ANALYSIS.md
T
2026-01-20 21:33:16 -03:00

12 KiB

Phase 7: Observer Integration Analysis

Status: INTEGRATION REQUIRED Date: 2025-10-07

Current State Analysis

Phase 6 Observers (Exist)

Location: src/modules/Playerbot/Events/Observers/

Discovered Observers:

  • Quest EventObserver.cpp (Quest events)
  • TradeEventObserver.cpp (Trade, Auction, Gold, Vendor events)
  • CombatEventObserver.cpp/h
  • MovementEventObserver.cpp/h
  • InstanceEventObserver.cpp/h
  • PvPEventObserver.cpp/h
  • SocialEventObserver.cpp/h
  • ResourceEventObserver.cpp
  • AuraEventObserver.cpp

Observer Pattern:

class QuestEventObserver : public IEventObserver
{
public:
    void OnEvent(BotEvent const& event) override;
    bool ShouldReceiveEvent(BotEvent const& event) const override;

private:
    void HandleQuestAccepted(BotEvent const& event);
    void HandleQuestCompleted(BotEvent const& event);
    // ... 20+ handlers
};

Phase 7 EventDispatcher (Exists)

Location: src/modules/Playerbot/Core/Events/EventDispatcher.h/cpp

EventDispatcher Pattern:

class EventDispatcher
{
public:
    void Subscribe(StateMachine::EventType eventType, IManagerBase* manager);
    void Dispatch(BotEvent const& event);
    uint32 ProcessQueue(uint32 maxEvents = 100);
};

Phase 7 Manager Subscriptions (Complete)

Location: src/modules/Playerbot/AI/BotAI.cpp (lines 89-363)

// Quest Manager subscriptions (16 events)
_eventDispatcher->Subscribe(StateMachine::EventType::QUEST_ACCEPTED, _questManager.get());
_eventDispatcher->Subscribe(StateMachine::EventType::QUEST_COMPLETED, _questManager.get());
// ... 14 more quest events

// Trade Manager subscriptions (11 events)
_eventDispatcher->Subscribe(StateMachine::EventType::TRADE_INITIATED, _tradeManager.get());
// ... 10 more trade events

// Auction Manager subscriptions (5 events)
_eventDispatcher->Subscribe(StateMachine::EventType::AUCTION_BID_PLACED, _auctionManager.get());
// ... 4 more auction events

The Integration Gap

Current Event Flow (BROKEN)

┌────────────────────────────────────────────────────────┐
│  Game World (TrinityCore)                              │
│  Player accepts quest, kills mob, completes objective  │
└───────────────────────┬────────────────────────────────┘
                        │
                        │ ScriptHook / GameEvent
                        ▼
┌────────────────────────────────────────────────────────┐
│  ??? WHO CREATES INITIAL BotEvent ???                  │
│  (This is the missing piece)                           │
└───────────────────────┬────────────────────────────────┘
                        │
                        │ BotEvent creation
                        ▼
┌────────────────────────────────────────────────────────┐
│  Legacy BotEventSystem (Phase 6)                       │
│  BotEventSystem::instance()->DispatchEvent(event)      │
└───────────────────────┬────────────────────────────────┘
                        │
                        │ Routes to observers
                        ▼
┌────────────────────────────────────────────────────────┐
│  Phase 6 Observers                                     │
│  QuestEventObserver::OnEvent(event)                    │
│  TradeEventObserver::OnEvent(event)                    │
└───────────────────────┬────────────────────────────────┘
                        │
                        │ Processes event, but...
                        │ ❌ DOES NOT FORWARD TO PHASE 7 EventDispatcher
                        ▼
                    [DEAD END]

┌────────────────────────────────────────────────────────┐
│  Phase 7 EventDispatcher (NEVER RECEIVES EVENTS!)      │
│  Waiting for events that never arrive...              │
└───────────────────────┬────────────────────────────────┘
                        │
                        │ Would route to managers if events arrived
                        ▼
┌────────────────────────────────────────────────────────┐
│  Phase 7 Managers (NEVER CALLED!)                      │
│  QuestManager::OnEventInternal() - never executes      │
│  TradeManager::OnEventInternal() - never executes      │
│  AuctionManager::OnEventInternal() - never executes    │
└────────────────────────────────────────────────────────┘

Root Cause Analysis

Issue #1: Dual Event Systems

Problem: Two separate event systems exist:

  1. Legacy BotEventSystem (Phase 6) - Singleton, global, observers registered here
  2. New EventDispatcher (Phase 7) - Per-bot instance in BotAI, managers subscribed here

Evidence:

  • TradeEventObserver.cpp:21 includes Events/BotEventSystem.h (legacy)
  • BotAI.cpp:89 creates EventDispatcher (new)
  • They don't communicate with each other

Issue #2: No Event Forwarding

Problem: Phase 6 observers receive events from legacy system but don't forward them to Phase 7 EventDispatcher.

Current Observer Implementation:

void QuestEventObserver::OnEvent(BotEvent const& event)
{
    // Receives event from legacy BotEventSystem
    switch (event.type)
    {
        case EventType::QUEST_ACCEPTED:
            HandleQuestAccepted(event);  // Processes locally
            break;
        // ... more cases
    }

    // ❌ MISSING: Forward to BotAI's EventDispatcher
    // Should call: m_ai->GetEventDispatcher()->Dispatch(event);
}

Issue #3: Event Origin Unknown

Problem: Unknown where initial BotEvents are created from game hooks.

Need to Find:

  • Where does Player::CompleteQuest() dispatch QUEST_COMPLETED event?
  • Where does Player::AddItem() dispatch QUEST_ITEM_COLLECTED event?
  • Are there TrinityCore hooks that create BotEvents?

Solution Options

Approach: Modify Phase 6 observers to forward events to Phase 7 EventDispatcher after processing.

Implementation:

// In QuestEventObserver::OnEvent()
void QuestEventObserver::OnEvent(BotEvent const& event)
{
    if (!m_ai)
        return;

    // 1. Process event locally (existing Phase 6 logic)
    switch (event.type)
    {
        case StateMachine::EventType::QUEST_ACCEPTED:
            HandleQuestAccepted(event);
            break;
        // ... more cases
    }

    // 2. NEW: Forward to Phase 7 EventDispatcher
    if (m_ai->GetEventDispatcher())
    {
        m_ai->GetEventDispatcher()->Dispatch(event);
    }
}

Benefits: ✅ Minimal code changes ✅ Preserves existing Phase 6 observer logic ✅ Connects Phase 6 → Phase 7 cleanly ✅ No breaking changes

Drawbacks: ⚠️ Events processed twice (once by observer, once by manager) ⚠️ Slight performance overhead (~2x event processing)


Option B: Bypass Legacy BotEventSystem, Use Only EventDispatcher

Approach: Find where BotEvents are created (game hooks) and dispatch directly to EventDispatcher, eliminating legacy BotEventSystem.

Implementation:

// Wherever events are created (likely in TrinityCore hooks)
// BEFORE:
BotEventSystem::instance()->DispatchEvent(event);

// AFTER:
if (BotAI* botAI = GetBotAI())
    botAI->GetEventDispatcher()->Dispatch(event);

Benefits: ✅ Single event flow (no duplication) ✅ Better performance ✅ Cleaner architecture ✅ Removes legacy system entirely

Drawbacks: ⚠️ Requires finding all event creation points ⚠️ More invasive changes ⚠️ May break Phase 6 observers if they still expect legacy events


Option C: Deprecate Phase 6 Observers, Use Only Managers

Approach: Remove Phase 6 observers entirely, let managers handle all event logic.

Implementation:

  • Delete all Phase 6 observer files
  • Move any critical observer logic into managers
  • Dispatch events directly to EventDispatcher from game hooks

Benefits: ✅ Simplest architecture ✅ Best performance ✅ No code duplication ✅ Single source of truth

Drawbacks: ⚠️ Requires significant refactoring ⚠️ Loses any valuable Phase 6 observer logic ⚠️ Major breaking change


Phase 7.3: Implement Option A (Event Forwarding)

Step 1: Add GetEventDispatcher() accessor to BotAI

// In BotAI.h
public:
    Events::EventDispatcher* GetEventDispatcher() const { return _eventDispatcher.get(); }

Step 2: Modify observers to forward events

// Pattern to apply to all observers
void Observer::OnEvent(BotEvent const& event)
{
    // Existing Phase 6 logic
    ProcessEventLocally(event);

    // NEW Phase 7 forwarding
    if (m_ai && m_ai->GetEventDispatcher())
    {
        m_ai->GetEventDispatcher()->Dispatch(event);
    }
}

Step 3: Test end-to-end

  • Spawn bot
  • Accept quest → Verify QuestManager::OnEventInternal() executes
  • Check logs for both observer AND manager processing

Files to Modify (11 observers):

  1. QuestEventObserver.cpp - Forward quest events
  2. TradeEventObserver.cpp - Forward trade/auction/gold events
  3. CombatEventObserver.cpp - Forward combat events
  4. MovementEventObserver.cpp - Forward movement events
  5. InstanceEventObserver.cpp - Forward instance events
  6. PvPEventObserver.cpp - Forward PvP events
  7. SocialEventObserver.cpp - Forward social events
  8. ResourceEventObserver.cpp - Forward resource events
  9. AuraEventObserver.cpp - Forward aura events
  10. (Add any missing observers)

Event Origin Investigation

Need to Find

Where are initial BotEvents created?

Likely locations:

  1. TrinityCore Player Hooks

    • Player::CompleteQuest() → QUEST_COMPLETED
    • Player::AddItem() → ITEM_LOOTED, QUEST_ITEM_COLLECTED
    • Player::KilledMonster() → QUEST_CREATURE_KILLED
  2. Playerbot Core Hooks

    • src/modules/Playerbot/Hooks/ (if exists)
    • src/modules/Playerbot/Core/Hooks/ (if exists)
  3. BotEventSystem Dispatch Calls

    grep -r "BotEventSystem.*Dispatch" src/modules/Playerbot/
    

Action Required: Search codebase for event creation points.


Next Steps

  1. ✅ Document this analysis (COMPLETE)
  2. Add GetEventDispatcher() to BotAI.h
  3. Implement event forwarding in all observers
  4. Test with simple quest acceptance
  5. Verify managers execute OnEventInternal()
  6. Profile performance impact
  7. Consider long-term migration to Option B or C

Timeline Estimate

  • Option A Implementation: 2-3 hours
  • Testing & Validation: 1-2 hours
  • Documentation: 30 minutes
  • Total: ~4-6 hours for complete Phase 7.3

Conclusion

Phase 7.2 is architecturally complete but non-functional because Phase 6 observers don't forward events to Phase 7's EventDispatcher.

Immediate Fix: Implement Option A (Event Forwarding) to connect Phase 6 → Phase 7.

Long-term Solution: Consider Option B (Direct Dispatch) or Option C (Manager-Only) to eliminate architectural duplication.