# mrgameeng 2D game engine built on MonoGame 3.8.4 (DesktopGL), .NET 8, C#. ECS-first: Friflo.Engine.ECS 3.6 is tightly integrated into the core — all gameplay state lives in components, all logic in systems. Design docs and developer documentation live in `docs/` and are written in **Russian**. Keep them up to date when architecture or conventions change. ## Solution layout ``` src/ MrGameEng.* engine libraries (grouped by role, not one-per-feature) tests/ xUnit test projects, one per engine library tools/ CLI tools (atlas packer) docs/ architecture, conventions, roadmap (Russian) ``` Libraries are grouped by architectural role rather than split per feature, to avoid a sprawl of two-file projects. A feature lives in a subfolder of its host library and keeps its own `MrGameEng.` namespace (namespaces are independent of the assembly), so `using MrGameEng.Tilemaps;` etc. still resolve after a merge. The engine has no sample project: the **LittleSim** game (https://gitea.hsrv.site/mrleo1nid/LittleSim, this repo as the `engine/` submodule) is the living showcase — new engine features are demonstrated there. Engine libraries (each feature is a namespaced subfolder of its host): - **`Core`** — game loop, ECS world, scenes, time (`GameClock` with `TimeScale`; `GameSpeed` for discrete pause/1×/3×/6× speed control over the clock, `context.UseGameSpeed(...)`; `Calendar` turning scaled time into in-game days, `context.UseCalendar(secondsPerDay)`; `Climate` — continuous seasonal/daily temperature and season over the calendar, `context.UseClimate(settings)`), plus **Input** (`MrGameEng.Input`: `InputManager`, `ActionMap`, `InputSystem`, in `Core/Input/`). Depends only on MonoGame and Friflo.Engine.ECS. - **`Graphics`** — custom batched renderer, camera, sprites, plus **Tilemaps** (`MrGameEng.Tilemaps`: code-built tile grids rendered through the batcher, `scene.UseTilemaps()` after `UseRenderer2D()`, in `Graphics/Tilemaps/`) and **Lighting** (`MrGameEng.Lighting`, `Graphics/Lighting/`: day/night ambient over the `Calendar` driving `Renderer2D.AmbientLight` on world layers, `scene.UseDayNight(renderer)`; plus a per-cell **lightmap** — `LightmapBuilder` (ambient × occlusion + point lights with grid-traced shadows), `PointLight` component, multiplied over the world via `scene.UseLighting(...)`, sampleable with `Lighting.SampleAt` for the simulation). → `Core`. - **`Audio`** — ogg playback (NVorbis); `AudioManager` with `SoundVolume`/`MasterVolume` (one knob for effects + music). → `Core`. - **`Content`** — the asset/content pipeline: **Assets** (`MrGameEng.Assets`: runtime loading, no MGCB pipeline; FontStash), **Atlases** (`MrGameEng.Atlases`: texture-atlas builder + runtime loader, CLI wrapper in `tools/MrGameEng.AtlasTool`; StbImage), and **Mods** (`MrGameEng.Mods`: mod discovery + load order from `About/About.json`, JSON `Defs/` with parent inheritance and later-mod override, `Languages//` localization, merged texture content trees; the game ships its content as the `Core` mod). → `Core`, `Graphics` (Atlases needs `Texture2DRegion`). - **`Simulation`** — deterministic gameplay primitives that own no world data: **Pathfinding** (`MrGameEng.Pathfinding`: grid A*/Dijkstra/BFS and flow fields over a game-implemented `IPathGrid`), **AI** (`MrGameEng.AI`: utility-AI primitives — `ResponseCurve`, `Consideration`, `UtilityAction`, `UtilityAi` selector, `Blackboard`; generic over a game context), and **Collisions** (`MrGameEng.Collisions`: `Collider` component, spatial hash rebuilt per tick, pairs/queries/raycast, `scene.UseCollisions()` after movement systems). → `Core`, `Graphics` (Collisions needs `Transform2D`, `RectF`). - **`UI`** — Myra integration (`scene.UseUI()` after `UseRenderer2D()`), **DevConsole** (`MrGameEng.DevConsole`: in-game console capturing `Core.Log`, `scene.UseDevConsole()` last in OnLoad) and **Inspector** (`MrGameEng.Inspector`: a Chrome-DevTools-style ECS debugger overlay — entity tree by archetype, component/field view with simple-field editing, world-pick with selection highlight, renderer perf tab; `scene.UseInspector(renderer)`, toggle F1). → `Core`, `Graphics` (the inspector picks entities and reads renderer timings; Myra renders with its own SpriteBatch internally). - **`Assets.Generator`** — Roslyn source generator for typed asset handles; standalone netstandard2.0 analyzer. Dependency rule: a library may depend only on `Core` and `Graphics`; `Core` depends only on MonoGame and Friflo.Engine.ECS. Features grouped into one library share its package set (e.g. `Content` carries both FontStash and StbImage) — keep optional/heavy deps (Myra, NVorbis) in their own library so the rest of the engine stays free of them. ## Commands ``` dotnet build MrGameEng.sln dotnet test MrGameEng.sln ``` Building requires the .NET 10+ SDK (Roslyn 5.3 packages used by the asset-handles generator do not load under the SDK 8 compiler); the target framework stays net8.0. ## Architecture rules - ECS-first: components are plain data (`struct` implementing `IComponent`), behavior goes into Friflo systems (`QuerySystem`), wired through `SystemRoot`. No `Update()` methods on game objects, no inheritance-based entities. - Hot paths (per-frame systems) must be allocation-free below the renderer's parallel threshold; above it Parallel.For scheduler overhead is the accepted trade. A Friflo chunk holds a whole archetype — parallelize by slicing chunks into segments, never by chunk alone. Measure in Release only, using the Renderer2D phase timings. - Rendering: custom batcher in `Graphics` (vertex buffers, layer→depth→texture sort, atlas support); `SpriteBatch` is not used in engine code. Draw systems write vertices directly from Friflo chunk iteration. Orthographic camera (one active per scene), registered render layers (World or Screen space, optional Y-sort), AABB culling against the camera rect before vertices are written. - No MGCB content pipeline. Assets are raw files under `Assets/`, loaded at runtime (textures via `Texture2D.FromFile`, fonts via FontStashSharp, ogg via NVorbis, shaders precompiled by `dotnet-mgfxc` at build time). Game code references assets only through generated typed handles (`AssetRef`), never string paths. - New engine functionality goes into the host library for its role (a namespaced subfolder, e.g. a new render feature under `Graphics/`), not a fresh project. Add a new `MrGameEng.` library only when the area is a genuinely new role or needs an isolated heavy/optional dependency — never into `Core` by default, never a two-file project per feature. - Every public engine feature must be covered by tests where logic is testable without a GPU, and demonstrated in the LittleSim game (the engine's showcase). ## Code conventions - Nullable reference types enabled, warnings as errors, file-scoped namespaces. - Public engine API requires XML doc comments (English). - Tests: xUnit, named `Method_Scenario_Expectation`. - Formatting: all C# code is formatted with **CSharpier**. Match its output — run `csharpier format .` (or let the editor's format-on-save handle it) before committing; never hand-format against it. ## Memory (echovault MCP) - At session start, call `memory_context` to load prior decisions for this project; call `memory_search` before working on a topic that may have prior context (e.g. "renderer", "transitions", "generator"). - Before ending a session where you decided, fixed or learned something, save it with `memory_save`: decisions (X over Y + why), bug root causes, non-obvious gotchas (e.g. Friflo/Myra API traps). Write for a future agent with zero context. - Don't save what the repo already records (code, docs/, git history) or trivia.