213 lines
8.7 KiB
Markdown
213 lines
8.7 KiB
Markdown
# GhostEngine — Agent Guidelines
|
|
|
|
## Repository Overview
|
|
|
|
GhostEngine is a C# game engine targeting .NET 10 / Windows, built around:
|
|
- **ECS runtime** (`Ghost.Entities`, `Ghost.Core`) — high-performance, AOT-compatible
|
|
- **Graphics** (`Ghost.Graphics`, `Ghost.Graphics.RHI`, `Ghost.Graphics.D3D12`) — D3D12 RHI
|
|
- **Editor** (`Ghost.Editor`, `Ghost.Editor.Core`, `Ghost.DSL`, `Ghost.Data`) — WinUI 3 (WindowsAppSDK)
|
|
- **Third-party bindings** (`Ghost.FMOD`, `Ghost.MeshOptimizer`, `Ghost.Nvtt`, `Ghost.Ufbx`)
|
|
- **Tools** (`Ghost.NativeWrapperGen`)
|
|
|
|
Solution file: `src/GhostEngine.slnx`
|
|
All commands below should be run from the `src/` directory unless noted.
|
|
|
|
---
|
|
|
|
## Build Commands
|
|
|
|
```shell
|
|
# Build entire solution (x64, Debug)
|
|
dotnet build GhostEngine.slnx -c Debug -p:Platform=x64
|
|
|
|
# Build entire solution (Release)
|
|
dotnet build GhostEngine.slnx -c Release -p:Platform=x64
|
|
|
|
# Build a single project
|
|
dotnet build Runtime/Ghost.Entities/Ghost.Entities.csproj
|
|
|
|
# Clean
|
|
dotnet clean GhostEngine.slnx
|
|
```
|
|
|
|
> **Note:** Editor projects (`Ghost.Editor`, `Ghost.Editor.Core`) require
|
|
> `net10.0-windows10.0.22621.0` and the Windows App SDK. They will only build
|
|
> on a Windows machine with the correct SDK installed. Platform-agnostic runtime
|
|
> and test projects target plain `net10.0`.
|
|
|
|
---
|
|
|
|
## Test Commands
|
|
|
|
There are two test frameworks in use:
|
|
|
|
### MSTest — `Ghost.UnitTest`
|
|
Standard `dotnet test` runner. Tests are parallelized at method level by default.
|
|
Currently the integration test file is `#if false`-guarded until the asset
|
|
service is fully wired.
|
|
|
|
```shell
|
|
# Run all MSTest tests
|
|
dotnet test Test/Ghost.UnitTest/Ghost.UnitTest.csproj -c Debug -p:Platform=x64
|
|
|
|
# Run a single test method by name
|
|
dotnet test Test/Ghost.UnitTest/Ghost.UnitTest.csproj \
|
|
--filter "FullyQualifiedName~TestAutoMetaGeneration_WhenFileCreated"
|
|
|
|
# Run a single test class
|
|
dotnet test Test/Ghost.UnitTest/Ghost.UnitTest.csproj \
|
|
--filter "ClassName~AssetDatabaseIntegrationTest"
|
|
```
|
|
|
|
### Custom TestRunner — `Ghost.MicroTest` / `Ghost.Entities.Test`
|
|
These are console executables driven by `Ghost.Test.Core.TestRunner`. There is
|
|
no `dotnet test` integration; run them directly:
|
|
|
|
```shell
|
|
# Micro tests (native binding smoke tests)
|
|
dotnet run --project Test/Ghost.MicroTest/Ghost.MicroTest.csproj
|
|
|
|
# ECS benchmarks / manual tests
|
|
dotnet run --project Test/Ghost.Entities.Test/Ghost.Entities.Test.csproj -c Release
|
|
```
|
|
|
|
To run a specific `ITest` implementation, edit `Program.cs` in the respective
|
|
project and call `TestRunner.Run<YourTestClass>()`.
|
|
|
|
---
|
|
|
|
## Code Style
|
|
|
|
### EditorConfig (enforced — `src/.editorconfig`)
|
|
- Max line length: **200**
|
|
- Opening braces always on a **new line** for all C# constructs
|
|
- Single-line statements and blocks are **preserved** (not force-expanded)
|
|
- **No** primary constructors (`csharp_style_prefer_primary_constructors = false`)
|
|
- `System.*` using directives are **not** sorted first
|
|
- Import directive groups are **not** separated by blank lines
|
|
- Collection expressions and collection initializer syntax are **disabled**
|
|
(`dotnet_style_prefer_collection_expression = false`)
|
|
|
|
### Language
|
|
- C# `latest` (runtime/test projects) or `preview` (editor projects, for `field`
|
|
keyword support in .NET 10)
|
|
- Nullable reference types: **enabled** everywhere (`<Nullable>enable</Nullable>`)
|
|
- Implicit usings: **enabled** (`<ImplicitUsings>enable</ImplicitUsings>`)
|
|
- Unsafe blocks: **enabled** where needed (ECS, graphics, native bindings)
|
|
|
|
### Namespaces & File Layout
|
|
- One type per file; file name matches type name exactly
|
|
- Namespace matches folder structure: `Ghost.<Module>[.<SubFolder>]`
|
|
- `partial` classes are split across files named `TypeName.Purpose.cs`
|
|
(e.g. `EntityManager.cs`, `EntityManager.Managed.cs`)
|
|
- `AssemblyInfo.cs` holds `[assembly: InternalsVisibleTo(...)]` and assembly
|
|
attributes; do not scatter these across regular source files
|
|
|
|
### Naming Conventions
|
|
| Symbol | Convention | Example |
|
|
|--------|-----------|---------|
|
|
| Private fields | `_camelCase` | `_jobScheduler` |
|
|
| Private static fields | `s_camelCase` | `s_worlds`, `s_logger` |
|
|
| Constants (public/private) | `UPPER_SNAKE_CASE` | `ASSET_EXTENSION`, `ASSETS_FOLDER_NAME` |
|
|
| Properties & public members | `PascalCase` | `EntityManager`, `IsSuccess` |
|
|
| Local variables / params | `camelCase` | `entityCapacity`, `signatureHash` |
|
|
| Interfaces | `I` prefix | `IComponent`, `ISystem`, `ITest` |
|
|
| Generic type parameters | `T`, `TKey`, `TValue`, `E` | |
|
|
| Type-tagged structs (handles) | Generic param encodes context | `Handle<T>`, `Identifier<T>`, `Key64<T>` |
|
|
|
|
### Types & Structs
|
|
- Prefer `readonly struct` for value types that are logically immutable.
|
|
- Prefer `ref struct` / `readonly ref struct` for stack-only types
|
|
(`RefResult<T,E>`, `SystemAPI`, `ChunkView`).
|
|
- Use `partial class` to split large classes by concern.
|
|
- Avoid primary constructors (disabled by editorconfig).
|
|
- Use the `field` keyword (preview feature) for auto-property backing fields
|
|
where it simplifies code — only in editor projects that opt in via
|
|
`<langversion>preview</langversion>`.
|
|
|
|
### Imports
|
|
- `using` directives at the top of each file, before the `namespace` declaration.
|
|
- No blank line between `using` groups (enforced by editorconfig).
|
|
- `System.*` namespaces may appear in any order alongside project namespaces.
|
|
- Prefer specific `using` imports over global usings for clarity in low-level
|
|
performance-critical files.
|
|
|
|
### Error Handling
|
|
- **Return `Result` / `Result<T>` instead of throwing** for expected failures
|
|
(file-not-found, invalid args, etc.).
|
|
`Result.Success()` / `Result.Failure(message)` or `Result.Failure(Error.XXX)`.
|
|
- Use the typed `Error` enum (`Ghost.Core.Error`) for structured error codes.
|
|
- Use `result.ThrowIfFailed()` / `result.GetValueOrThrow()` extension methods at
|
|
call sites that want throw-on-failure semantics.
|
|
- **Throw exceptions** only for programming errors / invariant violations
|
|
(corrupt state, null-ref on internal APIs).
|
|
- In performance-critical paths, guard validation behind `#if DEBUG || GHOST_EDITOR`
|
|
to eliminate overhead in release builds.
|
|
- `Logger.LogError(...)` / `Logger.LogWarning(...)` for non-fatal operational
|
|
issues; do not use `Console.WriteLine` in production library code.
|
|
|
|
### Performance Patterns
|
|
- Annotate hot paths with `[MethodImpl(MethodImplOptions.AggressiveInlining)]`.
|
|
- Annotate log/assert helpers with `[StackTraceHidden]`.
|
|
- Prefer `stackalloc` + `Span<T>` over heap allocation for small temporary arrays.
|
|
- Use the `Misaki.HighPerformance.*` allocation APIs (`AllocationManager`,
|
|
`UnsafeList<T>`, `UnsafeHashMap<T,V>`, etc.) for long-lived unmanaged buffers.
|
|
- All runtime/ECS types must be AOT-compatible and trimmable (set
|
|
`<IsAotCompatible>True</IsAotCompatible>` and `<IsTrimmable>True</IsTrimmable>`
|
|
in Release config).
|
|
- Avoid LINQ in hot paths; use `for` loops or `foreach` over `Span<T>`.
|
|
|
|
### Attributes & Extensibility
|
|
- Custom attributes for editor extension points inherit from
|
|
`DiscoverableAttributeBase` (discovered at startup via `TypeCache`).
|
|
- Use `[UpdateAfter(typeof(X))]` / `[UpdateBefore(typeof(X))]` to declare
|
|
`ISystem` ordering dependencies; `SystemGroup.SortSystems()` topologically sorts
|
|
them at startup.
|
|
- Use `[EditorInjection(ServiceLifetime.Singleton)]` to register editor services
|
|
via DI without manual wiring.
|
|
|
|
### XML Documentation
|
|
- All public API surface should have `<summary>` doc-comments.
|
|
- Use `<remarks>` for non-obvious behavior or threading constraints.
|
|
- Document thread-safety expectations explicitly (see `EntityCommandBuffer` /
|
|
`AssetRegistry` as reference).
|
|
|
|
### Preprocessor Defines
|
|
| Define | Meaning |
|
|
|--------|---------|
|
|
| `DEBUG` | Standard debug build |
|
|
| `GHOST_EDITOR` | Editor build (extra validation, reflection helpers) |
|
|
| `PLATEFORME_WIN64` | Windows 64-bit platform target |
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
src/
|
|
GhostEngine.slnx # Solution
|
|
.editorconfig # Formatting rules
|
|
Runtime/
|
|
Ghost.Core/ # Core types: Result, Handle, Logger, math helpers
|
|
Ghost.Engine/ # Engine entry point & loop
|
|
Ghost.Entities/ # ECS: World, Entity, Component, System
|
|
Ghost.Generator/ # Source generators
|
|
Ghost.Graphics/ # High-level graphics API
|
|
Ghost.Graphics.RHI/ # Render hardware interface abstractions
|
|
Ghost.Graphics.D3D12/ # D3D12 backend
|
|
Editor/
|
|
Ghost.Editor/ # WinUI 3 shell
|
|
Ghost.Editor.Core/ # Editor services, asset registry, inspector
|
|
Ghost.DSL/ # Shader DSL compiler
|
|
Ghost.Data/ # Serialization / project data models
|
|
ThridParty/ # Native binding wrappers (FMOD, MeshOptimizer, Nvtt, Ufbx)
|
|
Test/
|
|
Ghost.Test.Core/ # Shared ITest / TestRunner infrastructure
|
|
Ghost.UnitTest/ # MSTest integration tests
|
|
Ghost.MicroTest/ # Native binding smoke tests (console app)
|
|
Ghost.Entities.Test/ # ECS benchmarks (BenchmarkDotNet, console app)
|
|
Ghost.Shader.Test/ # Shader DSL manual tests (console app)
|
|
Tools/
|
|
Ghost.NativeWrapperGen/ # Code-gen tool for native wrappers
|
|
```
|