actor消息:
[Message(OuterOpcode.Actor_Test)]
[ProtoContract]
public partial class Actor_Test: IActorMessage
{
[ProtoMember(90, IsRequired = true)]
public int RpcId { get; set; }
[ProtoMember(93, IsRequired = true)]
public long ActorId { get; set; }
[ProtoMember(1, IsRequired = true)]
public string Info;
}
客户端:
private void OnSend()
{
// 发送一个actor消息
ETModel.SessionComponent.Instance.Session.Send(new Actor_Test() { Info = "message client->gate->map->gate->client" });
}
服务器:
一,网关服务器:
1,OuterMessageDispatcher:
收到消息,判断是否是actor消息,用ActorMessageSender发送actor消息,
case IActorMessage iActorMessage: // gate session收到actor消息直接转发给actor自己去处理
{
long unitId = session.GetComponent<SessionPlayerComponent>().Player.UnitId;//获取map服务器的unit的unitid
ActorMessageSender actorMessageSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(unitId);//根据unitid获取ActorMessageSender,ActorMessageSender包含了根据map服务器的unit的unitid得到的mapsession,来让ActorMessageSender知道发送到哪个服务器
actorMessageSender.Send(iActorMessage);向这个服务器发送actor消息
return;
}
二,map服务器:
1,InnerMessageDispatcher:map服务器,
收到网关服务器消息,进行分发,放入map服务器的MailBox里
public class InnerMessageDispatcher: IMessageDispatcher
{
public void Dispatch(Session session, Packet packet)
{
IMessage message;
try
{
Type messageType = Game.Scene.GetComponent<OpcodeTypeComponent>().GetType(packet.Opcode);
message = (IMessage)session.Network.MessagePacker.DeserializeFrom(messageType, packet.Bytes, packet.Offset, packet.Length);
}
catch (Exception e)
{
// 出现任何解析消息异常都要断开Session,防止客户端伪造消息
Log.Error(e);
session.Error = ErrorCode.ERR_PacketParserError;
session.Network.Remove(session.Id);
return;
}
// 收到actor消息,放入actor队列
if (message is IActorMessage iActorMessage)
{
Entity entity = (Entity)Game.EventSystem.Get(iActorMessage.ActorId);//根据ActorId获取到map服务器上的unit
if (entity == null)
{
Log.Warning($"not found actor: {iActorMessage.ActorId}");
ActorResponse response = new ActorResponse
{
Error = ErrorCode.ERR_NotFoundActor,
RpcId = iActorMessage.RpcId
};
session.Reply(response);
return;
}
MailBoxComponent mailBoxComponent = entity.GetComponent<MailBoxComponent>();//获取unit上的MailBox
if (mailBoxComponent == null)
{
ActorResponse response = new ActorResponse
{
Error = ErrorCode.ERR_ActorNoMailBoxComponent,
RpcId = iActorMessage.RpcId
};
session.Reply(response);
Log.Error($"actor没有挂载MailBoxComponent组件: {entity.GetType().Name} {entity.Id}");
return;
}
mailBoxComponent.Add(new ActorMessageInfo() { Session = session, Message = iActorMessage });//放入MailBox转发消息
return;
}
Game.Scene.GetComponent<MessageDispatherComponent>().Handle(session, new MessageInfo(packet.Opcode, message));
}
}
2,MailBoxComponent,map服务器,邮箱来处理actor消息
public static async void HandleAsync(this MailBoxComponent self)
{
ActorMessageDispatherComponent actorMessageDispatherComponent = Game.Scene.GetComponent<ActorMessageDispatherComponent>();
long instanceId = self.InstanceId;
while (true)
{
if (self.InstanceId != instanceId)
{
return;
}
try
{
ActorMessageInfo info = await self.GetAsync();
// 返回null表示actor已经删除,协程要终止
if (info.Message == null)
{
return;
}
// 根据这个actor的类型分发给相应的ActorHandler处理
await actorMessageDispatherComponent.ActorTypeHandle(self.ActorType, (Entity)self.Parent, info);//根据ActorType来判断是哪一个ActorTypeHandler来处理actor消息(CommonActorTypeHandler或者GateSessionActorTypeHandler),这里的actor消息是CommonActorTypeHandler。怎么判断是哪种actor消息呢?gate session收到的actor消息是GateSessionActorTypeHandler来处理,其他服务器是CommonActorTypeHandler来处理
}
catch (Exception e)
{
Log.Error(e);
}
}
}
3,CommonActorTypeHandler,map服务器,来处理map服务器的actor消息
public class CommonActorTypeHandler : IActorTypeHandler
{
public async Task Handle(Session session, Entity entity, IActorMessage actorMessage)
{
await Game.Scene.GetComponent<ActorMessageDispatherComponent>().Handle(session, entity, actorMessage);//执行actor消息的对应的处理函数,
}
}
4,Actor_TestHandler,map服务器,是Actor_Test消息的处理函数
public class Actor_TestHandler : AMActorHandler<Unit, Actor_Test>
{
protected override async Task Run(Unit unit, Actor_Test message)
{
Log.Debug(message.Info);
long gateSessionId= unit.GetComponent<UnitGateComponent>().GateSessionActorId;//这里获取到gate服务器上,客户端的sessionid。
ActorMessageSender gateSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().GetWithActorId(gateSessionId);//根据客户端的sessionid创建向gate服务器发送actor消息的ActorMessageSender,作用是map服务器-gate服务器,
Actor_TestGate msg=new Actor_TestGate();
msg.Info = message.Info;
gateSender.Send(msg);//向gate服务器发送actor消息
//await Task.CompletedTask;
}
}
5,InnerMessageDispatcher,gate服务器收到actor消息的处理函数
6,MailBoxComponent,gate服务器,邮箱来处理actor消息
7,GateSessionActorTypeHandler,gate服务器,收到actor消息将消息发给客户端
总结:客户端发来 IActorMessage,处理流程是:
客户端-gate服务器-map服务器-gate服务器-客户端