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:
- Legacy BotEventSystem (Phase 6) - Singleton, global, observers registered here
- New EventDispatcher (Phase 7) - Per-bot instance in BotAI, managers subscribed here
Evidence:
TradeEventObserver.cpp:21includesEvents/BotEventSystem.h(legacy)BotAI.cpp:89creates 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()dispatchQUEST_COMPLETEDevent? - Where does
Player::AddItem()dispatchQUEST_ITEM_COLLECTEDevent? - Are there TrinityCore hooks that create BotEvents?
Solution Options
Option A: Forward Events from Observers to EventDispatcher (RECOMMENDED)
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
Recommended Path Forward
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):
QuestEventObserver.cpp- Forward quest eventsTradeEventObserver.cpp- Forward trade/auction/gold eventsCombatEventObserver.cpp- Forward combat eventsMovementEventObserver.cpp- Forward movement eventsInstanceEventObserver.cpp- Forward instance eventsPvPEventObserver.cpp- Forward PvP eventsSocialEventObserver.cpp- Forward social eventsResourceEventObserver.cpp- Forward resource eventsAuraEventObserver.cpp- Forward aura events- (Add any missing observers)
Event Origin Investigation
Need to Find
Where are initial BotEvents created?
Likely locations:
-
TrinityCore Player Hooks
Player::CompleteQuest()→ QUEST_COMPLETEDPlayer::AddItem()→ ITEM_LOOTED, QUEST_ITEM_COLLECTEDPlayer::KilledMonster()→ QUEST_CREATURE_KILLED
-
Playerbot Core Hooks
src/modules/Playerbot/Hooks/(if exists)src/modules/Playerbot/Core/Hooks/(if exists)
-
BotEventSystem Dispatch Calls
grep -r "BotEventSystem.*Dispatch" src/modules/Playerbot/
Action Required: Search codebase for event creation points.
Next Steps
- ✅ Document this analysis (COMPLETE)
- Add GetEventDispatcher() to BotAI.h
- Implement event forwarding in all observers
- Test with simple quest acceptance
- Verify managers execute OnEventInternal()
- Profile performance impact
- 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.