@
CI / build-test (push) Failing after 1m8s

Add MrGameEng.AI utility-AI module; format codebase with CSharpier

New MrGameEng.AI module (ResponseCurve, Consideration, UtilityAction,
UtilityAi selector, Blackboard) plus CSharpier formatting applied across
the whole engine. Documents the CSharpier convention in CLAUDE.md.
@
This commit is contained in:
Leonid Pershin
2026-06-12 07:19:10 +03:00
parent 4ae730cafa
commit fd6343bd09
96 changed files with 2066 additions and 589 deletions
+4 -1
View File
@@ -22,7 +22,10 @@ public sealed class EngineContext
/// throws when accessed in a headless context (unit tests).
/// </summary>
public GraphicsDevice GraphicsDevice =>
_graphicsDevice ?? throw new InvalidOperationException("GraphicsDevice is not available (headless context).");
_graphicsDevice
?? throw new InvalidOperationException(
"GraphicsDevice is not available (headless context)."
);
/// <summary>True when a graphics device is attached.</summary>
public bool HasGraphicsDevice => _graphicsDevice is not null;
-2
View File
@@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
@@ -12,5 +11,4 @@
<ItemGroup>
<InternalsVisibleTo Include="MrGameEng.Core.Tests" />
</ItemGroup>
</Project>
+5 -3
View File
@@ -23,7 +23,8 @@ public abstract class Scene
public SystemRoot DrawSystems { get; }
/// <summary>Engine context. Valid from <see cref="OnLoad"/> until <see cref="OnUnload"/>.</summary>
public EngineContext Context => _context ?? throw new InvalidOperationException("Scene is not loaded.");
public EngineContext Context =>
_context ?? throw new InvalidOperationException("Scene is not loaded.");
/// <summary>True while the scene is the active, loaded scene.</summary>
public bool IsLoaded => _context is not null;
@@ -66,8 +67,9 @@ public abstract class Scene
if (_loadedOnce)
{
throw new InvalidOperationException(
$"Scene '{GetType().Name}' was already loaded once. Scene instances are " +
"single-use: create a new instance instead of switching back to an old one.");
$"Scene '{GetType().Name}' was already loaded once. Scene instances are "
+ "single-use: create a new instance instead of switching back to an old one."
);
}
_loadedOnce = true;
+18 -3
View File
@@ -67,7 +67,12 @@ public sealed class SceneManager
break;
case State.CoveringOut:
_coverage = Advance(_coverage, +1f, _transition!.OutDuration, clock.UnscaledDeltaTime);
_coverage = Advance(
_coverage,
+1f,
_transition!.OutDuration,
clock.UnscaledDeltaTime
);
if (_coverage >= 1f)
{
ApplyPending();
@@ -77,7 +82,12 @@ public sealed class SceneManager
break;
case State.RevealingIn:
_coverage = Advance(_coverage, -1f, _transition!.InDuration, clock.UnscaledDeltaTime);
_coverage = Advance(
_coverage,
-1f,
_transition!.InDuration,
clock.UnscaledDeltaTime
);
if (_coverage <= 0f)
{
_state = State.Idle;
@@ -127,7 +137,12 @@ public sealed class SceneManager
Log.Info($"Scene switched to {Current?.GetType().Name ?? "<none>"}");
}
private static float Advance(float coverage, float direction, float duration, float deltaTime) =>
private static float Advance(
float coverage,
float direction,
float duration,
float deltaTime
) =>
duration <= 0f
? coverage + direction
: Math.Clamp(coverage + direction * deltaTime / duration, 0f, 1f);
+17 -6
View File
@@ -9,24 +9,31 @@ public sealed class ServiceRegistry
private readonly Dictionary<Type, object> _services = new();
/// <summary>Registers a service instance under type <typeparamref name="T"/>. Throws if already registered.</summary>
public void Add<T>(T service) where T : class
public void Add<T>(T service)
where T : class
{
if (!_services.TryAdd(typeof(T), service))
{
throw new InvalidOperationException($"Service of type {typeof(T)} is already registered.");
throw new InvalidOperationException(
$"Service of type {typeof(T)} is already registered."
);
}
}
/// <summary>Returns the registered service of type <typeparamref name="T"/>. Throws if missing.</summary>
public T Get<T>() where T : class
public T Get<T>()
where T : class
{
return _services.TryGetValue(typeof(T), out var service)
? (T)service
: throw new InvalidOperationException($"Service of type {typeof(T)} is not registered.");
: throw new InvalidOperationException(
$"Service of type {typeof(T)} is not registered."
);
}
/// <summary>Returns the registered service of type <typeparamref name="T"/> or null.</summary>
public T? GetOrDefault<T>() where T : class
public T? GetOrDefault<T>()
where T : class
{
return _services.TryGetValue(typeof(T), out var service) ? (T)service : null;
}
@@ -41,7 +48,11 @@ public sealed class ServiceRegistry
var disposed = new HashSet<object>(ReferenceEqualityComparer.Instance);
foreach (var service in _services.Values)
{
if (!ReferenceEquals(service, except) && service is IDisposable disposable && disposed.Add(service))
if (
!ReferenceEquals(service, except)
&& service is IDisposable disposable
&& disposed.Add(service)
)
{
disposable.Dispose();
}
+10 -3
View File
@@ -50,14 +50,21 @@ public abstract class Transition
private sealed class FadeTransition(float outDuration, float inDuration, Color color)
: Transition(outDuration, inDuration)
{
public override void Draw(TransitionRenderer renderer, float coverage, TransitionPhase phase) =>
renderer.Fill(0f, 0f, 1f, 1f, color, coverage);
public override void Draw(
TransitionRenderer renderer,
float coverage,
TransitionPhase phase
) => renderer.Fill(0f, 0f, 1f, 1f, color, coverage);
}
private sealed class WipeTransition(float outDuration, float inDuration, Color color)
: Transition(outDuration, inDuration)
{
public override void Draw(TransitionRenderer renderer, float coverage, TransitionPhase phase)
public override void Draw(
TransitionRenderer renderer,
float coverage,
TransitionPhase phase
)
{
// Out: шторка растёт слева направо; In: уезжает дальше вправо.
if (phase == TransitionPhase.Out)