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

171 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
namespace ShrinkModFramework
{
public static class ShrinkModNetworkManager
{
private sealed class HandlerRegistration
{
public Type PayloadType;
public Action<ShrinkModNetworkMessageContext, object> Handler;
}
private static readonly Dictionary<string, HandlerRegistration> Handlers = new(StringComparer.Ordinal);
private static IShrinkModNetworkTransport _transport;
private static bool _enabled = true;
private static bool _verboseLogging;
public static bool HasTransport => _transport != null;
public static void Configure(bool enabled, bool verboseLogging)
{
_enabled = enabled;
_verboseLogging = verboseLogging;
}
public static void SetTransport(IShrinkModNetworkTransport transport)
{
if (_transport != null)
_transport.OnEnvelopeReceived -= OnEnvelopeReceived;
_transport = transport;
if (_transport != null)
{
_transport.OnEnvelopeReceived += OnEnvelopeReceived;
if (_verboseLogging)
Debug.Log("[ShrinkModNetwork] 已绑定网络传输层。");
}
}
public static void RegisterHandler<T>(string modId, string channel, Action<ShrinkModNetworkMessageContext, T> handler)
{
if (string.IsNullOrWhiteSpace(modId))
throw new ArgumentException("模组 ID 不能为空。", nameof(modId));
if (string.IsNullOrWhiteSpace(channel))
throw new ArgumentException("频道名不能为空。", nameof(channel));
if (handler == null)
throw new ArgumentNullException(nameof(handler));
var key = BuildKey(modId, channel);
if (Handlers.ContainsKey(key))
throw new InvalidOperationException($"网络频道已注册:{key}");
Handlers.Add(key, new HandlerRegistration
{
PayloadType = typeof(T),
Handler = (context, payload) => handler(context, (T)payload)
});
}
public static void SendToServer<T>(string modId, string channel, T payload, string senderPeerId = null)
{
SendInternal(modId, channel, payload, senderPeerId, null, ShrinkModNetworkTarget.Server);
}
public static void SendToAllClients<T>(string modId, string channel, T payload, string senderPeerId = null)
{
SendInternal(modId, channel, payload, senderPeerId, null, ShrinkModNetworkTarget.AllClients);
}
public static void SendToClient<T>(string modId, string channel, T payload, string targetPeerId, string senderPeerId = null)
{
SendInternal(modId, channel, payload, senderPeerId, targetPeerId, ShrinkModNetworkTarget.SpecificClient);
}
internal static void ResetForDomainReload()
{
Handlers.Clear();
SetTransport(null);
_enabled = true;
_verboseLogging = false;
}
internal static void UnregisterHandlers(string modId)
{
if (string.IsNullOrWhiteSpace(modId))
return;
var prefix = modId.Trim() + "::";
var keys = new List<string>();
foreach (var key in Handlers.Keys)
{
if (key.StartsWith(prefix, StringComparison.Ordinal))
keys.Add(key);
}
foreach (var key in keys)
Handlers.Remove(key);
}
private static void SendInternal<T>(string modId, string channel, T payload, string senderPeerId, string targetPeerId,
ShrinkModNetworkTarget target)
{
if (!_enabled)
return;
if (_transport == null)
{
Debug.LogWarning($"[ShrinkModNetwork] 当前没有传输层,消息 {modId}/{channel} 被丢弃。");
return;
}
var envelope = new ShrinkModNetworkEnvelope
{
ModId = modId,
Channel = channel,
PayloadJson = JsonConvert.SerializeObject(payload),
SenderPeerId = senderPeerId,
TargetPeerId = targetPeerId,
Target = target
};
_transport.Send(envelope);
}
private static void OnEnvelopeReceived(ShrinkModNetworkEnvelope envelope)
{
if (!_enabled || envelope == null)
return;
var key = BuildKey(envelope.ModId, envelope.Channel);
if (!Handlers.TryGetValue(key, out var registration))
{
if (_verboseLogging)
Debug.LogWarning($"[ShrinkModNetwork] 未找到频道处理器:{key}");
return;
}
try
{
var payload = JsonConvert.DeserializeObject(envelope.PayloadJson, registration.PayloadType);
var context = new ShrinkModNetworkMessageContext(
envelope.SenderPeerId,
envelope.TargetPeerId,
envelope.Target,
_transport != null && _transport.IsServer,
_transport != null && _transport.IsClient);
registration.Handler(context, payload);
}
catch (Exception ex)
{
Debug.LogError($"[ShrinkModNetwork] 处理频道 {key} 失败:{ex.Message}");
}
}
private static string BuildKey(string modId, string channel)
{
if (string.IsNullOrWhiteSpace(modId))
throw new ArgumentException("模组 ID 不能为空。", nameof(modId));
if (string.IsNullOrWhiteSpace(channel))
throw new ArgumentException("频道名不能为空。", nameof(channel));
return $"{modId.Trim()}::{channel.Trim()}";
}
}
}