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>
81 lines
4.4 KiB
Markdown
81 lines
4.4 KiB
Markdown
# LittleSim
|
|
|
|
A god-game: minimal graphics, deep simulation. Built on the **mrgameeng** engine
|
|
(MonoGame + Friflo ECS), vendored as the git submodule `engine/` so the game and the
|
|
engine are developed side by side in one editor window.
|
|
|
|
This game is also the **engine's showcase**: mrgameeng has no sample project, so every
|
|
new engine feature gets demonstrated here (a scene, a console command, or a system
|
|
using it) as part of landing the feature.
|
|
|
|
Game design docs live in `docs/` and are written in **Russian**. Engine rules live in
|
|
`engine/CLAUDE.md` — read it before touching engine code; both rule sets apply here.
|
|
|
|
## Layout
|
|
|
|
```
|
|
engine/ mrgameeng git submodule (own repo, own CLAUDE.md)
|
|
src/LittleSim the game (net8.0); references engine projects directly
|
|
src/LittleSim.Server dedicated server: the world headless (engine HeadlessHost) +
|
|
WebSocket replication (MrGameEng.Net); also fast-forward and probe modes
|
|
src/LittleSim.Web browser client (Blazor WASM + KNI/WebGL): connects to the dedicated
|
|
server, renders replicated pawns; mirrors the net contract (NetContract.cs)
|
|
because KNI and DesktopGL assemblies can't mix — keep in sync with
|
|
src/LittleSim/Net/NetSchema.cs. Outside LittleSim.sln's test flow.
|
|
Mods/Core the game's own content as a mod: About, Defs, Languages, Textures
|
|
Cache/ runtime-built atlases (gitignored)
|
|
docs/ концепт, симуляция, моды, roadmap (Russian)
|
|
LittleSim.sln game + engine sources + engine tests — one window for everything
|
|
```
|
|
|
|
## Commands
|
|
|
|
```
|
|
git submodule update --init # after fresh clone
|
|
dotnet build LittleSim.sln
|
|
dotnet run --project src/LittleSim -c Release # measure perf in Release only
|
|
dotnet run --project src/LittleSim.Server -- --days 10 --tps 60 # headless fast-forward
|
|
dotnet run --project src/LittleSim.Server -- --listen # multiplayer world (WebSocket)
|
|
dotnet run --project src/LittleSim -- --connect # client → ws://localhost:9050
|
|
dotnet run --project src/LittleSim.Server -- --probe # CLI check of a running server
|
|
dotnet run --project src/LittleSim.Web # browser client (?server=ws://…)
|
|
dotnet test LittleSim.sln # runs the engine test suites
|
|
```
|
|
|
|
## Content and mods
|
|
|
|
All game content is data in mods (`MrGameEng.Mods`): the game itself ships as the
|
|
`Core` mod. `Mods/Core/Defs` holds JSON defs (terrain, plants, pawns — see
|
|
`docs/mods.md`), `Mods/Core/Languages/{ru,en}` holds UI strings (default language is
|
|
`ru`), `Mods/Core/Textures` holds source images. New mechanics get defs + localization
|
|
keys, not hardcoded arrays; UI strings go through `LanguageManager`, never inline.
|
|
|
|
Atlases are built **at game start** from the merged texture tree of all active mods
|
|
into `Cache/Atlases` (incremental: unchanged groups are skipped, a clean first run
|
|
takes ~20 s). Region keys are paths relative to `Textures/` without extension:
|
|
`atlases.GetRegion(device, "things/plant/treeoak/TreeOakA")`. Console commands:
|
|
`mods`, `lang [code]`, `defs [type]`, `atlas [name]`.
|
|
|
|
## Submodule workflow
|
|
|
|
Engine changes are committed **inside `engine/` first** (engine repo, its commit style),
|
|
pushed to the engine remote, then the submodule pointer bump is committed here.
|
|
Never commit a pointer to an unpushed engine commit.
|
|
|
|
## Game rules
|
|
|
|
- Simulation first: depth of behavior over visuals. Graphics stay primitive
|
|
(tinted quads are fine); complexity budget goes to simulation systems.
|
|
- Determinism: the whole world derives from one integer seed. Systems that need
|
|
randomness own a seeded `Random`; never use `Random.Shared` inside simulation.
|
|
- Simulation/presentation split: simulation systems mutate components only;
|
|
rendering reads them. No draw calls or UI from simulation systems.
|
|
- ECS-first per the engine: plain `struct : IComponent` data, logic in systems.
|
|
- Content as data: numbers, textures and balance live in `Mods/Core/Defs`, user-facing
|
|
strings in `Mods/Core/Languages` — code only defines systems and def classes.
|
|
- Every new mechanic gets a dev-console command for testing (`regen`, `timescale`, …).
|
|
- Formatting: all C# code is formatted with **CSharpier** (`editor.defaultFormatter`
|
|
is `csharpier.csharpier-vscode`, format-on-save is on). Match CSharpier's output —
|
|
run `csharpier format .` (or let format-on-save handle it) before committing; never
|
|
hand-format against it.
|