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