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

146 lines
5.4 KiB
Plaintext

using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
namespace ShrinkNetwork.ServerHost.Framework;
public sealed class UnityNetworkScanManifest
{
public string AssetsPath { get; set; } = string.Empty;
public DateTimeOffset ScannedAtUtc { get; set; }
public List<UnityNetworkMessageEntry> Messages { get; set; } = new();
public List<UnityNetworkSubscriberEntry> Subscribers { get; set; } = new();
}
public sealed class UnityNetworkMessageEntry
{
public string FilePath { get; set; } = string.Empty;
public string TypeName { get; set; } = string.Empty;
public int Opcode { get; set; }
public string Route { get; set; } = string.Empty;
}
public sealed class UnityNetworkSubscriberEntry
{
public string FilePath { get; set; } = string.Empty;
public string MemberName { get; set; } = string.Empty;
public string Authority { get; set; } = string.Empty;
public string Permission { get; set; } = string.Empty;
}
public static class UnityNetworkCodeScanner
{
private static readonly Regex MessageRegex = new(
@"\[ShrinkNetworkMessage\((?<opcode>-?\d+)\s*,\s*""(?<route>[^""]+)""\)\][\s\S]*?(?:class|struct)\s+(?<name>\w+)",
RegexOptions.Compiled);
private static readonly Regex SubscriberRegex = new(
@"\[ShrinkNetworkSubscribe\((?<args>.*?)\)\][\s\S]*?(?:UniTask<.*?>|UniTask|void|Task<.*?>|Task)\s+(?<name>\w+)\s*\(",
RegexOptions.Compiled);
private static readonly Regex AuthorityRegex = new(
@"Authority\s*=\s*ShrinkNetworkAuthority\.(?<value>\w+)",
RegexOptions.Compiled);
private static readonly Regex PermissionRegex = new(
@"Permission\s*=\s*""(?<value>[^""]+)""",
RegexOptions.Compiled);
public static UnityNetworkScanManifest Scan(string assetsPath)
{
var manifest = new UnityNetworkScanManifest
{
AssetsPath = assetsPath,
ScannedAtUtc = DateTimeOffset.UtcNow
};
if (!Directory.Exists(assetsPath))
return manifest;
foreach (var file in Directory.EnumerateFiles(assetsPath, "*.cs", SearchOption.AllDirectories))
{
if (file.IndexOf($"{Path.DirectorySeparatorChar}Editor{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase) >= 0)
continue;
var content = File.ReadAllText(file);
var relativePath = Path.GetRelativePath(assetsPath, file).Replace('\\', '/');
foreach (Match match in MessageRegex.Matches(content))
{
manifest.Messages.Add(new UnityNetworkMessageEntry
{
FilePath = relativePath,
TypeName = match.Groups["name"].Value,
Opcode = int.Parse(match.Groups["opcode"].Value),
Route = match.Groups["route"].Value
});
}
foreach (Match match in SubscriberRegex.Matches(content))
{
var args = match.Groups["args"].Value;
manifest.Subscribers.Add(new UnityNetworkSubscriberEntry
{
FilePath = relativePath,
MemberName = match.Groups["name"].Value,
Authority = AuthorityRegex.Match(args).Groups["value"].Value,
Permission = PermissionRegex.Match(args).Groups["value"].Value
});
}
}
manifest.Messages = manifest.Messages
.OrderBy(item => item.Opcode)
.ThenBy(item => item.TypeName, StringComparer.Ordinal)
.ToList();
manifest.Subscribers = manifest.Subscribers
.OrderBy(item => item.Permission, StringComparer.Ordinal)
.ThenBy(item => item.MemberName, StringComparer.Ordinal)
.ToList();
return manifest;
}
public static void WriteOutputs(UnityNetworkScanManifest manifest, string outputDirectory)
{
Directory.CreateDirectory(outputDirectory);
var jsonPath = Path.Combine(outputDirectory, "unity-network-scan.json");
var markdownPath = Path.Combine(outputDirectory, "UNITY_NETWORK_SCAN.md");
File.WriteAllText(jsonPath, JsonSerializer.Serialize(manifest, new JsonSerializerOptions
{
WriteIndented = true
}));
var markdown = new StringBuilder();
markdown.AppendLine("# Unity 网络代码扫描清单");
markdown.AppendLine();
markdown.AppendLine($"扫描时间:{manifest.ScannedAtUtc:yyyy-MM-dd HH:mm:ss} UTC");
markdown.AppendLine($"Assets 路径:`{manifest.AssetsPath}`");
markdown.AppendLine();
markdown.AppendLine("## 网络消息");
markdown.AppendLine();
foreach (var message in manifest.Messages)
markdown.AppendLine($"- `{message.Opcode}` `{message.Route}` `{message.TypeName}` [{message.FilePath}]");
markdown.AppendLine();
markdown.AppendLine("## 订阅与权限");
markdown.AppendLine();
if (manifest.Subscribers.Count == 0)
{
markdown.AppendLine("- 本次扫描未发现 `[ShrinkNetworkSubscribe]`。");
}
else
{
foreach (var subscriber in manifest.Subscribers)
markdown.AppendLine($"- `{subscriber.MemberName}` authority=`{subscriber.Authority}` permission=`{subscriber.Permission}` [{subscriber.FilePath}]");
}
File.WriteAllText(markdownPath, markdown.ToString());
}
}