171 lines
6.0 KiB
C#
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()}";
|
|
}
|
|
}
|
|
}
|