Implements a retry mechanism for LFG groups where not all members
successfully teleported to the dungeon. This addresses the issue where
JIT bots that were still loading, or bots that failed initial teleport,
would never make it into the dungeon.
Safety Net Features:
- Tracks groups where not all members teleported successfully
- Retries teleportation every 3 seconds for failed members
- Waits for human player to be in dungeon before teleporting bots
- Verifies members actually arrived in the correct dungeon map
- Maximum 20 retries (~60 seconds) or 2 minute timeout
- Handles JIT bots that become available after initial teleport
Key changes:
- Add PendingSafetyTeleport structure to track groups needing retry
- Add ProcessSafetyNetRetries() called from Update() every 2 seconds
- Add RegisterSafetyNetGroup() to track failed teleport members
- Add IsMemberInDungeon() to verify member location
- Update TeleportGroupToDungeon() to register safety net on failures
- Update Initialize()/Shutdown() for safety net data management
This ensures all LFG-recruited bots eventually join the human player
in dungeons and battlegrounds, even if they weren't fully loaded
during the initial teleport attempt.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Phase 2 of ST-3: Implements reusable vector buffers to eliminate
~250k vector allocations/sec in target selection operations.
Changes:
- Add _enemiesBuffer, _alliesBuffer, _candidatesBuffer, _evaluatedTargetsBuffer
- Add PopulateNearbyEnemies(), PopulateNearbyAllies() internal methods
- Modify GetNearbyEnemies/GetNearbyAllies to use clear()+populate pattern
- Modify SelectBestTarget to iterate _candidatesBuffer directly
- Modify SelectHealTarget and SelectInterruptTarget to use buffers
Performance impact:
- Eliminates per-call vector heap allocations in hot path
- Buffers reuse capacity across calls (clear() keeps capacity)
- Thread-safe: class mutex held during all selection operations
Part of ZenFlow Performance Optimization Plan ST-3.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Implements per-PathfindingManager node pool that eliminates heap allocations
during A* pathfinding operations. Analysis showed 250k PathNode allocations/sec
in 5000-bot scenarios due to individual `new PathNode` calls.
Changes:
- Add PathNode::Reset() method for pool reuse
- Add _nodeStorage vector as pre-allocated pool within PathfindingManager
- Add AcquireNode() and ResetNodePool() helper methods
- Change CreateNode() to use pooled allocation
- Change allNodes map from unique_ptr to raw pointers (pool owns nodes)
- Add reserve() calls for closedSet and allNodes to reduce reallocations
- Fix memory leak where CreateNode was called but node not added when
position already existed in allNodes
Technical rationale:
- PathNodes are short-lived (single pathfinding operation)
- Per-manager pool allows simple index-based allocation (O(1))
- ResetNodePool() at start of each A* reclaims all nodes instantly
- No thread safety needed (single-threaded per-bot pathfinding)
- Pool statistics track usage patterns for tuning
Performance impact:
- Eliminates ~250k/sec heap allocations (5000-bot scenario)
- Pre-reserved vectors reduce reallocation overhead
- Memory: Fixed ~64KB per bot (256 * 64-byte PathNodes) vs unbounded growth
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Analysis showed the recursive_timed_mutex with 5ms try_lock_for timeout was
causing packet processing deferrals under high load (5000+ bots). The timeout
would fail, logging "Failed to acquire packet mutex within 5ms" and deferring
processing to the next tick (50ms latency).
Changes:
- Replace recursive_timed_mutex with simple std::mutex (no recursion needed)
- Replace try_lock_for(5ms) with blocking lock_guard in ProcessBotPackets
- Replace try_lock_for(10ms) with try_lock() in destructor (non-blocking)
- Update all lock_guard types to use std::mutex
Technical rationale:
- No recursive lock acquisition exists in the codebase (analyzed all 6 usages)
- Lock hold time is ~100µs (just queue push/pop operations)
- Blocking wait for microseconds is better than deferring for 50ms
- Simple mutex is cheaper than recursive_timed_mutex (no recursion tracking)
Expected impact:
- Eliminates cascading packet deferrals under contention
- Reduces mutex overhead (simpler lock type)
- More reliable packet processing at scale
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Implement adaptive AI update throttling system (ST-1) for CPU optimization:
New files:
- AI/AdaptiveAIUpdateThrottler.h: Throttle tier definitions, config, metrics
- AI/AdaptiveAIUpdateThrottler.cpp: Proximity detection, activity classification
Integration:
- BotAI constructor: Creates per-bot throttler instance
- BotAI::UpdateAI(): ShouldUpdate() check before expensive AI logic
- OnCombatStart/End: Combat state notifications for full rate override
Throttle Tiers (based on human player proximity):
- FULL_RATE (100%): <100m to human, in combat, or human group leader
- HIGH_RATE (75%): 100-250m, active questing/grinding
- MEDIUM_RATE (50%): 250-500m, simple following
- LOW_RATE (25%): 500-1000m, minimal activity
- MINIMAL_RATE (10%): >1000m or idle
Key features:
- Proximity check every 2 seconds (cached for efficiency)
- Combat state always forces full update rate
- Activity classification: COMBAT, QUESTING, FOLLOWING, TRAVELING, IDLE
- Global statistics singleton for monitoring effectiveness
- ForceNextUpdate() for critical events
Expected impact: 10-15% CPU reduction for bots far from human players
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Implemented threat score caching and group focus caching to eliminate
redundant calculations in TargetSelector::SelectBestTarget():
- Added _threatScoreCache with 500ms refresh interval to avoid
double GetThreat() calls per candidate (was called in TargetInfo
population AND in CalculateThreatScore)
- Added _groupFocusCache to pre-compute group member target counts
once per selection cycle, replacing O(n*m) iteration with O(m)
pre-computation + O(1) lookups
- New methods: RefreshThreatScoreCache(), RefreshGroupFocusCache(),
GetCachedThreatScore(), GetCachedGroupFocusCount()
Expected impact: ~15-25% CPU reduction in target selection hot path
for scenarios with many candidates and group members.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- Add disk cleanup step to free ~30GB before build
- Remove dotnet, android SDK, boost, swift, and CodeQL cache
- Reduce parallel build jobs from 4 to 2 to reduce disk usage
- Add disk space monitoring before/after cleanup and build
- Upgrade all CodeQL actions from v3 to v4 (v3 deprecated Dec 2026)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
GitHub Actions doesn't support ternary operators (?:) in expressions.
Also fixed PowerShell Get-Date inside JavaScript template literal.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
notifications.yml:
- Comment out repository_vulnerability_alert event (requires GitHub
Advanced Security which is an Enterprise feature)
- Comment out notify-security job until Advanced Security is enabled
playerbot-dependency-updates.yml:
- Make OpenSSL check more robust by checking if path exists first
- Fall back to system OpenSSL if custom path not found
- Skip check gracefully if OpenSSL not installed
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
The -DWITH_WARNINGS flag enables additional compiler warnings that
TrinityCore core code doesn't pass (size_t to int conversions in
BoundingIntervalHierarchy.cpp). Keep only -DWITH_WARNINGS_AS_ERRORS=ON
which treats the default warnings as errors without enabling extra ones.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Use shell export instead of env block to properly set LIBRARY_PATH
with correct handling of potentially empty existing value.
The ${VAR:+:$VAR} syntax only adds the colon and existing value
if VAR is non-empty, preventing the "search path '' not found" warning.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Files using Cell::VisitGridObjects template need CellImpl.h included
so the template implementation is available for instantiation when
linked as a separate module.
Fixed files:
- PortalDatabase.cpp
- BankInteractionManager.cpp
- MailInteractionManager.cpp
- InnkeeperInteractionManager.cpp
- TradeSystem.cpp
This fixes undefined reference errors on Linux/macOS for:
- Cell::VisitGridObjects<Trinity::GameObjectListSearcher<...>>
- Cell::VisitGridObjects<Trinity::CreatureListSearcher<...>>
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
The macOS build was failing with 'library icudata not found' because
Boost.Locale requires ICU libraries which are keg-only on Homebrew.
Changes:
- Install icu4c package via Homebrew
- Set ICU_ROOT environment variable for CMake
- Add ICU path to CMAKE_PREFIX_PATH
- Set LIBRARY_PATH to help linker find ICU libraries
This fixes the macOS worldserver link failure.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
GameSystemsManager (playerbot-core) uses types from playerbot-combat and
playerbot-gameplay, creating cross-library symbol references that cause
undefined reference errors on Linux/macOS but not Windows.
Platform-specific solutions:
- Linux: Use LINK_GROUP:RESCAN (--start-group/--end-group)
- macOS: Repeat libraries that provide cross-dependencies
- Windows: MSVC handles this automatically
Fixes undefined references on Linux:
- TargetScanner::~TargetScanner()
- GroupInvitationHandler::~GroupInvitationHandler()
- typeinfo for Playerbot::BotAI
- UnifiedMovementCoordinator methods
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
The Phase5 tests use DecisionFusionSystem, ActionPriorityQueue, and
BehaviorTree which are defined in playerbot-ai-base library.
Add conditional linking to playerbot target when BUILD_PLAYERBOT is enabled.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- QueryResult.h: Add missing <string> and <string_view> includes
Required for std::string_view when compiling without core PCH
- BaselineRotationManager.cpp: Fix QueuePacket API (now takes rvalue reference)
- ClassAI.cpp: Fix QueuePacket API (now takes rvalue reference)
- BotSessionIntegrationTest.cpp: Fix QueuePacket API usage in tests
- SocketCrashAnalyzer.cpp: Fix QueuePacket API usage in tests
The modern TrinityCore API changed WorldSession::QueuePacket from taking
a raw pointer (WorldPacket*) to taking an rvalue reference (WorldPacket&&).
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Ported from TrinityCore playerbot-dev commit 01ca4bd94b418667adf9d0ed3e2eccaf63616792
GameSystemsManager (playerbot-core) uses types from playerbot-combat and
playerbot-gameplay, creating cross-library symbol references that cause
undefined reference errors on Linux/macOS but not Windows.
Platform-specific solutions:
- Linux: Use LINK_GROUP:RESCAN (--start-group/--end-group)
- macOS: Repeat libraries that provide cross-dependencies
- Windows: MSVC handles this automatically
Fixes undefined references on Linux:
- TargetScanner::~TargetScanner()
- GroupInvitationHandler::~GroupInvitationHandler()
- typeinfo for Playerbot::BotAI
- UnifiedMovementCoordinator methods
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Ported from TrinityCore playerbot-dev commit 7081ebb5003918407615c1d59b6fef0d524e5717
Files using Cell::VisitGridObjects template need CellImpl.h included
so the template implementation is available for instantiation when
linked as a separate module.
Fixed files:
- PortalDatabase.cpp - Added CellImpl.h
- BankInteractionManager.cpp - Added CellImpl.h, GridNotifiers.h, GridNotifiersImpl.h
- MailInteractionManager.cpp - Added CellImpl.h, GridNotifiers.h, GridNotifiersImpl.h
- InnkeeperInteractionManager.cpp - Added CellImpl.h, GridNotifiers.h, GridNotifiersImpl.h
This fixes undefined reference errors on Linux/macOS for:
- Cell::VisitGridObjects<Trinity::GameObjectListSearcher<...>>
- Cell::VisitGridObjects<Trinity::CreatureListSearcher<...>>
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Ported from TrinityCore playerbot-dev commits 27c012014f and ed719c10e9
This fix ensures that when a bot is released from an instance, its current
level and gear score are captured from the live Player object before updating
the pool slot metadata. This preserves any level-ups or gear improvements
that occurred during the instance run.
Changes:
- Add missing #include "ObjectAccessor.h"
- Add CRITICAL FIX block in ReleaseBot() to capture player->GetLevel()
and player->GetAverageItemLevel() before slot state change
Without this fix, bots could lose track of progression gained during instances.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
- tests/CMakeLists.txt: Add Playerbot module include paths
- Fix include paths in all Phase5 test files to use relative paths
Signed-off-by: luis <[email protected]>
- BotSpawner.h: Add override to all IBotSpawner interface methods
- ActionPriorityQueue_tests.cpp: Fix include path to use CMake include dirs
Signed-off-by: luis <[email protected]>
- BotSpawner.h: Add override keyword to SetConfig()
- ThreadPool.cpp: Add macOS-specific thread affinity using thread_policy_set
(cpu_set_t and pthread_setaffinity_np are Linux-specific)
- WorldSession.h: Make destructor virtual for BotSession inheritance
(fixes gcc error: deleting polymorphic class with non-virtual destructor)
Signed-off-by: luis <[email protected]>
- BotSpawner.h: Add override keywords to Initialize(), Shutdown(), Update(), LoadConfig()
- HunterAI.h/.cpp: Change std::atomic<float> to float for timeAtRange and timeInDeadZone
(std::atomic<float> += operator not supported on all compilers)
Signed-off-by: luis <[email protected]>
- DragonridingMgr.h: Add missing <string> include for std::string
- PathOptimizer.h/.cpp: Change std::atomic<float> to float
(std::atomic<float>::fetch_add not supported on all compilers)
Signed-off-by: luis <[email protected]>
- QueueEventData.h: Include SharedDefines.h and DBCEnums.h instead of forward declaring enums
- ZoneLevelHelper.h: Add missing <atomic> include
- JITBotFactory.cpp: Remove duplicate static GetPlayerSpecRole (already in GroupRoleUtils.cpp)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- ResourceMonitor.cpp: Add macOS-specific includes (mach/mach.h, sysctl.h)
and memory collection implementation using mach task_info API
- AuraStateCache.cpp: Add missing <mutex> include for std::unique_lock
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- AuraStateCache.h: Add missing <atomic> include
- ResourceTypes.h: Change SoulShardSystem _shards from atomic<float> to float
(atomic<float> doesn't support compound operators like -= in C++20)
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- SafeObjectReference.h: Add <sstream> and <iomanip> for std::setprecision
- HealingTargetSelector.h: Include SharedDefines.h instead of forward declaring DispelType
- TacticalCoordinator.h: Remove unused BotAI forward declaration that conflicts with using directive
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- Skip FindSystemBoost.cmake on CI (GITHUB_ACTIONS env) to use standard
Boost finding with MarkusJx/install-boost action
- Change Linux build from SCRIPTS=dynamic to SCRIPTS=static to fix
linker error with static Boost libraries
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Playerbot requires Intel TBB which is vendored as a git submodule.
All CI workflows now initialize submodules before CMake configure.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- Update Boost version to 1.89.0 for Windows builds (required by upstream)
- Add BUILD_PLAYERBOT=ON to all workflow CMake configurations
- Make ModuleUpdateManager include/usage conditional on BUILD_PLAYERBOT
in World.cpp to support builds with/without playerbot module
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
Build fixes:
- Add Player forward declaration to JITBotFactory.h
- Add missing includes: BotWorldSessionMgr.h, BotSession.h, DB2Stores.h
- Fix LocalizedString usage with DEFAULT_LOCALE instead of integer index
- Fix SpellName pointer dereference: (*spellInfo->SpellName)[DEFAULT_LOCALE]
- Fix PlayerSpell member access: .active/.disabled instead of .IsActive()/.IsDisabled()
- Remove non-existent BotSessionMgr.cpp/.h from CMakeLists.txt
New features:
- Implement enterprise-grade role detection in JITBotFactory using DB2 spec data
- Add GetPlayerSpecRole() using ChrSpecializationEntry for accurate role detection
- Add GroupRoleToBotRole() conversion for pool system compatibility
- Add DetermineBotRole() as main entry point for spec-based role determination
- Distinguish melee/ranged DPS using ChrSpecializationFlag
Code cleanup:
- Remove obsolete BotSessionMgr files (replaced by BotWorldSessionMgr)
- Remove IBotSessionMgr interface (no longer needed)
- Remove MockSpatialGridManager test mock
- Remove invalid dynamic_cast<BotAI*>(UnitAI*) - types are unrelated
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- CRASH_ANALYSIS_2026-01-08.md - Documentation of crash investigation
- Quest/QUEST_SYSTEM_AUDIT_REPORT.md - Quest system audit findings
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>
- Enhanced DoubleBufferedSpatialGrid with better thread safety
- Improved LeaderFollowBehavior for smoother bot following
- Better position tracking and updates
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: luis <[email protected]>