# OpenWC Портирование клиента **World of Warcraft 3.3.5a (12340)** на **Godot 4.6**. Текущий фокус проекта: загрузка данных из клиента, разбор форматов WoW и отображение мира в Godot так, чтобы его можно было смотреть и дальше редактировать уже средствами движка. Сейчас проект уже умеет: - открывать MPQ-архивы клиента через editor plugin; - извлекать файлы из MPQ в `res://data/extracted`; - читать `BLP2` текстуры; - читать `ADT`-тайлы terrain; - рендерить terrain из `ADT` с текстурными слоями `MCLY/MCAL`; - учитывать `holes` в `MCNK`; - читать и рендерить воду из `MH2O`; - стримить мир чанками с LOD в runtime; - стримить мир в **editor preview** по мере движения камеры в 3D viewport; - читать `WMO` в отдельный `Dictionary` и собирать его в `Node3D` вручную. Что пока не доведено до полноценного world renderer: - автоматическая подстановка `WMO` и `M2` в мир из `ADT/WDT`; - вода без простого базового материала: нет нормального water shader, depth fade, shoreline blending, анимации; - world-level `WDT` loader; - импорт обратно в форматы WoW; - полноценные инструменты редактирования мира в editor. ## Текущее состояние ### Реализовано - `MPQManager` - открытие клиентских архивов; - список архивов по приоритету; - listing/extract по фильтру. - `BLPLoader` - чтение `BLP2` из файла или из байтов; - поддержка основных сжатых форматов, достаточная для terrain textures. - `ADTLoader` - `MTEX`, `MMDX/MMID`, `MWMO/MWID`; - `MDDF`, `MODF`; - `MCVT`, `MCNR`, `MCLY`, `MCAL`; - `holes`; - `MH2O`. - `ADTBuilder` - сборка terrain в `Node3D`; - terrain material с 4 слоями; - legacy/big/compressed alpha; - chunk-level LOD; - первый проход рендера воды. - `StreamingWorld` - runtime streaming тайлов и чанков; - editor streaming вокруг камеры viewport; - отдельные `ADT`-узлы под `Terrain` в дереве сцены. ### Частично реализовано - `WMOLoader` - root/group parsing есть; - `WMOBuilder` собирает mesh по группам; - в общий world streaming пока не интегрировано. ### Не реализовано - `M2` renderer; - `WDT` streaming metadata; - сохранение 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`. Это уже можно использовать вручную, но в world streaming оно пока не подключено. ## 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; - `WMO` читается отдельно, но world placement пока не подключён; - `M2` placements из `ADT` парсятся, но renderer нет; - `WDT` ещё не управляет составом мира; - проект сейчас ориентирован на просмотр и исследование данных, а не на полный round-trip import/export. ## Ближайшие логичные шаги 1. Подключить `WDT`, чтобы мир собирался не по сканированию папки, а по данным карты. 2. Интегрировать `WMO` placement в `StreamingWorld`. 3. Добавить `M2` loader/renderer. 4. Довести water shader. 5. Начать editor-side инструменты для редактирования terrain/liquid/object placement. 6. Подготовить формат сохранения обратно в 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`