docs: update API surface documentation

This commit is contained in:
hypercross 2026-07-18 21:59:09 +08:00
parent 32f4aa3e35
commit 58477aec50
1 changed files with 170 additions and 11 deletions

View File

@ -15,8 +15,8 @@ namespace OECS;
public readonly struct Entity : IEquatable<Entity> public readonly struct Entity : IEquatable<Entity>
{ {
public static Entity Null { get; } // ID=0, Version=0 public static Entity Null { get; } // ID=0, Version=0
public uint Id { get; } // 24-bit identifier public uint Id { get; } // lower 24-bit identifier
public uint Version { get; } // 8-bit generation public uint Version { get; } // upper 8-bit generation
public bool IsNull { get; } // true for Entity.Null public bool IsNull { get; } // true for Entity.Null
public bool Equals(Entity other); public bool Equals(Entity other);
@ -37,6 +37,9 @@ namespace OECS;
public class World : IDisposable public class World : IDisposable
{ {
// --- Singleton entity ---
public static Entity SingletonEntity { get; } // ID=1, Version=1
// --- Lifecycle --- // --- Lifecycle ---
public World(); public World();
@ -49,11 +52,14 @@ public class World : IDisposable
public void AddComponent<T>(Entity entity, T component) where T : struct; public void AddComponent<T>(Entity entity, T component) where T : struct;
public void RemoveComponent<T>(Entity entity) where T : struct; public void RemoveComponent<T>(Entity entity) where T : struct;
public ref T GetComponent<T>(Entity entity) where T : struct; public ref T GetComponent<T>(Entity entity) where T : struct;
public T ReadComponent<T>(Entity entity) where T : struct;
public bool TryGetComponent<T>(Entity entity, out T value) where T : struct;
public bool HasComponent<T>(Entity entity) where T : struct; public bool HasComponent<T>(Entity entity) where T : struct;
// --- Singleton --- // --- Singleton ---
public void SetSingleton<T>(T component) where T : struct; public void SetSingleton<T>(T component) where T : struct;
public ref T GetSingleton<T>() where T : struct; public ref T GetSingleton<T>() where T : struct;
public T ReadSingleton<T>() where T : struct;
public bool HasSingleton<T>() where T : struct; public bool HasSingleton<T>() where T : struct;
public void RemoveSingleton<T>() where T : struct; public void RemoveSingleton<T>() where T : struct;
@ -63,12 +69,19 @@ public class World : IDisposable
// --- Query Execution --- // --- Query Execution ---
public void ForEach<T1>( public void ForEach<T1>(
QueryDescriptor query, QueryDescriptor query,
Action<Entity, ref T1> action) where T1 : struct; ForEachAction<T1> action) where T1 : struct;
// Overloads for 26 component types: // Overloads for 26 component types:
public void ForEach<T1, T2>(QueryDescriptor, Action<Entity, ref T1, ref T2>) public void ForEach<T1, T2>(QueryDescriptor, ForEachAction<T1, T2>)
where T1 : struct where T2 : struct; where T1 : struct where T2 : struct;
// ... up to T6 public void ForEach<T1, T2, T3>(QueryDescriptor, ForEachAction<T1, T2, T3>)
where T1 : struct where T2 : struct where T3 : struct;
public void ForEach<T1, T2, T3, T4>(QueryDescriptor, ForEachAction<T1, T2, T3, T4>)
where T1 : struct where T2 : struct where T3 : struct where T4 : struct;
public void ForEach<T1, T2, T3, T4, T5>(QueryDescriptor, ForEachAction<T1, T2, T3, T4, T5>)
where T1 : struct where T2 : struct where T3 : struct where T4 : struct where T5 : struct;
public void ForEach<T1, T2, T3, T4, T5, T6>(QueryDescriptor, ForEachAction<T1, T2, T3, T4, T5, T6>)
where T1 : struct where T2 : struct where T3 : struct where T4 : struct where T5 : struct where T6 : struct;
// --- Commands --- // --- Commands ---
public CommandQueue Commands { get; } public CommandQueue Commands { get; }
@ -78,10 +91,10 @@ public class World : IDisposable
public void MarkModified<T>(Entity entity) where T : struct; public void MarkModified<T>(Entity entity) where T : struct;
public void PostChanges(); public void PostChanges();
public IObservable<EntityChange> ObserveEntityChanges(); public Observable<EntityChange> ObserveEntityChanges();
public IObservable<EntityChange> ObserveComponentChanges<T>() public Observable<EntityChange> ObserveComponentChanges<T>()
where T : struct; where T : struct;
public IObservable<EntityChange> ObserveQuery(QueryDescriptor query); public Observable<EntityChange> ObserveQuery(QueryDescriptor query);
// --- Relationships --- // --- Relationships ---
public IReadOnlyCollection<Entity> GetSources<T>(Entity target) public IReadOnlyCollection<Entity> GetSources<T>(Entity target)
@ -94,6 +107,70 @@ public class World : IDisposable
--- ---
## ForEachAction Delegates
Custom delegate types for query iteration with `ref` parameters. The built-in
`Action<...>` delegates do not support `ref` parameters.
```csharp
namespace OECS;
public delegate void ForEachAction<T1>(Entity entity, ref T1 c1) where T1 : struct;
public delegate void ForEachAction<T1, T2>(Entity entity, ref T1 c1, ref T2 c2)
where T1 : struct where T2 : struct;
public delegate void ForEachAction<T1, T2, T3>(Entity entity, ref T1 c1, ref T2 c2, ref T3 c3)
where T1 : struct where T2 : struct where T3 : struct;
public delegate void ForEachAction<T1, T2, T3, T4>(Entity entity, ref T1 c1, ref T2 c2, ref T3 c3, ref T4 c4)
where T1 : struct where T2 : struct where T3 : struct where T4 : struct;
public delegate void ForEachAction<T1, T2, T3, T4, T5>(Entity entity, ref T1 c1, ref T2 c2, ref T3 c3, ref T4 c4, ref T5 c5)
where T1 : struct where T2 : struct where T3 : struct where T4 : struct where T5 : struct;
public delegate void ForEachAction<T1, T2, T3, T4, T5, T6>(Entity entity, ref T1 c1, ref T2 c2, ref T3 c3, ref T4 c4, ref T5 c5, ref T6 c6)
where T1 : struct where T2 : struct where T3 : struct where T4 : struct where T5 : struct where T6 : struct;
```
---
## EntityIterator
Extension methods on `World` for `foreach`-style iteration over queries.
Returns `ref struct` iterators that support zero-allocation iteration with
`ref` access to components. Supports 13 component types.
```csharp
namespace OECS;
public static class EntityIterator
{
public static Select1<T1> Select<T1>(
this World world, QueryDescriptor query) where T1 : struct;
public static Select2<T1, T2> Select<T1, T2>(
this World world, QueryDescriptor query)
where T1 : struct where T2 : struct;
public static Select3<T1, T2, T3> Select<T1, T2, T3>(
this World world, QueryDescriptor query)
where T1 : struct where T2 : struct where T3 : struct;
}
```
Usage:
```csharp
using var iter = world.Select<Position, Velocity>(query);
foreach (ref var item in iter)
{
item.Current1.X += item.Current2.X * dt;
}
```
---
## QueryBuilder ## QueryBuilder
```csharp ```csharp
@ -180,6 +257,7 @@ namespace OECS;
public class SystemGroup public class SystemGroup
{ {
public SystemGroup(World world);
public void Add(ISystem system); public void Add(ISystem system);
public void Remove(ISystem system); public void Remove(ISystem system);
public void RunTimed(float deltaTime); public void RunTimed(float deltaTime);
@ -212,6 +290,8 @@ public class CommandQueue
{ {
public void Enqueue<T>(T command) where T : struct, ICommand; public void Enqueue<T>(T command) where T : struct, ICommand;
public void ExecuteAll(World world); public void ExecuteAll(World world);
public void Clear();
public void ClearErrors();
public int Count { get; } public int Count { get; }
public IReadOnlyList<Exception> Errors { get; } public IReadOnlyList<Exception> Errors { get; }
} }
@ -233,12 +313,31 @@ public interface IRelationship
--- ---
## Relationship\<TSelf, TTarget\>
A convenience base struct for relationship components. The type parameters are
phantom types that differentiate relationship kinds at the type level, enabling
type-safe queries and reverse lookups.
```csharp
namespace OECS;
[MessagePackObject]
public struct Relationship<TSelf, TTarget> : IRelationship
{
[Key(0)] public Entity Source { get; set; }
[Key(1)] public Entity Target { get; set; }
}
```
---
## EntityChange ## EntityChange
```csharp ```csharp
namespace OECS; namespace OECS;
public readonly struct EntityChange public readonly struct EntityChange : IEquatable<EntityChange>
{ {
public Entity Entity { get; } public Entity Entity { get; }
public ChangeKind Kind { get; } public ChangeKind Kind { get; }
@ -257,6 +356,56 @@ public enum ChangeKind
--- ---
## WorldSerializer
Saves and loads a `World` to/from a MessagePack stream. Components are
serialized by their runtime type.
```csharp
namespace OECS;
public static class WorldSerializer
{
public static void Save(World world, Stream stream);
public static void Load(World world, Stream stream);
}
```
---
## WorldSnapshot / EntitySnapshot / ComponentEntry
Serialization types used by `WorldSerializer`. These are public but intended
primarily for serialization infrastructure.
```csharp
namespace OECS;
[MessagePackObject]
public class WorldSnapshot
{
[Key(0)] public EntitySnapshot[] Entities { get; set; }
}
[MessagePackObject]
public class EntitySnapshot
{
[Key(0)] public uint Id { get; set; }
[Key(1)] public uint Version { get; set; }
[Key(2)] public ComponentEntry[] Components { get; set; }
public Entity Entity { get; }
}
[MessagePackObject]
public class ComponentEntry
{
[Key(0)] public string TypeName { get; set; }
[Key(1)] public byte[] Data { get; set; }
}
```
---
## Usage Example ## Usage Example
```csharp ```csharp
@ -269,13 +418,19 @@ public struct Position : IMessagePackSerializationCallbackReceiver
{ {
[Key(0)] public float X; [Key(0)] public float X;
[Key(1)] public float Y; [Key(1)] public float Y;
public void OnBeforeSerialize() { }
public void OnAfterDeserialize() { }
} }
[MessagePackObject] [MessagePackObject]
public struct Velocity public struct Velocity : IMessagePackSerializationCallbackReceiver
{ {
[Key(0)] public float X; [Key(0)] public float X;
[Key(1)] public float Y; [Key(1)] public float Y;
public void OnBeforeSerialize() { }
public void OnAfterDeserialize() { }
} }
// Define a system // Define a system
@ -291,6 +446,8 @@ public class MovementSystem : ITickedSystem
.Build(); .Build();
} }
public void Run(World world) => Run(world, Tick.Logical());
public void Run(World world, Tick tick) public void Run(World world, Tick tick)
{ {
float dt = tick.DeltaTime; float dt = tick.DeltaTime;
@ -306,7 +463,7 @@ public class MovementSystem : ITickedSystem
// Wire it up // Wire it up
var world = new World(); var world = new World();
var group = new SystemGroup(); var group = new SystemGroup(world);
group.Add(new MovementSystem(world)); group.Add(new MovementSystem(world));
// Observe changes // Observe changes
@ -334,5 +491,7 @@ These types are implementation details and may change without notice:
| `SparseSet<T>` | Dense/sparse array pair for component storage. | | `SparseSet<T>` | Dense/sparse array pair for component storage. |
| `ComponentStore` | Registry of `SparseSet<T>` instances by type. | | `ComponentStore` | Registry of `SparseSet<T>` instances by type. |
| `ChangeBuffer` | Accumulates `EntityChange` during system run, posts to R3 subjects. | | `ChangeBuffer` | Accumulates `EntityChange` during system run, posts to R3 subjects. |
| `ChangeSet` | Deduplicated change accumulator within a single batch. |
| `RelationshipIndex` | Reverse lookup from target entity to source entities. | | `RelationshipIndex` | Reverse lookup from target entity to source entities. |
| `EntityAllocator` | Free-list + bump allocator for entity IDs. | | `EntityAllocator` | Free-list + bump allocator for entity IDs. |
| `QueryExecutor` | Query iteration logic with smallest-set driver optimization. |