Skip to content

Commit bb92240

Browse files
committed
Merge remote-tracking branch 'master' into test-staging
2 parents bf451de + c914ef3 commit bb92240

64 files changed

Lines changed: 33680 additions & 407 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.git_commit_template.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
### TITLE
22
## Type(Scope/Subscope): Commit ultra short explanation
3-
## |---- Write below the examples with a maximum of 50 characters ----|
3+
## |---- Write below the examples with a maximum of 72 characters ----|
44
## Example 1: fix(DB/SAI): Missing spell to NPC Hogger
5-
## Example 2: fix(CORE/Raid): Phase 2 of Ragnaros
6-
## Example 3: feat(CORE/Commands): New GM command to do something
5+
## Example 2: feat(Scripts/Commands): Add .mail list and .mail return commands
6+
## Example 3: refactor(Scripts/Ulduar): Leverage DoorData and persistent data
7+
## Example 4: fix(Scripts/SlavePens): Despawn Frozen Core after Ahune emerges
8+
## Example 5: fix(Scripts/VioletHold): Prevent Sinclari from despawning
79

810

911
### DESCRIPTION
@@ -46,7 +48,7 @@
4648
## More info here https://www.conventionalcommits.org/en/v1.0.0-beta.2/
4749
## =======================================================
4850
## "Scope" can be:
49-
## CORE (core related, c++)
51+
## Core (core related, c++)
5052
## DB (database related, sql)
5153
## =======================================================
5254
## "Subscope" is optional and depends on the nature of the commit.

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2+
"github.copilot.chat.commitMessageGeneration.instructions": [
3+
{
4+
"file": ".git_commit_template.txt"
5+
},
6+
],
27
"files.associations": {
38
"*.dist": "properties",
49
"*.crash": "properties",

CLAUDE.md

Lines changed: 69 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,104 @@
11
# CLAUDE.md
22

3-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
3+
AzerothCore is a C++ MMORPG server emulator for World of Warcraft 3.3.5a (WotLK), built with CMake, backed by MySQL.
44

5-
## Project Overview
5+
## Agent rules
66

7-
AzerothCore is an open-source MMORPG server emulator for World of Warcraft patch 3.3.5a (Wrath of the Lich King). It's a C++ project built with CMake, using MySQL for data storage. Licensed under GNU GPL v2.
7+
- **Do not configure or build unless explicitly asked.** Builds are slow (CMake + compile of a large C++ codebase) and rarely needed to make code changes.
8+
- **Never edit SQL files outside `data/sql/updates/pending_db_*/`.** `data/sql/base/`, `data/sql/archive/`, and `data/sql/updates/db_*/` are immutable (do not modify).
9+
- **Do not run git commands that modify repo state** (commit, branch, merge, rebase, reset, push, …) unless explicitly requested, and do not include them in plans. Read-only git (status, diff, log) is fine.
810

9-
## Build Commands
11+
## Build
1012

11-
### Configure and build (out-of-source build required)
12-
13-
- Skip building unless explicitly requested.
13+
Out-of-source build is required (in-source is blocked by CMake).
1414

1515
```bash
16-
# Create build directory and configure
1716
mkdir -p build && cd build
1817
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/azeroth-server -DCMAKE_BUILD_TYPE=RelWithDebInfo \
1918
-DSCRIPTS=static -DMODULES=static
20-
21-
# Build (use appropriate core count)
22-
make -j$(nproc)
23-
make install
19+
make -j$(nproc) && make install
2420
```
2521

26-
### Key CMake options
27-
28-
- `SCRIPTS`: none, static, dynamic, minimal-static, minimal-dynamic (default: static)
29-
- `MODULES`: none, static, dynamic (default: static)
30-
- `APPS_BUILD`: none, all, auth-only, world-only (default: all)
31-
- `TOOLS_BUILD`: none, all, db-only, maps-only (default: none)
32-
- `BUILD_TESTING`: Enable unit tests (default: OFF)
33-
- `USE_COREPCH` / `USE_SCRIPTPCH`: Precompiled headers (default: ON)
22+
Compiler: **C++20** required (`CMAKE_CXX_STANDARD 20`). Useful CMake flags: `BUILD_TESTING=ON` (Google Test), `NOPCH=1` (disable precompiled headers). Full flag set in `conf/dist/config.cmake`. `compile_commands.json` is exported automatically.
3423

35-
### Unit tests
36-
37-
```bash
38-
# Configure with testing enabled
39-
cmake .. -DBUILD_TESTING=ON
40-
make -j$(nproc)
41-
42-
# Run tests
43-
./src/test/unit_tests
44-
# or
45-
ctest
46-
```
24+
Tests (Google Test, in `src/test/`): configure with `-DBUILD_TESTING=ON`, then `ctest` or `./src/test/unit_tests` from the build dir.
4725

48-
Tests use Google Test and live in `src/test/`. The test binary links against the `game` library.
26+
## Repository layout
4927

50-
## Architecture
28+
- `src/common/` — networking (Asio), crypto, config, logging, shared utilities.
29+
- `src/server/game/` — core gameplay; compiled into worldserver.
30+
- `src/server/scripts/` — content scripts grouped by region (`EasternKingdoms/`, `Northrend/`, …), class (`Spells/spell_mage.cpp`, …), and domain (`Commands/`, `Pet/`, `OutdoorPvP/`, `World/`).
31+
- `src/server/database/` — DB abstraction and schema updater.
32+
- `src/server/shared/` — code shared by auth and world servers.
33+
- `src/server/apps/{authserver,worldserver}/` — entry points (ports 3724 and 8085).
34+
- `src/test/` — Google Test unit tests + mocks.
35+
- `data/sql/``base/` (historical schema), `updates/db_*/` (merged), `updates/pending_db_*/` (in-flight, **edit here**), `custom/` (gitignored).
36+
- `modules/` — external modules (each a subdir with its own `CMakeLists.txt`). Disable with `-DDISABLED_AC_MODULES="mod1;mod2"`. See `modules/how_to_make_a_module.md`.
37+
- `apps/` — helper scripts; `apps/codestyle/` holds the lint scripts (see below).
38+
- `conf/dist/` — distributed config templates; `conf/*.conf` is gitignored.
39+
- `deps/` — vendored third-party dependencies.
5140

52-
### Two server executables
53-
- **authserver** (`src/server/apps/authserver/`): Handles authentication and realm selection (port 3724)
54-
- **worldserver** (`src/server/apps/worldserver/`): Main game server handling all gameplay (port 8085)
41+
## Adding SQL updates
5542

56-
### Source layout (`src/`)
43+
1. `cd data/sql/updates/pending_db_world/` (or `pending_db_auth` / `pending_db_characters`).
44+
2. `./create_sql.sh` generates an empty `rev_<timestamp>.sql` you write into.
45+
3. Required SQL conventions (enforced by `apps/codestyle/codestyle-sql.py`):
46+
- Every `INSERT` must be preceded by a matching `DELETE` (idempotency).
47+
- 4-space indent (no tabs), trailing newline, no double semicolons, no multiple blank lines.
48+
- Tables must use the InnoDB engine.
5749

58-
- **`src/common/`** - Shared libraries: networking (Asio), cryptography, configuration, logging, threading, collision detection, utilities
59-
- **`src/server/game/`** - Core game logic (~52 subsystems), the heart of the worldserver
60-
- **`src/server/scripts/`** - Content scripts (bosses, spells, commands, instances)
61-
- **`src/server/database/`** - Database abstraction layer and schema updater
62-
- **`src/server/shared/`** - Code shared between auth and world servers (packets, network, realm definitions)
63-
- **`src/test/`** - Unit tests (Google Test)
50+
The three databases:
6451

65-
### Key game subsystems (`src/server/game/`)
52+
- `acore_auth` — accounts, realm list, IP/account bans, session keys. Shared across all realms.
53+
- `acore_characters` — per-character state: characters, inventory, in-progress quests, mail, guilds, arena teams, achievements. One per realm.
54+
- `acore_world` — static game content: creature/gameobject/item/quest templates, spawn lists, loot tables, SmartAI scripts, gossip, conditions. Read-mostly; rebuilt from SQL.
6655

67-
- **Entities/** - Core game objects: `Player`, `Creature`, `Unit`, `Item`, `GameObject`
68-
- **Spells/** - Spell mechanics, aura system, spell effects
69-
- **Maps/** - Map management, grid system, instancing
70-
- **Handlers/** - Client packet handlers (one file per system: `MovementHandler.cpp`, `SpellHandler.cpp`, etc.). These are methods on `WorldSession`
71-
- **AI/** - Creature AI framework
72-
- **Scripting/** - Script system with typed base classes (`ScriptObject` subclasses: `CreatureScript`, `SpellScript`, `InstanceMapScript`, `GameObjectScript`, `CommandScript`, etc.)
73-
- **Server/** - `WorldSession` (per-player connection), `World` (global state), opcode definitions
56+
## Code style
7457

75-
### Scripting system
58+
Run the linters before claiming a change is done:
7659

77-
Scripts follow a registration pattern:
78-
1. Define a class inheriting from `SpellScript`, `CreatureScript`, etc.
79-
2. Implement an `AddSC_*()` function that calls `RegisterSpellScript(ClassName)` (or similar)
80-
3. The `AddSC_*()` is declared and called from the regional `*_script_loader.cpp`
81-
4. Script loaders per region: `spells_script_loader.cpp`, `eastern_kingdoms_script_loader.cpp`, `northrend_script_loader.cpp`, etc.
82-
5. Spell script files are organized by class: `spell_dk.cpp`, `spell_mage.cpp`, `spell_generic.cpp`, etc.
83-
84-
### Three databases
85-
- **acore_auth** - Accounts, realm list, bans (`data/sql/base/db_auth/`)
86-
- **acore_characters** - Character data, inventories, progress (`data/sql/base/db_characters/`)
87-
- **acore_world** - Game content: creatures, items, quests, spells, loot (`data/sql/base/db_world/`)
60+
```bash
61+
python apps/codestyle/codestyle-cpp.py # C++
62+
python apps/codestyle/codestyle-sql.py # SQL (compares to origin/master)
63+
```
8864

89-
- SQL updates go in `data/sql/updates/pending_*` with separate subdirectories per database until pull request is merged. Pending SQL files are assigned random names.
90-
- SQL updates go in `data/sql/updates/` with separate subdirectories per database after their pull request is merged.
91-
- SQL files outside the `data/sql/updates/pending_*` folders should never be updated.
65+
Hard rules (also enforced by CI with `-Werror`):
9266

93-
### Module system
67+
- 4-space indent for C++ (tabs forbidden); 2-space for JSON/YAML/sh/ts/js. UTF-8, LF, max 80 cols, trailing newline.
68+
- Allman braces. No braces around single-line statements. `if (x)` — never `if(x)` or `if ( x )`.
69+
- `auto const&` (not `const auto&`); `Type const*` (not `const Type*`).
70+
- Use `{}` format specifiers (`fmt`-style), not `%u`/`%s`.
71+
- Use the typed helpers, not raw flag access:
72+
- `IsPlayer()`, `IsCreature()`, `IsItem()`, … instead of `GetTypeId() == TYPEID_*`.
73+
- `GetNpcFlags()`, `HasNpcFlag()`, `SetNpcFlag()`, `RemoveNpcFlag()`, `ReplaceAllNpcFlags()` instead of `*Flag(UNIT_NPC_FLAGS, …)`.
74+
- `IsRefundable()`, `IsBOPTradable()`, `IsWrapped()` instead of `HasFlag(ITEM_FIELD_FLAGS, …)`.
75+
- `HasFlag(ItemFlag)` / `HasFlag2(ItemFlag2)` / `HasFlagCu(ItemFlagsCustom)` instead of bitwise `Flags & ITEM_FLAG…`.
76+
- `ObjectGuid::ToString().c_str()` instead of `ObjectGuid::GetCounter()`.
9477

95-
External modules are loaded from the `modules/` directory. Each module is a subdirectory with its own `CMakeLists.txt`. Disable specific modules with `-DDISABLED_AC_MODULES="mod1;mod2"`. Module skeleton: https://github.com/azerothcore/skeleton-module/
78+
CI also runs `cppcheck`.
9679

97-
### Dependencies
80+
## Project conventions
9881

99-
Bundled in `deps/`: boost, MySQL client, OpenSSL, zlib, recastnavigation (pathfinding), g3dlite (geometry), fmt, argon2, jemalloc, and others.
82+
- **Logging**: `LOG_INFO("category.sub", "msg with {}", arg)` (also `LOG_WARN`, `LOG_ERROR`, `LOG_DEBUG`, `LOG_TRACE`). Categories are hierarchical, dot-separated (e.g. `server.loading`, `entities.player`, `sql.dev`). No `printf`-style; no `sLog->`; no `TC_LOG_*`. Macro in `src/common/Logging/Log.h`.
83+
- **Random**: use project helpers from `src/common/Utilities/Random.h``urand`, `irand`, `frand`, `rand32`, `rand_chance`, `roll_chance_f`, `roll_chance_i`. Do not use `std::rand` or `<random>` directly.
84+
- **Strings**: `Acore::StringFormat(fmt, args...)` (wraps `fmt::format`, `{}` placeholders) — `src/common/Utilities/StringFormat.h`.
85+
- **Config**: read options with `sConfigMgr->GetOption<T>("Name", default)`.
86+
- **Namespace**: project-wide is `Acore::` (no `Trinity::` remnants — agents porting from upstream forks must rename).
87+
- **Long-lived references**: do not store a raw `Player*` / `Creature*` / `Unit*` past the current call/tick — the object can be removed (logout, despawn, instance unload) and the pointer dangles. Store the `ObjectGuid` and resolve at use time via `ObjectAccessor::FindPlayer(guid)`, `ObjectAccessor::GetCreature(*from, guid)`, `Map::GetCreature(guid)`, etc.
88+
- **DB queries**: use `PreparedStatement` (via `WorldDatabase` / `CharacterDatabase` / `LoginDatabase` and the prepared-statement enums) rather than raw query strings. Reads that don't need to block the world tick go through the async path: `_queryProcessor.AddCallback(db.AsyncQuery(stmt).WithPreparedCallback(...))` (or `WithCallback` for non-prepared). Multi-statement writes wrap in `SQLTransaction` + `Execute` / `AppendPreparedStatement`.
89+
- **Timed actions in AI**: use `EventMap` (event id → delay; simple) or `TaskScheduler` (lambdas, repeats, cancellation). Both are members of `CreatureAI`; see any boss script under `src/server/scripts/` for examples — don't roll your own tick counters.
10090

101-
## Commit Message Format
91+
## Scripting registration
10292

103-
Uses Conventional Commits:
104-
```
105-
Type(Scope/Subscope): Short description (max 50 chars)
106-
```
93+
Scripts inherit from a `ScriptObject` subclass (`SpellScript`, `AuraScript`, `CreatureScript`, `InstanceMapScript`, `GameObjectScript`, `CommandScript`, …). Two registration styles coexist:
10794

108-
- **Types**: feat, fix, refactor, style, docs, test, chore
109-
- **Scopes**: Core (C++ changes), DB (SQL changes)
110-
- **Examples**: `fix(Core/Spells): Fix damage calculation for Fireball`, `fix(DB/SAI): Missing spell to NPC Hogger`
95+
- **Spell / aura scripts**: use the `RegisterSpellScript(ClassName)` (or `RegisterSpellAndAuraScriptPair(...)`) macro inside `AddSC_<name>()`.
96+
- **Creature scripts**: prefer `RegisterCreatureAI(ClassName)` for new code; legacy zones still use `new ClassName();`. Match the surrounding pattern.
11197

112-
## Code Style
98+
Then declare and call `AddSC_<name>()` from the regional loader: `Spells/spells_script_loader.cpp`, `EasternKingdoms/eastern_kingdoms_script_loader.cpp`, etc.
11399

114-
- 4-space indentation for C++ (no tabs)
115-
- 2-space indentation for JSON, YAML, shell scripts
116-
- UTF-8 encoding, LF line endings
117-
- Max 80 character line length
118-
- No braces around single-line statements
119-
- Use {} to parse variables into output instead of %u etc.
120-
- CI enforces code style checks and compiles with `-Werror`
100+
**SmartAI** (data-driven creature behaviour) lives in the world DB's `smart_scripts` table — not in C++. Engine: `src/server/game/AI/SmartScripts/`. For new creature behaviour prefer SmartAI (added via the SQL update workflow); reach for `CreatureScript` only when SmartAI's event/action vocabulary isn't enough.
121101

122-
## PR Requirements
102+
**Module hooks** (e.g. `OnPlayerLogin`, `OnWorldUpdate`, `OnSpellCast`) are declared in `src/server/game/Scripting/ScriptDefines/*.h`. Implement by inheriting the matching base (`PlayerScript`, `WorldScript`, …) and registering with `new MyClass();` (or its `RegisterXxxScript` macro where one exists) inside `AddSC_<name>()`. Full hook list: https://www.azerothcore.org/wiki/hooks-script.
123103

124-
- AI tool usage must be disclosed in PRs
125-
- In-game testing expected
126-
- Changes to generic code require regression testing of related systems
104+
Custom (non-upstream) scripts go in `src/server/scripts/Custom/` (gitignored).
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- DB update 2026_05_17_00 -> 2026_05_24_00
2+
-- RBAC permission for .pet rename (sec 3+, Admin role 196).
3+
DELETE FROM `rbac_permissions` WHERE `id` = 922;
4+
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
5+
(922, 'Command: pet rename');
6+
7+
DELETE FROM `rbac_linked_permissions` WHERE `linkedId` = 922;
8+
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES
9+
(196, 922);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- DB update 2026_05_22_00 -> 2026_05_23_00
2+
--
3+
UPDATE `creature_template_addon` SET `auras` = '' WHERE (`entry` IN (31841, 31842));
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- DB update 2026_05_23_00 -> 2026_05_24_00
2+
--
3+
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 4) AND (`SourceEntry` = 30886);
4+
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
5+
(22, 4, 30886, 0, 0, 23, 1, 4526, 0, 0, 1, 0, 0, '', 'Despawn Subjugated Iskalder when outside quest areas'),
6+
(22, 4, 30886, 0, 0, 23, 1, 4498, 0, 0, 1, 0, 0, '', 'Despawn Subjugated Iskalder when outside quest areas'),
7+
(22, 4, 30886, 0, 0, 23, 1, 4496, 0, 0, 1, 0, 0, '', 'Despawn Subjugated Iskalder when outside quest areas');
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- DB update 2026_05_24_00 -> 2026_05_24_01
2+
--
3+
UPDATE `creature_template` SET `CreatureImmunitiesId` = -375 WHERE `entry` IN (30183, 16486);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- DB update 2026_05_24_01 -> 2026_05_24_02
2+
-- acore_string entries for .pet rename command.
3+
DELETE FROM `acore_string` WHERE `entry` IN (35453, 35454);
4+
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
5+
(35453, 'Invalid pet name: {}.', '잘못된 펫 이름입니다: {}.', 'Nom de familier invalide : {}.', 'Ungültiger Begleitername: {}.', '无效的宠物名称: {}。', '無效的寵物名稱:{}。', 'Nombre de mascota no válido: {}.', 'Nombre de mascota no válido: {}.', 'Недопустимое имя питомца: {}.'),
6+
(35454, 'Renamed pet {0} ({1} -> {2}) for player {3} ({4}).', '플레이어 {3} ({4})의 펫 {0}의 이름을 {1}에서 {2}(으)로 변경했습니다.', 'Familier {0} renommé ({1} -> {2}) pour le joueur {3} ({4}).', 'Begleiter {0} umbenannt ({1} -> {2}) für Spieler {3} ({4}).', '已将玩家 {3} ({4}) 的宠物 {0} 重命名 ({1} -> {2})。', '已將玩家 {3} ({4}) 的寵物 {0} 重新命名({1} -> {2})。', 'Mascota {0} renombrada ({1} -> {2}) para el jugador {3} ({4}).', 'Mascota {0} renombrada ({1} -> {2}) para el jugador {3} ({4}).', 'Питомец {0} переименован ({1} -> {2}) у игрока {3} ({4}).');
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- DB update 2026_05_24_02 -> 2026_05_25_00
2+
-- Hide Whispering Wind (30848) during Wintergrasp battle.
3+
-- Aura 52107 phases the creature out while war is active; the other five
4+
-- small WG elementals (30842, 30845, 30846, 30847, 30849) already have it
5+
-- in creature_template_addon — 30848 was missed.
6+
DELETE FROM `creature_template_addon` WHERE `entry` = 30848;
7+
INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES
8+
(30848, 0, 0, 0, 1, 0, 0, '52107');
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- DB update 2026_05_25_00 -> 2026_05_26_00
2+
--
3+
-- Change Target CREATURE_DISTANCE to CLOSEST_FRIENDLY
4+
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 23960) AND (`source_type` = 0) AND (`id` IN (1, 2));
5+
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
6+
(23960, 0, 1, 0, 0, 0, 100, 2, 5000, 7000, 14000, 17000, 0, 0, 11, 42740, 0, 0, 0, 0, 0, 26, 30, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Runecaster - In Combat - Cast \'Njord`s Rune of Protection\' (Normal Dungeon)'),
7+
(23960, 0, 2, 0, 0, 0, 100, 4, 5000, 7000, 14000, 17000, 0, 0, 11, 59616, 0, 0, 0, 0, 0, 26, 30, 0, 0, 0, 0, 0, 0, 0, 'Dragonflayer Runecaster - In Combat - Cast \'Njord`s Rune of Protection\' (Heroic Dungeon)');

0 commit comments

Comments
 (0)