# Веб-клиент: spike KNI и решение A/B Дата: 2026-06-12. Спайк живёт в `spikes/KniWeb` (вне `LittleSim.sln`). ## Вопрос Путь A — «MonoGame в браузере» через [KNI](https://github.com/kniEngine/kni) (форк MonoGame с платформой Blazor WebAssembly/WebGL, те же неймспейсы `Microsoft.Xna.Framework.*`). Путь B — тонкий веб-клиент без MonoGame (TypeScript/PixiJS поверх сетевой репликации). Спайк проверял минимальную жизнеспособность пути A: **ядро движка + Friflo + WebGL-спрайт в браузере**. ## Что сделано `dotnet new kni-blazor-gl` (пакет шаблонов `nkast.Kni.Templates`, KNI 4.2.9001, net8.0) + ProjectReference на `engine/src/MrGameEng.Core` + мини-хост в духе `GameHost` поверх KNI `Game`. Сцена: 300 сущностей в Friflo `EntityStore`, `QuerySystem` двигает их в Update-фазе (отскок от краёв, seed 42), Draw-фаза рисует через KNI `SpriteBatch` (WebGL). ## Результат — путь A жизнеспособен - **`MrGameEng.Core` работает в Blazor WASM без изменений**: `EngineContext`, `GameClock`, `Scene`/`SceneManager`, тайминг переходов — всё ядро завелось как есть (заслуга расслоения Core/Host: в ядре нет ни MonoGame, ни платформы). - **Friflo.Engine.ECS 3.6 работает в wasm**: создание сущностей, архетипы, `QuerySystem`, `ForEachEntity` — без ошибок в консоли браузера. - **KNI 4.2.9001 рендерит через WebGL** с XNA-API: `Game`, `GraphicsDeviceManager`, `SpriteBatch`, `Texture2D.SetData` — совпадает с кодом, который пишется под десктопный MonoGame. - Сборка тривиальна: обычный `Microsoft.NET.Sdk.BlazorWebAssembly` проект, никаких wasm-workload-плясок не понадобилось. ## Известные ограничения пути A (работа на этапе «веб-клиент») 1. **Пер-платформенная компиляция библиотек движка.** `MrGameEng.Graphics`, `Content`, `Audio`, `UI` ссылаются на `MonoGame.Framework.DesktopGL`; для веба их надо собирать против пакетов `nkast.*` (типы те же по API, но другие сборки). Решение — msbuild-условие (`KniPlatform=BlazorGL` → nkast-пакеты), без изменения исходников. 2. **Шейдеры.** `Renderer2D` использует прекомпилированные `dotnet-mgfxc` эффекты — KNI имеет собственный компилятор эффектов; совместимость надо проверять отдельным спайком, прежде чем тащить батчер в веб. 3. **Нет файловой системы.** Моды/дефы/атласы в браузер приезжают по HTTP; текущая схема «собрать атласы при старте из PNG» в вебе не работает — атласы пре-билдятся и кладутся в `wwwroot` (или приезжают с сервера). 4. **Потоки.** `Task.Run`-загрузка контента и `Thread.Sleep`-пейсинг не для браузера (клиенту `HeadlessHost.Run` и не нужен — цикл гонит `requestAnimationFrame` через KNI). 5. **Производительность не мерялась** (300 спрайтов — гладко); бюджет сущностей в wasm-интерпретаторе будет заметно ниже десктопного, замерять на реальной сцене с включённым AOT. ## Решение **Путь A (KNI)** — основной для веб-клиента: переиспользуем ядро, сцены и в перспективе графику движка; код игры один на все платформы. Путь B остаётся запасным, если упрёмся в шейдеры (п. 2) или производительность (п. 5). Порядок работ не меняется: сначала `MrGameEng.Net` (WebSocket-транспорт + репликация — нужен любому пути) и сетевой мультиплеер на десктопе, затем `MrGameEng.Host.Web` поверх KNI по образцу спайка.