style(coding-style): 统一代码风格并优化文档格式

- 移除多余using语句和空行,统一代码缩进格式
- 优化注释文档中的缩进和对齐格式
- 简化条件语句和方法实现,提升代码可读性
- 重构协程系统相关类的字段和方法定义格式
- 更新架构服务中容器访问方式的实现
- 调整异步操作类的属性和方法组织结构
- [skip ci]
This commit is contained in:
GeWuYou 2026-01-27 20:30:04 +08:00
parent a71c7f6f1a
commit b49079de3e
212 changed files with 2798 additions and 2835 deletions

View File

@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.command;
using GFramework.Core.Abstractions.environment;
using GFramework.Core.Abstractions.events;

View File

@ -1,6 +1,4 @@
using System.Threading.Tasks;
namespace GFramework.Core.Abstractions.architecture;
namespace GFramework.Core.Abstractions.architecture;
/// <summary>
/// 定义异步初始化接口,用于需要异步初始化的组件或服务

View File

@ -1,4 +1,3 @@
using System.Threading.Tasks;
using GFramework.Core.Abstractions.rule;
namespace GFramework.Core.Abstractions.command;

View File

@ -1,5 +1,3 @@
using System.Threading.Tasks;
namespace GFramework.Core.Abstractions.command;
/// <summary>

View File

@ -28,5 +28,5 @@ public enum CoroutineState
/// <summary>
/// 协程已被取消
/// </summary>
Cancelled,
Cancelled
}

View File

@ -1,6 +1,4 @@
using System;
namespace GFramework.Core.Abstractions.events;
namespace GFramework.Core.Abstractions.events;
/// <summary>
/// 事件接口,定义了事件注册的基本功能

View File

@ -1,6 +1,4 @@
using System;
namespace GFramework.Core.Abstractions.events;
namespace GFramework.Core.Abstractions.events;
/// <summary>
/// 事件总线接口,提供事件的发送、注册和注销功能

View File

@ -1,6 +1,4 @@
using System.Collections.Generic;
namespace GFramework.Core.Abstractions.events;
namespace GFramework.Core.Abstractions.events;
/// <summary>
/// 提供统一注销功能的接口,用于管理需要注销的对象列表

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using GFramework.Core.Abstractions.rule;
using GFramework.Core.Abstractions.rule;
using GFramework.Core.Abstractions.system;
namespace GFramework.Core.Abstractions.ioc;

View File

@ -1,6 +1,4 @@
using System;
namespace GFramework.Core.Abstractions.logging;
namespace GFramework.Core.Abstractions.logging;
/// <summary>
/// 定义日志记录接口,提供日志记录和级别检查功能

View File

@ -1,4 +1,3 @@
using System;
using GFramework.Core.Abstractions.events;
namespace GFramework.Core.Abstractions.property;

View File

@ -1,6 +1,4 @@
using System.Threading.Tasks;
namespace GFramework.Core.Abstractions.query;
namespace GFramework.Core.Abstractions.query;
/// <summary>
/// 异步查询接口,定义了执行异步查询操作的方法

View File

@ -1,6 +1,4 @@
using System.Threading.Tasks;
namespace GFramework.Core.Abstractions.query;
namespace GFramework.Core.Abstractions.query;
/// <summary>
/// 异步查询总线接口,用于处理异步查询请求

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using GFramework.Core.Abstractions.bases;
using GFramework.Core.Abstractions.bases;
using GFramework.Game.Abstractions.registry;
namespace GFramework.Core.Abstractions.registries;
@ -35,9 +34,11 @@ public abstract class KeyValueRegistryBase<TKey, TValue>
/// <returns>与键关联的值</returns>
/// <exception cref="KeyNotFoundException">当键不存在时抛出异常</exception>
public virtual TValue Get(TKey key)
=> Map.TryGetValue(key, out var value)
{
return Map.TryGetValue(key, out var value)
? value
: throw new KeyNotFoundException($"{GetType().Name}: key not registered: {key}");
}
/// <summary>
/// 判断是否包含指定的键
@ -45,7 +46,9 @@ public abstract class KeyValueRegistryBase<TKey, TValue>
/// <param name="key">要检查的键</param>
/// <returns>如果包含该键返回true否则返回false</returns>
public virtual bool Contains(TKey key)
=> Map.ContainsKey(key);
{
return Map.ContainsKey(key);
}
/// <summary>
/// 注册键值对到注册表中
@ -65,5 +68,7 @@ public abstract class KeyValueRegistryBase<TKey, TValue>
/// <param name="mapping">包含键值对的映射对象</param>
/// <returns>当前注册表实例,支持链式调用</returns>
public virtual IRegistry<TKey, TValue> Registry(IKeyValue<TKey, TValue> mapping)
=> Registry(mapping.Key, mapping.Value);
{
return Registry(mapping.Key, mapping.Value);
}
}

View File

@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
namespace GFramework.Core.Abstractions.state;
/// <summary>

View File

@ -1,5 +1,4 @@
using System.Threading.Tasks;
using GFramework.Core.Abstractions.utility;
using GFramework.Core.Abstractions.utility;
namespace GFramework.Core.Abstractions.storage;

View File

@ -50,10 +50,8 @@ public class ArchitectureConstantsTests
Assert.That(ArchitectureConstants.PhaseOrder.Length, Is.EqualTo(expectedPhases.Length));
foreach (var expectedPhase in expectedPhases)
{
Assert.That(ArchitectureConstants.PhaseOrder, Does.Contain(expectedPhase));
}
}
/// <summary>
/// 测试PhaseOrder数组是只读的
@ -164,11 +162,9 @@ public class ArchitectureConstantsTests
public void PhaseTransitions_Should_Have_Maximum_One_Transition_Per_Phase()
{
foreach (var transition in ArchitectureConstants.PhaseTransitions)
{
Assert.That(transition.Value, Has.Length.LessThanOrEqualTo(1),
$"Phase {transition.Key} should have at most 1 transition");
}
}
/// <summary>
/// 测试PhaseOrder和PhaseTransitions的一致性
@ -179,7 +175,7 @@ public class ArchitectureConstantsTests
var phaseOrder = ArchitectureConstants.PhaseOrder;
var transitions = ArchitectureConstants.PhaseTransitions;
for (int i = 0; i < phaseOrder.Length - 1; i++)
for (var i = 0; i < phaseOrder.Length - 1; i++)
{
var currentPhase = phaseOrder[i];
var nextPhase = phaseOrder[i + 1];

View File

@ -149,7 +149,7 @@ public class ArchitectureContextTests
[Test]
public void SendCommand_Should_ThrowArgumentNullException_When_Command_IsNull()
{
Assert.That(() => _context!.SendCommand((ICommand)null!),
Assert.That(() => _context!.SendCommand(null!),
Throws.ArgumentNullException.With.Property("ParamName").EqualTo("command"));
}
@ -181,7 +181,7 @@ public class ArchitectureContextTests
[Test]
public void SendEvent_Should_SendEvent_When_EventType_IsValid()
{
bool eventReceived = false;
var eventReceived = false;
_context!.RegisterEvent<TestEventV2>(_ => eventReceived = true);
_context.SendEvent<TestEventV2>();
@ -194,7 +194,7 @@ public class ArchitectureContextTests
[Test]
public void SendEvent_WithInstance_Should_SendEvent_When_EventInstance_IsValid()
{
bool eventReceived = false;
var eventReceived = false;
var testEvent = new TestEventV2();
_context!.RegisterEvent<TestEventV2>(_ => eventReceived = true);
_context.SendEvent(testEvent);
@ -310,8 +310,15 @@ public class TestSystemV2 : ISystem
private IArchitectureContext _context = null!;
public int Id { get; init; }
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
public void Init()
{
@ -331,8 +338,15 @@ public class TestModelV2 : IModel
private IArchitectureContext _context = null!;
public int Id { get; init; }
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
public void Init()
{
@ -352,8 +366,15 @@ public class TestUtilityV2 : IUtility
private IArchitectureContext _context = null!;
public int Id { get; init; }
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
}
public class TestQueryV2 : IQuery<int>
@ -361,9 +382,20 @@ public class TestQueryV2 : IQuery<int>
private IArchitectureContext _context = null!;
public int Result { get; init; }
public int Do() => Result;
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public int Do()
{
return Result;
}
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
}
public class TestCommandV2 : ICommand
@ -371,9 +403,20 @@ public class TestCommandV2 : ICommand
private IArchitectureContext _context = null!;
public bool Executed { get; private set; }
public void Execute() => Executed = true;
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public void Execute()
{
Executed = true;
}
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
}
public class TestCommandWithResultV2 : ICommand<int>
@ -381,9 +424,20 @@ public class TestCommandWithResultV2 : ICommand<int>
private IArchitectureContext _context = null!;
public int Result { get; init; }
public int Execute() => Result;
public void SetContext(IArchitectureContext context) => _context = context;
public IArchitectureContext GetContext() => _context;
public int Execute()
{
return Result;
}
public void SetContext(IArchitectureContext context)
{
_context = context;
}
public IArchitectureContext GetContext()
{
return _context;
}
}
public class TestEventV2

View File

@ -227,10 +227,25 @@ public class TestArchitectureContextV3 : IArchitectureContext
public ICommandBus CommandBus => new CommandBus();
public IQueryBus QueryBus => new QueryBus();
public TService? GetService<TService>() where TService : class => _container.Get<TService>();
public TModel? GetModel<TModel>() where TModel : class, IModel => _container.Get<TModel>();
public TSystem? GetSystem<TSystem>() where TSystem : class, ISystem => _container.Get<TSystem>();
public TUtility? GetUtility<TUtility>() where TUtility : class, IUtility => _container.Get<TUtility>();
public TService? GetService<TService>() where TService : class
{
return _container.Get<TService>();
}
public TModel? GetModel<TModel>() where TModel : class, IModel
{
return _container.Get<TModel>();
}
public TSystem? GetSystem<TSystem>() where TSystem : class, ISystem
{
return _container.Get<TSystem>();
}
public TUtility? GetUtility<TUtility>() where TUtility : class, IUtility
{
return _container.Get<TUtility>();
}
public void SendEvent<TEvent>() where TEvent : new()
{
@ -240,7 +255,10 @@ public class TestArchitectureContextV3 : IArchitectureContext
{
}
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler) => new DefaultUnRegister(() => { });
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler)
{
return new DefaultUnRegister(() => { });
}
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
{
@ -250,7 +268,10 @@ public class TestArchitectureContextV3 : IArchitectureContext
{
}
public TResult SendCommand<TResult>(ICommand<TResult> command) => default!;
public TResult SendCommand<TResult>(ICommand<TResult> command)
{
return default!;
}
public Task SendCommandAsync(IAsyncCommand command)
{
@ -262,11 +283,20 @@ public class TestArchitectureContextV3 : IArchitectureContext
return (Task<TResult>)Task.CompletedTask;
}
public TResult SendQuery<TResult>(IQuery<TResult> query) => default!;
public TResult SendQuery<TResult>(IQuery<TResult> query)
{
return default!;
}
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query) => (Task<TResult>)Task.CompletedTask;
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
{
return (Task<TResult>)Task.CompletedTask;
}
public IEnvironment GetEnvironment() => _environment;
public IEnvironment GetEnvironment()
{
return _environment;
}
}
#endregion

View File

@ -261,28 +261,40 @@ public class TestArchitectureContext : IArchitectureContext
/// </summary>
/// <typeparam name="TService">服务类型</typeparam>
/// <returns>服务实例或null</returns>
public TService? GetService<TService>() where TService : class => _container.Get<TService>();
public TService? GetService<TService>() where TService : class
{
return _container.Get<TService>();
}
/// <summary>
/// 获取指定类型的模型
/// </summary>
/// <typeparam name="TModel">模型类型</typeparam>
/// <returns>模型实例或null</returns>
public TModel? GetModel<TModel>() where TModel : class, IModel => _container.Get<TModel>();
public TModel? GetModel<TModel>() where TModel : class, IModel
{
return _container.Get<TModel>();
}
/// <summary>
/// 获取指定类型的系统
/// </summary>
/// <typeparam name="TSystem">系统类型</typeparam>
/// <returns>系统实例或null</returns>
public TSystem? GetSystem<TSystem>() where TSystem : class, ISystem => _container.Get<TSystem>();
public TSystem? GetSystem<TSystem>() where TSystem : class, ISystem
{
return _container.Get<TSystem>();
}
/// <summary>
/// 获取指定类型的工具
/// </summary>
/// <typeparam name="TUtility">工具类型</typeparam>
/// <returns>工具实例或null</returns>
public TUtility? GetUtility<TUtility>() where TUtility : class, IUtility => _container.Get<TUtility>();
public TUtility? GetUtility<TUtility>() where TUtility : class, IUtility
{
return _container.Get<TUtility>();
}
/// <summary>
/// 发送事件
@ -307,7 +319,10 @@ public class TestArchitectureContext : IArchitectureContext
/// <typeparam name="TEvent">事件类型</typeparam>
/// <param name="handler">事件处理委托</param>
/// <returns>取消注册接口</returns>
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler) => new DefaultUnRegister(() => { });
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler)
{
return new DefaultUnRegister(() => { });
}
/// <summary>
/// 取消注册事件处理器
@ -332,7 +347,10 @@ public class TestArchitectureContext : IArchitectureContext
/// <typeparam name="TResult">返回值类型</typeparam>
/// <param name="command">命令对象</param>
/// <returns>命令执行结果</returns>
public TResult SendCommand<TResult>(ICommand<TResult> command) => default!;
public TResult SendCommand<TResult>(ICommand<TResult> command)
{
return default!;
}
public Task SendCommandAsync(IAsyncCommand command)
{
@ -350,7 +368,10 @@ public class TestArchitectureContext : IArchitectureContext
/// <typeparam name="TResult">查询结果类型</typeparam>
/// <param name="query">查询对象</param>
/// <returns>查询结果</returns>
public TResult SendQuery<TResult>(IQuery<TResult> query) => default!;
public TResult SendQuery<TResult>(IQuery<TResult> query)
{
return default!;
}
/// <summary>
/// 异步发送查询请求
@ -358,11 +379,17 @@ public class TestArchitectureContext : IArchitectureContext
/// <typeparam name="TResult">查询结果类型</typeparam>
/// <param name="query">异步查询对象</param>
/// <returns>查询结果</returns>
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query) => (Task<TResult>)Task.CompletedTask;
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
{
return (Task<TResult>)Task.CompletedTask;
}
/// <summary>
/// 获取环境对象
/// </summary>
/// <returns>环境对象</returns>
public IEnvironment GetEnvironment() => Environment;
public IEnvironment GetEnvironment()
{
return Environment;
}
}

View File

@ -39,10 +39,7 @@ public class CoroutineExtensionsTests
var callCount = 0;
var coroutine = CoroutineExtensions.RepeatEvery(0.1, () => callCount++, 3);
while (coroutine.MoveNext())
{
coroutine.Current.Update(0.1);
}
while (coroutine.MoveNext()) coroutine.Current.Update(0.1);
Assert.That(callCount, Is.EqualTo(3));
}
@ -102,10 +99,7 @@ public class CoroutineExtensionsTests
Assert.DoesNotThrow(() =>
{
while (coroutine.MoveNext())
{
coroutine.Current.Update(0.1);
}
while (coroutine.MoveNext()) coroutine.Current.Update(0.1);
});
}
@ -212,10 +206,7 @@ public class CoroutineExtensionsTests
var sequence = CoroutineExtensions.Sequence(coroutine1, coroutine2, coroutine3);
while (sequence.MoveNext())
{
sequence.Current.Update(0.1);
}
while (sequence.MoveNext()) sequence.Current.Update(0.1);
Assert.That(executionOrder, Is.EqualTo(new List<int> { 1, 2, 3 }));
}
@ -254,10 +245,7 @@ public class CoroutineExtensionsTests
Assert.Throws<NullReferenceException>(() =>
{
while (sequence.MoveNext())
{
sequence.Current.Update(0.1);
}
while (sequence.MoveNext()) sequence.Current.Update(0.1);
});
}
@ -268,7 +256,7 @@ public class CoroutineExtensionsTests
public void ParallelCoroutines_Should_Return_Valid_Coroutine()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine1 = CreateSimpleCoroutine();
var coroutine2 = CreateSimpleCoroutine();
@ -284,7 +272,7 @@ public class CoroutineExtensionsTests
public void ParallelCoroutines_Should_Execute_Coroutines_In_Parallel()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var executionCounts = new Dictionary<int, int> { { 1, 0 }, { 2, 0 }, { 3, 0 } };
var coroutine1 = CreateDelayedCoroutine(() => executionCounts[1]++, 0.5);
@ -297,10 +285,7 @@ public class CoroutineExtensionsTests
Assert.That(scheduler.ActiveCoroutineCount, Is.GreaterThan(0));
while (scheduler.ActiveCoroutineCount > 0)
{
scheduler.Update();
}
while (scheduler.ActiveCoroutineCount > 0) scheduler.Update();
Assert.That(executionCounts[1], Is.EqualTo(1));
Assert.That(executionCounts[2], Is.EqualTo(1));
@ -314,7 +299,7 @@ public class CoroutineExtensionsTests
public void ParallelCoroutines_Should_Handle_Empty_Array()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var parallel = scheduler.ParallelCoroutines();
@ -328,7 +313,7 @@ public class CoroutineExtensionsTests
public void ParallelCoroutines_Should_Handle_Null_Array()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var parallel = scheduler.ParallelCoroutines(null);
@ -374,10 +359,7 @@ public class CoroutineExtensionsTests
coroutine.MoveNext();
while (!coroutine.Current.IsDone)
{
coroutine.Current.Update(0.1);
}
while (!coroutine.Current.IsDone) coroutine.Current.Update(0.1);
Assert.That(progressValues.Count, Is.GreaterThan(0));
Assert.That(progressValues[0], Is.EqualTo(0.0f).Within(0.01f));
@ -461,10 +443,7 @@ public class CoroutineExtensionsTests
var sequence = CoroutineExtensions.Sequence(coroutine1, coroutine2);
while (sequence.MoveNext())
{
sequence.Current.Update(0.1);
}
while (sequence.MoveNext()) sequence.Current.Update(0.1);
Assert.That(sequence.MoveNext(), Is.False);
}

View File

@ -207,15 +207,9 @@ public class CoroutineHandleTests
public void Multiple_Creates_Should_Increment_Keys()
{
var handles = new List<CoroutineHandle>();
for (var i = 0; i < 5; i++)
{
handles.Add(new CoroutineHandle(1));
}
for (var i = 0; i < 5; i++) handles.Add(new CoroutineHandle(1));
for (var i = 0; i < handles.Count - 1; i++)
{
Assert.That(handles[i].Equals(handles[i + 1]), Is.False);
}
for (var i = 0; i < handles.Count - 1; i++) Assert.That(handles[i].Equals(handles[i + 1]), Is.False);
}
/// <summary>

View File

@ -219,10 +219,7 @@ public class CoroutineHelperTests
var callCount = 0;
var coroutine = CoroutineHelper.RepeatCall(0.1, 3, () => callCount++);
while (coroutine.MoveNext())
{
coroutine.Current.Update(0.1);
}
while (coroutine.MoveNext()) coroutine.Current.Update(0.1);
Assert.That(callCount, Is.EqualTo(3));
}

View File

@ -31,7 +31,7 @@ public class CoroutineSchedulerTests
public void SetUp()
{
_timeSource = new TestTimeSource();
_scheduler = new CoroutineScheduler(_timeSource, instanceId: 1, initialCapacity: 4);
_scheduler = new CoroutineScheduler(_timeSource, 1, 4);
}
/// <summary>
@ -327,15 +327,9 @@ public class CoroutineSchedulerTests
public void Scheduler_Should_Expand_Capacity_When_Slots_Full()
{
var coroutines = new List<IEnumerator<IYieldInstruction>>();
for (var i = 0; i < 10; i++)
{
coroutines.Add(CreateYieldingCoroutine(new Delay(1.0)));
}
for (var i = 0; i < 10; i++) coroutines.Add(CreateYieldingCoroutine(new Delay(1.0)));
foreach (var coroutine in coroutines)
{
_scheduler.Run(coroutine);
}
foreach (var coroutine in coroutines) _scheduler.Run(coroutine);
Assert.That(_scheduler.ActiveCoroutineCount, Is.EqualTo(10));
}

View File

@ -34,7 +34,7 @@ public class TaskCoroutineExtensionsTests
public void AsCoroutineInstructionOfT_Should_Return_WaitForTaskOfT()
{
var task = Task.FromResult(42);
var instruction = task.AsCoroutineInstruction<int>();
var instruction = task.AsCoroutineInstruction();
Assert.That(instruction, Is.InstanceOf<WaitForTask<int>>());
}
@ -64,7 +64,7 @@ public class TaskCoroutineExtensionsTests
public void AsCoroutineInstructionOfT_Should_Access_Task_Result()
{
var task = Task.FromResult(42);
var instruction = task.AsCoroutineInstruction<int>();
var instruction = task.AsCoroutineInstruction();
task.Wait();
@ -90,7 +90,7 @@ public class TaskCoroutineExtensionsTests
{
Task<int> task = null!;
Assert.Throws<ArgumentNullException>(() => task.AsCoroutineInstruction<int>());
Assert.Throws<ArgumentNullException>(() => task.AsCoroutineInstruction());
}
/// <summary>
@ -112,7 +112,7 @@ public class TaskCoroutineExtensionsTests
public void AsCoroutineInstructionOfT_Should_Handle_Faulted_Task()
{
var task = Task.FromException<int>(new InvalidOperationException("Test exception"));
var instruction = task.AsCoroutineInstruction<int>();
var instruction = task.AsCoroutineInstruction();
Assert.That(instruction, Is.InstanceOf<WaitForTask<int>>());
}
@ -124,7 +124,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutine_Should_Return_Valid_Handle()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var task = Task.CompletedTask;
var handle = scheduler.StartTaskAsCoroutine(task);
@ -139,7 +139,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutineOfT_Should_Return_Valid_Handle()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var task = Task.FromResult(42);
var handle = scheduler.StartTaskAsCoroutine(task);
@ -154,7 +154,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutine_Should_Wait_For_Task_Completion()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var completed = false;
var tcs = new TaskCompletionSource<object?>();
@ -180,7 +180,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutineOfT_Should_Wait_For_Task_Completion()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var tcs = new TaskCompletionSource<int>();
@ -204,7 +204,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutine_Should_Handle_Completed_Task()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var task = Task.CompletedTask;
scheduler.StartTaskAsCoroutine(task);
@ -221,7 +221,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutine_Should_Handle_Faulted_Task()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var task = Task.FromException(new InvalidOperationException("Test"));
scheduler.StartTaskAsCoroutine(task);
@ -236,7 +236,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutineOfT_Should_Handle_Faulted_Task()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var task = Task.FromException<int>(new InvalidOperationException("Test"));
scheduler.StartTaskAsCoroutine(task);
@ -252,7 +252,7 @@ public class TaskCoroutineExtensionsTests
public void StartTaskAsCoroutine_Should_Work_With_Scheduler()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource);
var tcs = new TaskCompletionSource<object?>();
scheduler.StartTaskAsCoroutine(tcs.Task);

View File

@ -26,7 +26,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Not_Be_Done_Initially_With_Running_Coroutines()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine1 = CreateDelayedCoroutine(() => { }, 1.0);
var coroutine2 = CreateDelayedCoroutine(() => { }, 1.0);
@ -48,7 +48,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Be_Done_When_All_Coroutines_Complete()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine1 = CreateSimpleCoroutine();
var coroutine2 = CreateSimpleCoroutine();
@ -73,7 +73,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Wait_For_All_Delayed_Coroutines()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var executionCount = 0;
var coroutine1 = CreateDelayedCoroutine(() => executionCount++, 1.0);
@ -92,10 +92,7 @@ public class WaitForAllCoroutinesTests
Assert.That(wait.IsDone, Is.False);
Assert.That(executionCount, Is.EqualTo(0));
for (var i = 0; i < 12; i++)
{
scheduler.Update();
}
for (var i = 0; i < 12; i++) scheduler.Update();
Assert.That(wait.IsDone, Is.True);
Assert.That(executionCount, Is.EqualTo(3));
@ -108,7 +105,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Empty_Handles_List()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var handles = Array.Empty<CoroutineHandle>();
var wait = new WaitForAllCoroutines(scheduler, handles);
@ -123,7 +120,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Handles_Is_Null()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
Assert.Throws<ArgumentNullException>(() => new WaitForAllCoroutines(scheduler, null!));
}
@ -146,7 +143,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Single_Coroutine()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine = CreateSimpleCoroutine();
var handles = new List<CoroutineHandle> { scheduler.Run(coroutine) };
@ -165,7 +162,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Not_Be_Done_When_Some_Coroutines_Complete()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var executionCount = 0;
var coroutine1 = CreateSimpleCoroutine();
@ -194,7 +191,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Killed_Coroutines()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine1 = CreateDelayedCoroutine(() => { }, 1.0);
var coroutine2 = CreateDelayedCoroutine(() => { }, 1.0);
@ -225,7 +222,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Paused_And_Resumed_Coroutines()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var executionCount = 0;
var coroutine1 = CreateDelayedCoroutine(() => executionCount++, 1.0);
@ -241,20 +238,14 @@ public class WaitForAllCoroutinesTests
scheduler.Pause(handles[0]);
for (var i = 0; i < 12; i++)
{
scheduler.Update();
}
for (var i = 0; i < 12; i++) scheduler.Update();
Assert.That(wait.IsDone, Is.False);
Assert.That(executionCount, Is.EqualTo(1));
scheduler.Resume(handles[0]);
for (var i = 0; i < 12; i++)
{
scheduler.Update();
}
for (var i = 0; i < 12; i++) scheduler.Update();
Assert.That(wait.IsDone, Is.True);
Assert.That(executionCount, Is.EqualTo(2));
@ -267,7 +258,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Update_Should_Not_Affect_State()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine = CreateDelayedCoroutine(() => { }, 1.0);
var handles = new List<CoroutineHandle> { scheduler.Run(coroutine) };
@ -287,7 +278,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Invalid_Handles()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var handles = new List<CoroutineHandle> { default };
@ -303,7 +294,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Mixed_Valid_And_Invalid_Handles()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine = CreateSimpleCoroutine();
var handles = new List<CoroutineHandle>
@ -326,23 +317,17 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Many_Coroutines()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var executionCount = 0;
var handles = new List<CoroutineHandle>();
for (var i = 0; i < 20; i++)
{
handles.Add(scheduler.Run(CreateDelayedCoroutine(() => executionCount++, 1.0)));
}
for (var i = 0; i < 20; i++) handles.Add(scheduler.Run(CreateDelayedCoroutine(() => executionCount++, 1.0)));
var wait = new WaitForAllCoroutines(scheduler, handles);
Assert.That(wait.IsDone, Is.False);
for (var i = 0; i < 120; i++)
{
scheduler.Update();
}
for (var i = 0; i < 120; i++) scheduler.Update();
Assert.That(wait.IsDone, Is.True);
Assert.That(executionCount, Is.EqualTo(20));
@ -355,7 +340,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Coroutines_With_Exceptions()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine1 = CreateSimpleCoroutine();
var coroutine2 = CreateExceptionCoroutine();
@ -382,7 +367,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Work_With_ParallelCoroutines()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var executionOrder = new List<int>();
var coroutine1 = CreateDelayedCoroutine(() => executionOrder.Add(1), 0.5);
@ -412,7 +397,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Implement_IYieldInstruction()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var handles = Array.Empty<CoroutineHandle>();
var wait = new WaitForAllCoroutines(scheduler, handles);
@ -427,7 +412,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Be_Done_Immediately_When_All_Coroutines_Complete_Immediately()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine1 = CreateSimpleCoroutine();
var coroutine2 = CreateSimpleCoroutine();
@ -453,7 +438,7 @@ public class WaitForAllCoroutinesTests
public void WaitForAllCoroutines_Should_Handle_Duplicate_Handles()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource, instanceId: 1);
var scheduler = new CoroutineScheduler(timeSource, 1);
var coroutine = CreateDelayedCoroutine(() => { }, 1.0);
var handle = scheduler.Run(coroutine);
@ -461,10 +446,7 @@ public class WaitForAllCoroutinesTests
var wait = new WaitForAllCoroutines(scheduler, handles);
for (var i = 0; i < 12; i++)
{
scheduler.Update();
}
for (var i = 0; i < 12; i++) scheduler.Update();
Assert.That(wait.IsDone, Is.True);
}

View File

@ -66,10 +66,7 @@ public class WaitForProgressTests
var progressValues = new List<float>();
var wait = new WaitForProgress(1.0, progressValues.Add);
while (!wait.IsDone)
{
wait.Update(0.1);
}
while (!wait.IsDone) wait.Update(0.1);
foreach (var progress in progressValues)
{
@ -207,10 +204,7 @@ public class WaitForProgressTests
var progressValues = new List<float>();
var wait = new WaitForProgress(1.0, progressValues.Add);
while (!wait.IsDone)
{
wait.Update(0.1);
}
while (!wait.IsDone) wait.Update(0.1);
Assert.That(progressValues[^1], Is.EqualTo(1.0f).Within(0.01f));
}

View File

@ -8,7 +8,9 @@ namespace GFramework.Core.Tests.coroutine;
/// WaitForTask的单元测试类
/// 测试内容包括:
/// - WaitForTask初始化和等待
/// - WaitForTask<T>初始化、等待和结果获取
/// - WaitForTask
/// <T>
/// 初始化、等待和结果获取
/// - 异常处理
/// - 边界条件
/// </summary>
@ -185,7 +187,10 @@ public class WaitForTaskTests
Assert.That(wait.IsDone, Is.True);
Assert.Throws<InvalidOperationException>(() => { var _ = wait.Result; });
Assert.Throws<InvalidOperationException>(() =>
{
var _ = wait.Result;
});
}
/// <summary>

View File

@ -271,10 +271,7 @@ public class YieldInstructionTests
Assert.That(wait.IsDone, Is.False);
for (var i = 0; i < 10; i++)
{
Assert.That(wait.IsDone, Is.False);
}
for (var i = 0; i < 10; i++) Assert.That(wait.IsDone, Is.False);
continueWaiting = false;
Assert.That(wait.IsDone, Is.True);

View File

@ -56,7 +56,7 @@ public class UnRegisterTests
[Test]
public void BindablePropertyUnRegister_Should_UnRegister_From_Property()
{
var property = new BindableProperty<int>(0);
var property = new BindableProperty<int>();
var callCount = 0;
Action<int> handler = _ => { callCount++; };
@ -76,7 +76,7 @@ public class UnRegisterTests
[Test]
public void BindablePropertyUnRegister_Should_Clear_References()
{
var property = new BindableProperty<int>(0);
var property = new BindableProperty<int>();
Action<int> handler = _ => { };
var unRegister = new BindablePropertyUnRegister<int>(property, handler);
@ -106,7 +106,7 @@ public class UnRegisterTests
[Test]
public void BindablePropertyUnRegister_WithNull_Handler_Should_NotThrow()
{
var property = new BindableProperty<int>(0);
var property = new BindableProperty<int>();
var unRegister = new BindablePropertyUnRegister<int>(property, null!);
Assert.DoesNotThrow(() => unRegister.UnRegister());

View File

@ -18,7 +18,7 @@ public class LoggerFactoryTests
public void ConsoleLoggerFactory_GetLogger_ShouldReturnConsoleLogger()
{
var factory = new ConsoleLoggerFactory();
var logger = factory.GetLogger("TestLogger", LogLevel.Info);
var logger = factory.GetLogger("TestLogger");
Assert.That(logger, Is.Not.Null);
Assert.That(logger, Is.InstanceOf<ConsoleLogger>());
@ -228,7 +228,7 @@ public class LoggerFactoryTests
public void ConsoleLoggerFactory_MultipleLoggers_ShouldBeIndependent()
{
var factory = new ConsoleLoggerFactory();
var logger1 = factory.GetLogger("Logger1", LogLevel.Info);
var logger1 = factory.GetLogger("Logger1");
var logger2 = factory.GetLogger("Logger2", LogLevel.Debug);
Assert.That(logger1.Name(), Is.EqualTo("Logger1"));

View File

@ -17,7 +17,7 @@ public class LoggerTests
[SetUp]
public void SetUp()
{
_logger = new TestLogger("TestLogger", LogLevel.Info);
_logger = new TestLogger("TestLogger");
}
private TestLogger _logger = null!;

View File

@ -159,7 +159,7 @@ public class StateMachineSystemTests
public void ChangeTo_Should_Send_StateChangedEvent()
{
// 订阅StateChangedEvent事件以验证事件是否被正确发送
bool eventReceived = false;
var eventReceived = false;
StateChangedEvent? receivedEvent = null;
_eventBus!.Register<StateChangedEvent>(e =>
@ -191,7 +191,7 @@ public class StateMachineSystemTests
public void ChangeTo_Should_Send_StateChangedEvent_With_OldState()
{
// 订阅StateChangedEvent事件以验证事件是否被正确发送
bool eventReceived = false;
var eventReceived = false;
StateChangedEvent? receivedEvent = null;
_eventBus!.Register<StateChangedEvent>(e =>
@ -283,7 +283,10 @@ public class TestStateMachineSystemV5 : StateMachineSystem
/// 获取状态机内部的状态字典
/// </summary>
/// <returns>类型到状态实例的映射字典</returns>
public Dictionary<Type, IState> GetStates() => States;
public Dictionary<Type, IState> GetStates()
{
return States;
}
}
/// <summary>
@ -345,7 +348,10 @@ public class TestStateV5 : IState
/// </summary>
/// <param name="next">目标状态</param>
/// <returns>始终返回true表示允许转换</returns>
public bool CanTransitionTo(IState next) => true;
public bool CanTransitionTo(IState next)
{
return true;
}
/// <summary>
/// 进入状态时调用

View File

@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.architecture;
using GFramework.Core.Abstractions.enums;
using GFramework.Core.Abstractions.environment;
@ -86,9 +82,11 @@ public abstract class Architecture(
#endregion
#region Fields
private readonly TaskCompletionSource _readyTcs = new(TaskCreationOptions.RunContinuationsAsynchronously);
public bool IsReady => CurrentPhase == ArchitecturePhase.Ready;
/// <summary>
/// 待初始化组件的去重集合
/// </summary>
@ -336,14 +334,10 @@ public abstract class Architecture(
private static async Task InitializeComponentAsync(IInitializable component, bool asyncMode)
{
if (asyncMode && component is IAsyncInitializable asyncInit)
{
await asyncInit.InitializeAsync();
}
else
{
component.Init();
}
}
/// <summary>
/// 抽象初始化方法,由子类重写以进行自定义初始化操作
@ -568,5 +562,6 @@ public abstract class Architecture(
{
return IsReady ? Task.CompletedTask : _readyTcs.Task;
}
#endregion
}

View File

@ -26,8 +26,6 @@ public class ArchitectureServices : IArchitectureServices
/// </summary>
private readonly ICommandBus _commandBus;
private readonly IIocContainer _container;
/// <summary>
/// 事件总线实例
/// </summary>
@ -45,7 +43,7 @@ public class ArchitectureServices : IArchitectureServices
/// </summary>
public ArchitectureServices()
{
_container = new IocContainer();
Container = new IocContainer();
// 创建服务实例
_eventBus = new EventBus();
@ -54,16 +52,16 @@ public class ArchitectureServices : IArchitectureServices
_asyncQueryBus = new AsyncQueryBus();
// 将服务注册到容器
_container.RegisterPlurality(_eventBus);
_container.RegisterPlurality(_commandBus);
_container.RegisterPlurality(_queryBus);
_container.RegisterPlurality(_asyncQueryBus);
Container.RegisterPlurality(_eventBus);
Container.RegisterPlurality(_commandBus);
Container.RegisterPlurality(_queryBus);
Container.RegisterPlurality(_asyncQueryBus);
}
/// <summary>
/// 获取依赖注入容器
/// </summary>
public IIocContainer Container => _container;
public IIocContainer Container { get; }
/// <summary>
/// 获取类型事件系统

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Concurrent;
using GFramework.Core.Abstractions.architecture;
namespace GFramework.Core.architecture;

View File

@ -161,6 +161,7 @@ public class GameArchitecture : Architecture
RegisterUtility(new StorageUtility());
RegisterUtility(new TimeUtility());
}
}
// 2. 创建并初始化架构
@ -202,7 +203,9 @@ public class GameController : IController
{
// 处理玩家死亡事件
}
}
```
**核心方法与属性:**
@ -244,6 +247,7 @@ await architecture.InitializeAsync(); // 异步等待初始化完成
```
**优势:**
- 支持异步初始化 Model 和 System
- 可以利用异步 I/O 操作(如异步加载数据)
- 提高初始化性能
@ -259,6 +263,7 @@ public void InstallModule(IArchitectureModule module)
```
**参数:**
- `module`:要安装的模块实例
**使用示例:**
@ -291,6 +296,7 @@ public void RegisterLifecycleHook(IArchitectureLifecycle hook)
```
**参数:**
- `hook`:生命周期钩子实例
**使用示例:**
@ -411,6 +417,7 @@ public class LifecycleHook : IArchitectureLifecycle
GD.Print($"架构阶段变化: {phase}");
}
}
```
### [`ArchitectureConfiguration`](ArchitectureConfiguration.cs)

View File

@ -61,20 +61,29 @@ public readonly struct CoroutineHandle : IEquatable<CoroutineHandle>
/// </summary>
/// <param name="other">要比较的协程句柄</param>
/// <returns>如果两个句柄的ID相同则返回true否则返回false</returns>
public bool Equals(CoroutineHandle other) => _id == other._id;
public bool Equals(CoroutineHandle other)
{
return _id == other._id;
}
/// <summary>
/// 比较当前对象与指定对象是否相等
/// </summary>
/// <param name="obj">要比较的对象</param>
/// <returns>如果对象是协程句柄且ID相同则返回true否则返回false</returns>
public override bool Equals(object? obj) => obj is CoroutineHandle handle && Equals(handle);
public override bool Equals(object? obj)
{
return obj is CoroutineHandle handle && Equals(handle);
}
/// <summary>
/// 获取当前协程句柄的哈希码
/// </summary>
/// <returns>基于内部ID计算的哈希码</returns>
public override int GetHashCode() => _id;
public override int GetHashCode()
{
return _id;
}
/// <summary>
/// 比较两个协程句柄是否相等
@ -82,7 +91,10 @@ public readonly struct CoroutineHandle : IEquatable<CoroutineHandle>
/// <param name="a">第一个协程句柄</param>
/// <param name="b">第二个协程句柄</param>
/// <returns>如果两个句柄的ID相同则返回true否则返回false</returns>
public static bool operator ==(CoroutineHandle a, CoroutineHandle b) => a._id == b._id;
public static bool operator ==(CoroutineHandle a, CoroutineHandle b)
{
return a._id == b._id;
}
/// <summary>
/// 比较两个协程句柄是否不相等
@ -90,5 +102,8 @@ public readonly struct CoroutineHandle : IEquatable<CoroutineHandle>
/// <param name="a">第一个协程句柄</param>
/// <param name="b">第二个协程句柄</param>
/// <returns>如果两个句柄的ID不同则返回true否则返回false</returns>
public static bool operator !=(CoroutineHandle a, CoroutineHandle b) => a._id != b._id;
public static bool operator !=(CoroutineHandle a, CoroutineHandle b)
{
return a._id != b._id;
}
}

View File

@ -1,4 +1,3 @@
using System.Threading;
using GFramework.Core.Abstractions.coroutine;
using GFramework.Core.coroutine.instructions;

View File

@ -17,7 +17,6 @@ public sealed class CoroutineScheduler(
private readonly Dictionary<string, HashSet<CoroutineHandle>> _tagged = new();
private readonly ITimeSource _timeSource = timeSource ?? throw new ArgumentNullException(nameof(timeSource));
private readonly Dictionary<CoroutineHandle, HashSet<CoroutineHandle>> _waiting = new();
private int _activeCount;
private int _nextSlot;
private CoroutineSlot?[] _slots = new CoroutineSlot?[initialCapacity];
@ -30,7 +29,12 @@ public sealed class CoroutineScheduler(
/// <summary>
/// 获取活跃协程数量
/// </summary>
public int ActiveCoroutineCount => _activeCount;
public int ActiveCoroutineCount { get; private set; }
public bool IsCoroutineAlive(CoroutineHandle handle)
{
return _metadata.ContainsKey(handle);
}
#region Run / Update
@ -72,7 +76,7 @@ public sealed class CoroutineScheduler(
AddTag(tag, handle);
Prewarm(slotIndex);
_activeCount++;
ActiveCoroutineCount++;
return handle;
}
@ -106,14 +110,10 @@ public sealed class CoroutineScheduler(
// 2⃣ 推进协程
if (!slot.Enumerator.MoveNext())
{
Complete(i);
}
else
{
slot.Waiting = slot.Enumerator.Current;
}
}
catch (Exception ex)
{
OnError(i, ex);
@ -234,7 +234,7 @@ public sealed class CoroutineScheduler(
/// <returns>被清除的协程数量</returns>
public int Clear()
{
var count = _activeCount;
var count = ActiveCoroutineCount;
Array.Clear(_slots);
_metadata.Clear();
@ -242,7 +242,7 @@ public sealed class CoroutineScheduler(
_waiting.Clear();
_nextSlot = 0;
_activeCount = 0;
ActiveCoroutineCount = 0;
return count;
}
@ -264,14 +264,10 @@ public sealed class CoroutineScheduler(
try
{
if (!slot.Enumerator.MoveNext())
{
Complete(slotIndex);
}
else
{
slot.Waiting = slot.Enumerator.Current;
}
}
catch (Exception ex)
{
OnError(slotIndex, ex);
@ -293,7 +289,7 @@ public sealed class CoroutineScheduler(
return;
_slots[slotIndex] = null;
_activeCount--;
ActiveCoroutineCount--;
RemoveTag(handle);
_metadata.Remove(handle);
@ -368,8 +364,4 @@ public sealed class CoroutineScheduler(
}
#endregion
public bool IsCoroutineAlive(CoroutineHandle handle)
{
return _metadata.ContainsKey(handle);
}
}

View File

@ -12,6 +12,11 @@ internal sealed class CoroutineSlot
/// </summary>
public required IEnumerator<IYieldInstruction> Enumerator;
/// <summary>
/// 协程句柄,用于标识和管理协程实例
/// </summary>
public CoroutineHandle Handle;
/// <summary>
/// 协程当前状态
/// </summary>
@ -21,9 +26,4 @@ internal sealed class CoroutineSlot
/// 当前等待的指令,用于控制协程的暂停和恢复
/// </summary>
public IYieldInstruction? Waiting;
/// <summary>
/// 协程句柄,用于标识和管理协程实例
/// </summary>
public CoroutineHandle Handle;
}

View File

@ -20,10 +20,7 @@ public static class CoroutineExtensions
Action action,
int? count = null)
{
if (count is < 0)
{
yield break;
}
if (count is < 0) yield break;
var executedCount = 0;
while (count == null || executedCount < count)
@ -44,10 +41,7 @@ public static class CoroutineExtensions
double delay,
Action? action)
{
if (delay < 0)
{
yield break;
}
if (delay < 0) yield break;
yield return new Delay(delay);
action?.Invoke();
@ -63,10 +57,7 @@ public static class CoroutineExtensions
{
foreach (var coroutine in coroutines)
{
while (coroutine.MoveNext())
{
yield return coroutine.Current;
}
while (coroutine.MoveNext()) yield return coroutine.Current;
// 清理协程
coroutine.Dispose();
@ -84,10 +75,7 @@ public static class CoroutineExtensions
this CoroutineScheduler scheduler,
params IEnumerator<IYieldInstruction>[]? coroutines)
{
if (coroutines == null || coroutines.Length == 0)
{
yield break;
}
if (coroutines == null || coroutines.Length == 0) yield break;
// 启动所有协程并收集句柄
var handles = new List<CoroutineHandle>();
@ -120,12 +108,8 @@ public static class CoroutineExtensions
onProgress?.Invoke(0.0f);
if (onProgress != null)
{
yield return new WaitForProgress(totalTime, onProgress);
}
else
{
yield return new Delay(totalTime);
}
}
}

View File

@ -1,5 +1,4 @@
using System.Runtime.CompilerServices;
using System.Threading;
using GFramework.Core.Abstractions.coroutine;
namespace GFramework.Core.coroutine.instructions;
@ -13,16 +12,51 @@ public class AsyncOperation : IYieldInstruction, INotifyCompletion
private volatile bool _completed;
private volatile Action? _continuation;
/// <summary>
/// 获取异步操作是否已完成
/// </summary>
public bool IsDone => _completed;
/// <summary>
/// 获取异步操作的任务
/// </summary>
public Task Task => _tcs.Task;
/// <summary>
/// 检查是否已完成
/// </summary>
public bool IsCompleted => _completed;
/// <summary>
/// 设置延续操作
/// </summary>
/// <param name="continuation">要执行的延续操作</param>
public void OnCompleted(Action continuation)
{
// 尝试添加延续
var current = _continuation;
var newContinuation = current == null ? continuation : current + continuation;
if (Interlocked.CompareExchange(ref _continuation, newContinuation, current) != current)
{
// 如果CAS失败说明可能已经完成直接执行
if (_completed)
continuation();
else
// 重试
OnCompleted(continuation);
return;
}
// 双重检查:如果在设置延续后发现已完成,需要执行延续
if (_completed)
{
var cont = Interlocked.Exchange(ref _continuation, null);
if (cont != null) cont();
}
}
/// <summary>
/// 获取异步操作是否已完成
/// </summary>
public bool IsDone => _completed;
/// <summary>
/// 更新方法,用于处理时间更新逻辑
/// </summary>
@ -44,7 +78,6 @@ public class AsyncOperation : IYieldInstruction, INotifyCompletion
var continuation = Interlocked.Exchange(ref _continuation, null);
if (continuation != null)
{
try
{
continuation.Invoke();
@ -54,7 +87,6 @@ public class AsyncOperation : IYieldInstruction, INotifyCompletion
// 忽略延续中的异常
}
}
}
/// <summary>
/// 标记异步操作因异常而失败
@ -69,7 +101,6 @@ public class AsyncOperation : IYieldInstruction, INotifyCompletion
var continuation = Interlocked.Exchange(ref _continuation, null);
if (continuation != null)
{
try
{
continuation.Invoke();
@ -79,44 +110,6 @@ public class AsyncOperation : IYieldInstruction, INotifyCompletion
// 忽略延续中的异常
}
}
}
/// <summary>
/// 设置延续操作
/// </summary>
/// <param name="continuation">要执行的延续操作</param>
public void OnCompleted(Action continuation)
{
// 尝试添加延续
var current = _continuation;
var newContinuation = current == null ? continuation : current + continuation;
if (Interlocked.CompareExchange(ref _continuation, newContinuation, current) != current)
{
// 如果CAS失败说明可能已经完成直接执行
if (_completed)
{
continuation();
}
else
{
// 重试
OnCompleted(continuation);
}
return;
}
// 双重检查:如果在设置延续后发现已完成,需要执行延续
if (_completed)
{
var cont = Interlocked.Exchange(ref _continuation, null);
if (cont != null)
{
cont();
}
}
}
/// <summary>
/// 获取异步操作结果
@ -134,9 +127,4 @@ public class AsyncOperation : IYieldInstruction, INotifyCompletion
{
return this;
}
/// <summary>
/// 检查是否已完成
/// </summary>
public bool IsCompleted => _completed;
}

View File

@ -10,8 +10,10 @@ public sealed class WaitForAllCoroutines(
IReadOnlyList<CoroutineHandle> handles)
: IYieldInstruction
{
private readonly IReadOnlyList<CoroutineHandle> _handles =
handles ?? throw new ArgumentNullException(nameof(handles));
private readonly CoroutineScheduler _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
private readonly IReadOnlyList<CoroutineHandle> _handles = handles ?? throw new ArgumentNullException(nameof(handles));
public void Update(double deltaTime)
{
@ -20,9 +22,6 @@ public sealed class WaitForAllCoroutines(
public bool IsDone
{
get
{
return _handles.All(handle => !_scheduler.IsCoroutineAlive(handle));
}
get { return _handles.All(handle => !_scheduler.IsCoroutineAlive(handle)); }
}
}

View File

@ -7,8 +7,6 @@ namespace GFramework.Core.coroutine.instructions;
/// </summary>
public sealed class WaitForCoroutine : IYieldInstruction
{
private bool _done;
/// <summary>
/// 更新方法,用于处理时间更新逻辑
/// </summary>
@ -20,10 +18,13 @@ public sealed class WaitForCoroutine : IYieldInstruction
/// <summary>
/// 获取协程是否已完成的状态
/// </summary>
public bool IsDone => _done;
public bool IsDone { get; private set; }
/// <summary>
/// 内部方法,用于标记协程完成状态
/// </summary>
internal void Complete() => _done = true;
internal void Complete()
{
IsDone = true;
}
}

View File

@ -10,7 +10,6 @@ public class WaitForProgress : IYieldInstruction
private readonly double _duration;
private readonly Action<float> _onProgress;
private double _elapsed;
private bool _progressCompleted;
/// <summary>
/// 初始化等待进度指令
@ -25,7 +24,7 @@ public class WaitForProgress : IYieldInstruction
_duration = duration;
_onProgress = onProgress ?? throw new ArgumentNullException(nameof(onProgress));
_elapsed = 0;
_progressCompleted = false;
IsDone = false;
}
/// <summary>
@ -34,7 +33,7 @@ public class WaitForProgress : IYieldInstruction
/// <param name="deltaTime">时间增量</param>
public void Update(double deltaTime)
{
if (_progressCompleted)
if (IsDone)
return;
_elapsed += deltaTime;
@ -43,7 +42,7 @@ public class WaitForProgress : IYieldInstruction
if (_elapsed >= _duration)
{
_elapsed = _duration;
_progressCompleted = true;
IsDone = true;
_onProgress(1.0f);
}
else
@ -56,5 +55,5 @@ public class WaitForProgress : IYieldInstruction
/// <summary>
/// 获取等待是否已完成
/// </summary>
public bool IsDone => _progressCompleted;
public bool IsDone { get; private set; }
}

View File

@ -21,19 +21,22 @@ public sealed class WaitForTask<T> : IYieldInstruction
// 检查Task是否已经完成
if (_task.IsCompleted)
{
_done = true;
}
else
{
// 注册完成回调
_task.ContinueWith(_ =>
{
_done = true;
}, TaskContinuationOptions.ExecuteSynchronously);
}
_task.ContinueWith(_ => { _done = true; }, TaskContinuationOptions.ExecuteSynchronously);
}
/// <summary>
/// 获取Task的结果值
/// </summary>
public T Result => _task.GetAwaiter().GetResult();
/// <summary>
/// 获取Task的异常如果有
/// </summary>
public Exception? Exception => _task.Exception;
/// <summary>
/// 更新方法,用于处理时间更新逻辑
/// </summary>
@ -47,14 +50,4 @@ public sealed class WaitForTask<T> : IYieldInstruction
/// 获取等待是否已完成
/// </summary>
public bool IsDone => _done;
/// <summary>
/// 获取Task的结果值
/// </summary>
public T Result => _task.GetAwaiter().GetResult();
/// <summary>
/// 获取Task的异常如果有
/// </summary>
public Exception? Exception => _task.Exception;
}

View File

@ -23,19 +23,17 @@ public sealed class WaitForTask : IYieldInstruction
// 检查Task是否已经完成
if (_task.IsCompleted)
{
_done = true;
}
else
{
// 注册完成回调
_task.ContinueWith(_ =>
{
_done = true;
}, TaskContinuationOptions.ExecuteSynchronously);
}
_task.ContinueWith(_ => { _done = true; }, TaskContinuationOptions.ExecuteSynchronously);
}
/// <summary>
/// 获取Task的异常如果有
/// </summary>
public Exception? Exception => _task.Exception;
/// <summary>
/// 更新方法,用于处理时间更新逻辑
/// </summary>
@ -49,9 +47,4 @@ public sealed class WaitForTask : IYieldInstruction
/// 获取等待是否已完成
/// </summary>
public bool IsDone => _done;
/// <summary>
/// 获取Task的异常如果有
/// </summary>
public Exception? Exception => _task.Exception;
}

View File

@ -8,19 +8,17 @@ namespace GFramework.Core.coroutine.instructions;
/// </summary>
public sealed class WaitOneFrame : IYieldInstruction
{
private bool _done;
/// <summary>
/// 更新方法在每一帧被调用时将完成状态设置为true
/// </summary>
/// <param name="deltaTime">时间间隔,表示当前帧与上一帧的时间差</param>
public void Update(double deltaTime)
{
_done = true;
IsDone = true;
}
/// <summary>
/// 获取当前等待指令是否已完成
/// </summary>
public bool IsDone => _done;
public bool IsDone { get; private set; }
}

View File

@ -1,5 +1,4 @@
using System;
using GFramework.Core.Abstractions.events;
using GFramework.Core.Abstractions.events;
namespace GFramework.Core.events;

View File

@ -1,5 +1,4 @@
using System;
using GFramework.Core.Abstractions.events;
using GFramework.Core.Abstractions.events;
namespace GFramework.Core.events;

View File

@ -27,6 +27,7 @@ void UnRegister(); // 执行注销操作
```
### 3. [
`IUnRegisterList`](file:///d:/Project/Rider/GFramework/GFramework.Core.Abstractions/events/IUnRegisterList.cs#L6-L10)
注销列表接口,用于批量管理注销对象。

View File

@ -1,6 +1,4 @@
using System;
namespace GFramework.Core.extensions;
namespace GFramework.Core.extensions;
/// <summary>
/// 提供基于运行时类型判断的对象扩展方法,

View File

@ -1,4 +1,3 @@
using System.Threading;
using GFramework.Core.Abstractions.ioc;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.system;

View File

@ -390,9 +390,11 @@ public bool Contains<T>() where T : class
```
**参数:**
- 无泛型参数
**返回值:**
- 如果容器中包含指定类型的实例则返回 `true`,否则返回 `false`
**使用示例:**
@ -414,6 +416,7 @@ if (!container.Contains<ISettingsService>())
```
**应用场景:**
- 条件注册服务
- 检查依赖是否可用
- 动态功能开关
@ -427,9 +430,11 @@ public bool ContainsInstance(object instance)
```
**参数:**
- `instance`:待查询的实例对象
**返回值:**
- 若容器中包含该实例则返回 `true`,否则返回 `false`
**使用示例:**
@ -455,6 +460,7 @@ if (!container.ContainsInstance(anotherService))
```
**应用场景:**
- 避免重复注册同一实例
- 检查对象是否已被管理
- 调试和日志记录
@ -486,11 +492,13 @@ Console.WriteLine($"Contains IService2: {container.Contains<IService2>()}"); //
```
**应用场景:**
- 重置容器状态
- 内存清理
- 测试环境准备
**注意事项:**
- 容器冻结后也可以调用 `Clear()` 方法
- 清空后,所有已注册的实例都将丢失
- 不会自动清理已注册对象的其他引用

View File

@ -1,5 +1,4 @@
using System;
using GFramework.Core.Abstractions.logging;
using GFramework.Core.Abstractions.logging;
namespace GFramework.Core.logging;

View File

@ -1,4 +1,3 @@
using System;
using System.IO;
using GFramework.Core.Abstractions.logging;

View File

@ -61,10 +61,7 @@ public abstract class AbstractObjectPoolSystem<TKey, TObject>
public void Clear()
{
// 遍历所有对象池,调用每个对象的销毁方法
foreach (var obj in Pools.Values.SelectMany(pool => pool))
{
obj.OnPoolDestroy();
}
foreach (var obj in Pools.Values.SelectMany(pool => pool)) obj.OnPoolDestroy();
Pools.Clear();
}

View File

@ -477,6 +477,7 @@ public class DebuggablePoolSystem : AbstractObjectPoolSystem<string, PoolableObj
### 1. 游戏对象池
**适用对象:**
- 子弹、箭矢、投射物
- 敌人、NPC
- 爆炸效果、粒子系统
@ -559,6 +560,7 @@ public class ShootingSystem : AbstractSystem
### 2. UI 元素池
**适用对象:**
- 对话框
- 提示框
- 菜单项
@ -617,6 +619,7 @@ public class UISystem : AbstractSystem
### 3. 网络消息对象池
**适用对象:**
- 网络包
- 协议消息
- 数据包

View File

@ -8,7 +8,8 @@ namespace GFramework.Core.query;
/// 继承自ContextAwareBase并实现IAsyncQuery&lt;TResult&gt;接口
/// </summary>
/// <typeparam name="TResult">查询结果的类型</typeparam>
public abstract class AbstractAsyncQuery<TResult> : ContextAwareBase, IAsyncQuery<TResult> {
public abstract class AbstractAsyncQuery<TResult> : ContextAwareBase, IAsyncQuery<TResult>
{
/// <summary>
/// 执行异步查询操作
/// </summary>

View File

@ -83,6 +83,7 @@ public GetPlayerGoldQuery() : base(new EmptyQueryInput())
{
return this.GetModel<PlayerModel>().Gold.Value;
}
}
// 查询玩家是否死亡
@ -98,6 +99,7 @@ public IsPlayerDeadQuery() : base(new EmptyQueryInput())
{
return this.GetModel<PlayerModel>().Health.Value <= 0;
}
}
// 查询背包中指定物品的数量
@ -114,7 +116,9 @@ public GetItemCountQuery(string itemId) : base(new GetItemCountQueryInput(itemId
var inventory = this.GetModel<InventoryModel>();
return inventory.GetItemCount(input.ItemId);
}
}
```
### 2. 发送查询(在 Controller 中)
@ -172,7 +176,9 @@ public class CombatSystem : AbstractSystem
this.SendCommand(new TakeDamageCommand { Damage = e.Damage });
}
}
}
```
## 高级用法
@ -221,6 +227,7 @@ public class CanUseSkillQuery : AbstractQuery<bool>
return playerModel.Mana.Value >= skillCost.ManaCost
&& !this.SendQuery(new IsSkillOnCooldownQuery { SkillId = SkillId });
}
}
public class GetSkillCostQuery : AbstractQuery<SkillCost>
@ -231,6 +238,7 @@ public class GetSkillCostQuery : AbstractQuery<SkillCost>
{
return this.GetModel<SkillModel>().GetSkillCost(SkillId);
}
}
public class IsSkillOnCooldownQuery : AbstractQuery<bool>
@ -241,7 +249,9 @@ public class IsSkillOnCooldownQuery : AbstractQuery<bool>
{
return this.GetModel<SkillModel>().IsOnCooldown(SkillId);
}
}
```
### 3. 聚合数据查询
@ -317,7 +327,9 @@ public class EnemyAISystem : AbstractSystem
}
}
}
}
```
## Command vs Query
@ -405,7 +417,9 @@ public class PlayerModel : AbstractModel
{
_cachedPower = null;
}
}
```
### 2. 批量查询

View File

@ -21,6 +21,7 @@ public interface IContextAware
```
**实现此接口的类型:**
- System
- Query
- Model

View File

@ -55,10 +55,7 @@ public class StateMachine(int maxHistorySize = 10) : IStateMachine
// 从历史记录中移除该状态的所有引用
var tempStack = new Stack<IState>(_stateHistory.Reverse());
_stateHistory.Clear();
foreach (var historyState in tempStack.Where(s => s != state))
{
_stateHistory.Push(historyState);
}
foreach (var historyState in tempStack.Where(s => s != state)) _stateHistory.Push(historyState);
States.Remove(type);
}
@ -110,20 +107,29 @@ public class StateMachine(int maxHistorySize = 10) : IStateMachine
/// </summary>
/// <typeparam name="T">要检查的状态类型</typeparam>
/// <returns>如果状态已注册则返回true否则返回false</returns>
public bool IsRegistered<T>() where T : IState => States.ContainsKey(typeof(T));
public bool IsRegistered<T>() where T : IState
{
return States.ContainsKey(typeof(T));
}
/// <summary>
/// 获取指定类型的已注册状态实例
/// </summary>
/// <typeparam name="T">要获取的状态类型</typeparam>
/// <returns>如果状态存在则返回对应实例否则返回null</returns>
public T? GetState<T>() where T : class, IState => States.TryGetValue(typeof(T), out var state) ? state as T : null;
public T? GetState<T>() where T : class, IState
{
return States.TryGetValue(typeof(T), out var state) ? state as T : null;
}
/// <summary>
/// 获取所有已注册状态的类型集合
/// </summary>
/// <returns>包含所有已注册状态类型的枚举器</returns>
public IEnumerable<Type> GetRegisteredStateTypes() => States.Keys;
public IEnumerable<Type> GetRegisteredStateTypes()
{
return States.Keys;
}
/// <summary>
/// 获取上一个状态
@ -163,10 +169,8 @@ public class StateMachine(int maxHistorySize = 10) : IStateMachine
// 检查上一个状态是否仍然注册
if (!States.ContainsValue(previousState))
{
// 如果状态已被注销,继续尝试更早的状态
return GoBack();
}
// 回退时不添加到历史记录
ChangeInternalWithoutHistory(previousState);
@ -233,10 +237,7 @@ public class StateMachine(int maxHistorySize = 10) : IStateMachine
// 移除最旧的记录(栈底元素)
var tempStack = new Stack<IState>(_stateHistory.Reverse().Skip(1));
_stateHistory.Clear();
foreach (var state in tempStack.Reverse())
{
_stateHistory.Push(state);
}
foreach (var state in tempStack.Reverse()) _stateHistory.Push(state);
}
}

View File

@ -50,10 +50,7 @@ public class StateMachineSystem : StateMachine, IStateMachineSystem
/// </summary>
public virtual void Init()
{
foreach (var state in States.Values.OfType<IContextAware>())
{
state.SetContext(_context);
}
foreach (var state in States.Values.OfType<IContextAware>()) state.SetContext(_context);
}
/// <summary>
@ -69,10 +66,7 @@ public class StateMachineSystem : StateMachine, IStateMachineSystem
}
// 清理所有状态
foreach (var state in States.Values.OfType<IDisposable>())
{
state.Destroy();
}
foreach (var state in States.Values.OfType<IDisposable>()) state.Destroy();
States.Clear();
}

View File

@ -13,5 +13,5 @@ public enum CacheEvictionPolicy
/// <summary>
/// 最少使用频率
/// </summary>
Lfu,
Lfu
}

View File

@ -1,5 +1,3 @@
using System;
namespace GFramework.Game.Abstractions.enums;
/// <summary>

View File

@ -23,5 +23,5 @@ public enum UiTransitionType
/// <summary>
/// 清空所有页面
/// </summary>
Clear,
Clear
}

View File

@ -8,7 +8,7 @@ public class GraphicsSettings : ISettingsData
/// <summary>
/// 获取或设置是否启用全屏模式
/// </summary>
public bool Fullscreen { get; set; } = false;
public bool Fullscreen { get; set; }
/// <summary>
/// 获取或设置屏幕分辨率宽度

View File

@ -1,6 +1,4 @@
using System.Threading.Tasks;
namespace GFramework.Game.Abstractions.setting;
namespace GFramework.Game.Abstractions.setting;
/// <summary>
/// 定义可应用设置的接口继承自ISettingsSection

View File

@ -1,6 +1,4 @@
using System;
namespace GFramework.Game.Abstractions.setting;
namespace GFramework.Game.Abstractions.setting;
/// <summary>
/// 设置变更事件基类

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using GFramework.Core.Abstractions.model;
using GFramework.Core.Abstractions.model;
namespace GFramework.Game.Abstractions.setting;

View File

@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.utility;
namespace GFramework.Game.Abstractions.setting;

View File

@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.system;
namespace GFramework.Game.Abstractions.setting;

View File

@ -1,4 +1,3 @@
using System;
using System.Reflection;
namespace GFramework.Game.Abstractions.setting;

View File

@ -1,6 +1,4 @@
using System;
namespace GFramework.Game.Abstractions.ui;
namespace GFramework.Game.Abstractions.ui;
/// <summary>
/// UI缓存统计信息接口

View File

@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using GFramework.Core.Abstractions.utility;
namespace GFramework.Game.Abstractions.ui;

View File

@ -23,6 +23,21 @@ public interface IUiPageBehavior
/// </summary>
bool IsAlive { get; }
/// <summary>
/// 获取页面是否为模态页面
/// </summary>
bool IsModal { get; }
/// <summary>
/// 获取页面是否阻断下层交互
/// </summary>
bool BlocksInput { get; }
/// <summary>
/// 获取页面是否需要蒙版
/// </summary>
bool RequiresMask { get; }
/// <summary>
/// 页面进入时调用的方法
/// </summary>
@ -53,20 +68,4 @@ public interface IUiPageBehavior
/// 页面重新显示时调用的方法
/// </summary>
void OnShow();
/// <summary>
/// 获取页面是否为模态页面
/// </summary>
bool IsModal { get; }
/// <summary>
/// 获取页面是否阻断下层交互
/// </summary>
bool BlocksInput { get; }
/// <summary>
/// 获取页面是否需要蒙版
/// </summary>
bool RequiresMask { get; }
}

View File

@ -1,4 +1,3 @@
using System.Collections.Generic;
using GFramework.Game.Abstractions.enums;
namespace GFramework.Game.Abstractions.ui;

View File

@ -1,5 +1,3 @@
using System.Threading.Tasks;
namespace GFramework.Game.Abstractions.ui;
/// <summary>

View File

@ -74,6 +74,7 @@ public interface IUiRouter : ISystem
IUiPageEnterParam? param = null,
UiPopPolicy popPolicy = UiPopPolicy.Destroy,
UiTransitionPolicy pushPolicy = UiTransitionPolicy.Exclusive);
/// <summary>
/// 清空所有UI界面重置路由状态
/// </summary>
@ -128,6 +129,7 @@ public interface IUiRouter : ISystem
/// </summary>
/// <typeparam name="T">守卫类型,必须实现 IUiRouteGuard 且有无参构造函数</typeparam>
void AddGuard<T>() where T : IUiRouteGuard, new();
/// <summary>
/// 移除路由守卫
/// </summary>

View File

@ -1,5 +1,3 @@
using System.Threading.Tasks;
namespace GFramework.Game.Abstractions.ui;
/// <summary>

View File

@ -1,5 +1,3 @@
using System.Threading;
using System.Threading.Tasks;
using GFramework.Game.Abstractions.enums;
namespace GFramework.Game.Abstractions.ui;

View File

@ -1,4 +1,3 @@
using System;
using GFramework.Game.Abstractions.enums;
namespace GFramework.Game.Abstractions.ui;
@ -40,12 +39,14 @@ public class UiCacheConfig
/// <param name="maxSize">最大缓存数量</param>
/// <param name="expireAfter">访问后过期时间</param>
public static UiCacheConfig Lru(int maxSize = 10, TimeSpan? expireAfter = null)
=> new()
{
return new UiCacheConfig
{
MaxCacheSize = maxSize,
EvictionPolicy = CacheEvictionPolicy.Lru,
ExpireAfterAccess = expireAfter
};
}
/// <summary>
/// 创建 LFU 策略配置
@ -53,10 +54,12 @@ public class UiCacheConfig
/// <param name="maxSize">最大缓存数量</param>
/// <param name="expireAfter">访问后过期时间</param>
public static UiCacheConfig Lfu(int maxSize = 10, TimeSpan? expireAfter = null)
=> new()
{
return new UiCacheConfig
{
MaxCacheSize = maxSize,
EvictionPolicy = CacheEvictionPolicy.Lfu,
ExpireAfterAccess = expireAfter
};
}
}

View File

@ -1,5 +1,4 @@

namespace GFramework.Game.Abstractions.ui;
namespace GFramework.Game.Abstractions.ui;
/// <summary>
/// UI页面实例管理策略控制实例的生命周期

View File

@ -1,5 +1,3 @@
using System;
using System.Collections.Generic;
using GFramework.Game.Abstractions.enums;
namespace GFramework.Game.Abstractions.ui;

View File

@ -30,24 +30,28 @@ GFramework.Game 为游戏开发提供了专门的功能模块,与 GFramework.C
## 核心特性
### 🏗️ 模块化架构
- **AbstractModule**:可重用的架构模块基类
- **生命周期管理**:与框架生命周期深度集成
- **依赖注入**:模块间的依赖自动管理
- **配置驱动**:灵活的模块配置系统
### 📦 资产管理
- **统一资源目录**:集中化的资源注册和查询
- **类型安全**:编译时类型检查和泛型支持
- **重复检测**:自动检测资源重复注册
- **映射支持**:灵活的资源映射和别名系统
### 💾 存储系统
- **分层存储**:命名空间支持的存储隔离
- **多格式支持**JSON、二进制等多种存储格式
- **异步操作**:完整的异步存储 API
- **版本兼容**:存档版本管理和迁移支持
### 🔄 序列化系统
- **JSON 集成**:基于 Newtonsoft.Json 的序列化
- **自定义序列化**:支持自定义序列化逻辑
- **性能优化**:序列化缓存和优化策略

View File

@ -15,7 +15,9 @@ public sealed class JsonSerializer : ISerializer
/// <param name="value">要序列化的对象实例</param>
/// <returns>序列化后的JSON字符串</returns>
public string Serialize<T>(T value)
=> JsonConvert.SerializeObject(value);
{
return JsonConvert.SerializeObject(value);
}
/// <summary>
/// 将JSON字符串反序列化为指定类型的对象
@ -25,5 +27,7 @@ public sealed class JsonSerializer : ISerializer
/// <returns>反序列化后的对象实例</returns>
/// <exception cref="ArgumentException">当无法反序列化数据时抛出</exception>
public T Deserialize<T>(string data)
=> JsonConvert.DeserializeObject<T>(data) ?? throw new ArgumentException("Cannot deserialize data");
{
return JsonConvert.DeserializeObject<T>(data) ?? throw new ArgumentException("Cannot deserialize data");
}
}

View File

@ -129,7 +129,9 @@ public class SettingsPersistence : AbstractContextUtility, ISettingsPersistence
/// <typeparam name="T">设置数据类型</typeparam>
/// <returns>格式为"Settings_类型名称"的键名</returns>
private static string GetKey<T>() where T : ISettingsData
=> GetKey(typeof(T));
{
return GetKey(typeof(T));
}
/// <summary>
/// 获取指定类型的存储键名
@ -137,5 +139,7 @@ public class SettingsPersistence : AbstractContextUtility, ISettingsPersistence
/// <param name="type">设置数据类型</param>
/// <returns>格式为"Settings_类型名称"的键名</returns>
private static string GetKey(Type type)
=> $"Settings_{type.Name}";
{
return $"Settings_{type.Name}";
}
}

View File

@ -19,10 +19,7 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
public Task ApplyAll()
{
// 遍历所有设置配置并尝试应用
foreach (var section in _model.All())
{
TryApply(section);
}
foreach (var section in _model.All()) TryApply(section);
return Task.CompletedTask;
}
@ -33,7 +30,9 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
/// <typeparam name="T">设置配置类型必须是类且实现ISettingsSection接口</typeparam>
/// <returns>完成的任务</returns>
public Task Apply<T>() where T : class, ISettingsSection
=> Apply(typeof(T));
{
return Apply(typeof(T));
}
/// <summary>
/// 应用指定类型的设置配置
@ -58,12 +57,8 @@ public class SettingsSystem : AbstractSystem, ISettingsSystem
{
// 去重后遍历设置类型,获取并应用对应的设置配置
foreach (var type in settingsTypes.Distinct())
{
if (_model.TryGet(type, out var section))
{
TryApply(section);
}
}
return Task.CompletedTask;
}

View File

@ -14,7 +14,9 @@ public sealed class GameStateMachineSystem : StateMachineSystem
/// <typeparam name="T">要检查的状态类型必须实现IState接口</typeparam>
/// <returns>如果当前状态是指定类型则返回true否则返回false</returns>
public bool IsIn<T>() where T : IState
=> Current is T;
{
return Current is T;
}
/// <summary>
/// 获取当前状态的实例,如果当前状态是指定类型则进行类型转换
@ -22,5 +24,7 @@ public sealed class GameStateMachineSystem : StateMachineSystem
/// <typeparam name="T">要获取的状态类型必须是引用类型并实现IState接口</typeparam>
/// <returns>如果当前状态是指定类型则返回转换后的实例否则返回null</returns>
public T? Get<T>() where T : class, IState
=> Current as T;
{
return Current as T;
}
}

View File

@ -129,7 +129,9 @@ public sealed class FileStorage : IFileStorage
/// <param name="key">存储键</param>
/// <returns>如果存储项存在则返回true否则返回false</returns>
public Task<bool> ExistsAsync(string key)
=> Task.FromResult(Exists(key));
{
return Task.FromResult(Exists(key));
}
#endregion

View File

@ -16,7 +16,9 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">要检查的键</param>
/// <returns>如果键存在则返回true否则返回false</returns>
public bool Exists(string key)
=> inner.Exists(Key(key));
{
return inner.Exists(Key(key));
}
/// <summary>
/// 异步检查指定键是否存在
@ -24,7 +26,9 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">要检查的键</param>
/// <returns>如果键存在则返回true否则返回false</returns>
public Task<bool> ExistsAsync(string key)
=> inner.ExistsAsync(Key(key));
{
return inner.ExistsAsync(Key(key));
}
/// <summary>
/// 读取指定键的值
@ -33,7 +37,9 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">要读取的键</param>
/// <returns>键对应的值</returns>
public T Read<T>(string key)
=> inner.Read<T>(Key(key));
{
return inner.Read<T>(Key(key));
}
/// <summary>
/// 读取指定键的值,如果键不存在则返回默认值
@ -43,7 +49,9 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="defaultValue">当键不存在时返回的默认值</param>
/// <returns>键对应的值或默认值</returns>
public T Read<T>(string key, T defaultValue)
=> inner.Read(Key(key), defaultValue);
{
return inner.Read(Key(key), defaultValue);
}
/// <summary>
/// 异步读取指定键的值
@ -52,7 +60,9 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">要读取的键</param>
/// <returns>键对应的值的任务</returns>
public Task<T> ReadAsync<T>(string key)
=> inner.ReadAsync<T>(Key(key));
{
return inner.ReadAsync<T>(Key(key));
}
/// <summary>
/// 写入指定键值对
@ -61,7 +71,9 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">要写入的键</param>
/// <param name="value">要写入的值</param>
public void Write<T>(string key, T value)
=> inner.Write(Key(key), value);
{
inner.Write(Key(key), value);
}
/// <summary>
/// 异步写入指定键值对
@ -70,14 +82,18 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">要写入的键</param>
/// <param name="value">要写入的值</param>
public Task WriteAsync<T>(string key, T value)
=> inner.WriteAsync(Key(key), value);
{
return inner.WriteAsync(Key(key), value);
}
/// <summary>
/// 删除指定键
/// </summary>
/// <param name="key">要删除的键</param>
public void Delete(string key)
=> inner.Delete(Key(key));
{
inner.Delete(Key(key));
}
/// <summary>
/// 为给定的键添加前缀
@ -85,9 +101,11 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="key">原始键</param>
/// <returns>添加前缀后的键</returns>
private string Key(string key)
=> string.IsNullOrEmpty(prefix)
{
return string.IsNullOrEmpty(prefix)
? key
: $"{prefix}/{key}";
}
/// <summary>
/// 创建一个新的作用域存储实例
@ -95,5 +113,7 @@ public sealed class ScopedStorage(IStorage inner, string prefix) : IScopedStorag
/// <param name="scope">新的作用域名称</param>
/// <returns>新的作用域存储实例</returns>
public IStorage Scope(string scope)
=> new ScopedStorage(inner, Key(scope));
{
return new ScopedStorage(inner, Key(scope));
}
}

View File

@ -158,7 +158,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
var @event = CreateEvent(
nextUiKey,
type: UiTransitionType.Pop
UiTransitionType.Pop
);
BeforeChange(@event);
@ -484,10 +484,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
IUiPageEnterParam? param = null,
UiInstancePolicy instancePolicy = UiInstancePolicy.Reuse)
{
if (layer == UiLayer.Page)
{
throw new ArgumentException("Use Push() for Page layer");
}
if (layer == UiLayer.Page) throw new ArgumentException("Use Push() for Page layer");
// 初始化层级字典
if (!_layers.ContainsKey(layer))
@ -575,10 +572,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
return;
var keys = layerDict.Keys.ToArray();
foreach (var key in keys)
{
Hide(key, layer, destroy);
}
foreach (var key in keys) Hide(key, layer, destroy);
Log.Debug("Cleared layer: {0}, destroyed={1}", layer, destroy);
}
@ -641,10 +635,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
{
ArgumentNullException.ThrowIfNull(guard);
if (_guards.Remove(guard))
{
Log.Debug("Guard removed: {0}", guard.GetType().Name);
}
if (_guards.Remove(guard)) Log.Debug("Guard removed: {0}", guard.GetType().Name);
}
/// <summary>
@ -653,7 +644,6 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
private async Task<bool> ExecuteEnterGuardsAsync(string uiKey, IUiPageEnterParam? param)
{
foreach (var guard in _guards)
{
try
{
Log.Debug("Executing enter guard: {0} for {1}", guard.GetType().Name, uiKey);
@ -674,11 +664,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
catch (Exception ex)
{
Log.Error("Enter guard {0} failed: {1}", guard.GetType().Name, ex.Message);
if (guard.CanInterrupt)
{
return false;
}
}
if (guard.CanInterrupt) return false;
}
return true;
@ -690,7 +676,6 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
private async Task<bool> ExecuteLeaveGuardsAsync(string uiKey)
{
foreach (var guard in _guards)
{
try
{
Log.Debug("Executing leave guard: {0} for {1}", guard.GetType().Name, uiKey);
@ -711,11 +696,7 @@ public abstract class UiRouterBase : AbstractSystem, IUiRouter
catch (Exception ex)
{
Log.Error("Leave guard {0} failed: {1}", guard.GetType().Name, ex.Message);
if (guard.CanInterrupt)
{
return false;
}
}
if (guard.CanInterrupt) return false;
}
return true;

View File

@ -20,7 +20,8 @@ GFramework.Godot 是 GFramework 框架的 Godot 特定实现,将框架的架
## 概述
GFramework.Godot 提供了与 Godot 引擎的深度集成,让开发者能够在保持 GFramework 架构优势的同时,充分利用 Godot 的节点系统、信号机制和场景管理功能。
GFramework.Godot 提供了与 Godot 引擎的深度集成,让开发者能够在保持 GFramework 架构优势的同时,充分利用 Godot
的节点系统、信号机制和场景管理功能。
### 核心设计理念
@ -32,33 +33,39 @@ GFramework.Godot 提供了与 Godot 引擎的深度集成,让开发者能够
## 核心特性
### 🎯 架构生命周期绑定
- 自动将框架初始化与 Godot 场景树绑定
- 支持节点销毁时的自动清理
- 阶段式架构初始化与 Godot `_Ready` 周期同步
### 🔧 丰富的 Node 扩展方法
- **50+** 个实用扩展方法
- 安全的节点操作和验证
- 流畅的场景树遍历和查找
- 简化的输入处理
### 📡 流畅的信号 API
- 类型安全的信号连接
- 链式调用支持
- 自动生命周期管理
- Godot 信号与框架事件系统的桥接
### 🏊‍♂️ 高效的节点池化
- 专用的 Node 对象池
- 自动回收和重用机制
- 内存友好的高频节点创建/销毁
### 📦 智能资源管理
- 简化的 Godot 资源加载
- 类型安全的资源工厂
- 缓存和预加载支持
### 📝 Godot 原生日志
- 与 Godot 日志系统完全集成
- 框架日志自动输出到 Godot 控制台
- 可配置的日志级别
@ -725,6 +732,7 @@ public partial class MainScene : Node2D
### 🏗️ 架构设计最佳实践
#### 1. 模块化设计
```csharp
// 好的做法:按功能分组模块
public class AudioModule : AbstractGodotModule { }
@ -739,6 +747,7 @@ public class GameModule : AbstractGodotModule // ❌ 太大
```
#### 2. 生命周期管理
```csharp
// 好的做法:使用自动清理
this.RegisterEvent<GameEvent>(OnGameEvent)
@ -763,6 +772,7 @@ public override void _ExitTree()
### 🎮 Godot 集成最佳实践
#### 1. 节点安全操作
```csharp
// 好的做法:使用安全扩展
var player = GetNodeX<Player>("Player");
@ -773,6 +783,7 @@ var player = GetNode<Player>("Player"); // 可能抛出异常
```
#### 2. 信号连接模式
```csharp
// 好的做法:使用 SignalBuilder
this.CreateSignalBuilder(Button.SignalName.Pressed)
@ -786,6 +797,7 @@ Button.Pressed += OnButtonPressed; // 容易忘记清理
### 🏊‍♂️ 性能优化最佳实践
#### 1. 节点池化策略
```csharp
// 好的做法:高频创建对象使用池化
public class BulletPool : AbstractNodePoolSystem<string, Bullet>
@ -803,6 +815,7 @@ public void Shoot()
```
#### 2. 资源预加载
```csharp
// 好的做法:预加载常用资源
public override void _Ready()
@ -816,6 +829,7 @@ public override void _Ready()
### 🔧 调试和错误处理
#### 1. 日志使用策略
```csharp
// 好的做法:分级别记录
Logger.Debug($"Player position: {Position}"); // 调试信息
@ -828,6 +842,7 @@ Logger.Debug($"Frame: {Engine.GetProcessFrames()}"); // 太频繁
```
#### 2. 异常处理
```csharp
// 好的做法:优雅的错误处理
public T LoadResource<T>(string path) where T : Resource

View File

@ -56,10 +56,8 @@ public static class CoroutineExtensions
private static bool AllNodesAlive(Node[] nodes)
{
foreach (var node in nodes)
{
if (!Timing.IsNodeAlive(node))
return false;
}
return true;
}

View File

@ -9,18 +9,16 @@ namespace GFramework.Godot.coroutine;
public class GodotTimeSource(Func<double> getDeltaFunc) : ITimeSource
{
private readonly Func<double> _getDeltaFunc = getDeltaFunc ?? throw new ArgumentNullException(nameof(getDeltaFunc));
private double _currentTime;
private double _deltaTime;
/// <summary>
/// 获取当前累计时间
/// </summary>
public double CurrentTime => _currentTime;
public double CurrentTime { get; private set; }
/// <summary>
/// 获取上一帧的时间增量
/// </summary>
public double DeltaTime => _deltaTime;
public double DeltaTime { get; private set; }
/// <summary>
/// 更新时间源,计算新的增量时间和累计时间
@ -28,9 +26,9 @@ public class GodotTimeSource(Func<double> getDeltaFunc) : ITimeSource
public void Update()
{
// 调用外部提供的函数获取当前帧的时间增量
_deltaTime = _getDeltaFunc();
DeltaTime = _getDeltaFunc();
// 累加到总时间中
_currentTime += _deltaTime;
CurrentTime += DeltaTime;
}
/// <summary>
@ -38,7 +36,7 @@ public class GodotTimeSource(Func<double> getDeltaFunc) : ITimeSource
/// </summary>
public void Reset()
{
_currentTime = 0;
_deltaTime = 0;
CurrentTime = 0;
DeltaTime = 0;
}
}

View File

@ -182,19 +182,19 @@ public partial class Timing : Node
_processScheduler = new CoroutineScheduler(
_processTimeSource,
_instanceId,
initialCapacity: 256
256
);
_physicsScheduler = new CoroutineScheduler(
_physicsTimeSource,
_instanceId,
initialCapacity: 128
128
);
_deferredScheduler = new CoroutineScheduler(
_deferredTimeSource,
_instanceId,
initialCapacity: 64
64
);
}
@ -211,14 +211,12 @@ public partial class Timing : Node
}
for (byte i = 1; i < ActiveInstances.Length; i++)
{
if (ActiveInstances[i] == null)
{
_instanceId = i;
ActiveInstances[i] = this;
return;
}
}
throw new OverflowException("最多只能存在 15 个 Timing 实例");
}
@ -389,7 +387,7 @@ public partial class Timing : Node
/// <returns>被终止的协程数量</returns>
private int KillByTagOnInstance(string tag)
{
int count = 0;
var count = 0;
count += ProcessScheduler.KillByTag(tag);
count += PhysicsScheduler.KillByTag(tag);
count += DeferredScheduler.KillByTag(tag);
@ -403,7 +401,7 @@ public partial class Timing : Node
/// <returns>被清除的协程总数</returns>
private int ClearOnInstance()
{
int count = 0;
var count = 0;
count += ProcessScheduler.Clear();
count += PhysicsScheduler.Clear();
count += DeferredScheduler.Clear();

View File

@ -6,17 +6,23 @@ public static class GodotPathExtensions
/// 判断是否是 Godot 用户数据路径user://
/// </summary>
public static bool IsUserPath(this string path)
=> !string.IsNullOrEmpty(path) && path.StartsWith("user://");
{
return !string.IsNullOrEmpty(path) && path.StartsWith("user://");
}
/// <summary>
/// 判断是否是 Godot 资源路径res://
/// </summary>
public static bool IsResPath(this string path)
=> !string.IsNullOrEmpty(path) && path.StartsWith("res://");
{
return !string.IsNullOrEmpty(path) && path.StartsWith("res://");
}
/// <summary>
/// 判断是否是 Godot 特殊路径user:// 或 res://
/// </summary>
public static bool IsGodotPath(this string path)
=> path.IsUserPath() || path.IsResPath();
{
return path.IsUserPath() || path.IsResPath();
}
}

View File

@ -229,8 +229,6 @@ public sealed class AudioBusMap
- 提供合理的默认值
- 支持对象初始化语法
### GodotAudioSettings
```csharp

View File

@ -55,10 +55,7 @@ public sealed class GodotFileStorage : IStorage
}
else
{
if (File.Exists(path))
{
File.Delete(path);
}
if (File.Exists(path)) File.Delete(path);
}
}
@ -76,7 +73,9 @@ public sealed class GodotFileStorage : IStorage
/// <param name="segment">要清理的路径段</param>
/// <returns>清理后的路径段</returns>
private static string SanitizeSegment(string segment)
=> Path.GetInvalidFileNameChars().Aggregate(segment, (current, c) => current.Replace(c, '_'));
{
return Path.GetInvalidFileNameChars().Aggregate(segment, (current, c) => current.Replace(c, '_'));
}
/// <summary>
/// 将存储键转换为绝对路径,处理 Godot 虚拟路径和普通文件系统路径
@ -119,7 +118,10 @@ public sealed class GodotFileStorage : IStorage
/// </summary>
/// <param name="path">文件路径</param>
/// <returns>对应路径的锁对象</returns>
private object GetLock(string path) => _keyLocks.GetOrAdd(path, _ => new object());
private object GetLock(string path)
{
return _keyLocks.GetOrAdd(path, _ => new object());
}
#endregion
@ -149,7 +151,9 @@ public sealed class GodotFileStorage : IStorage
/// <param name="key">存储键</param>
/// <returns>表示异步操作的任务,结果为布尔值表示文件是否存在</returns>
public Task<bool> ExistsAsync(string key)
=> Task.FromResult(Exists(key));
{
return Task.FromResult(Exists(key));
}
#endregion
@ -202,7 +206,7 @@ public sealed class GodotFileStorage : IStorage
lock (keyLock)
{
if (path.IsGodotPath() && !FileAccess.FileExists(path) || !path.IsGodotPath() && !File.Exists(path))
if ((path.IsGodotPath() && !FileAccess.FileExists(path)) || (!path.IsGodotPath() && !File.Exists(path)))
return defaultValue;
return Read<T>(key);

Some files were not shown because too many files have changed in this diff Show More