From 55e271805bbf2401082934b5bb38ec6e7be8f1ed Mon Sep 17 00:00:00 2001 From: Konstantin Dyachenko Date: Wed, 27 May 2026 04:13:29 +0700 Subject: [PATCH] =?UTF-8?q?=EF=BB=BFfeat(task-0003):=20implement=20boot=20?= =?UTF-8?q?flow=20service=20with=20menu=20restart=20signal=20and=20state?= =?UTF-8?q?=20transitions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implement BootFlowService with IStatesController injection and RunFlowAsync logic - Add Splash → Load → Menu loop with cancellation support in boot flow - Create IMenuRestartSignal interface for menu restart coordination - Implement MenuRestartSignal using UniTaskCompletionSource - Update MenuState to wait for restart signal instead of completing immediately - Register MenuRestartSignal as singleton in GameLifetimeScope DI container Выполнена задача TASK-0003 и реализован поток загрузки: - Реализован BootFlowService с внедрением IStatesController и логикой RunFlowAsync - Добавлен цикл Splash → Load → Menu с поддержкой отмены в потоке загрузки - Создан интерфейс IMenuRestartSignal для координации перезапуска меню - Реализован MenuRestartSignal с использованием UniTaskCompletionSource - Обновлён MenuState для ожидания сигнала перезапуска вместо немедленного завершения - Зарегистрирован MenuRestartSignal как синглтон в DI контейнере GameLifetimeScope --- Agent/Task/TASK-0003.md | 4 +++ .../Boot/Composition/GameLifetimeScope.cs | 3 +++ Assets/Scripts/Boot/Flow/BootFlowService.cs | 27 +++++++++++++++++-- .../Scripts/Boot/Flow/IMenuRestartSignal.cs | 11 ++++++++ .../Boot/Flow/IMenuRestartSignal.cs.meta | 11 ++++++++ Assets/Scripts/Boot/Flow/MenuRestartSignal.cs | 23 ++++++++++++++++ .../Boot/Flow/MenuRestartSignal.cs.meta | 11 ++++++++ Assets/Scripts/Boot/States/MenuState.cs | 9 ++++--- 8 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs create mode 100644 Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs.meta create mode 100644 Assets/Scripts/Boot/Flow/MenuRestartSignal.cs create mode 100644 Assets/Scripts/Boot/Flow/MenuRestartSignal.cs.meta diff --git a/Agent/Task/TASK-0003.md b/Agent/Task/TASK-0003.md index bad01ff..95ce4a1 100644 --- a/Agent/Task/TASK-0003.md +++ b/Agent/Task/TASK-0003.md @@ -1,5 +1,9 @@ # TASK-0003: BootFlowService и запуск сценария +## Статус + +Ready + ## Цель Реализовать внешний flow coordinator, который запускает и управляет сценарием загрузки приложения. diff --git a/Assets/Scripts/Boot/Composition/GameLifetimeScope.cs b/Assets/Scripts/Boot/Composition/GameLifetimeScope.cs index d2ee5f6..937f3dd 100644 --- a/Assets/Scripts/Boot/Composition/GameLifetimeScope.cs +++ b/Assets/Scripts/Boot/Composition/GameLifetimeScope.cs @@ -29,6 +29,9 @@ namespace QuizPleaseTest.Boot.Composition .As() .As(); + builder.Register(Lifetime.Singleton) + .As(); + builder.Register(Lifetime.Singleton) .As>() .AsSelf(); diff --git a/Assets/Scripts/Boot/Flow/BootFlowService.cs b/Assets/Scripts/Boot/Flow/BootFlowService.cs index e3923d4..849550f 100644 --- a/Assets/Scripts/Boot/Flow/BootFlowService.cs +++ b/Assets/Scripts/Boot/Flow/BootFlowService.cs @@ -1,19 +1,42 @@ using System.Threading; using Cysharp.Threading.Tasks; +using QuizPleaseTest.Boot.States; using QuizPleaseTest.Common.Services; +using QuizPleaseTest.Common.StateMachine; namespace QuizPleaseTest.Boot.Flow { public class BootFlowService : Service, IBootFlowService { - public override UniTask InitializeAsync(CancellationToken ct) + private readonly IStatesController _statesController; + + public BootFlowService(IStatesController statesController) { - return UniTask.CompletedTask; + _statesController = statesController; + } + + public override async UniTask InitializeAsync(CancellationToken ct) + { + await RunFlowAsync(ct); } public override UniTask ReleaseAsync(CancellationToken ct) { return UniTask.CompletedTask; } + + private async UniTask RunFlowAsync(CancellationToken ct) + { + await _statesController.EnterStateAsync(BootStateCode.Splash, ct); + await _statesController.EnterStateAsync(BootStateCode.Load, ct); + + while (!ct.IsCancellationRequested) + { + await _statesController.EnterStateAsync(BootStateCode.Menu, ct); + await _statesController.EnterStateAsync(BootStateCode.Load, ct); + } + + ct.ThrowIfCancellationRequested(); + } } } diff --git a/Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs b/Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs new file mode 100644 index 0000000..bd49427 --- /dev/null +++ b/Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs @@ -0,0 +1,11 @@ +using System.Threading; +using Cysharp.Threading.Tasks; + +namespace QuizPleaseTest.Boot.Flow +{ + public interface IMenuRestartSignal + { + UniTask WaitAsync(CancellationToken ct); + void RequestRestart(); + } +} diff --git a/Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs.meta b/Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs.meta new file mode 100644 index 0000000..5c45f2e --- /dev/null +++ b/Assets/Scripts/Boot/Flow/IMenuRestartSignal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2222222222222222222222222222222 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs b/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs new file mode 100644 index 0000000..f6194af --- /dev/null +++ b/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs @@ -0,0 +1,23 @@ +using System.Threading; +using Cysharp.Threading.Tasks; + +namespace QuizPleaseTest.Boot.Flow +{ + public class MenuRestartSignal : IMenuRestartSignal + { + private UniTaskCompletionSource _restartCompletionSource; + + public UniTask WaitAsync(CancellationToken ct) + { + ct.ThrowIfCancellationRequested(); + + _restartCompletionSource = new UniTaskCompletionSource(); + return _restartCompletionSource.Task.AttachExternalCancellation(ct); + } + + public void RequestRestart() + { + _restartCompletionSource?.TrySetResult(); + } + } +} diff --git a/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs.meta b/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs.meta new file mode 100644 index 0000000..db12321 --- /dev/null +++ b/Assets/Scripts/Boot/Flow/MenuRestartSignal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3333333333333333333333333333333 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Boot/States/MenuState.cs b/Assets/Scripts/Boot/States/MenuState.cs index e058b15..18dae41 100644 --- a/Assets/Scripts/Boot/States/MenuState.cs +++ b/Assets/Scripts/Boot/States/MenuState.cs @@ -1,5 +1,6 @@ using System.Threading; using Cysharp.Threading.Tasks; +using QuizPleaseTest.Boot.Flow; using QuizPleaseTest.Boot.UI; using QuizPleaseTest.Common.StateMachine; @@ -8,16 +9,18 @@ namespace QuizPleaseTest.Boot.States public class MenuState : IState { private readonly MenuUIView _view; + private readonly IMenuRestartSignal _restartSignal; - public MenuState(MenuUIView view) + public MenuState(MenuUIView view, IMenuRestartSignal restartSignal) { _view = view; + _restartSignal = restartSignal; } - public UniTask EnterAsync(CancellationToken ct) + public async UniTask EnterAsync(CancellationToken ct) { _view.Initialize(); - return UniTask.CompletedTask; + await _restartSignal.WaitAsync(ct); } public UniTask ExitAsync(CancellationToken ct)