361 lines
12 KiB
Markdown
361 lines
12 KiB
Markdown
# 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:**
|
||
|
|
```cpp
|
||
|
|
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:**
|
||
|
|
```cpp
|
||
|
|
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)
|
||
|
|
|
||
|
|
```cpp
|
||
|
|
// 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**:
|
||
|
|
```cpp
|
||
|
|
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
|
||
|
|
|
||
|
|
### Option A: Forward Events from Observers to EventDispatcher (RECOMMENDED)
|
||
|
|
|
||
|
|
**Approach**: Modify Phase 6 observers to forward events to Phase 7 EventDispatcher after processing.
|
||
|
|
|
||
|
|
**Implementation**:
|
||
|
|
```cpp
|
||
|
|
// 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**:
|
||
|
|
```cpp
|
||
|
|
// 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
|
||
|
|
```cpp
|
||
|
|
// In BotAI.h
|
||
|
|
public:
|
||
|
|
Events::EventDispatcher* GetEventDispatcher() const { return _eventDispatcher.get(); }
|
||
|
|
```
|
||
|
|
|
||
|
|
**Step 2**: Modify observers to forward events
|
||
|
|
```cpp
|
||
|
|
// 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**
|
||
|
|
```bash
|
||
|
|
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.
|
||
|
|
|