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.
300 lines
11 KiB
300 lines
11 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
using Sog;
|
|
using ProtoCSStruct;
|
|
|
|
namespace World
|
|
{
|
|
public static class GameReportSvc
|
|
{
|
|
//上报时间间隔,服务器启动的时候会变
|
|
private static int m_ReportAccountSecondInterVal = 5;
|
|
//最大上报时间间隔, 也不能太慢,realmList进程需要及时知道个game进程的online情况,用来做选择
|
|
private const int ReportAccountSecondInterValMax = 20;
|
|
private static long lastReportAccountTime = 0;
|
|
|
|
private static long lastLogOnlineTime = 0;
|
|
|
|
private static long lastForceGetAllRealmTime = 0;
|
|
|
|
public static int WorldOnlinePlayerCount { get; private set;}
|
|
|
|
|
|
//game或者gamegate的上报
|
|
public static void OnGameReportReq(uint remoteAppID, StructPacket packet)
|
|
{
|
|
ref SSGameReportReq gameReportReq = ref packet.GetMessage<SSGameReportReq>();
|
|
|
|
int onlinePlayer = gameReportReq.OnlinePlayer;
|
|
|
|
bool find = false;
|
|
var svrData = WorldServerUtils.GetWorldServerData();
|
|
|
|
foreach (var info in svrData.m_gameSvrInfo)
|
|
{
|
|
if (info.serverId == gameReportReq.GameSvrid)
|
|
{
|
|
info.onlinePlayer = onlinePlayer;
|
|
find = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (find == false)
|
|
{
|
|
svrData.m_gameSvrInfo.Add(new GameSvrInfoWorld {serverId = gameReportReq.GameSvrid, onlinePlayer = onlinePlayer});
|
|
}
|
|
|
|
//如果是game,要判断md5是否已经成功拉取
|
|
if (ServerIDUtils.GetServerType(gameReportReq.GameSvrid) == (int)ServerType.Game)
|
|
{
|
|
//如果有game进程没有获取成功RecvConfigRealmListMd5, 则强制全量拉取
|
|
if (gameReportReq.RecvConfigRealmListMd5.IsEmpty())
|
|
{
|
|
svrData.recvRealmListMd5 = null;
|
|
m_ReportAccountSecondInterVal = 2; //马上发起一次查询
|
|
|
|
TraceLog.Trace("SysSvc.OnGameReportReq from server {0}, RecvConfigRealmListMd5 is empty , force clear svrData.recvRealmListMd5"
|
|
, ServerIDUtils.IDToString(gameReportReq.GameSvrid));
|
|
}
|
|
}
|
|
|
|
TraceLog.Trace("SysSvc.OnGameReportReq from server {0}, online {1}"
|
|
, ServerIDUtils.IDToString(gameReportReq.GameSvrid)
|
|
, gameReportReq.OnlinePlayer);
|
|
}
|
|
|
|
public static void OnRealmOnlineReport(uint remoteAppID, StructPacket packet)
|
|
{
|
|
ref SSOnlineReport report = ref packet.GetMessage<SSOnlineReport>();
|
|
|
|
var onlineTable = WorldServerUtils.GetWorldServerData().realmOnlineGame;
|
|
|
|
// 一个realm可以分布在多个gamesvr上, 一个gamesvr可以有多个realm
|
|
// 统计每个gamesvr上的realm在线信息, 然后在tick时累加获得realm的实际在线
|
|
List<RealmOnline> gameSvrOnline;
|
|
if (! onlineTable.TryGetValue(remoteAppID, out gameSvrOnline))
|
|
{
|
|
gameSvrOnline = new List<RealmOnline>();
|
|
onlineTable.Add(remoteAppID, gameSvrOnline);
|
|
}
|
|
|
|
for (int i = 0; i < report.RealmOnline.Count; i++)
|
|
{
|
|
int realmId = report.RealmOnline[i].Id;
|
|
int onlineNum = report.RealmOnline[i].Value;
|
|
|
|
RealmOnline info = gameSvrOnline.FirstOrDefault(d => d.realmId == realmId);
|
|
if (info != null)
|
|
{
|
|
info.onlineNum = onlineNum;
|
|
}
|
|
else
|
|
{
|
|
info = new RealmOnline {realmId = realmId, onlineNum = onlineNum};
|
|
gameSvrOnline.Add(info);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void OnGameReportRealmlistRes(uint remoteAppID, StructPacket packet)
|
|
{
|
|
//备机不处理
|
|
if(AccountServerSelect.IsBackAccountServer(remoteAppID))
|
|
{
|
|
return;
|
|
}
|
|
|
|
ref SSGameReportRealmlistRes res = ref packet.GetMessage<SSGameReportRealmlistRes>();
|
|
var serverData = WorldServerUtils.GetWorldServerData();
|
|
//需要这个临时保存列表,是为了防止2个消息过程中有不完整的configRealm的情况发生
|
|
var tmpRealmsRecv = serverData.m_configRealmTempForRecv;
|
|
|
|
//0 表示realmList服务器还没有更新,是老的, 1表示是新的realmList发出的第一个消息
|
|
if (res.MsgIndexFrom1 == 0 || res.MsgIndexFrom1 == 1)
|
|
{
|
|
tmpRealmsRecv.Clear();
|
|
}
|
|
|
|
//先加入临时列表
|
|
for (int i = 0; i < res.RealmList.Count; i++)
|
|
{
|
|
var realm = new RealmBriefInfo(ref res.RealmList[i]);
|
|
tmpRealmsRecv[realm.realmId] = realm;
|
|
}
|
|
|
|
//如果是最后一个消息了
|
|
if (res.MsgIndexFrom1 == 0 || res.RealmList.Count == 0)
|
|
{
|
|
serverData.m_configRealm.Clear();
|
|
serverData.m_configRealmMap.Clear();
|
|
|
|
var recordInfo = WorldServerUtils.GetWorldMainlandRecordData();
|
|
//排个序
|
|
var list = tmpRealmsRecv.OrderBy(o => o.Key).ToList();
|
|
for (int i = 0; i < list.Count; i++)
|
|
{
|
|
var realm = list[i].Value;
|
|
serverData.m_configRealm.Add(realm);
|
|
serverData.m_configRealmMap.Add(realm.realmId, realm);
|
|
if (!recordInfo.m_logicWorldMap.ContainsKey(realm.logicWorldId))
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
serverData.recvRealmListMd5 = res.RealmListMd5.GetString();
|
|
}
|
|
|
|
TraceLog.Trace("GameReportSvc.OnGameReportRealmlistRes m_configRealm count {0}, m_configRealmTempForRecv count {1}",
|
|
serverData.m_configRealm.Count, serverData.m_configRealmTempForRecv.Count);
|
|
|
|
//广播给所有game
|
|
WorldServerUtils.GetPacketSender().Broadcast<SSGameReportRealmlistRes>((int)ServerType.Game, packet);
|
|
}
|
|
|
|
public static void OnTick(long nowSec)
|
|
{
|
|
TickNotifyAccountGateCount(nowSec);
|
|
TickLogOnlineReportWorldOnline(nowSec);
|
|
}
|
|
|
|
public static void TickNotifyAccountGateCount(long nowSec)
|
|
{
|
|
if (nowSec - lastReportAccountTime < m_ReportAccountSecondInterVal)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lastReportAccountTime = nowSec;
|
|
|
|
if (m_ReportAccountSecondInterVal < ReportAccountSecondInterValMax)
|
|
{
|
|
m_ReportAccountSecondInterVal += 1;
|
|
}
|
|
|
|
var reportReq = new SSGameReportRealmlistReq();
|
|
|
|
var svrData = WorldServerUtils.GetWorldServerData();
|
|
int iAllServerOnlinePlayer = 0;
|
|
foreach (var info in svrData.m_gameSvrInfo)
|
|
{
|
|
if (ServerIDUtils.GetServerType(info.serverId) == (int)ServerType.Game)
|
|
{
|
|
iAllServerOnlinePlayer += info.onlinePlayer;
|
|
}
|
|
|
|
if(ServerIDUtils.GetServerType(info.serverId) == (int)ServerType.GameGate ||
|
|
ServerIDUtils.GetServerType(info.serverId) == (int)ServerType.ChatGate)
|
|
{
|
|
GameGateSvrInfo gateInfo;
|
|
gateInfo.GateSvrid = info.serverId;
|
|
gateInfo.OnlinePlayer = info.onlinePlayer;
|
|
|
|
reportReq.Gates.Add(ref gateInfo);
|
|
}
|
|
}
|
|
|
|
//上报world的在线(包括gate的连接数量)给account->realmlist,
|
|
|
|
reportReq.OnlinePlayer = iAllServerOnlinePlayer;
|
|
reportReq.WorldSvrid = WorldServerUtils.GetAppID();
|
|
|
|
//为了以防万一,每10分钟强制拉一次全量
|
|
if (nowSec - lastForceGetAllRealmTime >= 600)
|
|
{
|
|
lastForceGetAllRealmTime = nowSec;
|
|
}
|
|
else
|
|
{
|
|
reportReq.RealmListMd5.SetString(svrData.recvRealmListMd5);
|
|
}
|
|
|
|
// 广播给主机和备机上的RealmsList
|
|
WorldServerUtils.GetPacketSender().Broadcast((int)ServerType.RealmsList, (int)SSMsgID.GameReportRealmlistReq, ref reportReq, 0 , 0);
|
|
|
|
WorldOnlinePlayerCount = iAllServerOnlinePlayer;
|
|
}
|
|
|
|
public static void TickLogOnlineReportWorldOnline(long nowSec)
|
|
{
|
|
//1分钟1次就行了,其实也没啥用
|
|
if (nowSec - lastLogOnlineTime < 60)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lastLogOnlineTime = nowSec;
|
|
|
|
var svrData = WorldServerUtils.GetWorldServerData();
|
|
int iAllServerOnlinePlayer = 0;
|
|
foreach (var info in svrData.m_gameSvrInfo)
|
|
{
|
|
if (ServerIDUtils.GetServerType(info.serverId) == (int)ServerType.Game)
|
|
{
|
|
iAllServerOnlinePlayer += info.onlinePlayer;
|
|
}
|
|
}
|
|
|
|
|
|
//上报全服人数
|
|
// 写 bill 日记
|
|
WorldBillLogUtils.LogOnlinePlayer(iAllServerOnlinePlayer);
|
|
}
|
|
|
|
// 统计每个realm的在线数据
|
|
public static void TickRealmOnline()
|
|
{
|
|
var allOnline = WorldServerUtils.GetWorldServerData().realmOnlineAll;
|
|
allOnline.Clear();
|
|
|
|
var gameOnline = WorldServerUtils.GetWorldServerData().realmOnlineGame;
|
|
|
|
// 把不同gamesvr上的同一个realm的在线人数累加起来
|
|
foreach (List<RealmOnline> realmList in gameOnline.Values)
|
|
{
|
|
foreach (RealmOnline realmOne in realmList)
|
|
{
|
|
if (! allOnline.ContainsKey(realmOne.realmId))
|
|
{
|
|
allOnline[realmOne.realmId] = realmOne.onlineNum;
|
|
}
|
|
else
|
|
{
|
|
allOnline[realmOne.realmId] += realmOne.onlineNum;
|
|
}
|
|
}
|
|
}
|
|
|
|
SSRealmOnlinePlayerToOpsvr req = new SSRealmOnlinePlayerToOpsvr();
|
|
foreach (KeyValuePair<int, int> kvp in allOnline)
|
|
{
|
|
RealmOnlineInfo info = new RealmOnlineInfo();
|
|
info.RealmID = kvp.Key;
|
|
info.OnlinePlayer = kvp.Value;
|
|
|
|
if (req.RealmList.Count < req.RealmList.GetMaxCount())
|
|
{
|
|
req.RealmList.Add(info);
|
|
}
|
|
else
|
|
{
|
|
// 同步发送到 op
|
|
WorldServerUtils.GetPacketSender().Broadcast((int)ServerType.Operation, (int)SSMsgID.RealmOnlineplayerToOpsvr, ref req, 0, 0);
|
|
|
|
req.RealmList.Clear();
|
|
req.RealmList.Add(info);
|
|
}
|
|
}
|
|
|
|
if (req.RealmList.Count > 0)
|
|
{
|
|
// 同步发送到 op
|
|
WorldServerUtils.GetPacketSender().Broadcast((int)ServerType.Operation, (int)SSMsgID.RealmOnlineplayerToOpsvr, ref req, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|