Files
cneicy 8eaaa3040a
Publish UPM package / publish (push) Failing after 1s
chore: initialize standalone UPM package
2026-08-26 02:50:34 +08:00

110 lines
5.0 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Reflection;
using ShrinkNetwork;
using ShrinkNetwork.ServerHost;
using ShrinkNetwork.ServerHost.Framework;
ShrinkNetworkLogger.InfoHandler = msg => Console.WriteLine(msg);
ShrinkNetworkLogger.WarningHandler = msg => Console.WriteLine("[Warn] " + msg);
ShrinkNetworkLogger.ErrorHandler = msg => Console.Error.WriteLine(msg);
ShrinkNetworkLogger.ExceptionHandler = ex => Console.Error.WriteLine(ex);
var config = ServerHostProperties.LoadOrCreate();
var options = config.Options;
var modules = DiscoverModules();
var app = new ShrinkDedicatedServerApp(options, modules);
await app.StartAsync();
Console.WriteLine("ShrinkNetwork 独立服务器模板已启动。");
Console.WriteLine($"配置文件:{config.FilePath}");
Console.WriteLine($"首次生成默认配置:{config.CreatedDefaultFile}");
foreach (var warning in config.Warnings)
Console.WriteLine($"[Warn] 配置文件:{warning}");
Console.WriteLine($"TCP: 0.0.0.0:{options.Port}");
Console.WriteLine($"KCP: 0.0.0.0:{options.Port}");
Console.WriteLine($"Unity 扫描输出目录:{options.ScanOutputDirectory}");
Console.WriteLine($"Unity 资产扫描目录:{options.UnityAssetsPath}");
Console.WriteLine($"共享口令鉴权已启用:{!string.IsNullOrWhiteSpace(options.SharedAuthToken)}");
Console.WriteLine($"缺少口令时允许匿名登录:{options.AllowAnonymousWhenAuthTokenMissing}");
Console.WriteLine($"会话令牌已启用:{options.EnableSessionTokens}");
Console.WriteLine($"会话令牌 TTL(秒){options.SessionTokenTtlSeconds}");
Console.WriteLine($"会话令牌续期窗口(秒){options.SessionTokenRefreshWindowSeconds}");
Console.WriteLine($"会话令牌校验失败时断开会话:{options.DisconnectOnInvalidSessionToken}");
Console.WriteLine($"协议版本范围:{options.MinProtocolVersion}-{options.MaxProtocolVersion}");
Console.WriteLine($"Schema 版本范围:{options.MinSchemaVersion}-{options.MaxSchemaVersion}");
Console.WriteLine($"TCP TLS 已启用:{options.EnableTcpTls}");
if (options.EnableTcpTls)
{
Console.WriteLine($"TCP TLS 证书路径:{options.TcpTlsCertificatePath}");
Console.WriteLine($"TCP TLS SNI/目标主机:{options.TcpTlsTargetHost}");
}
if (string.IsNullOrWhiteSpace(options.SharedAuthToken) && !options.AllowAnonymousWhenAuthTokenMissing)
{
Console.WriteLine("[Warn] 当前未配置 SHRINK_SERVER_AUTH_TOKEN,登录请求默认会被拒绝。");
}
Console.WriteLine("[Info] 配置优先级:代码默认值 < server.properties < 环境变量");
Console.WriteLine("已加载模块:");
foreach (var module in modules)
Console.WriteLine($"- {module.Name}");
Console.WriteLine("按 Ctrl+C 退出。");
using var metricsCts = new CancellationTokenSource();
if (options.DiagnosticsLogIntervalSeconds > 0)
_ = RunDiagnosticsLoopAsync(app, options.DiagnosticsLogIntervalSeconds, metricsCts.Token);
Console.CancelKeyPress += (_, args) =>
{
args.Cancel = true;
metricsCts.Cancel();
DumpDiagnostics(app);
Environment.Exit(0);
};
try
{
await Task.Delay(Timeout.Infinite, metricsCts.Token);
}
catch (OperationCanceledException)
{
}
static IShrinkServerModule[] DiscoverModules()
{
return Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => typeof(IShrinkServerModule).IsAssignableFrom(type))
.Where(type => !type.IsAbstract && !type.IsInterface)
.Where(type => type.GetConstructor(Type.EmptyTypes) != null)
.Select(type => (IShrinkServerModule)Activator.CreateInstance(type)!)
.OrderBy(module => module.Name, StringComparer.Ordinal)
.ToArray();
}
static async Task RunDiagnosticsLoopAsync(ShrinkDedicatedServerApp app, int intervalSeconds, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
await Task.Delay(TimeSpan.FromSeconds(intervalSeconds), cancellationToken);
}
catch (OperationCanceledException)
{
break;
}
DumpDiagnostics(app);
}
}
static void DumpDiagnostics(ShrinkDedicatedServerApp app)
{
Console.WriteLine("[Metrics] ShrinkNetwork service snapshots:");
foreach (var pair in app.Context.Services.OrderBy(item => item.Key, StringComparer.OrdinalIgnoreCase))
{
var metrics = pair.Value.GetDiagnosticsSnapshot();
Console.WriteLine(
$"[Metrics][{pair.Key}] sessions={metrics.CurrentSessions} connected={metrics.SessionsConnected} disconnected={metrics.SessionsDisconnected} sent={metrics.PacketsSent}/{metrics.BytesSent}B recv={metrics.PacketsReceived}/{metrics.BytesReceived}B rpc={metrics.RpcStarted}/{metrics.RpcCompleted} timeout={metrics.RpcTimedOut} canceled={metrics.RpcCanceled} failed={metrics.RpcFailed} proto={metrics.ProtocolViolations} authRejected={metrics.AuthRejectedCount} denied={metrics.PermissionDeniedCount} handlerEx={metrics.HandlerExceptionCount} unknownOpcode={metrics.UnknownOpcodeCount} dispatchMiss={metrics.DispatchMissCount} serialization={metrics.SerializationErrorCount} queueReject={metrics.DispatchQueueRejectedCount}");
}
}