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
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|