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

5.5 KiB
Raw Permalink Blame History

Веб-клиент: 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 (форк 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 по образцу спайка.