Files
mrgameeng/CLAUDE.md
T
Leonid Pershin 3f3c0200a8
CI / build-test (push) Successful in 1m9s
Refactor engine architecture and project structure
Updated the organization of engine libraries to group features by architectural role rather than by individual feature. Enhanced documentation in CLAUDE.md and architecture.md to reflect these changes. Removed obsolete project references and added new modules for content management and simulation. Adjusted project files for MrGameEng.Graphics and MrGameEng.UI.Tests to align with the new structure.

This refactor aims to streamline the development process and improve clarity in the engine's architecture.
2026-06-12 07:47:12 +03:00

118 lines
6.6 KiB
Markdown

# 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.<Feature>` 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, 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/`). → `Core`.
- **`Audio`** — ogg playback (NVorbis). → `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/<code>/`
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<TContext>`, `UtilityAction<TContext>`,
`UtilityAi<TContext>` 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()`) plus
**DevConsole** (`MrGameEng.DevConsole`: in-game console capturing `Core.Log`,
`scene.UseDevConsole()` last in OnLoad). → `Core` (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<T>`), 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.<Area>` 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.