refactor: remove QueryDescriptor from ISystem interface

Remove the mandatory Query property from the ISystem interface,
allowing systems to manage their own queries locally or via other
means. Update all implementing systems and tests to use local
query descriptors instead.
This commit is contained in:
hypercross 2026-07-18 22:22:52 +08:00
parent ac7cd80a6f
commit df388ee9b3
7 changed files with 11 additions and 44 deletions

View File

@ -7,13 +7,6 @@ namespace TicTacToe;
/// </summary> /// </summary>
public class RenderSystem : ISystem public class RenderSystem : ISystem
{ {
public QueryDescriptor Query { get; }
public RenderSystem(World world)
{
Query = world.Query().With<Cell>().Build();
}
public void Run(World world) public void Run(World world)
{ {
var state = world.ReadSingleton<GameState>(); var state = world.ReadSingleton<GameState>();
@ -66,4 +59,4 @@ public class RenderSystem : ISystem
Console.WriteLine(); Console.WriteLine();
Console.Write(" Enter row col (e.g. \"1 2\"): "); Console.Write(" Enter row col (e.g. \"1 2\"): ");
} }
} }

View File

@ -8,13 +8,6 @@ namespace TicTacToe;
/// </summary> /// </summary>
public class WinCheckSystem : ISystem public class WinCheckSystem : ISystem
{ {
public QueryDescriptor Query { get; }
public WinCheckSystem(World world)
{
Query = world.Query().With<Cell>().With<Mark>().Build();
}
public void Run(World world) public void Run(World world)
{ {
ref var state = ref world.GetSingleton<GameState>(); ref var state = ref world.GetSingleton<GameState>();
@ -25,7 +18,8 @@ public class WinCheckSystem : ISystem
// Build a 3×3 grid of marks using the iterator API. // Build a 3×3 grid of marks using the iterator API.
var grid = new Player[3, 3]; var grid = new Player[3, 3];
using var iter = world.Select<Cell, Mark>(Query); var query = world.Query().With<Cell>().With<Mark>().Build();
using var iter = world.Select<Cell, Mark>(query);
while (iter.MoveNext()) while (iter.MoveNext())
{ {
grid[iter.Current1.Row, iter.Current1.Col] = iter.Current2.Player; grid[iter.Current1.Row, iter.Current1.Col] = iter.Current2.Player;
@ -87,4 +81,4 @@ public class WinCheckSystem : ISystem
state.Status = winner == Player.X ? GameStatus.XWon : GameStatus.OWon; state.Status = winner == Player.X ? GameStatus.XWon : GameStatus.OWon;
world.MarkModified<GameState>(World.SingletonEntity); world.MarkModified<GameState>(World.SingletonEntity);
} }
} }

View File

@ -2,15 +2,10 @@ namespace OECS;
/// <summary> /// <summary>
/// A system that runs on every tick. /// A system that runs on every tick.
/// Systems declare a query and receive the world in their <see cref="Run"/> method. /// Systems receive the world in their <see cref="Run"/> method.
/// </summary> /// </summary>
public interface ISystem public interface ISystem
{ {
/// <summary>
/// The query that defines which entities this system operates on.
/// </summary>
QueryDescriptor Query { get; }
/// <summary> /// <summary>
/// Executes the system logic for this tick. /// Executes the system logic for this tick.
/// </summary> /// </summary>

View File

@ -249,13 +249,10 @@ public class CommandTests
private readonly World _world; private readonly World _world;
private readonly SpawnCommand _command; private readonly SpawnCommand _command;
public QueryDescriptor Query { get; }
public CommandEnqueueSystem(World world, SpawnCommand command) public CommandEnqueueSystem(World world, SpawnCommand command)
{ {
_world = world; _world = world;
_command = command; _command = command;
Query = world.Query().With<TestPosition>().Build();
} }
public void Run(World world) public void Run(World world)
@ -266,18 +263,17 @@ public class CommandTests
private class EntityCountObserver : ISystem private class EntityCountObserver : ISystem
{ {
private readonly QueryDescriptor _query;
public int SeenCount { get; private set; } public int SeenCount { get; private set; }
public QueryDescriptor Query { get; }
public EntityCountObserver(World world) public EntityCountObserver(World world)
{ {
Query = world.Query().With<TestPosition>().Build(); _query = world.Query().With<TestPosition>().Build();
} }
public void Run(World world) public void Run(World world)
{ {
world.ForEach(Query, (Entity e, ref TestPosition pos) => world.ForEach(_query, (Entity e, ref TestPosition pos) =>
{ {
SeenCount++; SeenCount++;
}); });

View File

@ -175,11 +175,11 @@ public class SystemTests
private class MovementSystem : ITickedSystem private class MovementSystem : ITickedSystem
{ {
public QueryDescriptor Query { get; } private readonly QueryDescriptor _query;
public MovementSystem(World world) public MovementSystem(World world)
{ {
Query = world.Query().With<Position>().With<Velocity>().Build(); _query = world.Query().With<Position>().With<Velocity>().Build();
} }
public void Run(World world) => Run(world, Tick.Logical()); public void Run(World world) => Run(world, Tick.Logical());
@ -187,7 +187,7 @@ public class SystemTests
public void Run(World world, Tick tick) public void Run(World world, Tick tick)
{ {
float dt = tick.DeltaTime; float dt = tick.DeltaTime;
world.ForEach(Query, (Entity entity, ref Position pos, ref Velocity vel) => world.ForEach(_query, (Entity entity, ref Position pos, ref Velocity vel) =>
{ {
pos.X += vel.X * dt; pos.X += vel.X * dt;
pos.Y += vel.Y * dt; pos.Y += vel.Y * dt;
@ -232,13 +232,11 @@ public class SystemTests
private class TestLogicalSystem : ITickedSystem private class TestLogicalSystem : ITickedSystem
{ {
public QueryDescriptor Query { get; }
public bool WasCalled { get; private set; } public bool WasCalled { get; private set; }
public Tick ReceivedTick { get; private set; } public Tick ReceivedTick { get; private set; }
public TestLogicalSystem(World world) public TestLogicalSystem(World world)
{ {
Query = world.Query().With<Position>().Build();
} }
public void Run(World world) => Run(world, Tick.Logical()); public void Run(World world) => Run(world, Tick.Logical());
@ -272,13 +270,10 @@ public class SystemTests
private readonly int _id; private readonly int _id;
private readonly List<int> _order; private readonly List<int> _order;
public QueryDescriptor Query { get; }
public OrderTrackingSystem(World world, int id, List<int> order) public OrderTrackingSystem(World world, int id, List<int> order)
{ {
_id = id; _id = id;
_order = order; _order = order;
Query = world.Query().With<Position>().Build();
} }
public void Run(World world) public void Run(World world)

View File

@ -268,12 +268,9 @@ public class ReactivityTests
{ {
private readonly World _world; private readonly World _world;
public QueryDescriptor Query { get; }
public EntityCreatorSystem(World world) public EntityCreatorSystem(World world)
{ {
_world = world; _world = world;
Query = world.Query().With<Position>().Build();
} }
public void Run(World world) public void Run(World world)

View File

@ -148,12 +148,9 @@ public class SingletonTests
{ {
private readonly World _world; private readonly World _world;
public QueryDescriptor Query { get; }
public TimeSystem(World world) public TimeSystem(World world)
{ {
_world = world; _world = world;
Query = world.Query().With<GameConfig>().Build();
} }
public void Run(World world) => Run(world, Tick.Logical()); public void Run(World world) => Run(world, Tick.Logical());