You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

320 lines
12 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Sog;
using Sog.Service;
using ProtoCSStruct;
namespace Mail
{
public class MailMsgHandler : BaseReloadableService
{
public override int GetServiceType()
{
return MailServiceType.MailMsgHandler;
}
//销毁的时候置空
public override void Dispose()
{
}
public void Tick()
{
var data = MailServerUtils.GetMailServerData();
var queue = data.m_threadSafePacketQueue;
int max = 500; //每次处理消息数,一般都是中转消息修改,不会处理复杂逻辑,这个值可以先大点,后续看性能情况
while (max > 0 && queue.TryDequeue(out var msg))
{
HandlerPacket(msg.RemoteApp, msg.Packet);
max--;
}
}
public bool IsCanStop()
{
var data = MailServerUtils.GetMailServerData();
var queue = data.m_threadSafePacketQueue;
if(!queue.IsEmpty)
{
TraceLog.Debug("MailMsgHandler.IsCanStop queue count {0}", queue.Count);
return false;
}
return true;
}
public void HandlerPacket(uint remoteAppID, StructPacket packet)
{
TraceLog.TraceDetail("MailMsgHandler.HandlerPacket MsgID {0}", packet.MsgID);
switch (packet.MsgID)
{
case (int)SSGameMsgID.MailOpRes:
OnMailOpRes(remoteAppID, packet);
break;
case (int)SSGameMsgID.QueryMailVersionRes:
OnQueryMailVersionRes(remoteAppID, packet);
break;
default:
TraceLog.Error("MailMsgHandler.HandlerPacket unknow MsgID {0}", packet.MsgID);
break;
}
}
public void HandlerMessage(uint remoteAppID, MessageData message)
{
StructPacket packet;
bool bSuccess = MailServerUtils.GetProtoPacker().UnpackMessage(message, out packet);
if(bSuccess == false)
{
TraceLog.Error("MailMsgHandler.HandlerMessage ,unpack msg failed {0}, remoteAppID {1}", message.Header.Type, remoteAppID);
return;
}
packet = packet.Clone();
//预先判断,提高效率
if (TraceLog.GetLogLevel() <= (int)Sog.Log.LogLevel.TraceDetail
&& TraceLog.IsSkipLogMsgID(packet.MsgID) == false)
{
TraceLog.TraceDetail("MailMsgHandler recv message from server {0}, message type {1} length {2} : {3}->{4}"
, ServerIDUtils.IDToString(remoteAppID)
, message.Header.Type
, message.Header.Length
, packet.MessageName()
, packet.ToString());
}
int iTaskIndex = 0;
switch (packet.MsgID)
{
case (int)SSGameMsgID.AddServerTimeSync:
OnAddServerTimeSync(remoteAppID, packet);
//不往后走了,直接return
return;
case (int)SSGameMsgID.RoleLoginSuccessNotify:
OnRoleLoginSuccessNotify(remoteAppID, packet);
return;
case (int)SSGameMsgID.GamePlayerDestroy:
OnGamePlayerDestroy(remoteAppID, packet);
return;
case (int)SSGameMsgID.SendMailWithRule://这个也不能多线程
OnSendMailWithRule(remoteAppID, packet);
return;
case (int)CSGameMsgID.SetLanguageReq:
OnSetPlayerLanguage(remoteAppID, packet);
return;
case (int)SSGameMsgID.DiscardMailWithRuleReq:
MailSendWithRule.OnDiscardMailWithRuleReq(remoteAppID, packet);
break;
case (int)SSGameMsgID.GetMailWithRuleRes:
MailSendWithRule.OnGetMailWithRuleRes(remoteAppID, packet);
break;
default:
long uid = GetUidFromPacket(packet);
iTaskIndex = (int)(uid % MessageTaskHandler.MailDBWorkThreadCount);
TraceLog.Debug("MailMsgHandler.HandlerMessage GetUidFromPacket MsgID {0} uid {1}", packet.MsgID, uid);
break;
}
//其它单线程处理,实际数据库操作Task多线程
if(packet.MsgID == (int)SSGameMsgID.OperationMailSearchReq || packet.MsgID == (int)SSGameMsgID.QueryMailReq || packet.MsgID == (int)SSGameMsgID.MailOpReq)
{
MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex);
}
}
private long GetUidFromPacket(StructPacket packet)
{
switch (packet.MsgID)
{
//mail
case (int)SSGameMsgID.QueryMailReq:
ref SSQueryMailReq querymailreq = ref packet.GetMessage<SSQueryMailReq>();
return querymailreq.Uid;
case (int)SSGameMsgID.OperationMailSearchReq:
ref SSOperationSearchMailReq req = ref packet.GetMessage<SSOperationSearchMailReq>();
return req.Uid;
case (int)SSGameMsgID.MailOpReq:
ref SSMailOpReq mailopreq = ref packet.GetMessage<SSMailOpReq>();
return mailopreq.Mail.Uid;
default:
TraceLog.Error("MailMsgHandler.GetUidFromPacket unknow MsgID {0}", packet.MsgID);
break;
}
//其他情况一律返回0
return 0;
}
public void OnSetPlayerLanguage(uint remoteAppID, StructPacket packet)
{
ref CSSetLanguageReq req = ref packet.GetMessage<CSSetLanguageReq>();
var players = MailServerUtils.GetMailServerData().m_playerTable;
long uid = packet.ObjectID;
if (players.ContainsKey(uid))
{
players[uid].Language = req.Lang.GetString();
}
}
private void OnMailOpRes(uint remoteAppID, StructPacket packet)
{
ref SSMailOpRes res = ref packet.GetMessage<SSMailOpRes>();
long uid = res.ClientOpUid;
var player = MailServerUtils.GetPlayerInfo(uid);
if(player == null)
{
return;
}
if(player.GameServerID != remoteAppID && res.OpType != (int)MailOpType.MailVerChange)
{
MailServerUtils.GetPacketSender().SendToServerByID(player.GameServerID,
(int)SSGameMsgID.MailOpRes, ref res, packet.ObjectID);
}
if(res.OpType == (int)MailOpType.MailVerChange)
{
player.SavedSuccessSeq = res.Seq;
}
}
private void OnQueryMailVersionRes(uint remoteAppID, StructPacket packet)
{
ref SSQueryMailVersionRes res = ref packet.GetMessage<SSQueryMailVersionRes>();
TraceLog.TraceDetail("MailMsgHandler.OnQueryMailVersionRes msg {0}", res.ToString());
var player = MailServerUtils.GetPlayerInfo(res.Uid);
if(player == null)
{
return;
}
//已经查询过了
if(player.isQueryMailVer)
{
return;
}
player.lastMailVer = res.Version;
player.isQueryMailVer = true;
MailSendWithRule.CheckAndSendMailWithRule(player);//检查全局邮件
}
public void OnAddServerTimeSync(uint remoteAppID, StructPacket packet)
{
ref SSAddServerTimeSync sync = ref packet.GetMessage<SSAddServerTimeSync>();
TraceLog.Debug("MailMsgHandler.OnAddServerTimeSync serverid {0} offset {1}"
, ServerIDUtils.IDToString(remoteAppID), sync.Offset);
MailServerUtils.GetApp().Time.SetOffset(sync.Offset);
MailServerUtils.GetApp().Time.UpdateTime();
TraceLog.Debug("MailMsgHandler.OnAddServerTimeSync serverid {0} offset {1} set time success"
, ServerIDUtils.IDToString(remoteAppID), sync.Offset);
}
public void OnRoleLoginSuccessNotify(uint remoteAppID, StructPacket packet)
{
ref SSRoleLoginSuccessNotify req = ref packet.GetMessage<SSRoleLoginSuccessNotify>();
if(req.Uid < 10000)
{
return;
}
TraceLog.Debug("MailMsgHandler.OnRoleLoginSuccessNotify userID {0} login",req.Uid);
var players = MailServerUtils.GetMailServerData().m_playerTable;
if(players.TryGetValue(req.Uid, out var player))
{
player.IsOnline = true;
player.RealmID = req.RealmID;
player.GameServerID = req.GameServerID;
player.ChatServerID = req.ChatServerID;
player.LogoutTime = 0;
player.Language = req.Language.GetString();
player.ApkVersion = req.ApkVersion.GetString();
}
else
{
player = new PlayerInfoMail();
player.UserID = req.Uid;
player.IsOnline = true;
player.RealmID = req.RealmID;
player.GameServerID = req.GameServerID;
player.ChatServerID = req.ChatServerID;
player.CreateTime = req.CreateTime;
player.LogoutTime = 0;
player.Language = req.Language.GetString();
player.ApkVersion = req.ApkVersion.GetString();
players.Add(req.Uid, player);
}
if(player.isQueryMailVer) //es
{
MailSendWithRule.CheckAndSendMailWithRule(player);//检查全局邮件
}
else
{
PlayerMailVerSeqSvc.SendQueryMailVer(player);
}
}
public void OnGamePlayerDestroy(uint remoteAppID, StructPacket packet)
{
ref SSGamePlayerDestroy req = ref packet.GetMessage<SSGamePlayerDestroy>();
var players = MailServerUtils.GetMailServerData().m_playerTable;
if (players.ContainsKey(req.Uid))
{
players[req.Uid].IsOnline = false;
players[req.Uid].LogoutTime = MailServerUtils.GetTimeSecond();
}
}
//批量邮件
public void OnSendMailWithRule(uint remoteAppID, StructPacket packet)
{
MailSendWithRule.GmSendMailWithRule(remoteAppID, packet);
}
//每分钟检查一次,和消息同属主线程
private static int TickPlayerIndex = 0;
public static void TickOneMinute(long nowSec)
{
var data = MailServerUtils.GetMailServerData();
if(data.m_playerTable.Count == 0)
{
return;
}
if(data.m_playerForUpdate == null)
{
TickPlayerIndex = 0;
data.m_playerForUpdate = data.m_playerTable.Values.ToList();
return;
}
for (int i = 0; i < 100; i++)
{
if(TickPlayerIndex >= data.m_playerForUpdate.Count)
{
TickPlayerIndex = 0;
data.m_playerForUpdate = data.m_playerTable.Values.ToList();
return;
}
PlayerInfoMail player = data.m_playerForUpdate[TickPlayerIndex];
TickPlayerIndex++;
if(player.IsOnline == false && player.LogoutTime + 1800 >= nowSec && !player.IsDirty())
{
data.m_playerTable.Remove(player.UserID);
}
}
}
}
}