Files
ShrinkApp.Starter.Basic/Runtime/ShrinkAppBasicDemoRuntime.cs
T
cneicy 4930099af7
Publish UPM package / publish (push) Failing after 1s
chore: initialize standalone UPM package
2026-08-26 02:49:29 +08:00

215 lines
9.4 KiB
C#

#nullable enable
using System;
using System.Linq;
using Cysharp.Threading.Tasks;
using ShrinkCommand;
using ShrinkCommand.Integration.App;
using ShrinkContext.AppAdapter;
using ShrinkNetwork;
using ShrinkNetwork.Integration.App;
using UnityEngine;
namespace ShrinkApp.Starter.Basic
{
public sealed class ShrinkAppBasicCommandSource : IShrinkCommandSource
{
private readonly Action<string>? _sink;
private readonly bool _logToConsole;
public ShrinkAppBasicCommandSource(Action<string>? sink = null, bool logToConsole = true)
{
_sink = sink;
_logToConsole = logToConsole;
}
public string SourceId => "starter.basic.console";
public string DisplayName => "StarterBasicConsole";
public bool IsConsole => true;
public bool HasPermission(string permission) => true;
public UniTask WriteLineAsync(string message, System.Threading.CancellationToken cancellationToken = default)
{
_sink?.Invoke(message);
if (_logToConsole)
Debug.Log("[ShrinkApp.Basic.Command] " + message);
return UniTask.CompletedTask;
}
}
[ShrinkCommandSubscriber]
public static class ShrinkAppBasicDemoCommands
{
[ShrinkCommand("starter status", Description = "显示 Starter.Basic 当前状态")]
private static string StarterStatus()
{
var appRunning = ShrinkApp.IsRunning;
var loadedSlot = ShrinkDataSaver.ShrinkSave.LoadedSlot;
return $"appRunning={appRunning}, loadedSlot={loadedSlot}";
}
}
public static class ShrinkAppBasicDemoRuntime
{
private const string SettingsResourceName = "ShrinkAppBasicStarterSettings";
private static ShrinkLoopbackTransport? _loopbackClientTransport;
private static ShrinkLoopbackTransport? _loopbackServerTransport;
private static long _activeLoopbackSessionId = -1;
public static ShrinkAppBasicStarterSettings GetOrCreateSettings()
{
var asset = Resources.Load<ShrinkAppBasicStarterSettings>(SettingsResourceName);
if (asset != null)
return asset;
var fallback = ScriptableObject.CreateInstance<ShrinkAppBasicStarterSettings>();
fallback.defaultCommandText = "starter status";
fallback.defaultLoopbackSessionId = 1;
fallback.logCommandOutputToConsole = true;
return fallback;
}
public static string BuildStatusSummary()
{
var commandReady = ShrinkApp.Context?.Services.TryGet<ShrinkCommandAppService>(out _) == true;
var networkReady = ShrinkApp.Context?.Services.TryGet<ShrinkNetworkAppService>(out _) == true;
var dataSaverReady = ShrinkApp.Context?.Services.TryGet<ShrinkDataSaver.Integration.App.ShrinkDataSaverService>(out _) == true;
var appRunning = ShrinkApp.IsRunning || ShrinkAppLoaderBootstrapper.Instance?.Host.IsRunning == true;
return $"app={appRunning}, save={dataSaverReady}, cmd={commandReady}, net={networkReady}, loopbackSession={_activeLoopbackSessionId}";
}
public static string BuildDetailedStatus()
{
var settings = GetOrCreateSettings();
var recentSlot = ShrinkDataSaver.ShrinkSave.GetRecentSlotIndex();
var commandService = ShrinkApp.Context?.Services.TryGet<ShrinkCommandAppService>(out var command) == true ? command : null;
var networkService = ShrinkApp.Context?.Services.TryGet<ShrinkNetworkAppService>(out var network) == true ? network : null;
var diagnostics = networkService?.GetDiagnosticsSnapshot();
var moduleCount = ShrinkAppLoaderBootstrapper.Instance?.Host.ActiveModuleIds.Count
?? ShrinkApp.Host?.StartedModules.Count
?? 0;
var serviceCount = ShrinkApp.Context?.Services.GetRegisteredServiceTypeNames().Count ?? 0;
return
$"defaultCommand={settings.defaultCommandText}\n" +
$"loopbackAutoBind={settings.autoBindLoopbackTransport}, sessionId={settings.defaultLoopbackSessionId}\n" +
$"recentSlot={recentSlot}, loadedSlot={ShrinkDataSaver.ShrinkSave.LoadedSlot}\n" +
$"modules={moduleCount}, services={serviceCount}, commandCount={commandService?.Commands.Count ?? 0}, currentSessions={diagnostics?.CurrentSessions ?? 0}\n" +
$"{BuildStatusSummary()}";
}
public static string BuildModuleSummary()
{
var loaderHost = ShrinkAppLoaderBootstrapper.Instance?.Host;
if (loaderHost != null && loaderHost.ActiveModuleIds.Count > 0)
return string.Join("\n", loaderHost.ActiveModuleIds);
if (ShrinkApp.Host?.StartedModules == null || ShrinkApp.Host.StartedModules.Count == 0)
return "No started modules.";
return string.Join("\n", ShrinkApp.Host.StartedModules);
}
public static string BuildServiceSummary()
{
if (ShrinkApp.Context == null)
return "No registered services.";
return string.Join("\n", ShrinkApp.Context.Services.GetRegisteredServiceTypeNames());
}
public static string BuildSaveMetaSummary(ShrinkDataSaver.SaveMeta[]? metas)
{
if (metas == null || metas.Length == 0)
return "No save slots found.";
return string.Join("\n", metas
.OrderBy(meta => meta.SlotIndex)
.Select(meta =>
$"slot={meta.SlotIndex}, name={meta.SlotName}, playtime={meta.PlaytimeSeconds:F0}s, modified={meta.LastModifiedTime:g}"));
}
public static string BuildCommandListSummary()
{
if (ShrinkApp.Context?.Services.TryGet<ShrinkCommandAppService>(out var commandService) != true || commandService == null)
return "Command service not ready.";
return string.Join("\n", commandService.Commands
.OrderBy(command => command.Path, StringComparer.OrdinalIgnoreCase)
.Take(10)
.Select(command => command.Path));
}
public static string BuildNetworkSummary()
{
if (ShrinkApp.Context?.Services.TryGet<ShrinkNetworkAppService>(out var networkService) != true || networkService == null)
return "Network service not ready.";
var diagnostics = networkService.GetDiagnosticsSnapshot();
var sessions = networkService.GetSessionSummaries();
return
$"sessions={diagnostics.CurrentSessions}, connected={diagnostics.SessionsConnected}, disconnected={diagnostics.SessionsDisconnected}\n" +
$"packetsSent={diagnostics.PacketsSent}, packetsReceived={diagnostics.PacketsReceived}\n" +
$"rpcStarted={diagnostics.RpcStarted}, rpcCompleted={diagnostics.RpcCompleted}\n" +
string.Join("\n", sessions);
}
public static async UniTask<string> ExecuteCommandAsync(string? commandText, Action<string>? outputSink = null)
{
var command = ShrinkApp.Services.GetRequired<ShrinkCommandAppService>();
var settings = GetOrCreateSettings();
var source = new ShrinkAppBasicCommandSource(outputSink, settings.logCommandOutputToConsole);
var effectiveCommand = string.IsNullOrWhiteSpace(commandText)
? settings.defaultCommandText
: commandText.Trim();
var result = await command.ExecuteAsync(source, effectiveCommand);
if (!string.IsNullOrWhiteSpace(result.Message))
outputSink?.Invoke(result.Message);
return result.Message;
}
public static string EnsureLoopbackReady()
{
var network = ShrinkApp.Services.GetRequired<ShrinkNetworkAppService>().Service;
var settings = GetOrCreateSettings();
if (_loopbackClientTransport == null || _loopbackServerTransport == null)
{
_loopbackClientTransport = new ShrinkLoopbackTransport();
_loopbackServerTransport = new ShrinkLoopbackTransport();
_loopbackClientTransport.LinkPeer(_loopbackServerTransport);
}
network.BindTransport(_loopbackClientTransport);
if (_activeLoopbackSessionId != settings.defaultLoopbackSessionId)
{
if (_activeLoopbackSessionId >= 0)
_loopbackClientTransport.CloseSession(_activeLoopbackSessionId);
_activeLoopbackSessionId = settings.defaultLoopbackSessionId;
_loopbackClientTransport.OpenSession(_activeLoopbackSessionId);
}
return $"loopbackBound={network.Sessions.Count}, session={_activeLoopbackSessionId}";
}
public static string AutoBindLoopbackIfEnabled()
{
var settings = GetOrCreateSettings();
if (!settings.autoBindLoopbackTransport)
return string.Empty;
return EnsureLoopbackReady();
}
public static string DisconnectLoopback()
{
if (_loopbackClientTransport == null || _activeLoopbackSessionId < 0)
return "loopbackNotBound";
_loopbackClientTransport.CloseSession(_activeLoopbackSessionId);
_activeLoopbackSessionId = -1;
return "loopbackDisconnected";
}
}
}