Загрузка данных


Вот полная техническая выжимка с примерами исходного кода и финальными патчами для передачи разработчикам/нейросети:

---

# Техническое резюме: Система изоляции `.matrix` для TrinityCore Master (Dragonflight 12.x)

## 1. Цель
Реализовать кастомную систему сценариев (`.matrix <id>`), обеспечивающую полную взаимную изоляцию игроков, NPC и ГО по ID матрицы. Объекты с одинаковым `matrix_id` видят друг друга, с разным — нет. Матрица `0` = обычный мир. Требование: персистентность после рестарта, минимальное вторжение в ядро.

## 2. Исследованные альтернативы (отклонены)

| Вариант | Причина отказа | Источник |
|---|---|---|
| **Eluna/Lua** | Не поддерживает TC master/Dragonflight 12.x. Работает только с 3.3.5 и Cata Preservation | GitHub ElunaLuaEngine, talk.trinitycore.org |
| **SmartScripts** | Не перехватывают проверку видимости (`CanNeverSee`) | trinitycore.info/database/master/world/smart_scripts |
| **Штатная фазовая система** | `.modify phase` работает для изоляции игроков, но `.npc set phase` не функционирует для NPC в Dragonflight. Фаза NPC определяется полем `PhaseId` в таблице `creature`, а не наследуется от спавнера | trinitycore.info/database/master/world/creature, DB2Structure.h |
| **Внешний C++ модуль** | Невозможно без изменения ядра: хук `CanNeverSee()` требует модификации `WorldObject` | ScriptMgr.h, Object.h |

## 3. Ключевые структуры ядра (исходные)

### PhaseEntry (DB2Structure.h)
```cpp
struct PhaseEntry
{
    uint32 ID;
    int32 Flags;
    EnumFlag<PhaseEntryFlags> GetFlags() const { return static_cast<PhaseEntryFlags>(Flags); }
};
```

### PhaseEntryFlags (DBCEnums.h)
```cpp
enum class PhaseEntryFlags : int32
{
    ReadOnly                = 0x001,
    InternalPhase           = 0x002,
    Normal                  = 0x008,
    Cosmetic                = 0x010,
    Personal                = 0x020,
    Expensive               = 0x040,
    EventsAreObservable     = 0x080,
    UsesPreloadConditions   = 0x100,
    UnshareablePersonal     = 0x200,
    ObjectsAreVisible       = 0x400,
};
```

### InSamePhase (Object.h — ДО изменений)
```cpp
bool InSamePhase(WorldObject const* obj) const
{
    return GetPhaseShift().CanSee(obj->GetPhaseShift());
}
```

### CanNeverSee (Object.cpp — ДО изменений)
```cpp
bool WorldObject::CanNeverSee(WorldObject const* obj, bool ignorePhaseShift /*= false*/) const
{
    return GetMap() != obj->GetMap()
        || (!ignorePhaseShift && !InSamePhase(obj));
}
```

### Поля WorldObject (Object.h — ДО изменений)
```cpp
PhaseShift _phaseShift;
PhaseShift _suppressedPhaseShift;
int32 _dbPhase;
```

## 4. Выбранное решение: Минимальный патч ядра (3 файла)

### Изменение 1: Object.h — добавление поля и геттера/сеттера

**Было:**
```cpp
int32 GetDBPhase() const { return _dbPhase; }
void SetDBPhase(int32 p) { _dbPhase = p; }
```

**Стало:**
```cpp
int32 GetDBPhase() const { return _dbPhase; }
void SetDBPhase(int32 p) { _dbPhase = p; }
uint32 GetMatrixId() const { return _matrixId; }
void SetMatrixId(uint32 matrixId) { _matrixId = matrixId; }
```

**Поля — было:**
```cpp
PhaseShift _phaseShift;
PhaseShift _suppressedPhaseShift;
int32 _dbPhase;
```

**Поля — стало:**
```cpp
PhaseShift _phaseShift;
PhaseShift _suppressedPhaseShift;
int32 _dbPhase;
uint32 _matrixId = 0;
```

### Изменение 2: Object.h — модификация InSamePhase()

**Было:**
```cpp
bool InSamePhase(WorldObject const* obj) const
{
    return GetPhaseShift().CanSee(obj->GetPhaseShift());
}
```

**Стало:**
```cpp
bool InSamePhase(WorldObject const* obj) const
{
    return GetMatrixId() == obj->GetMatrixId()
        && GetPhaseShift().CanSee(obj->GetPhaseShift());
}
```

### Изменение 3: Object.cpp — модификация CanNeverSee()

**Было:**
```cpp
bool WorldObject::CanNeverSee(WorldObject const* obj, bool ignorePhaseShift /*= false*/) const
{
    return GetMap() != obj->GetMap()
        || (!ignorePhaseShift && !InSamePhase(obj));
}
```

**Стало:**
```cpp
bool WorldObject::CanNeverSee(WorldObject const* obj, bool ignorePhaseShift /*= false*/) const
{
    return GetMap() != obj->GetMap()
        || GetMatrixId() != obj->GetMatrixId()
        || (!ignorePhaseShift && !GetPhaseShift().CanSee(obj->GetPhaseShift()));
}
```

## 5. Архитектурные решения
- `_matrixId = 0` по умолчанию → полная обратная совместимость, сервер ведёт себя идентично стоку до внедрения команды
- Проверка matrix идёт **до** проверки PhaseShift в `InSamePhase()` → приоритет изоляции над штатными фазами
- В `CanNeverSee()` проверка `GetMatrixId() != obj->GetMatrixId()` стоит отдельным условием через `||` → если матрицы разные, объекты невидимы независимо от фаз и карт
- Персистентность планируется через отдельные таблицы БД (не реализовано на текущем этапе)

## 6. Текущий статус
- ✅ Патч ядра определён и готов к внесению (3 изменения в 2 файлах)
- ⏳ Компиляция не выполнена
- ❌ Команда `.matrix` не написана (`MatrixCommand.cpp` / `SpawndancerCommand.cpp` не создан)
- ❌ Передача MatrixId при спавне NPC/ГО не реализована (`Map::SummonCreature` не изменён)
- ❌ SQL-миграция и персистентность не реализованы

## 7. План следующего этапа
1. Внести 3 изменения в ядро → скомпилировать → убедиться что сток не сломан
2. Написать `MatrixCommand.cpp` (`.matrix <id>`, `.spawndancer <entry>`)
3. Добавить наследование MatrixId при создании NPC/ГО: `Player.MatrixId → NPC.MatrixId` в `Map::SummonCreature` / `Map::AddToMap`
4. Реализовать SQL-таблицы и загрузку/сохранение при логине/спавне
5. Тестирование изоляции в одном окне:
   ```
   .matrix 1          → игрок в матрице 1
   .spawndancer 1401  → NPC наследует матрицу 1, виден игроку
   .matrix 0          → игрок возвращается в сток, NPC исчезает
   .matrix 1          → NPC снова появляется
   ```

## 8. Среда разработки
- **Ядро:** TrinityCore master (Dragonflight 12.x)
- **Клиент:** WoW Retail 12.0.1.65867
- **ОС:** Windows 11 x64
- **IDE:** Visual Studio
- **БД:** MySQL (world, hotfixes)
- **Лаунчер:** Arctium Game Launcher / Burralis (кастомный клиент)
- **Пути:** `G:\TRIN\SERVAK_STUFF\TrinityCore\src\server\game\Entities\Object\`

## 9. Ключевые источники в коде
| Файл | Что содержит |
|---|---|
| `src/server/game/DataStores/DB2Structure.h` | `struct PhaseEntry`, все DB2-структуры |
| `src/server/game/DataStores/DBCEnums.h` | `PhaseEntryFlags`, все enum-флаги |
| `src/server/game/Entities/Object/Object.h` | `InSamePhase()`, `_phaseShift`, `_dbPhase`, поля WorldObject |
| `src/server/game/Entities/Object/Object.cpp` | `CanNeverSee()` |
| `hotfixes.phase` | Кастомные фазы (ID, Flags, VerifiedBuild) |
| `world.creature` | Поля `PhaseId`, `PhaseGroup`, `phaseUseFlags` |