Add event hooks for:
- AuctionEvent (sold, expired) in AuctionHouseMgr.cpp
- SpellCastEvent in Spell.cpp (player-only, disabled by default)
- TradeEvent in TradeHandler.cpp
- MailEvent in Mail.cpp
- GuildEvent (join/leave) in Guild.cpp
- ZoneChangeEvent in Player.cpp
- PartyChangeEvent in Group.cpp
- ItemEquipEvent in Player.cpp
- LevelUpEvent in Player.cpp
- ChatEvent in ChatHandler.cpp
- AchievementEvent in AchievementMgr.cpp
- CombatEvent in Unit.cpp
- EncounterEvent in InstanceScript.cpp
- SpawnEvent in Creature.cpp
All events include IsEnabled() checks via AraxiaEventBusConfig.
Added eventbus_integration_test.py for testing.
- Hook into Player::AddToWorld() for login events
- Hook into Player::RemoveFromWorld() for logout events
- Hook into Player::KillPlayer() for death events
- Events include: player_guid, player_name, map context
- Context-aware topics: world.player.*, dungeon.player.*, etc.
- Respects Araxia.EventBus.EnablePlayerEvents config toggle
- Add TC_LOG_DEBUG for PublishSpawnEvent calls
- Add TC_LOG_DEBUG when messages are sent via ZMQ
- Verified spawn events working with Python subscriber
- Create araxia.conf.dist with all Araxia-specific configuration
- Move EventBus ZMQ settings from worldserver.conf.dist to araxia.conf.dist
- Add MCP server and Eluna extension config placeholders
- Install to worldserver.conf.d/ for automatic loading after worldserver.conf
- Add CMake custom target 'araxia-conf' to copy config during build
The config is loaded via TrinityCore's LoadAdditionalDir mechanism,
allowing Araxia settings to override worldserver.conf values.
- ServerTools.cpp: Use ChatHandler::ParseCommands() as fallback for any unhandled GM command
- ServerTools.cpp: Add leading dot to commands for ChatHandler compatibility
- ServerTools.cpp: Add detailed header comments about GM command implementation pattern
- AGENTS.md: Add code commenting guidelines section
The CollectGarbage metamethod was calling Eluna::GetEluna(L) which uses
lua_pushstring internally. This can trigger another GC cycle while already
inside the GC handler, causing memory corruption and crashes.
The fix avoids GetEluna entirely by directly casting the userdata to
ElunaObject without type checking, which is safe since the __gc metamethod
is only called on valid userdata of the correct type.
This fixes crashes in SHOW_WAYPOINTS and other handlers that hold creature
references when GC runs during method calls.
- Same-map teleport now uses direct Relocate() instead of NearTeleportTo()
which expects client ACK that headless sessions can't provide
- Add phase initialization (phase 169) so bot players are visible to others
ExecuteCommand now properly executes GM commands using ChatHandler::ParseCommands()
instead of just logging them.
Also includes cross-map teleport fix from previous commit.
Player::TeleportTo() + HandleMoveWorldportAck() crashes for headless sessions
because it expects client state we don't have.
New approach:
- Same-map teleports use NearTeleportTo()
- Cross-map teleports manually: validate coords, create map, remove from old,
relocate, set new map, add to new map
Tested: Scarletseer successfully teleported from map 1 to map 870 and walked
in a circle around a real player.
The destructor was calling Shutdown() which accesses other singletons that may
already be destroyed during static destruction. Now the destructor only handles
thread cleanup directly without accessing other singletons.
- Add MCPPlayerManager for multi-session AI player management
- Add Player::InitializeForBot() for minimal bot player initialization
- Add AraxiaCore hook system for World::Update callbacks
- Add packet capture callback for headless WorldSession
- Add 14 MCP tools for session/player control
Key fixes:
- Async login/logout to ensure map operations run on world thread
- Manual player cleanup to avoid RemoveFromWorld() hangs
- Null socket handling in WorldSession for headless sessions
- Safe shutdown without mutex issues during static destruction
Test scripts:
- test_mcp_player.sh - Interactive bash test
- test_mcp_integration.py - Python integration tests
Files:
- src/araxiaonline/mcp/MCPPlayerManager.{h,cpp}
- src/araxiaonline/mcp/MCPPlayerTools.cpp
- src/araxiaonline/AraxiaCore.{h,cpp}
- Modified: Player.{h,cpp}, WorldSession.{h,cpp}, World.cpp
- Add .flight toggle/sky/steady commands for players to switch flight styles
- Default to Steady Flight on login (TC behavior), opt-in to Skyriding
- Grant dragonriding spells (376777, 372608, 377920) when enabling Skyriding
- Prevent both flight style auras from being saved (managed by command)
- Add FlightCapability.SpellID application in SetFlightCapabilityID
- Extend MCP gm_command with aura/unaura/learn/unlearn support
- Add .gm advfly command for advanced flying toggle
Note: Vigor UI still requires UI Widget packet implementation (not in TC)
DatabaseTools.cpp:
- Add comments explaining DirectExecute doesn't return errors
- Change message from 'Query executed successfully' to 'Query submitted'
- Add warning field advising to check DBErrors.log
TC's database layer logs MySQL errors to DBErrors.log but doesn't
expose them to callers. This change makes that limitation explicit
so MCP users know to check the log after batch operations.
- DB2Stores.h instead of DBCStores.h
- FindMap(mapId, 0) instead of FindBaseNonInstanceMap
- Creature::Create with full parameter list
- Remove SaveToDB (complex in TC 11.x, use db_execute instead)
- LoadCreatureTemplates() instead of single-entry reload
- LOCALE_enUS for LocalizedString access
New MCP tools that work without a player in-game:
- spawn_query: Query creatures spawned on a map (filter by entry/area)
- spawn_count: Get creature counts on a map
- spawn_creature: Force spawn a creature at a location
- reload_creatures: Reload creature templates from database
- console_command: Execute server console commands
- map_info: Get map information and creature counts
These tools enable AI assistants to:
- Validate spawn data after database imports
- Test creature spawns without logging in
- Query map state programmatically
- Reload creature data without restart
Part of the Scarlet Seer initiative for AI-assisted content development.
New MCP Tools:
- get_ground_height: VMAP/DB height lookup for spawn Z coordinates
- gm_command: Direct execution of go xyz, tele, gps, additem, die, revive
Key changes:
- WorldScan.cpp: Added GetGroundHeightAt() with VMAP + DB fallback
- ServerTools.cpp: Implemented gm_command with teleport support
- Updated MCP_SERVER.md with Dec 3 session summary
Validated Jade Forest import: 1,767 templates, 6,540 spawns working in-game
- Fix waypoint markers showing as human models in 11.2.5 client
- Use Elven Wisp (displayId 1824) which renders correctly
- Add runtime display config via Lua shared data (no recompile needed)
- Add client refresh (DestroyForNearbyPlayers + UpdateObjectVisibilityOnCreate)
- Graceful MySQL error handling (no crash on bad MCP queries)
- Fix displayId arg parsing in VisualizeWaypointPath
- Add documentation for display IDs and configuration
World Scan WORKING! First successful scan in Scarlet Monastery:
- Detected walls using VMAP ray casting
- Found Scarlet Sentry, Disciple, Augur
- Generated room layout visualization
Fixes:
- VMapManager2.h include for full class definition
- Use VMapManager2* not IVMapManager*
Documentation:
- Updated MCP_SERVER.md with all learnings
- Added VMAP usage tips
- Added database safety notes
- Session summary with first world scan results
The moment we achieved spatial awareness:
Location: Scarlet Monastery (2898.6, -802.9, 160.3)
Creatures: 4 Scarlets surrounding player
Room: Walls detected, corridor opening identified
Tonight we gave an AI eyes inside a game world.
New MCP tool: world_scan
- Casts rays in 360 degrees using VMAP collision data
- Detects walls, obstacles, room boundaries
- Detects all creatures in range with relative positions
- Generates ASCII art visualization
How it works:
1. Binary search ray casting using isInLineOfSight()
2. VMAP provides wall/building geometry
3. Nearby creatures enumerated with GetCreatureListInGrid()
4. ASCII map shows @ (you), # (walls), letters (creatures)
Example output:
+---------------------+
| ####### |
| # S # |
| # @> # |
| # D # |
| ########### |
+---------------------+
No player action needed - AI calls world_scan directly!
This gives me spatial awareness of your environment!
New command: /mcpbridge ui
- Captures target info (name, GUID, level, health, type)
- Captures player info (position, zone, combat status)
- Captures mouseover, tooltip, open frames
- Stores in ElunaSharedData for MCP to read
New shared data keys:
- mcp_ui_state - Full UI state JSON
- mcp_current_target - Target details JSON
Usage:
1. Player runs /mcpbridge ui in WoW
2. AI reads via shared_data_read('mcp_current_target')
3. AI can now 'see' what you're targeting!
This enables visual debugging without actual screenshots.
Database Tools:
- Wrapped all queries in try/catch to prevent server crashes
- Errors returned as JSON instead of crashing
- Logged to araxia.mcp for debugging
AMS Bridge Fixes:
- Fixed AMS.RegisterHandler (dot not colon)
- Fixed JSON parsing for MCP messages
- Disabled auto-polling by default
Event Bus Design (EVENT_BUS_DESIGN.md):
- Unified pub/sub for C++ Core, Eluna, MCP, AMS
- Real-time event streaming (no polling)
- Enables MCP to see player targets, spawns, errors
- Phased implementation plan
Roadmap Updated:
- Phase 3: Content Creator Commands (non-GM)
- Phase 6: Event Bus implementation
HUGE MILESTONE: AI assistant now has direct real-time access to worldserver!
Phase 1 - Database & Server Tools:
- db_query, db_execute, db_tables, db_describe
- server_info, player_list, gm_command, reload_scripts
Phase 2 - Shared Data Bridge:
- shared_data_read, shared_data_write, shared_data_keys
- ElunaSharedData integration for cross-state communication
- Full client MCP bidirectional data flow
AMS Bridge Implementation:
- Server: mcp_bridge.lua handles MCP_CHAT, MCP_CLIENT_LOG, MCP_GET_MESSAGES
- Client: MCPBridge.lua with /mcpbridge commands
- Data stored in ElunaSharedData, readable by MCP tools
Key Learnings Documented:
- nlohmann/json: Don't use value() with nullptr
- TrinityCore: Use GetBoolDefault() not GetOption<T>()
- AMS: Use AMS.Send (dot) not AMS:Send (colon) on client
- Smallfolk: Never serialize functions
Windsurf Integration:
- Add to ~/.codeium/windsurf/mcp_config.json
- AI gets direct access to all MCP tools
- No more manual curl commands!
This is SOOO FUCKING COOL!!!
MCP Server is fully operational:
- Fixed JSON-RPC id field handling (can't use value() with nullptr)
- Fixed params extraction for tools/call
- All database tools working: db_query, db_execute, db_tables, db_describe
- Server tools working: server_info, player_list
Verified working:
- Health check endpoint returns ok
- tools/list returns all 9 registered tools
- db_query successfully queries world database
Documentation updated with:
- Implementation notes and API learnings
- File structure overview
- Phase roadmap
- Use GetBoolDefault/GetIntDefault/GetStringDefault instead of GetOption<T>
- Remove non-existent GetRealmName(), use hardcoded name
- Simplify Field access to just GetString() (no GetType())
- Handle null Alias in field metadata gracefully