215 lines
9.4 KiB
C#
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";
|
|
}
|
|
}
|
|
}
|