Files
hjha-server/ServerCore/Actor/MailBox.cs
xiaoou e9616125ce feat: initial commit - HJHA game server full source
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
2026-07-07 12:02:15 +08:00

242 lines
8.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NetWorkMessage;
using Server.Core;
using MrWu.Debug;
namespace ActorCore
{
public struct MessageInfo
{
/// <summary>
/// 谁发来的
/// </summary>
public ActorId FormActorId;
/// <summary>
/// 包体
/// </summary>
public MessageObject MessageObject;
}
public class MailBox : IMailBox
{
private readonly Actor actor;
private ActorId actorId => actor.ActorId;
public MailBoxType MailBoxType => actor.MailBoxType;
public int HandleMaxMessageCount => actor.HandleMaxMessageCount;
private int actorTypeId => actor.ActorId.ActorTypeId;
//这里可以改成普通字典,这里没有线程安全问题
private readonly ConcurrentDictionary<uint, MessageSenderStruct> requestCallback =
new ConcurrentDictionary<uint, MessageSenderStruct>();
private readonly Dictionary<Type, ActorHandle> actorMessageHandle = new Dictionary<Type, ActorHandle>();
private readonly Dictionary<Type, ActorRpcHandle> actorRpcHandles = new Dictionary<Type, ActorRpcHandle>();
private readonly List<MessageInfo> list = new List<MessageInfo>();
public void RegisterMessageHandle(Type type, ActorHandle handle)
{
this.actorMessageHandle[type] = handle;
}
public void RegisterRPCHandle(Type type, ActorRpcHandle rpcHandle)
{
this.actorRpcHandles[type] = rpcHandle;
}
public MailBox(Actor actor)
{
this.actor = actor;
}
public void Update()
{
HandleActorMessage();
}
/// <summary>
/// 处理Actor消息
/// </summary>
private void HandleActorMessage()
{
list.Clear();
ActorMessageQueue.Instance.Fetch(this.actorTypeId, HandleMaxMessageCount, list);
// if (this.actorTypeId == ActorTypeId.NetInner)
// {
// Debug.Log($"当前数量:{list.Count}");
// }
foreach (MessageInfo messageInfo in list)
{
//执行Actor消息
_ = HandleActorMessage(messageInfo.FormActorId,messageInfo.MessageObject);
}
}
private async Task HandleActorMessage(ActorId fromActorId, MessageObject messageObject)
{
//Debug.Info($"HandleActorMessage {messageObject.GetType()}");
if (messageObject is IResponse response)
{
HandleIActorResponse(response);
return;
}
if (MailBoxType == MailBoxType.OrderedMessage)
{
using (await actor.Wait(CoroutineLockType.MailBox, actorTypeId))
{
try
{
//Debug.Log($"等待锁! {Thread.CurrentThread.ManagedThreadId}");
await _HandleActorMessage(fromActorId, messageObject);
//Debug.Log($"结束锁! {Thread.CurrentThread.ManagedThreadId}");
}
catch (Exception e)
{
Debug.Error("MailBox:" + e);
throw e;
}
}
}
else
{
await _HandleActorMessage(fromActorId, messageObject);
}
}
private async Task _HandleActorMessage(ActorId fromActorId,MessageObject messageObject)
{
switch (messageObject)
{
case IRequest request:
await HandleIActorRequest(fromActorId,request);
break;
default:
await HandleIActorMessage(fromActorId,messageObject);
break;
}
//执行完就回收消息 - 如果消息不想被回收 那就不要用池
ReferencePool.Recycle(messageObject);
}
/// <summary>
/// RPC 请求消息
/// </summary>
/// <param name="fromActorId"></param>>
/// <param name="request"></param>
private async Task HandleIActorRequest(ActorId fromActorId,IRequest request)
{
//等待处理
Type type = request.GetType();
IResponse response = MessageHelper.CreateResponse(type,request.RpcId,0);
if (!this.actorRpcHandles.TryGetValue(type,out ActorRpcHandle thisHandle))
{
Debug.Error($"not found rpc handle:{type} ActorId:{this.actor.ActorId} {this.actorRpcHandles.Count}");
response.Error = NetErrorCode.ERR_NotFoundHandle;
}
uint rpcId = request.RpcId;
if (response.Error == 0)
{
try
{
await thisHandle(fromActorId,request,response);
}
catch (Exception exception)
{
response.Error = NetErrorCode.ERR_RPCFail;
response.Message = exception.ToString();
Debug.Log($"exception:{exception}");
}
}
response.RpcId = rpcId;
Debug.Log($"Reply:{fromActorId} {response.GetType()}");
this.actor.Reply(fromActorId,response);
}
/// <summary>
/// RPC 响应消息
/// </summary>
/// <param name="response"></param>
private void HandleIActorResponse(IResponse response)
{
//Debug.Log($"HandleIActorResponse RpcId:{response.RpcId}");
if (!this.requestCallback.TryRemove(response.RpcId,out MessageSenderStruct actorMessageSender))
{
Debug.Warning($"ActorResponse: {response.GetType()}");
return;
}
Run(actorMessageSender,response);
}
private void Run(MessageSenderStruct self,IResponse response)
{
self.SetResult(response);
}
/// <summary>
/// 普通消息
/// </summary>
/// <param name="fromActorId"></param>
/// <param name="messageObject"></param>
private async Task HandleIActorMessage(ActorId fromActorId,MessageObject messageObject)
{
Type type = messageObject.GetType();
if (!this.actorMessageHandle.TryGetValue(type, out ActorHandle thisHandle))
{
Debug.Error($"not found message handle:{type} ActorId:{this.actor.ActorId}");
return;
}
//todo 等待处理
//此处要加上MailType的判断是否要等待上一个消息处理完成
//Debug.Log($"---- id:{this.ActorId.ActorTypeId}");
await thisHandle(fromActorId,messageObject);
}
public bool AddActorRpcResponse(uint rpcId, MessageSenderStruct messageSenderStruct)
{
return this.requestCallback.TryAdd(rpcId, messageSenderStruct);
}
public bool RemoveActorRpcResponse(uint rpcId,out MessageSenderStruct messageSenderStruct)
{
return this.requestCallback.TryRemove(rpcId, out messageSenderStruct);
}
public void Send(ActorId target, MessageObject messageObject)
{
if (target.Process == this.actorId.Process)
{
//发给内部Actor
ActorMessageQueue.Instance.Send(this.actorId, target, messageObject);
return;
}
//发给外部Actor
NetInnerMessage netInnerMessage = NetInnerMessage.Create();
netInnerMessage.ActorId = target;
netInnerMessage.MessageObject = messageObject;
ActorMessageQueue.Instance.Send(this.actorId,
new ActorId(this.actorId.Process, ActorTypeId.NetInner), netInnerMessage);
}
}
}