This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
#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";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user