6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) + game logic (GameFix/GameDAL/ServerData) + network layer (NetWorkMessage) + data layer (ObjectModel) + utilities (MrWu/Core/Config/CloudAPI/dll) + adapters (zyxAdapter/base) .NET 8.0 C# solution, 16 projects, 958 source files
150 lines
4.7 KiB
C#
150 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
using MrWu.Debug;
|
|
using Server.Core;
|
|
|
|
namespace Server.Net
|
|
{
|
|
public delegate Task MessageDispatcherDelegate(GamePacket gamePacket);
|
|
|
|
/// <summary>
|
|
/// 网络消息 分发器
|
|
/// </summary>
|
|
public sealed class MessageDispatcher : SingleInstance<MessageDispatcher>
|
|
{
|
|
/// <summary>
|
|
/// 是否需要按顺序执行 一般来说子游戏需要按顺序执行,中心服务器不需要按顺序等待
|
|
/// </summary>
|
|
public bool IsOrderMessage { get; private set; }
|
|
|
|
private ConcurrentQueue<GamePacket> packes = new ConcurrentQueue<GamePacket>();
|
|
|
|
public void AddPack(GamePacket gamePacket)
|
|
{
|
|
//Debug.Info($"添加一个待处理包裹:{gamePacket.OpCode}");
|
|
packes.Enqueue(gamePacket);
|
|
}
|
|
|
|
private CoroutineLockManager coroutineLockManager;
|
|
|
|
private Dictionary<int, MessageDispatcherDelegate> listeners =
|
|
new Dictionary<int, MessageDispatcherDelegate>();
|
|
|
|
public void Start(bool isOrderMessage, CoroutineLockManager coroutineLockManager)
|
|
{
|
|
this.IsOrderMessage = isOrderMessage;
|
|
this.coroutineLockManager = coroutineLockManager;
|
|
}
|
|
|
|
public void AddListener(int msgId, MessageDispatcherDelegate messageDispatcherDelegate)
|
|
{
|
|
listeners[msgId] = messageDispatcherDelegate;
|
|
}
|
|
|
|
public void RemoveListener(int msgId, MessageDispatcherDelegate messageDispatcherDelegate)
|
|
{
|
|
if (listeners.ContainsKey(msgId) && listeners[msgId] == messageDispatcherDelegate)
|
|
{
|
|
listeners.Remove(msgId);
|
|
}
|
|
}
|
|
|
|
private const int MaxCnt = 200;
|
|
|
|
private int PackCnt;
|
|
|
|
//此处可以优化
|
|
public void Handle()
|
|
{
|
|
PackCnt = packes.Count;
|
|
if (PackCnt > MaxCnt)
|
|
{
|
|
Debug.ImportantLog($"单帧处理消息过多! {packes.Count}");
|
|
PackCnt = MaxCnt;
|
|
//进行统计
|
|
}
|
|
|
|
while (PackCnt -- > 0)
|
|
{
|
|
if (!packes.TryDequeue(out GamePacket pack))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (!listeners.TryGetValue(pack.OpCode, out var handle))
|
|
{
|
|
Debug.Error($"这个客户端消息没有处理器! {pack.OpCode}");
|
|
pack.Dispose();
|
|
continue;
|
|
}
|
|
|
|
if (IsOrderMessage)
|
|
{
|
|
_ = SafeInvokeOrderMessage(pack, handle);
|
|
// //同用户的消息顺序才需要等待上一个包的完成
|
|
// using (await coroutineLockManager.Wait(CoroutineLockType.ClientMessage, pack.Session.Id))
|
|
// {
|
|
// await SafeInvoke(pack, handle);
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
_ = SafeInvoke(pack, handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按玩家的顺序来处理
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task SafeInvokeOrderMessage(GamePacket packet, MessageDispatcherDelegate handler)
|
|
{
|
|
using (await coroutineLockManager.Wait(CoroutineLockType.ClientMessage, packet.Session.InstanceId))
|
|
{
|
|
await SafeInvoke(packet, handler);
|
|
}
|
|
}
|
|
|
|
private async Task SafeInvoke(GamePacket packet, MessageDispatcherDelegate handler)
|
|
{
|
|
try
|
|
{
|
|
if (packet.Session.IsDisConnected)
|
|
{
|
|
return;
|
|
}
|
|
|
|
long key = Debug.StartTiming();
|
|
await handler(packet);
|
|
double _runtime = Debug.GetRunTime(key);
|
|
if (_runtime > 1000f)
|
|
{
|
|
Debug.Warning($"消息执行处理慢:{packet.OpCode} {_runtime}");
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Error($"消息处理异常:{packet.OpCode} {e.Message}");
|
|
}
|
|
finally
|
|
{
|
|
await PacketDispose(packet);
|
|
}
|
|
}
|
|
|
|
private async Task PacketDispose(GamePacket packet)
|
|
{
|
|
try
|
|
{
|
|
await packet.Wait();
|
|
}
|
|
finally
|
|
{
|
|
packet.Dispose();
|
|
}
|
|
}
|
|
}
|
|
} |