From a1a3c4e56268f0c022d13879096f45bcfbd642e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Borz=C3=AC?= Date: Tue, 14 Jul 2026 17:47:00 +0200 Subject: [PATCH] docs: compact CLAUDE.md (#26234) --- CLAUDE.md | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 7e6e9031d..0d4c0b76b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,13 +4,12 @@ AzerothCore is a C++ MMORPG server emulator for World of Warcraft 3.3.5a (WotLK) ## Agent rules -- **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. -- **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). -- **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. +- **Do not configure or build unless explicitly asked.** Builds are slow and rarely needed for code changes. +- **Never edit SQL files outside `data/sql/updates/pending_db_*/` unless explicitly requested. ** `data/sql/base/`, `data/sql/archive/`, and `data/sql/updates/db_*/` are immutable. ## Build -Out-of-source build is required (in-source is blocked by CMake). +Out-of-source build is required (in-source is blocked). ```bash mkdir -p build && cd build @@ -19,9 +18,9 @@ cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/azeroth-server -DCMAKE_BUILD_TYPE=RelWithD make -j$(nproc) && make install ``` -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. +C++20 required (`CMAKE_CXX_STANDARD 20`). Useful flags: `BUILD_TESTING=ON` (Google Test), `NOPCH=1` (disable precompiled headers). Full set in `conf/dist/config.cmake`. `compile_commands.json` is exported automatically. -Tests (Google Test, in `src/test/`): configure with `-DBUILD_TESTING=ON`, then `ctest` or `./src/test/unit_tests` from the build dir. +Tests (Google Test, in `src/test/`): configure `-DBUILD_TESTING=ON`, then `ctest` or `./src/test/unit_tests` from the build dir. ## Repository layout @@ -34,18 +33,15 @@ Tests (Google Test, in `src/test/`): configure with `-DBUILD_TESTING=ON`, then ` - `src/test/` — Google Test unit tests + mocks. - `data/sql/` — `base/` (historical schema), `updates/db_*/` (merged), `updates/pending_db_*/` (in-flight, **edit here**), `custom/` (gitignored). - `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`. -- `apps/` — helper scripts; `apps/codestyle/` holds the lint scripts (see below). +- `apps/` — helper scripts; `apps/codestyle/` holds the lint scripts. - `conf/dist/` — distributed config templates; `conf/*.conf` is gitignored. - `deps/` — vendored third-party dependencies. ## Adding SQL updates 1. `cd data/sql/updates/pending_db_world/` (or `pending_db_auth` / `pending_db_characters`). -2. `./create_sql.sh` generates an empty `rev_.sql` you write into. -3. Required SQL conventions (enforced by `apps/codestyle/codestyle-sql.py`): - - Every `INSERT` must be preceded by a matching `DELETE` (idempotency). - - 4-space indent (no tabs), trailing newline, no double semicolons, no multiple blank lines. - - Tables must use the InnoDB engine. +2. `./create_sql.sh` generates an empty `rev_.sql` to write into. +3. Conventions enforced by `apps/codestyle/codestyle-sql.py`: every `INSERT` preceded by a matching `DELETE` (idempotency); no double semicolons; no multiple blank lines; InnoDB engine. The three databases: @@ -55,6 +51,8 @@ The three databases: ## Code style +Formatting (charset, indent width, line length, final newline, trailing whitespace) follows `.editorconfig`. + Run the linters before claiming a change is done: ```bash @@ -62,7 +60,7 @@ python apps/codestyle/codestyle-cpp.py # C++ python apps/codestyle/codestyle-sql.py # SQL (compares to origin/master) ``` -Hard rules (also enforced by CI with `-Werror`): +Hard rules (also enforced by CI with `-Werror`, plus `cppcheck`): - 4-space indent for C++ (tabs forbidden); 2-space for JSON/YAML/sh/ts/js. UTF-8, LF, max 120 cols, trailing newline. - Allman braces. No braces around single-line statements. `if (x)` — never `if(x)` or `if ( x )`. @@ -75,30 +73,28 @@ Hard rules (also enforced by CI with `-Werror`): - `HasFlag(ItemFlag)` / `HasFlag2(ItemFlag2)` / `HasFlagCu(ItemFlagsCustom)` instead of bitwise `Flags & ITEM_FLAG…`. - `ObjectGuid::ToString().c_str()` instead of `ObjectGuid::GetCounter()`. -CI also runs `cppcheck`. - ## Project conventions -- **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`. -- **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 `` directly. -- **Strings**: `Acore::StringFormat(fmt, args...)` (wraps `fmt::format`, `{}` placeholders) — `src/common/Utilities/StringFormat.h`. -- **Config**: read options with `sConfigMgr->GetOption("Name", default)`. -- **Namespace**: project-wide is `Acore::` (no `Trinity::` remnants — agents porting from upstream forks must rename). -- **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. -- **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`. -- **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. +- **Logging**: `LOG_INFO("category.sub", "msg with {}", arg)` (also `LOG_WARN`/`ERROR`/`DEBUG`/`TRACE`). Categories are hierarchical, dot-separated (`server.loading`, `entities.player`, `sql.dev`). No `printf`-style, no `sLog->`, no `TC_LOG_*`. Macro in `src/common/Logging/Log.h`. +- **Random**: use helpers in `src/common/Utilities/Random.h` — `urand`, `irand`, `frand`, `rand32`, `rand_chance`, `roll_chance_f`, `roll_chance_i`. Not `std::rand` or ``. +- **Strings**: `Acore::StringFormat(fmt, args...)` (`{}` placeholders) — `src/common/Utilities/StringFormat.h`. +- **Config**: `sConfigMgr->GetOption("Name", default)`. +- **Namespace**: project-wide `Acore::` (no `Trinity::` remnants — rename when porting from upstream forks). +- **Long-lived references**: don't 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)`, `Map::GetCreature(guid)`, etc. +- **DB queries**: use `PreparedStatement` (via `WorldDatabase` / `CharacterDatabase` / `LoginDatabase` and the prepared-statement enums), not raw query strings. Non-blocking reads go async: `_queryProcessor.AddCallback(db.AsyncQuery(stmt).WithPreparedCallback(...))` (or `WithCallback`). Multi-statement writes wrap in `SQLTransaction` + `Execute` / `AppendPreparedStatement`. +- **Timed actions in AI**: use `EventMap` (event id → delay; simple) or `TaskScheduler` (lambdas, repeats, cancellation), both members of `CreatureAI` — don't roll your own tick counters. See any boss script under `src/server/scripts/`. ## Scripting registration Scripts inherit from a `ScriptObject` subclass (`SpellScript`, `AuraScript`, `CreatureScript`, `InstanceMapScript`, `GameObjectScript`, `CommandScript`, …). Two registration styles coexist: -- **Spell / aura scripts**: use the `RegisterSpellScript(ClassName)` (or `RegisterSpellAndAuraScriptPair(...)`) macro inside `AddSC_()`. +- **Spell / aura scripts**: `RegisterSpellScript(ClassName)` (or `RegisterSpellAndAuraScriptPair(...)`) inside `AddSC_()`. - **Creature scripts**: prefer `RegisterCreatureAI(ClassName)` for new code; legacy zones still use `new ClassName();`. Match the surrounding pattern. -Then declare and call `AddSC_()` from the regional loader: `Spells/spells_script_loader.cpp`, `EasternKingdoms/eastern_kingdoms_script_loader.cpp`, etc. +Then declare and call `AddSC_()` from the regional loader (`Spells/spells_script_loader.cpp`, `EasternKingdoms/eastern_kingdoms_script_loader.cpp`, …). -**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. +**SmartAI** (data-driven creature behaviour) lives in the world DB's `smart_scripts` table, not C++ (engine: `src/server/game/AI/SmartScripts/`). For new creature behaviour prefer SmartAI (via the SQL update workflow); reach for `CreatureScript` only when SmartAI's event/action vocabulary isn't enough. -**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_()`. Full hook list: https://www.azerothcore.org/wiki/hooks-script. +**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) inside `AddSC_()`. Full list: https://www.azerothcore.org/wiki/hooks-script. Custom (non-upstream) scripts go in `src/server/scripts/Custom/` (gitignored).