# Godot Best Practices for OpenWC

## Статус

Это нормативные правила применения Godot в OpenWC. Они дополняют общую архитектуру и основаны на официальных Godot practices с учётом большого streaming world, native parsers и встроенного Editor tooling.

## Nodes только на границах

- Domain, packet codecs, validators, coordinate math, build graph и canonical content не должны быть Nodes.
- Node/Control используются для lifecycle, scene composition, input, rendering/audio presentation и Editor UI.
- Большой объём однородных данных хранится в typed objects/packed arrays/resources, а не в тысячах служебных Nodes.
- Scene не ищет глобально dependency по имени; parent composition передаёт contract/reference явно.

## Scene organization

- Каждая scene имеет одну ответственность и может запускаться в isolation с test doubles.
- Parent-child означает ownership: удаление parent логично удаляет child. Иначе системы являются siblings/services.
- Scene наружу публикует небольшой API/signals, а внутренние NodePaths не становятся публичным контрактом.
- Runtime, render sandbox, preview и capture scenes собираются из общих presenters/services.
- Generated world preview не сохраняется как authoring source.

## Dependency injection и signals

- Dependencies передаются composition root, initializer или exported interface reference.
- Signals используются для notification; commands/intents вызываются через явные методы/bus contracts.
- Signal connections снимаются симметрично при unload/plugin disable.
- Не использовать SceneTree groups как скрытый service locator для core architecture.

## Autoload policy

Autoload разрешён только для действительно process-wide lifecycle:

- composition/bootstrap coordinator;
- глобальная immutable build/version information;
- crash/diagnostic sink, если ему нужен process lifetime.

Gameplay state, network session, renderer world, editor session, caches конкретного проекта и audio emitters не должны становиться неявными глобальными managers. Они создаются/освобождаются владельцем режима.

## Resources and data

- Resource подходит для immutable/imported descriptors и editor-inspectable configuration.
- Runtime mutable authoritative state не хранится в shared Resource, который может быть случайно разделён сценами.
- Resource schema имеет version и migration, если сохраняется пользователем.
- Original extracted corpus и bulk caches не следует заставлять Godot массово импортировать без необходимости; применять `.gdignore`, custom import staging или native repository.
- Importer проверяет malformed input и записывает dependency/profile metadata.

## Background work

- Blocking `load()` не используется в frame-critical streaming path; применяются threaded load/jobs.
- Worker выполняет file I/O, parsing, decompression, grouping и pure data generation.
- SceneTree mutation, Node attach и большинство GPU/RID finalization выполняются main thread budget.
- Один Resource не модифицируется несколькими workers.
- GDScript container resize/mutation между threads защищается mutex или заменяется message passing.
- Все worker tasks ожидаются/очищаются; session cancellation не оставляет orphan work.

## Rendering performance

- Сначала измерять SceneTree/CPU/GPU bottleneck, затем переходить к RenderingServer.
- Repeated static M2 группировать spatial MultiMesh cells; один MultiMesh на весь мир ухудшает culling.
- Large transform buffers готовить линейно/в native code и отправлять батчем.
- Visibility ranges/HLOD, occlusion и automatic mesh LOD использовать совместно по профилю.
- Unique materials/textures минимизировать; descriptor/resource counts являются budget metric.
- RenderingServer RIDs имеют явного владельца и освобождаются в deterministic shutdown test.
- Shader/material profiles разделяют Blizzlike и Enhanced; runtime не компилирует тяжёлые варианты при пересечении ADT boundary.

## EditorPlugin lifecycle

- Любая регистрация в `_enter_tree()` имеет соответствующее удаление в `_exit_tree()`.
- Docks, inspectors, importers, gizmos, debugger plugins, signals и jobs снимаются при disable/reload.
- Editor UI не пишет файлы/SQL напрямую — только создаёт application commands.
- Mutation интегрирована с EditorUndoRedoManager или общей command history.
- Preview nodes считаются disposable; stable content IDs не равны instance IDs.
- Долгая операция имеет progress, cancellation и staging output.

## Editor imports and inspectors

- Custom import plugin применяется для формата, которому действительно нужен first-class Godot Resource lifecycle.
- Один extension/type имеет стабильный importer name и version.
- Platform/profile variants фиксируются явно.
- Custom inspectors редактируют canonical data через commands и показывают field-level validation.
- Gizmos не владеют сущностью и создают одну undoable logical operation на drag/stroke.

## UI

- Control tree не читает network packets и не ищет world nodes.
- View models immutable на frame/update boundary.
- Layout использует anchors/containers/theme tokens, а не hardcoded pixel positions вне fidelity backend.
- FrameXML compatibility layout изолирован от modern Godot-native screens.
- Input consumption и focus/modal context тестируются сценами.

## Profiling and diagnostics

- Использовать Godot profiler для script/physics и Visual Profiler для render CPU/GPU.
- Headless/CLI runs сохраняют JSON metrics; GPU runs фиксируют backend/device/driver/resolution.
- Performance changes сравниваются cold/warm и p50/p95/p99, а не одним FPS.
- GPU validation, memory tracking и RenderDoc workflow документируются для shader/backend defects.
- Custom monitors публикуют streaming queues, cache hits, entities, materials, RIDs и job latency.

## Tests

- Pure logic тестируется без SceneTree.
- Scene runner используется только для lifecycle/input/signals/layout/presentation.
- EditorPlugin имеет enable/disable/reload и undo/save/reload tests.
- Headless является обязательным CI path; visual tests запускаются отдельно на GPU runner.
- GdUnit4 рассматривается как кандидат для GDScript/scene tests; native tests остаются отдельным target.

## Official references

- [Godot Best practices](https://docs.godotengine.org/en/stable/tutorials/best_practices/index.html)
- [Scene organization](https://docs.godotengine.org/en/stable/tutorials/best_practices/scene_organization.html)
- [Autoloads versus regular nodes](https://docs.godotengine.org/en/stable/tutorials/best_practices/autoloads_versus_regular_nodes.html)
- [Background loading](https://docs.godotengine.org/en/stable/tutorials/io/background_loading.html)
- [Thread-safe APIs](https://docs.godotengine.org/en/stable/tutorials/performance/thread_safe_apis.html)
- [Optimization using MultiMeshes](https://docs.godotengine.org/en/stable/tutorials/performance/using_multimesh.html)
- [RenderingServer](https://docs.godotengine.org/en/stable/classes/class_renderingserver.html)
- [Import plugins](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/import_plugins.html)
- [Inspector plugins](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/inspector_plugins.html)
- [3D gizmo plugins](https://docs.godotengine.org/en/stable/tutorials/plugins/editor/3d_gizmos.html)
- [Command line tutorial](https://docs.godotengine.org/en/stable/tutorials/editor/command_line_tutorial.html)
- [Debugging tools](https://docs.godotengine.org/en/stable/tutorials/scripting/debug/overview_of_debugging_tools.html)
