#nullable enable using System; using System.Linq; using System.Collections.Generic; using Godot; using ShrinkApp; using ShrinkApp.Starter.Basic; using ShrinkCommand; using Cysharp.Threading.Tasks; using ShrinkDataSaver; using ShrinkEventBus; using ShrinkNetwork; using ShrinkSDK.Godot; using ShrinkTutorial; public partial class SampleRoot : ShrinkGodotHost { public override void _Ready() { base._Ready(); RunSmokeAsync().Forget(); } private async UniTaskVoid RunSmokeAsync() { var marker = RequireWoven(GetType().Assembly); using var binding = EventBus.Attach(new GodotSubscriber()); EventBus.Post(new GodotSmokeEvent()); var assembly = GetType().Assembly; var registries = assembly.GetCustomAttributes(false).Select(value => value.GetType().Name).ToHashSet(); var savedValue = 42; ShrinkDataSaverRuntime.Initialize(new ShrinkDataSaverRuntimeConfig { RootPath = PersistentDataPath, CurrentSaveVersion = 1 }); ShrinkSave.RegisterModule("godot-smoke", () => savedValue, value => savedValue = value); await ShrinkSave.SaveSlotAsync(0, new SaveOptions { SlotName = "Godot Smoke" }); savedValue = 0; await ShrinkSave.LoadSlotAsync(0); var app = await StartAppAsync(); var composition = ShrinkBasicComposition.CreateHost(app.Context.Services); var entries = ShrinkBasicComposition.CreateEntries(app.Context.Services); await composition.ApplyAsync(entries); await composition.ApplyAsync(entries); var activeFibers = composition.Runtime.Fibers.Count(fiber => fiber.State == ShrinkContext.ShrinkFiberState.Active); var tutorialStorage = new MemoryTutorialStorage(); var tutorial = new ShrinkTutorialRunner(tutorialStorage); var tutorialStarted = tutorial.Start(new ShrinkTutorialData { TutorialId = "godot-smoke", Steps = { new ShrinkTutorialStep { StepId = "one", CompleteCondition = ShrinkTutorialCompleteCondition.AnyClick } } }); var tutorialCompleted = tutorial.CompleteStep(); if (GodotSubscriber.Calls != 1 || GodotStaticSubscriber.Calls != 1 || savedValue != 42 || !app.IsRunning || !GodotInstaller.Initialized || activeFibers != 3 || !tutorialStarted || !tutorialCompleted || !tutorialStorage.Saved || !registries.Contains(nameof(ShrinkCommandStaticRegistryAttribute)) || !registries.Contains(nameof(ShrinkNetworkMessageRegistryAttribute))) { GD.PushError("ShrinkSDK Godot smoke failed."); GetTree().Quit(1); return; } await composition.ShutdownAsync(); var smokePath = System.IO.Path.Combine(OS.GetUserDataDir(), "shrink_smoke_pass.txt"); System.IO.File.WriteAllText(smokePath, $"CodeGen={marker.WeaverVersion};DataSaver={savedValue}"); if (!System.IO.File.Exists(smokePath)) throw new System.IO.IOException($"Failed to create smoke sentinel: {smokePath}"); GD.Print($"SHRINK_GODOT_SMOKE_PASS CodeGen={marker.WeaverVersion} DataSaver={savedValue}"); GetTree().Quit(0); } } public sealed class MemoryTutorialStorage : IShrinkTutorialStorage { private ShrinkTutorialProgress _progress = new(); public bool Saved { get; private set; } public ShrinkTutorialProgress Load() => _progress; public void Save(ShrinkTutorialProgress progress) { _progress = progress; Saved = true; } public void Reset() { _progress = new ShrinkTutorialProgress(); Saved = false; } } public readonly struct GodotSmokeEvent : IShrinkEvent { } [ShrinkEventSubscriber] public sealed class GodotSubscriber { public static int Calls; [ShrinkSubscribe] private void Handle(GodotSmokeEvent value) => Calls++; } [ShrinkEventSubscriber] public static class GodotStaticSubscriber { public static int Calls; [ShrinkSubscribe] private static void Handle(GodotSmokeEvent value) => Calls++; } [ShrinkCommandSubscriber] public static class GodotCommands { [ShrinkCommand("godot/smoke")] public static void Smoke() { } } [ShrinkNetworkMessage(42001, "godot/smoke")] public sealed class GodotSmokeMessage : IShrinkNetworkMessage { } [ShrinkAppModuleInstaller] public sealed class GodotInstaller : IShrinkAppModuleInstaller { public static bool Initialized; public string ModuleId => "godot-smoke"; public int Order => 0; public IReadOnlyList DependsOn => Array.Empty(); public void RegisterServices(ShrinkAppContext context) => context.Services.Register(this); public UniTask InitializeAsync(ShrinkAppContext context) { Initialized = true; return UniTask.CompletedTask; } }