Files
Leonid PershinandClaude Fable 5 580cb6ccc9 Browser multiplayer client: promote the KNI spike to src/LittleSim.Web
LittleSim.Web (Blazor WASM + KNI/WebGL) is a real network client now: it
connects to the dedicated server over WebSocket (ClientWebSocket maps to
the browser socket), applies MrGameEng.Net delta snapshots into its
EntityStore and draws pawns through SpriteBatch — fatigue dims them just
like on desktop. The server address comes from ?server=ws://host:port
in the page URL, defaulting to the page's host on port 9050. The net
contract is mirrored in NetContract.cs (KNI and DesktopGL assemblies
can't mix until the graphics libraries build per platform) with loud
keep-in-sync comments on both sides.

Both clients now smooth replicated positions between 10 Hz snapshots:
NetLerp + NetSmoothingSystem lerp the visual position toward the latest
server position every frame (exponential, ~0.25 s to converge).

Verified against a live LittleSim.Server --listen: the browser client
connects (server log), draws ~3.3k lit pixels of pawns whose layout
changes between samples, and survives 400+ ticks without errors. Found
along the way: requestAnimationFrame freezes in hidden windows — the
game loop only runs while the tab is visible.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 00:04:11 +03:00

69 lines
5.5 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.
# Веб-клиент: spike KNI и решение A/B
Дата: 2026-06-12. Спайк жил в `spikes/KniWeb`; после успеха повышен до
**`src/LittleSim.Web`** — рабочего браузерного клиента мультиплеера (Blazor WASM + KNI):
он подключается к `LittleSim.Server --listen` по WebSocket, применяет дельта-снапшоты
`MrGameEng.Net` и рисует жителей через WebGL со сглаживанием позиций. Адрес сервера —
`?server=ws://host:port` в URL страницы (по умолчанию — хост страницы, порт 9050).
Сетевой контракт там продублирован бинарным зеркалом (`NetContract.cs`) — KNI- и
DesktopGL-сборки нельзя смешивать, пока графика движка не собирается пер-платформенно.
## Вопрос
Путь 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 по образцу спайка.