Files

564 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenWC
Портирование клиента **World of Warcraft 3.3.5a (12340)** на **Godot 4.6**.
Текущий фокус проекта: загрузка данных из клиента, разбор форматов WoW и отображение мира в Godot так, чтобы его можно было смотреть и дальше редактировать уже средствами движка.
Целевая архитектура клиента, Godot Editor-инструментов, Content Project, интеграции с TrinityCore/AzerothCore и тестовой стратегии собрана в [`docs/README.md`](docs/README.md). Фактическое состояние renderer-подсистемы ведётся в [`RENDER.md`](RENDER.md).
Текущая последовательность реализации и критерии завершения находятся в [`targets/README.md`](targets/README.md); правила работы агентов — в [`AGENTS.md`](AGENTS.md).
Сейчас проект уже умеет:
- открывать MPQ-архивы клиента через editor plugin;
- извлекать файлы из MPQ в `res://data/extracted`;
- читать `BLP2` текстуры;
- читать `ADT`-тайлы terrain;
- рендерить terrain из `ADT` с текстурными слоями `MCLY/MCAL`;
- учитывать `holes` в `MCNK`;
- читать и рендерить воду из `MH2O`;
- стримить мир чанками с LOD в runtime;
- стримить мир в **editor preview** по мере движения камеры в 3D viewport;
- читать `WDT` и собирать состав мира по данным карты, а не по сканированию папки;
- читать `WMO` и автоматически расставлять его в мире через world-level registry с дедупом по `unique_id` (WMO на границе тайлов не дублируется);
- подхватывать глобальный WMO из `WDT.MWMO/MODF` для WMO-only карт (инстансы);
- читать `M2` (MD20 + SKIN00) и ставить его через `MultiMesh` из ADT doodad placements.
Что пока не доведено до полноценного world renderer:
- вода без простого базового материала: нет нормального water shader, depth fade, shoreline blending, анимации;
- M2 renderer статический: material flags (cull/unshaded), blend modes 2+, billboards для листвы и UV-transform'ы не применяются; анимация/скиннинг не парсятся;
- импорт обратно в форматы WoW;
- полноценные инструменты редактирования мира в editor.
## Текущее состояние
### Реализовано
- `MPQManager`
- открытие клиентских архивов;
- список архивов по приоритету;
- listing/extract по фильтру.
- `BLPLoader`
- чтение `BLP2` из файла или из байтов;
- поддержка основных сжатых форматов, достаточная для terrain textures.
- `ADTLoader`
- `MTEX`, `MMDX/MMID`, `MWMO/MWID`;
- `MDDF`, `MODF` (с `unique_id`, `flags`, `doodad_set`, `name_set`);
- `MCVT`, `MCNR`, `MCLY`, `MCAL`;
- `holes`;
- `MH2O`.
- `WDTLoader`
- `MVER`, `MPHD` (flags карты: global_wmo / big_alpha / sort_by_size_class);
- `MAIN` — таблица присутствия 64×64 ADT-тайлов;
- `MWMO` + `MODF` — глобальный WMO для инстансных/WMO-only карт.
- `ADTBuilder`
- сборка terrain в `Node3D`;
- terrain material с 4 слоями;
- legacy/big/compressed alpha;
- chunk-level LOD;
- первый проход рендера воды.
- `StreamingWorld`
- runtime streaming тайлов и чанков;
- editor streaming вокруг камеры viewport;
- состав мира берётся из `WDT` (fallback на папочный скан, если `.wdt` отсутствует);
- отдельные `ADT`-узлы под `Terrain` в дереве сцены;
- world-level WMO registry с refcount-дедупом по `unique_id`: WMO живёт пока на него ссылается хотя бы один загруженный тайл.
- `WMOLoader` / `WMOBuilder`
- root/group parsing;
- `WMOBuilder` собирает mesh по группам;
- интегрирован в `StreamingWorld` через world-level registry;
- глобальный WMO из `WDT` ставится один раз при загрузке карты.
- `M2Loader` / `M2Builder`
- парсинг `MD20` + `SKIN00`: vertices/normals/UVs, materials (flags + blend_mode), texture combos, batches;
- `M2Builder` собирает `ArrayMesh` + `StandardMaterial3D`;
- в `StreamingWorld` расставляется через `MultiMesh` из `ADT.MDDF`.
### Частично реализовано
- `M2` renderer
- статическая геометрия рендерится корректно;
- material flags пока не применяются (cull_mode, unshaded, depth_write);
- blend modes 2+ (additive / modulate) схлопнуты в обычный alpha;
- билборды (leaf bones) не распознаются — листва деревьев плоская;
- UV-трансформы (waterfalls, флаги, порталы) не применяются.
### Не реализовано
- скиннинг и анимации `M2` (bones, key frames);
- particles / ribbons;
- сохранение terrain/liquid/object placement обратно в WoW-форматы;
- редакторские инструменты изменения ADT/WMO данных.
## Структура проекта
- `sources/`
- исходный клиент WoW 3.3.5a, без модификаций.
- `data/extracted/`
- извлечённые из MPQ файлы, с которыми работает Godot.
- `data/cache/`
- generated/offline cache: baked terrain, M2 GLB cache, WMO scene cache. Эти файлы не являются исходниками проекта и игнорируются git.
- `addons/mpq_extractor/`
- editor plugin и GDScript-сборщики сцен.
- `src/native/`
- C++ GDExtension: MPQ, BLP, ADT, WMO.
- `src/scenes/`
- готовые сцены для просмотра мира.
- `src/tools/`
- bake/conversion scripts.
- `src/resources/`
- Godot resources, generated GLB assets and runtime resource scripts.
- `reference/`
- external reference sources/tools: Blender WoW Studio, wow.export and Noggit RED. Runtime-project must not depend on this directory.
- `reference/noggit-red/`
- Noggit RED source reference for WoW 3.3.5 map editing, ADT/WMO/M2 placement behavior and UID workflows.
- внешние reference sources и tools для сверки форматов. Runtime-проект не должен зависеть от этой директории.
- `third_party/`
- `godot-cpp`, `StormLib` и другие зависимости.
## Требования
- Windows
- Godot `4.6`
- Visual Studio 2022 с C++ workload
- CMake
- клиент **WoW 3.3.5a (12340)**
## Сборка
Собрать GDExtension:
```bat
cd src\native
build.bat Release
```
После успешной сборки DLL появится в:
```text
addons/mpq_extractor/bin/
```
VS Code/CMake использует `src/native` как `cmake.sourceDirectory`.
## Подготовка данных
По умолчанию plugin смотрит на клиент в:
```text
res://sources
```
И извлекает файлы в:
```text
res://data/extracted
```
### Через editor plugin
1. Открой проект в Godot.
2. Убедись, что plugin `MPQ Extractor` включён.
3. Внизу editor открой панель `MPQ Extractor`.
4. Укажи путь к клиенту WoW 3.3.5a.
5. Выбери locale.
6. Нажми `Open Client Archives`.
7. Для полной распаковки используй фильтр `*` и `Extract`.
Для terrain/world обычно нужны как минимум:
- `World/Maps/...`
- `Textures/...`
- `World/wmo/...`
- `DBFilesClient/...` если позже понадобится работа с DBC
## Основные классы GDExtension
### `MPQManager`
Доступен из GDScript. Основные методы:
- `open_client(base_path, locale)`
- `list_files(filter="*")`
- `extract_files(filter, output_dir)`
- `read_file(internal_path)`
### `BLPLoader`
Читает WoW `BLP2` и возвращает `Image`.
Основные методы:
- `load_image(path)`
- `load_image_from_bytes(bytes)`
### `ADTLoader`
Читает `ADT` и возвращает `Dictionary` с terrain, texture layers, placements и liquid.
Основные поля результата:
- `textures`
- `m2_names`
- `wmo_names`
- `m2_placements`
- `wmo_placements`
- `chunks`
Каждый chunk содержит:
- `index_x`, `index_y`
- `origin`
- `heights`
- `normals`
- `holes`
- `layers`
- `alpha_maps`
- `liquids`
### `WMOLoader`
Читает root/group файлы `WMO` и возвращает `Dictionary` с `materials` и `groups`.
Подключён в `StreamingWorld` через world-level registry. Дедуп по `unique_id` из `ADT.MODF`, refcount по тайлам.
### `WDTLoader`
Читает `WDT` карты и возвращает `Dictionary`:
- `version``MVER` (ожидается 18);
- `flags`, `has_global_wmo`, `big_alpha`, `sort_by_size_class` — из `MPHD`;
- `tiles: Array[Dictionary]` — присутствующие тайлы `{x, y, flags}` из `MAIN`;
- `global_wmo_name: String` + `global_wmo_placement: Dictionary` — если карта WMO-only.
`StreamingWorld` по умолчанию строит мир из этого списка. Папочный скан остаётся fallback'ом.
### `M2Loader`
Читает `.m2` (`MD20`) + `<basename>00.skin` и возвращает `Dictionary` с геометрией:
- `textures`, `materials` (`flags`, `blend_mode`), `texture_combos`;
- `vertices`, `normals`, `uvs`, `indices`;
- `batches: Array[Dictionary]``{index_start, index_count, material_id, texture_combo_index}`.
Кости, анимации и частицы пока не читаются.
## Export/bake scripts
Все проектные скрипты экспорта и запекания лежат в `src/tools/`. Скрипты с расширением `.gd` запускаются через Godot headless и требуют собранный GDExtension, потому что используют `ADTLoader`, `M2Loader` и `WMOLoader`. Перед запуском данные клиента должны быть извлечены в `res://data/extracted`.
Если `godot` не добавлен в `PATH`, используй путь из `.vscode/settings.json`, например:
```powershell
& 'c:\Godot 4.6\Godot_v4.6.1-stable_win64.exe' --headless --path . --script res://src/tools/bake_all.gd -- --map Azeroth --force
```
### `src/tools/bake_all.gd`
Запекает terrain, M2 doodads и WMO objects за один проход.
```powershell
godot --headless --path . --script res://src/tools/bake_all.gd -- --map Azeroth --force
```
Основные аргументы:
- `--map Azeroth`
- `--extracted res://data/extracted`
- `--terrain-output res://data/cache/baked_terrain_v2`
- `--m2-output res://data/cache/m2_glb`
- `--wmo-output res://data/cache/wmo_tscn`
- `--full-texture-size 2048`
- `--coarse-texture-size 512`
- `--skip-terrain`, `--skip-m2`, `--skip-wmo`
- `--force`
### `src/tools/bake_adt_terrain_cache.gd`
Запекает terrain tiles в `.res` ресурсы `BakedADTTile`. Runtime streaming читает их из `baked_tile_cache_dir`.
```powershell
godot --headless --path . --script res://src/tools/bake_adt_terrain_cache.gd -- --map Azeroth --output res://data/cache/baked_terrain_v2 --force
```
Основные аргументы:
- `--map Azeroth`
- `--extracted res://data/extracted`
- `--output res://data/cache/baked_terrain_v2`
- `--tile-x 32`, `--tile-y 48` для одного тайла
- `--full-texture-size 2048`
- `--coarse-texture-size 512`
- `--texture-size N` legacy alias для обоих размеров
- `--force`
### `src/tools/bake_m2_cache.gd`
Сканирует ADT tiles, собирает уникальные M2 paths и запекает M2 doodads в `PackedScene` `.tscn`.
```powershell
godot --headless --path . --script res://src/tools/bake_m2_cache.gd -- --map Azeroth --output res://data/cache/m2_glb --force
```
Основные аргументы:
- `--map Azeroth`
- `--extracted res://data/extracted`
- `--output res://data/cache/m2_glb`
- `--force`
### `src/tools/bake_wmo_cache.gd`
Сканирует ADT tiles, собирает уникальные WMO paths и запекает WMO world objects в `PackedScene` `.tscn`.
```powershell
godot --headless --path . --script res://src/tools/bake_wmo_cache.gd -- --map Azeroth --output res://data/cache/wmo_tscn --force
```
Основные аргументы:
- `--map Azeroth`
- `--extracted res://data/extracted`
- `--output res://data/cache/wmo_tscn`
- `--force`
### `src/tools/collect_world_m2_list.gd`
Сканирует ADT tiles и сохраняет список уникальных M2 paths. Полезно перед массовой конвертацией или для оценки объема M2 cache.
```powershell
godot --headless --path . --script res://src/tools/collect_world_m2_list.gd -- --map Azeroth --output res://data/cache/m2_glb/Azeroth_m2_list.txt
```
Основные аргументы:
- `--map Azeroth`
- `--extracted res://data/extracted`
- `--output res://data/cache/m2_glb/Azeroth_m2_list.txt`
### `src/tools/m2_to_gltf.py`
Python converter для WoW 3.3.5 M2 v264 в GLTF 2.0 `.glb`. Также экспортирует texture layers рядом с GLB. Для DXT BLP decoding нужен `Pillow`.
Один M2:
```powershell
python src/tools/m2_to_gltf.py data/extracted/Character/BloodElf/Female/BloodElfFemale.M2 src/resources/characters/BloodElf/Female
```
Рекурсивная конвертация:
```powershell
python src/tools/m2_to_gltf.py --all data/extracted/Character --out src/resources/characters
```
Аргументы:
- `input` путь к одному `.M2`
- `output_dir` директория вывода для одного `.M2`
- `--all SEARCH_DIR` рекурсивно конвертирует все `.M2` под директорией
- `--out OUT_ROOT` root вывода для `--all`; по умолчанию `src/resources`
### Reference-only export scripts
В `reference/` лежат внешние скрипты и исходники для сверки форматов, включая Blender/WoW export tools из `reference/` и `reference/wow.export/`. Они не являются частью project pipeline, не вызываются runtime-кодом и не должны использоваться как источник project cache без явного переноса в `src/tools/`.
Найденные reference scripts, связанные с export/conversion:
- `reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/export_m2.py`
- `reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/operations/convert_m2_bones.py`
- `reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/m2/operations/m2_export_validation.py`
- `reference/blender-wow-studio-3.4-1.1.0_Experimental/io_scene_wmo/wmo/export_wmo.py`
- `reference/wow.export/addons/blender/io_scene_wowobj/animation_processor.py`
- `reference/wow.export/addons/blender/io_scene_wowobj/import_wowobj.py`
- `reference/wow.export/addons/blender/io_scene_wowobj/__init__.py`
`toolbar.py` files в reference UI directories относятся к Blender UI этих внешних tools и не являются самостоятельными export/bake entrypoints.
`reference/noggit-red/` is not an export script collection. It is a source reference for WoW 3.3.5 map editing behavior: ADT/WMO/M2 placement, UID handling, map editing workflows and related editor code.
## GDScript-сборщики
### `ADTBuilder`
Файл: `addons/mpq_extractor/loaders/adt_builder.gd`
Умеет:
- собрать весь `ADT` в `Node3D`;
- собрать отдельный chunk с нужным LOD;
- собрать water root для тайла;
- создать layered terrain material;
- загрузить BLP-текстуры через `BLPLoader`.
### `WMOBuilder`
Файл: `addons/mpq_extractor/loaders/wmo_builder.gd`
Умеет:
- собрать `Node3D` из данных `WMOLoader`;
- создать по одному `MeshInstance3D` на группу;
- назначить базовые материалы.
## Сцены просмотра
### `src/scenes/streaming/test.tscn`
Файл: `src/scenes/streaming/test.tscn`
Тестовая сцена, которая грузит квадрат тайлов вокруг центра карты.
Скрипт: `src/scenes/streaming/test_world_loader.gd`
Подходит для:
- быстрой проверки terrain;
- отладки парсинга `ADT`;
- проверки AABB и координат.
### `src/scenes/preview/adt_tile_preview.tscn`
Файл: `src/scenes/preview/adt_tile_preview.tscn`
Preview одного `ADT` прямо в editor.
Скрипт: `src/scenes/preview/adt_tile_preview.gd`
Полезно для:
- проверки одного конкретного тайла;
- отладки terrain layers;
- проверки воды и дыр по отдельному `ADT`.
Основные export-поля:
- `map_name`
- `tile_x`
- `tile_y`
- `reload_now`
### `src/scenes/streaming/eastern_kingdoms_streaming.tscn`
Файл: `src/scenes/streaming/eastern_kingdoms_streaming.tscn`
Главная сцена для стриминга мира.
Скрипт: `src/scenes/streaming/streaming_world_loader.gd`
Умеет:
- находить все доступные `ADT` тайлы в `World/Maps/Azeroth`;
- загружать/выгружать тайлы по мере перемещения;
- строить chunk mesh по LOD;
- отдельно добавлять воду на тайл;
- работать и в runtime, и в editor.
## Editor streaming
`StreamingWorld` теперь умеет подгружать мир прямо в editor по мере движения камеры viewport.
Ключевые export-поля:
- `editor_preview_enabled`
- `editor_follow_view_camera`
- `editor_preview_center_x`
- `editor_preview_center_y`
- `editor_preview_tile_radius`
- `editor_reload_now`
Логика такая:
- `editor_preview_center_x/y` задают anchor, который сдвигается к `origin`, чтобы мир было удобно смотреть в Godot;
- при `editor_follow_view_camera = true` стриминг идёт вокруг положения editor camera в 3D viewport;
- тайлы и их children появляются под `Terrain` в Scene Tree.
Это нужно, чтобы визуально проверить, что мир действительно собирается по мере перемещения по карте, а не только как статичный превью-блок.
## Runtime streaming и LOD
В runtime `StreamingWorld`:
- подгружает `ADT` тайлы по расстоянию;
- для terrain использует chunk-level LOD;
- хранит дальний мир на грубом chunk LOD;
- отдельно создаёт воду на тайл.
Основные параметры:
- `tiles_per_tick`
- `chunk_ops_per_tick`
- `lod0_radius_chunks`
- `lod1_radius_chunks`
- `lod2_radius_chunks`
- `lod2_tile_radius`
## Управление камерой
Файл: `src/scenes/camera/fly_camera.gd`
Управление:
- `RMB` удерживать для обзора;
- `WASD` движение;
- `Q/E` вниз/вверх;
- `Shift` ускорение.
## Что именно уже исправлено в terrain pipeline
По сравнению с самым ранним состоянием проекта уже поправлены:
- layout `MCNKHeader`;
- offsets внутри `MCNK`;
- чтение `MCVT`;
- чтение `MCNR`;
- legacy `MCAL`;
- big alpha / compressed alpha;
- корректные local coordinates внутри `ADT`-узла;
- holes;
- chunk winding/culling;
- editor preview одного тайла;
- streaming всего `Azeroth`;
- первый проход `MH2O`.
## Ограничения текущей версии
- terrain текстурирование уже рабочее, но ещё не 1:1 как в клиенте/Noggit во всех edge cases;
- water renderer сейчас базовый, без настоящих WoW water materials;
- `M2` рендерится статикой без билбордов, UV-анимаций и скелетной анимации;
- старые `baked_terrain_v2` tile-кэши (до добавления `unique_id` в `MODF`) не дедупят WMO на границах тайлов до перезапечки через `bake_all.gd`;
- проект сейчас ориентирован на просмотр и исследование данных, а не на полный round-trip import/export.
## Ближайшие логичные шаги
1. Довести M2 renderer:
- **A.** Применять material flags: корректный `cull_mode`, `unshaded`, `depth_write`; blend modes 2+ (`additive`, `modulate`) вместо плоского alpha.
- **B.** Билборды: парсить bones из `M2`, помечать billboard-флаги, для батчей ссылающихся на billboard-bone выдавать отдельные ноды с `BillboardMode = BILLBOARD_ENABLED`. Листва деревьев перестанет быть плоской.
- **C.** UV-трансформы и vertex colors — custom shader, per-instance UV offset в `MultiMesh`. Waterfalls, порталы, флаги.
2. Скелетная анимация и скиннинг `M2` (bones, key frames, attachments) — отдельный крупный кусок.
3. Довести water shader (depth fade, shoreline blending, анимация).
4. Editor-side инструменты редактирования terrain/liquid/object placement.
5. Подготовить формат сохранения обратно в WoW-совместимые структуры.
## Быстрый старт
1. Положить клиент WoW 3.3.5a в `sources/` или указать путь через plugin.
2. Собрать расширение:
```bat
cd src\native
build.bat Release
```
3. Извлечь данные в `res://data/extracted` через `MPQ Extractor`.
4. Открыть одну из сцен:
- `src/scenes/preview/adt_tile_preview.tscn`
- `src/scenes/streaming/test.tscn`
- `src/scenes/streaming/eastern_kingdoms_streaming.tscn`
Если нужен именно просмотр мира в editor по движению камеры, используй:
- `src/scenes/streaming/eastern_kingdoms_streaming.tscn`
- `editor_preview_enabled = true`
- `editor_follow_view_camera = true`