From 78fc5f1debf1395d5df0bab7cc0dde54351205cb Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Mon, 22 Jun 2026 01:58:51 +0400 Subject: docs: rewrite MkDocs documentation --- docs/tomes/06-behavior.md | 769 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 769 insertions(+) create mode 100644 docs/tomes/06-behavior.md (limited to 'docs/tomes/06-behavior.md') diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md new file mode 100644 index 0000000..93ec301 --- /dev/null +++ b/docs/tomes/06-behavior.md @@ -0,0 +1,769 @@ +# VI. Поведение, управление, звук и сеть + +Шестой том описывает подсистемы, которые превращают загруженный мир в +реагирующую игру: AI, Behavior, Wizard, Control, ввод, камеру, звук и сеть. +Эти области нельзя восстанавливать только по структуре файлов. Для них важны +порядок кадра, ownership объектов, timing событий и доказуемые границы между +решением, движением, presentation и транспортом. + +Ключевой принцип: reader compatibility не равна gameplay compatibility. +Корректно разобранный ресурс ещё не доказывает, что runtime выбирает ту же +цель, строит тот же маршрут, применяет ту же collision correction, создаёт тот +же sound event или отправляет тот же network payload. Поэтому все утверждения +ниже разделяют подтверждённую структуру, восстановленный архитектурный +контракт и открытые участки, требующие динамической трассировки. + +```text +AI / mission script + -> стратегическая цель, условия, команды миссии +Behavior + -> состояние объекта, target, global/local path +Wizard + -> локальная коррекция траектории +Control + -> physical step, collision proxy, итоговый transform +World3D + -> очередь событий, ownership, deferred deletion +Render / Sound / Net + -> представление, listener, mirrors и сообщения +``` + +Связанные главы: [мир и миссии](04-world.md), [геометрия и рендер](05-render.md) +и справочный [render frame](../reference/render-frame.md). + +## AI, Behavior и Wizard + +Iron3D разделяет стратегическое принятие решений, поведение конкретного объекта +и локальную коррекцию движения. Это разделение должно сохраниться в новой +реализации: стратегический AI не меняет transform напрямую, а collision manager +не выбирает игровую цель. + +```text +ai.dll / SuperAI + -> цель клана, миссии и группы +Behavior.dll + -> состояние юнита, target, global path, local corridor +Wizard.dll + -> ближайшая допустимая траектория +Control.dll + -> физическое движение и столкновения +``` + +### Behavior + +`CreateBehaviour` создаёт controller для отдельного игрового объекта. +`CreateDistributor` восстановлен по consumers как посредник распределения +команд или ресурсов; это высокоуверенный архитектурный вывод, а не доказанное +имя внутреннего класса. Behavior получает `IArealMap` через AI/клановый +контекст, ведёт radar/target state, строит global path, превращает его в local +corridor и передаёт движение Wizard. + +Ошибочные состояния проверяются явно: + +1. отсутствует system map; +2. отсутствует terrain interface; +3. active behavior не имеет `IArealMap`; +4. объект попал в non-reachable area; +5. объект пытается выйти из non-walkable area; +6. path generator вошёл в infinite cycle. + +Эти случаи являются fatal или diagnostic conditions. Совместимая реализация не +должна тихо исправлять их teleport-ом, потому что такое исправление скрывает +ошибку areal graph, terrain query или state machine. + +### Параметры Behavior.ini + +Подтверждены настройки: + +```text +PathFind_BuildingHitDist +PathFind_BuildingNearestDist +PathFind_NearBuildSpeedPercent +PathFind_CorridorRadius +PathFind_NearDoorCoeff +PathFind_fStepOffBuilding +PathFind_MaxAccel +PathFind_MaxRotation +PathFind_fStepDist +PathFind_MinPointInTrajectory +Network_ResourceTransferMaxDelay +``` + +Они задают геометрию corridor, дистанции реакции на здания, снижение скорости +возле препятствий, пределы ускорения и поворота, дискретизацию trajectory и +сетевой timeout передачи ресурсов. Значения читаются как runtime-конфигурация, +а не компилируются в код. Parser должен поддерживать комментарии `//`, пробелы +вокруг `=` и CRLF. + +Файл также содержит logging/debug switches: `Behavior.log`, уровни ошибок, +show vectors и z-buffer debug. Эти переключатели полезны не только для +совместимости, но и как модель современных trace flags. + +### Wizard + +Wizard получает желаемое направление и corridor, анализирует ближайшие +ограничения и выдаёт скорректированную локальную траекторию. Behavior может +очищать её через `ClearWizardPath` при смене цели, повреждении global path или +переходе объекта в неактивное состояние. + +Нужно различать четыре уровня движения: + +- **global path** -- последовательность areals; +- **local path** -- точки или сегменты внутри corridor; +- **wizard path** -- краткосрочное движение с учётом ближайших препятствий; +- **physical step** -- фактически разрешённое Control перемещение. + +Хранение всего маршрута одним массивом лишает систему возможности локально +обойти препятствие без полного повторного поиска. Граница Behavior/Wizard +существует именно для того, чтобы краткосрочная геометрическая коррекция не +ломала стратегический path state. + +### SuperAI и миссионные сценарии + +`CreateSuperAI` создаёт центральный controller клана; `GetSuperAI` возвращает +его. AI загружает файлы из `MISSIONS\SCRIPTS\`, проверяет версию и пишет ошибки +в `ai.log`. Несовпадение версии является отдельной ошибкой, а не неизвестной +командой. + +Сценарный корпус содержит binary `.scr`, formula exports `.fml`, таблицу +переменных `varset.var` и `.trf`-данные. `.scr` хранит именованные секции и +события, например `Init`, `Mission`, `Problems0`, `Fort_Task_Complete` и +`Hero_Teleported`, вместе с числовыми ссылками на compiled instructions. +`.fml` является текстовым экспортом formula set. `varset.var` декларативно +описывает типы, defaults, ranges и строки через макросоподобные формы +`VAR(...)` и `STRING(...)`. + +Безопасная runtime-модель: + +```text +load script bundle + -> validate version and symbol tables + -> create global/formula variables + -> bind named events to instruction offsets + -> instantiate SuperAI per clan + -> dispatch MISSION_START and object events + -> update timers/conditions each simulation tick + -> enqueue game commands through World3D/Behavior +``` + +Сценарий не должен владеть игровым объектом напрямую. Он хранит logical/object +IDs и отправляет команды через игровые interfaces, чтобы удаление объекта или +сетевой mirror не оставили dangling pointer. + +Полная grammar compiled instructions и точное значение всех opcodes остаются +открытым направлением. До появления decompiler-а `.scr` binary body сохраняется +lossless, а доказанные symbol/event tables документируются отдельно. + +### TRF и preload-данные + +TRF-файлы проходят структурный разбор. `auto.trf`, `data.trf` и tutorial +variants имеют сигнатуру [NRes](../reference/nres.md) и содержат большие +таблицы имён игровых прототипов: оружия, башен, сооружений и других объектов. +Также найдены preload-записи, ANI и SKE resources. + +По содержимому, порядку загрузки и consumers TRF с высокой вероятностью +предоставляет AI/сценарному слою заранее подготовленную таблицу типов и +связанных данных. Framing и имена подтверждены corpus-ом, но полная семантика +каждой TRF-записи ещё не закрыта. Имена должны разрешаться через тот же +resource registry, что и миссионные объекты. + +### Стабильность AI-слоя + +`ai.dll`, `Behavior.dll` и `Wizard.dll` побайтно идентичны в Частях 1 и 2. Это +подтверждает, что разделение SuperAI -> Behavior -> Wizard и бинарная +реализация этих трёх уровней не менялись. + +Сценарный корпус: + +```text +Часть 1: 58 SCR, 58 FML, 29 TRF +Часть 2: 59 SCR, 59 FML, 44 TRF +``` + +Все TRF являются структурно валидными NRes. Неизменность DLL усиливает вывод о +стабильной VM, но не закрывает instruction grammar `.scr`: для неё нужен +dispatcher/jump-table decompiler. Дополнительные сценарные данные расширяют +differential corpus, но не заменяют анализ VM. + +## Control, физика и коллизии + +Control превращает желаемое движение в физически допустимое изменение +состояния. World3D владеет жизненным циклом объекта; Terrain предоставляет +поверхность и world queries; Behavior/Wizard задают намерение; Control создаёт +physical controller и collision representation. + +Публичная поверхность: + +```text +InitializeSettings +LoadControlSystem +LoadPhysicalModel +CreateCollManager +CreateCollObject +``` + +Модуль импортирует World3D queue/object functions, `Terrain::GetWorld`, часы, +тригонометрию и `g_FastProc`. Это подтверждает его положение между gameplay +object и геометрией мира. + +### Control system и physical model + +`LoadControlSystem` загружает настройки controller-а: ограничения скорости, +ускорения, поворота и режимы управления. `LoadPhysicalModel` загружает форму и +параметры, используемые для столкновений. Visible MSH не обязан совпадать с +collision representation: для физики часто нужна более простая и устойчивая +форма. + +Практичная runtime-модель: + +```c +struct PhysicalState { + Transform transform; + Vec3 linear_velocity; + Vec3 angular_velocity; + float requested_speed; + float requested_turn; + uint32_t flags; +}; + +struct CollisionProxy { + ObjectId owner; + ShapeSet shapes; + Bounds broad_phase_bounds; + uint32_t category_mask; +}; +``` + +Названия полей здесь описывают контракт совместимой реализации, а не точный +layout исходного C++-объекта. + +### Collision pipeline + +Один расчётный шаг удобно разделить так: + +1. controller получает желаемые `speed`/`turn` от Behavior или manual input; +2. вычисляет кандидатный transform на основе `dt`; +3. обновляет broad-phase bounds collision object; +4. collision manager находит потенциальные пары и terrain candidates; +5. narrow phase вычисляет контакт или допустимый остаток перемещения; +6. physical state корректируется; +7. World3D получает итоговый transform; +8. событие `GMSG_COLLISION_DETECTED` отправляется в согласованной фазе. + +Позиция collision event после narrow phase является рекомендуемой фазой +реализации и согласуется с назначением сообщения, но точный call-site +относительно всех correction steps требует динамической трассировки Control. +Удаление объекта из обработчика остаётся отложенным по правилам World3D. +Collision manager не должен хранить прямую незащищённую ссылку на объект, +который уже pending-delete. + +### CTLD и physical resources + +Реестр прототипов ссылается на `*.ctl`, `*.cpt` и связанные control resources. +В Части 1 структурно проверен 531 CTLD payload без ошибок. Размеры и пять +внутренних счётчиков образуют множество вариантов: наиболее частый размер +392 байта с pattern `(0,0,0,1,0)`, но встречаются блоки от примерно 212 до +1868 байт и более сложные комбинации. + +CTLD является составным count-driven форматом, а не фиксированной struct. +Parser должен: + +- прочитать prefix и все счётчики с проверкой переполнения; +- вычислить границы секций по их counts; +- сохранять неизвестные records в typed raw containers; +- требовать точного завершения payload; +- не использовать размер одного популярного варианта как универсальный layout. + +Полная предметная семантика всех секций ещё не доказана, но существующие файлы +можно безопасно читать, индексировать и сохранять. + +### Terrain queries и movement handoff + +Control получает world-interface Terrain и использует поверхность, faces и +ускорители для высоты, нормали и пересечений. Навигационный маршрут сообщает, +куда двигаться, но итоговый transform определяется по физической поверхности. +При переходе через склон controller должен согласовать горизонтальный шаг, +высоту и ориентацию с terrain normal. + +Порядок операций должен быть детерминированным: пары collision objects +сортируются по стабильному ID, contacts обрабатываются в фиксированной +последовательности, а интеграция использует одну политику `dt` и округления. +Иначе одинаковая миссия постепенно расходится даже без сети. + +### Различия Control в Части 2 + +`Control.dll` пересобрана при неизменных размере, imports и пяти именах/ordinals +exports; RVA всех пяти exports изменились. Форматы и cross-module boundary +сохранились, но точное physical/collision behavior нельзя считать побайтно тем +же. + +CTLD-корпус расширен с 531 до 623 payload. Новых framing errors не найдено; +большинство общих CTLD изменено вместе с переработанными моделями. Это +подтверждает count-driven parser, но не закрывает предметную семантику shape +records и contact solver. + +Differential test обеих частей должен воспроизводить движение без препятствий, +slope following, pair collision, timing collision event и удаление объекта в +callback. Сравниваются transforms и contact events по tick, а не только факт +успешной загрузки. + +## Ввод, камера и управление + +World3D нормализует клавиатуру, мышь и joystick в общие scan codes и manual +commands. Win32 message handler вызывает `UpdateManualEventsList`; перед +обработкой новой порции сообщений основной цикл вызывает +`ClearManualEventsList`. Снимок клавиатуры очищается отдельно через +`stdClearKeyboard`. + +Публичная поверхность включает `WinMsg2ScanCode`, converters для +keyboard/mouse/joystick/predicate, `ScanCode2Str`, `ManualCommand2Str`, +`stdIsKeyPressed`, lock/unlock keyboard и чтение mouse shift. Это позволяет +хранить конфигурацию управления независимо от физического устройства. + +### Event, state и axis + +Ввод имеет минимум три семантики: + +- **edge event** -- нажатие или отпускание в текущей порции сообщений; +- **held state** -- клавиша остаётся нажатой между кадрами; +- **analog value** -- смещение мыши или положение joystick axis. + +Manual command дополняет источник коэффициентом, режимом wrap, dead +zone/threshold и временной характеристикой. Строки camera bindings показывают +команды `MCMD_STATE`, `MCMD_ANGLE_X`, `MCMD_ANGLE_Y`, режимы `MAN_WRAP` и +`MAN_NOTWRAP`, а также параметры ускорения в миллисекундах. + +Simulation читает подготовленный input snapshot. Renderer не должен +самостоятельно опрашивать OS, иначе одно и то же нажатие будет зависеть от +частоты кадров. + +### Joystick через DirectInput + +`Joystick.dll` экспортирует: + +```text +QueryJoy +CreateJoy +ReleaseJoy +SetJoyRange +PeekJoyMessage +GetJoyCaps +``` + +`QueryJoy` обнаруживает устройство, `CreateJoy` получает интерфейс DirectInput, +`SetJoyRange` нормализует оси в диапазон движка, `PeekJoyMessage` выдаёт +очередное унифицированное событие. + +При потере устройства чтение может вернуть ошибку acquired state. Интерфейс +следует повторно получить, очистить устаревшее состояние и продолжить. +Hot-unplug не должен оставлять последнюю ось навсегда отклонённой. +`GetInstalledJoyNames` и `SetActiveJoy` в World3D связывают device list с +game-facing выбором. + +### Два camera interface + +World3D предоставляет `stdSetCurrentCamera`/`stdGetCurrentCamera`: это камера +как часть игрового состояния. Terrain имеет +`stdSetCurrentCamera2`/`stdGetCurrentCamera2`: concrete camera, которую world +renderer использует для matrices, viewport и visibility. + +`LoadCamera` экспортирован обоими модулями. По call graph World3D-вариант +играет роль component bridge, а Terrain-вариант связан с concrete +camera/world implementation. Это архитектурный вывод: точные class names и +layout не восстановлены. + +Минимальные данные камеры: + +```text +world position and orientation +view matrix +projection parameters / field of view +near and far planes +viewport rectangle +camera mode and target object +manual angles/state +``` + +Такая граница позволяет game code работать с абстрактной камерой, не зная +внутреннего renderer representation. + +### Camera commands и порядок кадра + +Подтверждены команды `CMD_CAMERA_LEFT`, `CMD_CAMERA_RIGHT`, `CMD_CAMERA_UP`, +`CMD_CAMERA_DOWN`, `CMD_CAMERA_CENTER`, `CMD_CAMERA_INFRARED`, а также +spotlight и внешние/миссионные camera modes. Горизонтальный угол использует +wrap, вертикальный -- ограниченный диапазон. Center плавно возвращает обе оси к +заданному значению. + +Порядок кадра: + +1. собрать manual events; +2. обновить camera controller во время calculation; +3. вычислить итоговый transform и ограничения; +4. перед render установить current camera; +5. передать её Terrain и sound listener; +6. после кадра сохранить mode-specific state. + +Camera smoothing должно использовать игровое время или специально +подтверждённые часы. Привязка к render delta делает управление разным при 30 и +144 FPS. + +## Звуковая подсистема + +Ngi32 создаёт низкоуровневый DirectSound backend. `services.dll` публикует +`ISoundServer`. Game, Terrain и FX работают уже через эти интерфейсы: +воспроизводят 2D/3D sources, меняют volume и связывают listener с camera. + +Публичные функции Ngi32: + +```text +niCreate3DSound +niGet3DSound +niGet3DSoundCaps +niMuteSound +``` + +Backend динамически вызывает `DirectSoundEnumerateA` и `DirectSoundCreate`; +параметр `DisableDSound` может полностью отключить этот путь. + +### Устройство и capabilities + +Конфигурация учитывает `3D Sound`, качество, reverse sound, частоту buffer, +режим постоянного воспроизведения и автоматический выбор лучшего устройства. +Эти значения преобразуются во внутренний capability/profile object до создания +sources. + +Код содержит отдельный no-device state и строку `3D Sound was not initialized`. +Отсутствие 3D sound обрабатывается отдельно от ошибок simulation/resources. +Новый runtime не должен позволять отсутствию звука разрушать simulation и +обязан возвращать звуковым командам явный no-device result. + +Общий sound object разделяется между подсистемами и использует счётчик +владельцев. Закрывать DirectSound следует после остановки всех sources и +atmosphere/FX managers. + +### Sound resources и SWAV + +Основная библиотека называется `sounds.lib`; `mission.cfg` также создаёт +именованные sound resources и variations. Legacy API `rsLoadWave` загружает +waveform из archive. Импорт `MSACM32` подтверждает путь преобразования сжатых +wave-данных в формат playback buffer. + +Resource identity состоит из library и name. Один sound asset может иметь +несколько runtime sources с различными position, volume, pitch/flags и временем +запуска. Поэтому кэшировать следует decoded sample/buffer, а source object +создавать на событие. + +FX opcode 2 хранит `archive[32] + name[32]` и обычно создаёт sound command. +Atmosphere использует отдельные loop/variation sources, например rain +background. Миссионный слой содержит voice events для завершения или провала +задания. + +Проверенный SWAV-корпус: + +```text +Часть 1: 399 — 306 MS ADPCM, 93 PCM +Часть 2: 540 — 446 MS ADPCM, 93 PCM, 1 empty entry +``` + +Все непустые записи имеют RIFF/WAVE framing и частоту 22 050 Hz. В Части 2 +entry `ALIEN_ME.WAV` имеет размер 0. Это присутствующий archive key без +decodable waveform. + +Sound loader должен различать: + +- `entry_missing`; +- `entry_empty`; +- `wave_invalid`; +- `decoded_sample`. + +Нулевой payload не передаётся RIFF parser-у и не должен приводить к чтению +header за границей. + +### 3D listener и sources + +Перед world traversal `stdRenderGame` обновляет listener из camera transform. +Listener содержит position, orientation и, при наличии, velocity. Source +содержит world position и параметры затухания. Spatialization выполняется +backend-ом либо совместимой программной моделью. + +```text +camera transform + -> listener position/front/up +object or effect transform + -> source position +sample + source parameters + -> DirectSound 3D buffer +``` + +Прямо подтверждено обновление listener в начале `stdRenderGame`, до world +traversal. Sound events могут создаваться и в calculation/FX path, поэтому +нельзя утверждать, что listener предшествует созданию каждого source. Важно, +что spatial backend получает camera state текущего отображаемого кадра до +завершения его обработки. Перенос listener update после world render создаст +как минимум однокадровое рассогласование presentation. + +### Громкость, mute и CD-аудио + +`iron3d.dll` применяет отдельные настройки эффектов и CD sound. Параметр +`FORCE_CD_SOUND` меняет политику выбора музыкального источника. `niMuteSound` +должен временно остановить вывод без разрушения sample cache и logical playback +state. + +В новой реализации полезно разделить buses: master, effects, ambient, voice и +music/CD. Это проектное решение совместимого backend-а, а не доказанный layout +оригинального mixer-а. Оно позволяет применять старые коэффициенты, не +переписывая individual source volume. + +### Граница service layer + +`Ngi32.dll` с DirectSound/backend code не изменилась между Частями 1 и 2, но +`services.dll` пересобрана и уменьшилась на 4 096 байт. Поэтому low-level +decoder/device path подтверждается одной машинной реализацией, а service +lifecycle, GUI/audio wiring и defaults требуют раздельной трассировки обеих +частей. + +## Сетевая подсистема + +Net инкапсулирует DirectPlay4A и lobby/service-provider API. World3D строит над +транспортом player identity, mirror objects и игровые сообщения. Эти уровни +следует разделять: DirectPlay отвечает за доставку bytes между players, +World3D -- за смысл сообщения и владение объектом. + +Application GUID: + +```text +{3C1D1F01-A870-11D1-8400-000021B14415} +``` + +Он передаётся network instance и service layer. Экземпляры с другим GUID не +принадлежат одному логическому приложению. + +### Lifecycle соединения + +Публичные функции Net покрывают полный цикл: + +```text +CreateNetworkInstance + -> select/use service provider + -> setup connection + -> enumerate or create session + -> join/create session + -> create local player + -> send/receive messages and player data + -> destroy player + -> close session + -> close connection +``` + +Поддерживаются providers эпохи DirectPlay: TCP/IP, IPX и modem/lobby варианты, +если они установлены в системе. Функции явно проверяют, что DirectPlay enabled +до enumeration, session и player operations. Неверный порядок вызовов должен +возвращать понятную ошибку, а не разыменовывать пустой interface. + +### Sessions, players и адреса + +Net предоставляет enumeration service providers и sessions, выбор host/join, +player name/password/data, latency, максимальный размер сообщения, размер +очереди, server player info и provider address. Lobby launch обрабатывается +отдельной веткой. + +Внутренняя модель должна хранить как минимум: + +```c +struct NetPlayer { + TransportPlayerId transport_id; + uint16_t game_player_number; + string name; + RawBytes player_data; + bool is_local; + bool is_host; +}; +``` + +Transport ID нельзя использовать как постоянный `ObjectId`. NetWatcher связывает +временный DirectPlay identifier с номером игрока и World3D entities. + +### Игровые сообщения World3D + +Подтверждённые имена message surface: + +```text +GMSG_CREATE_REMOTE_PLAYER +GMSG_APPEND_RESOURCE +GMSG_CHANGE_OBJECT_OWNER +GMSG_SET_PLAYER_DATA +GMSG_MISSION_DATA_PATH +GMSG_TAKE_OBJECT +GMSG_TEXT_FOR_PLAYER +GMSG_SYNC_STATE +GMSG_CREATE_MIRROR +GMSG_PAUSE_REMOTE_PLAYER +GMSG_CONFIRM_PLAYER_DATA +GMSG_KILL_PLAYER +SYSMSG_SET_TIME +SYSMSG_SET_PLAYER_NUMBER +GMSG_END_MESSAGE_SEQ +GMSG_REMOVE_RESOURCE +``` + +`GMSG_COLLISION_DETECTED` относится к общей очереди, но не обязательно +передаётся по сети. Message ID, payload size и delivery policy должны быть +частью явной schema. Нельзя сериализовать C++ pointers или native padding. + +### Mirror objects и ownership + +Удалённо принадлежащий объект представлен local mirror instance. Он участвует в +рендере и spatial queries, но authority над его созданием, ключевыми properties +и удалением находится у owner player. Сообщение смены владельца обновляет эту +границу; оно не должно создавать второй объект с тем же ID. + +Типовой путь: + +```text +remote create message + -> validate player and ObjectId + -> resolve prototype/resources + -> CreateMirrorObject + -> apply initial state + -> AddMirrorObjectToGame + -> subsequent sync messages update mirror +``` + +При потере player NetWatcher инициирует предписанное удаление или transfer +ownership через World3D queue. Мгновенное освобождение во время receive callback +запрещено по тем же причинам, что и в calculation pass. + +### Сжатие и wire compatibility + +`netZipData` и `netUnZipData` образуют встроенный слой упаковки payload. Он +находится выше транспорта: переход с DirectPlay на UDP/ENet не отменяет +необходимость воспроизводить формат упакованного сообщения, если требуется +соединение с оригинальной игрой. + +Полный wire schema, framing и алгоритм сжатия пока не доказаны packet +capture-ом. Поэтому нужны два режима: + +- **native compatibility** -- отдельный adapter, реализуемый после трассировки + оригинальных packets; +- **modern multiplayer** -- новая versioned protocol schema, использующая ту же + game-message семантику, но не заявляющая совместимость с DirectPlay client. + +Эти режимы нельзя незаметно смешивать. До доказательства native wire +compatibility современный transport должен быть versioned и отделён от слоя, +который претендует на совместимость с оригинальным клиентом. + +### Стабильность сетевого слоя + +`Net.dll` и `World3D.dll` побайтно идентичны в обеих частях. Application GUID, +DirectPlay wrapper, mirror-object API и World3D message surface относятся к +одной машинной реализации. + +Это подтверждает отсутствие отдельной сетевой реализации для Части 2, но не +закрывает wire schema: без packet/send-receive capture по-прежнему неизвестны +точное framing, reliability flags, payload layouts и алгоритм `netZipData` для +native interoperability. + +Для binary regression достаточно одного профиля неизменённых DLL, но message +captures должны включать контент обеих частей, потому что prototype/resource IDs +и mission data различаются. + +## Контракты реализации + +Совместимая реализация должна фиксировать не только результат, но и момент его +появления в кадре. Для Behavior, Control, input, sound и network особенно важны +tick boundaries: одна и та же команда, применённая на один tick раньше или +позже, меняет дальнейшую симуляцию. + +### Trace-события + +Минимальный trace для этого тома: + +- input snapshot: edge events, held state, analog values; +- camera state: mode, target, angles, matrices, viewport; +- Behavior: target, areal, global path revision, local corridor; +- Wizard: requested vector, constraints, wizard path; +- Control: candidate transform, contacts, correction, final transform; +- World3D queue: message name, ObjectId, dispatch phase, deferred deletion; +- sound: sample key, source owner, position, event tick, listener state; +- network: player mapping, message ID, payload length, delivery policy. + +Для рендера это связывается с [render frame](../reference/render-frame.md): +camera и listener должны попадать в trace до world traversal, иначе нельзя +отделить ошибку presentation от ошибки управления. + +### Проверки Behavior и сценариев + +- script version mismatch даёт отдельную ошибку; +- event table читается lossless; +- VM body сохраняется без потери неизвестных bytes; +- отсутствующий `IArealMap` не замалчивается; +- non-walkable/non-reachable states дают diagnostic condition; +- одинаковый input log воспроизводит одинаковый sequence Behavior commands; +- resource names из TRF разрешаются через общий registry. + +### Проверки Control + +- движение без препятствий; +- slope/terrain-following; +- симметричные pair-collision tests с переставленными IDs; +- contact event отправляется один раз в предписанной фазе; +- удаление объекта в collision callback безопасно; +- replay одинакового input log даёт одинаковые transforms; +- collision proxy перестраивается после смены component/model state. + +### Проверки input и камеры + +- edge event не повторяется как held state; +- mouse/joystick axis сбрасывается по правилам snapshot; +- hot-unplug joystick не оставляет старое отклонение; +- camera horizontal angle wraps, vertical angle clamps; +- center command использует подтверждённое время, а не render FPS; +- Terrain и sound получают одну и ту же camera frame. + +### Проверки звука + +- backend может отсутствовать без нарушения simulation; +- один decoded sample переиспользуется несколькими sources; +- `entry_missing`, `entry_empty` и `wave_invalid` различаются; +- listener совпадает с camera frame; +- loop source корректно переживает pause/resume; +- mute не сбрасывает position и time; +- missing sound resource содержит полную диагностическую цепочку; +- deterministic test сравнивает список sound events, а не waveform устройства. + +### Проверки сети + +- нельзя создавать queue с активной сетью и нулевым player ID; +- session/player operations до enable/setup возвращают ошибку; +- сообщения проверяют длину до чтения payload; +- sequence/end markers обрабатываются в стабильном порядке; +- duplicate create mirror не создаёт второй instance; +- ownership change атомарно обновляет routing; +- pause/time messages применяются в одной simulation boundary; +- resource transfer имеет timeout `Network_ResourceTransferMaxDelay`; +- disconnect не оставляет objects с несуществующим owner; +- replay записанного message log даёт одинаковое World3D state. + +`resnet.log` и `NetWatch.log` следует поддерживать как отдельные каналы: первый +относится к transport/resource exchange, второй -- к связи players и game +objects. + +## Границы знания + +Подтверждены внешние interfaces, часть runtime order, значимые строки, +конфигурационные параметры, corpus-level counts и стабильность ряда DLL между +двумя частями. Открытыми остаются: + +- instruction grammar `.scr` и semantics всех VM opcodes; +- точная семантика всех TRF-записей; +- полный layout CTLD shape records; +- contact solver и порядок всех correction steps; +- class layout камер, контроллеров, sound service и network watcher; +- DirectPlay wire framing, reliability flags и payload schema; +- алгоритм `netZipData`/`netUnZipData`; +- точные defaults service layer там, где DLL пересобраны. + +Эти границы должны оставаться видимыми в документации и тестах. Если новая +реализация вводит удобный современный abstraction layer, он обязан быть +отделён от утверждений о native compatibility и покрыт отдельным trace. -- cgit v1.2.3