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.
1011 lines
44 KiB
1011 lines
44 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Sog;
|
|
using ProtoCSStruct;
|
|
using System.IO;
|
|
using System.Diagnostics;
|
|
|
|
namespace Realmlist
|
|
{
|
|
public class ClassSSGameReportRealmlistRes
|
|
{
|
|
public SSGameReportRealmlistRes structRes;
|
|
}
|
|
public class SSGameReportRealmlistResList
|
|
{
|
|
//c#里不允许数组里的struct大小超过64K
|
|
//public List<SSGameReportRealmlistRes> resList = new List<SSGameReportRealmlistRes>();
|
|
public List<ClassSSGameReportRealmlistRes> resList = new List<ClassSSGameReportRealmlistRes>();
|
|
public string calcMd5;
|
|
|
|
|
|
public void CalcMd5()
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
for (int i = 0; i < resList.Count; i++)
|
|
{
|
|
ref SSGameReportRealmlistRes res = ref resList[i].structRes;
|
|
int size = res.CalculateSize();
|
|
byte[] data = new byte[size];
|
|
CodedOutputStream ouput = new CodedOutputStream(data);
|
|
res.WriteTo(ouput);
|
|
ms.Write(data);
|
|
}
|
|
|
|
calcMd5 = HashHelper.MD5Bytes(ms.GetBuffer());
|
|
}
|
|
}
|
|
|
|
|
|
public class ClassSSRealmBriefRes
|
|
{
|
|
public SSRealmBriefRes structRes;
|
|
}
|
|
public class SSRealmBriefResList
|
|
{
|
|
public List<ClassSSRealmBriefRes> resList = new List<ClassSSRealmBriefRes>();
|
|
public string calcMd5;
|
|
|
|
public void CalcMd5()
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
for (int i = 0; i < resList.Count; i++)
|
|
{
|
|
ref SSRealmBriefRes res = ref resList[i].structRes;
|
|
int size = res.CalculateSize();
|
|
byte[] data = new byte[size];
|
|
CodedOutputStream ouput = new CodedOutputStream(data);
|
|
res.WriteTo(ouput);
|
|
ms.Write(data);
|
|
}
|
|
|
|
calcMd5 = HashHelper.MD5Bytes(ms.GetBuffer());
|
|
}
|
|
}
|
|
|
|
public static class RealmInfoHandler
|
|
{
|
|
//account sessionId, time second
|
|
static Dictionary<long, long> s_sessionSendAreaServerIpDict = new Dictionary<long, long>();
|
|
static long lastCheckDeleteSessionDictTime = 0;
|
|
|
|
const int SendRealmMaxCountOnce = 128;
|
|
private static void TryDeleteSessionDictByTime()
|
|
{
|
|
long now = RealmlistServerUtils.GetTimeSecond();
|
|
//1分钟一次
|
|
if (now - lastCheckDeleteSessionDictTime < 60)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lastCheckDeleteSessionDictTime = now;
|
|
|
|
List<long> needDeleteSession = new List<long>();
|
|
foreach(var pair in s_sessionSendAreaServerIpDict)
|
|
{
|
|
//删除超过10分钟的
|
|
if(now - pair.Value > 300)
|
|
{
|
|
needDeleteSession.Add(pair.Key);
|
|
}
|
|
}
|
|
|
|
foreach(var session in needDeleteSession)
|
|
{
|
|
s_sessionSendAreaServerIpDict.Remove(session);
|
|
}
|
|
|
|
TraceLog.Debug("RealmInfoHandler.TryDeleteSessionDictByTime s_sessionSendAreaServerIpDict new count {0} after delete count {1}"
|
|
, s_sessionSendAreaServerIpDict.Count, needDeleteSession.Count);
|
|
}
|
|
public static void OnClientGameListReq(uint remoteAppID, StructPacket packet)
|
|
{
|
|
ref CSGameListReq req = ref packet.GetMessage<CSGameListReq>();
|
|
string accountID = req.AccountID.GetString();
|
|
string ip = req.Ip.ToString();
|
|
string deviceId = req.DeviceId.ToString();
|
|
|
|
bool isInWhiteList = LimitIPList.IsInWhiteList(ip, deviceId);
|
|
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq accountType {0} accountId {1} ip {2} deviceId {3} isInWhiteList {4}"
|
|
, req.AccountType, accountID, ip, deviceId, isInWhiteList);
|
|
|
|
List<AreaRealm> visiableAreas = null;
|
|
//表示是客户端来的
|
|
if (req.FromAccountSession != 0 && s_sessionSendAreaServerIpDict.ContainsKey(req.FromAccountSession) == false)
|
|
{
|
|
visiableAreas = GetAllAreaServerIPList(ref req, ip, deviceId, true);
|
|
}
|
|
|
|
PlayerRealmInfo player = RealmlistServerUtils.GetCreatePlayerInfo(req.AccountType, accountID);
|
|
AreaRealm area = null;
|
|
string reqArea = req.AreaName.ToString();
|
|
|
|
// 客户端指定大区
|
|
if (! string.IsNullOrEmpty(reqArea))
|
|
{
|
|
if (! RealmlistSvc.areaDict.TryGetValue(reqArea, out area))
|
|
{
|
|
// 增加默认大区, 方便渠道包登录内网服务器
|
|
if (string.IsNullOrEmpty(RealmlistServerUtils.GetServerConfig().defaultAreaName))
|
|
{
|
|
TraceLog.Error("RealmInfoHandler.OnClientGameListReq area {0} no data", reqArea);
|
|
return;
|
|
}
|
|
|
|
reqArea = RealmlistServerUtils.GetServerConfig().defaultAreaName;
|
|
if (! RealmlistSvc.areaDict.TryGetValue(reqArea, out area))
|
|
{
|
|
TraceLog.Error("RealmInfoHandler.OnClientGameListReq default area {0} no data", reqArea);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 没有登录过, 先根据ip选择,再选客户端所在时区最近的大区
|
|
if (req.LastLoginRealm == 0)
|
|
{
|
|
area = RecommendRealmByIP.GetAreaByIP(ip);
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq GetAreaByIP {0} area {1}", ip, area == null ? "null" : area.areaName);
|
|
|
|
//如果强制配置成ip白名单可见,那么不在名单里的肯定不可见
|
|
if (area != null && area.visibleOnlyWhiteList == 1 && !LimitIPList.IsInWhiteList(ip, deviceId))
|
|
{
|
|
area = null;
|
|
}
|
|
|
|
if (area == null)
|
|
{
|
|
area = RealmlistSvc.GetAreaByTimezone(req.CltTimezone, ip, deviceId);
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq GetAreaByTimezone {0} area {1}", req.CltTimezone, area == null ? "null" : area.areaName);
|
|
}
|
|
}
|
|
else//已经登录过,选最近登录大区
|
|
{
|
|
area = RealmlistSvc.GetAreaByRealmId(req.LastLoginRealm);
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq GetAreaByRealmId {0} area {1}", req.LastLoginRealm, area == null ? "null" : area.areaName);
|
|
}
|
|
|
|
if (area == null)
|
|
{
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq 1 area is null, clt timezone {0} lastLogin {1}"
|
|
, req.CltTimezone, req.LastLoginRealm);
|
|
|
|
area = RealmlistSvc.GetAreaByTimezone(req.CltTimezone, ip, deviceId);
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq GetAreaByTimezone by default {0} area {1}", req.CltTimezone, area == null ? "null" : area.areaName);
|
|
if (area == null)
|
|
{
|
|
TraceLog.Error("RealmInfoHandler.OnClientGameListReq 2 area is null, clt timezone {0} lastLogin {1}"
|
|
, req.CltTimezone, req.LastLoginRealm);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(visiableAreas != null)
|
|
{
|
|
//这种情况是: 比如开了美区,设置了推荐美区的新用户的号屏蔽了其他区,但是美区又不可见(比如开白名单),
|
|
//这种情况非常少见,但还是需要处理,要不然玩家一个区都看不见了
|
|
if (area != null && visiableAreas.Contains(area) == false)
|
|
{
|
|
TraceLog.Debug("RealmInfoHandler.OnClientGameListReq find area {0} but not in visiableAreas", area.areaName);
|
|
visiableAreas = GetAllAreaServerIPList(ref req, ip, deviceId, false);
|
|
}
|
|
|
|
SendAllAreaServerIPList(visiableAreas, remoteAppID, packet.ObjectID);
|
|
|
|
s_sessionSendAreaServerIpDict.Add(req.FromAccountSession, RealmlistServerUtils.GetTimeSecond());
|
|
TryDeleteSessionDictByTime();
|
|
}
|
|
|
|
var res = new CSGameListRes
|
|
{
|
|
CurrPage = req.ReqPage,
|
|
RealmPerPage = RealmlistSvc.realmNumPerPage,
|
|
TotalPage = RealmlistSvc.GetTotalRealmPage(area),
|
|
AccountType = req.AccountType,
|
|
FromGameSvr = req.FromGameSvr,
|
|
FromWorldSvr = req.FromWorldSvr,
|
|
FromAccountSession = req.FromAccountSession,
|
|
FromUid = req.FromUid
|
|
};
|
|
res.AccountID.SetString(req.AccountID.GetPtr());
|
|
res.AreaName.SetString(area.areaName);
|
|
|
|
// 0号页签是推荐页签, 包含一个最新realm和这个大区所有已创建角色的realm
|
|
if (req.ReqPage <= 0)
|
|
{
|
|
RealmInfo recommendRealm = RealmlistSvc.GetRecommendRealm(area, req.ClientVer.GetString(), ip, req.LastLoginRealm == 0, deviceId);
|
|
if (recommendRealm != null)
|
|
{
|
|
RealmlistSvc.FillCSRealmInfo(area, recommendRealm, player, ref res.RecommendRealm, isInWhiteList);
|
|
}
|
|
else
|
|
{
|
|
// 没有推荐服, 只有一种情况就是所有服务器当前都不可见
|
|
TraceLog.Error("RealmInfoHandler.OnClientGameListReq area {0} lastlogin {1} no recommend realm"
|
|
, area.areaName, req.LastLoginRealm);
|
|
}
|
|
|
|
// 加入属于这个大区的已创建角色realm
|
|
for (int i = 0; i < req.CreateRoleRealms.Count; i++)
|
|
{
|
|
var realm = RealmlistSvc.GetRealm(area, req.CreateRoleRealms[i]);
|
|
//共享显示大区
|
|
if(realm == null && area.shareShowAreaRealm != null)
|
|
{
|
|
realm = RealmlistSvc.GetRealm(area.shareShowAreaRealm, req.CreateRoleRealms[i]);
|
|
}
|
|
if (realm != null)
|
|
{
|
|
var csrealm = new CSRealmInfo();
|
|
RealmlistSvc.FillCSRealmInfo(area, realm, player, ref csrealm, isInWhiteList);
|
|
res.Realms.Add(ref csrealm);
|
|
}
|
|
}
|
|
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(
|
|
remoteAppID, (int)CSMsgID.GameListRes, ref res, packet.ObjectID);
|
|
return;
|
|
}
|
|
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq area {0} lastlogin {1} no recommend realm"
|
|
, area.areaName, req.LastLoginRealm);
|
|
|
|
WorldInfo worldInfo = null;
|
|
int thisAreaRealmsCount = area.sortedRealms.Count;
|
|
int totalRealmsCount = thisAreaRealmsCount;
|
|
//加上要显示的共享大区的区服数量
|
|
if (area.shareShowAreaRealm != null)
|
|
{
|
|
totalRealmsCount += area.shareShowAreaRealm.sortedRealms.Count;
|
|
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq area {0} share count {1} totalRealmsCount {2} thisAreaRealmsCount {3}"
|
|
, area.areaName, area.shareShowAreaRealm.sortedRealms.Count, totalRealmsCount, thisAreaRealmsCount);
|
|
}
|
|
int startIdx = (req.ReqPage - 1) * RealmlistSvc.realmNumPerPage;
|
|
int endIdx = startIdx + RealmlistSvc.realmNumPerPage - 1;
|
|
if (endIdx >= totalRealmsCount)
|
|
{
|
|
endIdx = totalRealmsCount - 1;
|
|
}
|
|
|
|
TraceLog.Trace("RealmInfoHandler.OnClientGameListReq area {0} startIdx {1} endIdx {2}"
|
|
, area.areaName, startIdx, endIdx);
|
|
|
|
// 倒序发给客户端
|
|
for (int i = endIdx; i >= startIdx; i--)
|
|
{
|
|
if (res.Realms.Count >= res.Realms.GetMaxCount())
|
|
{
|
|
break;
|
|
}
|
|
|
|
RealmInfo realm = null;
|
|
if(i < thisAreaRealmsCount)
|
|
{
|
|
realm = area.sortedRealms[i];
|
|
}
|
|
else
|
|
{
|
|
realm = area.shareShowAreaRealm.sortedRealms[i - thisAreaRealmsCount];
|
|
}
|
|
|
|
|
|
//检查版本和ip白名单
|
|
if (RealmlistSvc.CheckCanVisibleRealmByClintVerIp(realm, req.ClientVer.GetString(), ip, deviceId) == false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//如果未到可见时间(可见时间可以配置成比开服时间晚,方便自己人进去测试),那么只有ip白名单的人可以看见
|
|
if (! RealmlistServerUtils.CheckRealmCanVisible(realm) && !LimitIPList.IsInWhiteList(ip, deviceId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (worldInfo == null || worldInfo.worldId != realm.worldId)
|
|
{
|
|
area.areaWorldDict.TryGetValue(realm.worldId, out worldInfo);
|
|
if(worldInfo == null)
|
|
{
|
|
area.shareShowAreaRealm.areaWorldDict.TryGetValue(realm.worldId, out worldInfo);
|
|
}
|
|
}
|
|
|
|
if (worldInfo == null)
|
|
{
|
|
TraceLog.Error("RealmInfoHandler.OnClientGameListReq area {0} worldId {1} no worldinfo"
|
|
, area.areaName, realm.worldId);
|
|
continue;
|
|
}
|
|
|
|
CSRealmInfo csrealmInfo = new CSRealmInfo();
|
|
RealmlistSvc.FillCSRealmInfo(worldInfo, realm, player, ref csrealmInfo, i >= thisAreaRealmsCount, isInWhiteList);
|
|
|
|
res.Realms.Add(ref csrealmInfo);
|
|
}
|
|
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)CSMsgID.GameListRes, ref res, packet.ObjectID);
|
|
}
|
|
|
|
public static void OnGameWorldReport(uint serverID, StructPacket packet)
|
|
{
|
|
ref SSGameReportRealmlistReq req = ref packet.GetMessage<SSGameReportRealmlistReq>();
|
|
|
|
int worldID = (int)ServerIDUtils.GetWorldID(req.WorldSvrid);
|
|
string worldSvrId = ServerIDUtils.IDToString(req.WorldSvrid);
|
|
TraceLog.Trace("RealmInfoHandler.OnGameWorldReport world {0} online {1}", worldSvrId, req.OnlinePlayer);
|
|
|
|
// 这里找不到world先不返回, 至少先更新全局的gateOnlineDict
|
|
RealmlistSvc.worldDict.TryGetValue(worldID, out WorldInfo worldInfo);
|
|
|
|
var svrData = RealmlistServerUtils.GetRealmlistServerData();
|
|
for (int i = 0; i < req.Gates.Count; i++)
|
|
{
|
|
ref GameGateSvrInfo gate = ref req.Gates[i];
|
|
// 更新全局的gateOnlineDict
|
|
if (! svrData.gateOnlineDict.TryGetValue(gate.GateSvrid, out int online))
|
|
{
|
|
svrData.gateOnlineDict.Add(gate.GateSvrid, gate.OnlinePlayer);
|
|
}
|
|
else
|
|
{
|
|
svrData.gateOnlineDict[gate.GateSvrid] = gate.OnlinePlayer;
|
|
}
|
|
|
|
// 更新worldInfo中的gate在线数据
|
|
if (worldInfo != null)
|
|
{
|
|
List<GameGateInfo> gatelist;
|
|
int serverType = ServerIDUtils.GetServerType(gate.GateSvrid);
|
|
if (serverType == (int) ServerType.GameGate)
|
|
{
|
|
gatelist = worldInfo.gameGates;
|
|
}
|
|
else
|
|
{
|
|
gatelist = worldInfo.chatGates;
|
|
}
|
|
|
|
for (int j = 0; j < gatelist.Count; j++)
|
|
{
|
|
if (gatelist[j].gatesvrId == gate.GateSvrid)
|
|
{
|
|
gatelist[j].online = gate.OnlinePlayer;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (worldInfo == null)
|
|
{
|
|
TraceLog.Error("RealmInfoHandler.OnGameWorldReport world {0} {1} no worldInfo", worldSvrId, worldID);
|
|
return;
|
|
}
|
|
|
|
// 回包时同步world所有可登录的realm
|
|
SSGameReportRealmlistResList resListForCheck = new SSGameReportRealmlistResList();
|
|
ClassSSGameReportRealmlistRes classResForCheck = new ClassSSGameReportRealmlistRes();
|
|
ref SSGameReportRealmlistRes resForCheck = ref classResForCheck.structRes;
|
|
int resMsgIndexFrom1 = 1;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
|
|
foreach (RealmInfo realm in worldInfo.worldRealms.Values)
|
|
{
|
|
if (!RealmlistServerUtils.CheckRealmOpen(realm))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var brief = new CSRealmBrief();
|
|
RealmlistSvc.FillCSRealmBrief(worldInfo.areaName, realm, ref brief);
|
|
|
|
resForCheck.RealmList.Add(brief);
|
|
if (resForCheck.RealmList.Count >= resForCheck.RealmList.GetMaxCount()
|
|
|| resForCheck.RealmList.Count >= SendRealmMaxCountOnce)
|
|
{
|
|
resListForCheck.resList.Add(classResForCheck);
|
|
|
|
classResForCheck = new ClassSSGameReportRealmlistRes();
|
|
resForCheck = ref classResForCheck.structRes;
|
|
resMsgIndexFrom1++;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
}
|
|
}
|
|
|
|
if (resForCheck.RealmList.Count > 0)
|
|
{
|
|
resListForCheck.resList.Add(classResForCheck);
|
|
}
|
|
|
|
//最后发一个结束包
|
|
classResForCheck = new ClassSSGameReportRealmlistRes();
|
|
resForCheck = ref classResForCheck.structRes;
|
|
resMsgIndexFrom1++;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
resListForCheck.resList.Add(classResForCheck);
|
|
|
|
//计算md5
|
|
resListForCheck.CalcMd5();
|
|
|
|
TraceLog.Trace("RealmInfoHandler.OnGameWorldReport world {0} req md5 {1} res md5 {2}", worldSvrId, req.RealmListMd5.GetString(), resListForCheck.calcMd5);
|
|
|
|
if (resListForCheck.calcMd5 != req.RealmListMd5.GetString())
|
|
{
|
|
for (int i = 0; i < resListForCheck.resList.Count; i++)
|
|
{
|
|
ref SSGameReportRealmlistRes res = ref resListForCheck.resList[i].structRes;
|
|
if (i == resListForCheck.resList.Count - 1)
|
|
{
|
|
res.RealmListMd5.SetString(resListForCheck.calcMd5);
|
|
}
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(serverID,
|
|
(int)SSMsgID.GameReportRealmlistRes, ref res, 0, req.WorldSvrid);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 返回全部服务器
|
|
/// </summary>
|
|
/// <param name="remoteAppID"></param>
|
|
/// <param name="packet"></param>
|
|
public static void OnRealmBriefReq(uint remoteAppID, StructPacket packet)
|
|
{
|
|
ref var req = ref packet.GetMessage<SSRealmBriefReq>();
|
|
|
|
SSRealmBriefResList resListForCheck = new SSRealmBriefResList();
|
|
ClassSSRealmBriefRes classResForCheck = new ClassSSRealmBriefRes();
|
|
ref SSRealmBriefRes resForCheck = ref classResForCheck.structRes;
|
|
resForCheck.GameSvrId = req.GameSvrId;
|
|
resForCheck.WorldSvrId = req.WorldSvrId;
|
|
|
|
int resMsgIndexFrom1 = 1;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
|
|
foreach (var area in RealmlistSvc.areaDict.Values)
|
|
{
|
|
foreach (RealmInfo realm in area.sortedRealms)
|
|
{
|
|
if (!RealmlistServerUtils.CheckRealmOpen(realm))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var brief = new CSRealmBrief();
|
|
RealmlistSvc.FillCSRealmBrief(area.areaName, realm, ref brief, area.timezone);
|
|
|
|
resForCheck.RealmList.Add(ref brief);
|
|
if (resForCheck.RealmList.Count >= resForCheck.RealmList.GetMaxCount()
|
|
|| resForCheck.RealmList.Count >= SendRealmMaxCountOnce)
|
|
{
|
|
resListForCheck.resList.Add(classResForCheck);
|
|
|
|
classResForCheck = new ClassSSRealmBriefRes();
|
|
resForCheck = ref classResForCheck.structRes;
|
|
resForCheck.GameSvrId = req.GameSvrId;
|
|
resForCheck.WorldSvrId = req.WorldSvrId;
|
|
|
|
resMsgIndexFrom1++;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (resForCheck.RealmList.Count > 0)
|
|
{
|
|
resListForCheck.resList.Add(classResForCheck);
|
|
}
|
|
|
|
//最后发一个结束包
|
|
classResForCheck = new ClassSSRealmBriefRes();
|
|
resForCheck = ref classResForCheck.structRes;
|
|
resForCheck.GameSvrId = req.GameSvrId;
|
|
resForCheck.WorldSvrId = req.WorldSvrId;
|
|
resMsgIndexFrom1++;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
resListForCheck.resList.Add(classResForCheck);
|
|
|
|
|
|
//计算md5
|
|
resListForCheck.CalcMd5();
|
|
|
|
TraceLog.Trace("RealmInfoHandler.OnRealmBriefReq remote {0} game {1} world {2} req md5 {3} res md5 {4}",
|
|
ServerIDUtils.IDToString(remoteAppID), ServerIDUtils.IDToString(req.GameSvrId), ServerIDUtils.IDToString(req.WorldSvrId), req.RealmListMd5.GetString(), resListForCheck.calcMd5);
|
|
|
|
if (resListForCheck.calcMd5 != req.RealmListMd5.GetString())
|
|
{
|
|
for (int i = 0; i < resListForCheck.resList.Count; i++)
|
|
{
|
|
ref SSRealmBriefRes res = ref resListForCheck.resList[i].structRes;
|
|
if (i == resListForCheck.resList.Count - 1)
|
|
{
|
|
res.RealmListMd5.SetString(resListForCheck.calcMd5);
|
|
}
|
|
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID,
|
|
(int)SSMsgID.RealmBriefRes, ref res, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 返回全部服务器
|
|
/// </summary>
|
|
/// <param name="remoteAppID"></param>
|
|
/// <param name="packet"></param>
|
|
public static void OnRealmAllBriefReq(uint remoteAppID, StructPacket packet)
|
|
{
|
|
ref var req = ref packet.GetMessage<SSRealmAllBriefReq>();
|
|
SSRealmAllBriefRes resForCheck = new SSRealmAllBriefRes();
|
|
resForCheck.Guid = req.Guid;
|
|
resForCheck.GameSvrId = req.GameSvrId;
|
|
resForCheck.WorldSvrId = req.WorldSvrId;
|
|
|
|
int resMsgIndexFrom1 = 1;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
|
|
foreach (var area in RealmlistSvc.areaDict.Values)
|
|
{
|
|
foreach (RealmInfo realm in area.sortedRealms)
|
|
{
|
|
var brief = new CSRealmBrief();
|
|
RealmlistSvc.FillCSRealmBrief(area.areaName, realm, ref brief, area.timezone);
|
|
resForCheck.RealmList.Add(ref brief);
|
|
resMsgIndexFrom1++;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
if(resForCheck.RealmList.Count == 500)
|
|
{
|
|
TraceLog.Trace("RealmInfoHandler.OnRealmAllBriefReq remote {0} game {1} world {2}",
|
|
ServerIDUtils.IDToString(remoteAppID), ServerIDUtils.IDToString(req.GameSvrId), ServerIDUtils.IDToString(req.WorldSvrId));
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID,
|
|
(int)SSMsgID.RealmAllbriefRes, ref resForCheck, 0);
|
|
resForCheck.RealmList.Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
//最后发一个结束包
|
|
resMsgIndexFrom1++;
|
|
resForCheck.MsgIndexFrom1 = resMsgIndexFrom1;
|
|
resForCheck.IsEnd = 1;
|
|
TraceLog.Trace("RealmInfoHandler.OnRealmAllBriefReq remote {0} game {1} world {2}",
|
|
ServerIDUtils.IDToString(remoteAppID), ServerIDUtils.IDToString(req.GameSvrId), ServerIDUtils.IDToString(req.WorldSvrId));
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID,
|
|
(int)SSMsgID.RealmAllbriefRes, ref resForCheck, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 查询服务器最大bigrealmid
|
|
/// </summary>
|
|
public static void OnAllRealmReq(uint remoteAppID, StructPacket packet)
|
|
{
|
|
ref var req = ref packet.GetMessage<SSAllRealmReq>();
|
|
var res = new SSAllRealmRes { GameSvrId = req.GameSvrId, WorldSvrId = req.WorldSvrId };
|
|
|
|
ServerApp m_app = RealmlistServerUtils.GetApp();
|
|
|
|
RealmlistServerConfig serverConfig = RealmlistServerUtils.GetServerConfig();
|
|
string svnRealmListVersion = "";
|
|
|
|
if (serverConfig.enableModifykRealmListOpen && req.UpdateSvnFlag)
|
|
{
|
|
string svnFileName = m_app.GetCluster().GetAppConfigPath() + "/" + "svn.sh";
|
|
string svnInfo = Bash(svnFileName + " update");
|
|
if (svnInfo != null)
|
|
{
|
|
string[] info = svnInfo.Split("\n");
|
|
for (int i = 0; i < info.Length; i++)
|
|
{
|
|
if (info[i].Contains("At revision"))
|
|
{
|
|
svnRealmListVersion = info[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
res.SvnRealmListVersion.SetString(svnRealmListVersion);
|
|
res.Guid = req.Guid;
|
|
|
|
foreach (var area in RealmlistSvc.areaDict.Values)
|
|
{
|
|
foreach (RealmInfo realm in area.sortedRealms)
|
|
{
|
|
var brief = new CSRealmBrief();
|
|
RealmlistSvc.FillCSRealmBrief(area.areaName, realm, ref brief, area.timezone);
|
|
|
|
res.RealmList.Add(ref brief);
|
|
if (res.RealmList.Count >= res.RealmList.GetMaxCount())
|
|
{
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID,
|
|
(int)SSMsgID.AllRealmRes, ref res, 0);
|
|
|
|
res.RealmList.Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (res.RealmList.Count > 0)
|
|
{
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID,
|
|
(int)SSMsgID.AllRealmRes, ref res, 0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 新增服务器
|
|
/// </summary>
|
|
public static void OnSsAddRealmReq(uint serverID, StructPacket packet)
|
|
{
|
|
RealmlistServerConfig serverConfig = RealmlistServerUtils.GetServerConfig();
|
|
|
|
ref SSAddRealmReq req = ref packet.GetMessage<SSAddRealmReq>();
|
|
var res = new SSAddRealmRes { Code = 0 };
|
|
res.Msg.SetString("成功");
|
|
res.Id = req.Id;
|
|
|
|
if (!serverConfig.enableModifykRealmListOpen)
|
|
{
|
|
res.Code = 1;
|
|
res.Msg.SetString("更新svn开关未打开");
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(serverID, (int)SSMsgID.SsAddRealmRes, ref res, 0);
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
ServerApp m_app = RealmlistServerUtils.GetApp();
|
|
string newVersion = req.SvnRealmListVersion.ToString();
|
|
string filePathName = m_app.GetCluster().GetAppConfigPath() + "/" + serverConfig.realmListFile;
|
|
string svnFileName = m_app.GetCluster().GetAppConfigPath() + "/" + "svn.sh";
|
|
|
|
//svn更新本地realmlist文件
|
|
string svnInfo = Bash(svnFileName + " update");
|
|
|
|
if (string.IsNullOrEmpty(svnInfo))
|
|
{
|
|
string[] info = svnInfo.Split("\n");
|
|
for (int i = 0; i < info.Length; i++)
|
|
{
|
|
if (info[i].Contains("At revision"))
|
|
{
|
|
newVersion = info[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (newVersion == req.SvnRealmListVersion.ToString())
|
|
{
|
|
List<string> lines = File.ReadAllLines(filePathName).ToList();
|
|
var addLines = new List<string>();
|
|
var newLines = new List<string>();
|
|
|
|
string areaName = "";
|
|
int worldId = 0;
|
|
int beginRealmId = int.MaxValue;
|
|
|
|
for (int i = 0; i < lines.Count; i++)
|
|
{
|
|
if (lines[i].Contains("\"areaName\""))
|
|
{
|
|
areaName = lines[i].Split(":")[1].Replace("\"", "").Replace("\t", "").Replace(",", "");
|
|
newLines.Add(lines[i]);
|
|
}
|
|
else if (lines[i].Contains("\"worldId\""))
|
|
{
|
|
worldId = int.Parse(lines[i].Split(":")[1].Replace("\"", "").Replace("\t", "").Replace(",", ""));
|
|
newLines.Add(lines[i]);
|
|
}
|
|
else if (lines[i].Contains("\"realmList\""))
|
|
{
|
|
for (int j = 0; j < req.RealmList.Count; j++)
|
|
{
|
|
string res111 = req.RealmList[j].ToString();
|
|
if (req.RealmList[j].AreaName.ToString() == areaName && req.RealmList[j].WorldId == worldId)
|
|
{
|
|
beginRealmId = (beginRealmId < req.RealmList[j].RealmId) ? beginRealmId : req.RealmList[j].RealmId;
|
|
int k = 1;
|
|
int startRealmId = 0;
|
|
int startRealmIdUnit = 0;
|
|
while (!lines[i + k].Contains("}"))
|
|
{
|
|
string[] temp = new string[2];
|
|
if (lines[i + k].Replace("\t", "").StartsWith("//"))
|
|
{
|
|
addLines.Add(lines[i + k]);
|
|
}
|
|
else if (lines[i + k].Contains("realmId"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
startRealmId = Convert.ToInt32(temp[1].Replace("/t", "").Replace(",", "").Replace("\"", ""));
|
|
startRealmIdUnit = startRealmId % 1000;
|
|
addLines.Add(temp[0] + ":" + temp[temp.Length - 1].Replace(startRealmId.ToString(), req.RealmList[j].RealmId.ToString()));
|
|
}
|
|
else if (lines[i + k].Contains("name"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
int num = req.RealmList[j].RealmId % 1000;
|
|
addLines.Add(temp[0] + ":" + temp[temp.Length - 1].Replace(startRealmIdUnit.ToString(), num.ToString()));
|
|
}
|
|
else if (lines[i + k].Contains("showSeq"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
int num = req.RealmList[j].RealmId % 1000;
|
|
addLines.Add(temp[0] + ":" + temp[temp.Length - 1].Replace(startRealmIdUnit.ToString(), num.ToString()));
|
|
}
|
|
else if (lines[i + k].Contains("bdcName"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
addLines.Add(temp[0] + ":" + temp[temp.Length - 1].Replace(startRealmId.ToString(), req.RealmList[j].RealmId.ToString()));
|
|
}
|
|
else if (lines[i + k].Contains("openTime"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
addLines.Add(temp[0] + ": \"" +
|
|
AppTime.ConvertUnixTimeToDateTime((long)(req.RealmList[j].OpenTime) * 1000).ToString("yyyy-MM-dd HH:mm:ss") +
|
|
"\"" + (temp[temp.Length - 1].EndsWith(",") ? "," : ""));
|
|
}
|
|
else if (lines[i + k].Contains("visibleTime"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
addLines.Add(temp[0] + ": \"" +
|
|
AppTime.ConvertUnixTimeToDateTime((long)(req.RealmList[j].VisibleTime) * 1000).ToString("yyyy-MM-dd HH:mm:ss") +
|
|
"\"" + (temp[temp.Length - 1].EndsWith(",") ? "," : ""));
|
|
}
|
|
else if (lines[i + k].Contains("bigRealmId"))
|
|
{
|
|
temp = lines[i + k].Split(':');
|
|
addLines.Add(temp[0] + ":" + req.RealmList[j].BigRealmId + (temp[temp.Length - 1].EndsWith(",") ? "," : ""));
|
|
}
|
|
else addLines.Add(lines[i + k]);
|
|
k++;
|
|
}
|
|
addLines.Add(lines[i + k]);
|
|
}
|
|
}
|
|
if (addLines.Count > 0)
|
|
{
|
|
addLines[addLines.Count - 1] = addLines[addLines.Count-1].Replace(",", "");
|
|
}
|
|
newLines.Add(lines[i]);
|
|
}
|
|
else if (lines[i].Contains("\"realmId\""))
|
|
{
|
|
int realmId = Convert.ToInt32(lines[i].Split(':')[1].Replace("\t", "").Replace(",", ""));
|
|
if (realmId == beginRealmId)
|
|
{
|
|
for (int m = 1; m < addLines.Count; m++)
|
|
{
|
|
newLines.Add(addLines[m]);
|
|
}
|
|
while (!lines[i].Contains("]")) i++;
|
|
newLines.Add(lines[i]);
|
|
|
|
//插入完成后清理addLines
|
|
addLines.Clear();
|
|
beginRealmId = int.MaxValue;
|
|
}
|
|
else
|
|
{
|
|
newLines.Add(lines[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
newLines.Add(lines[i]);
|
|
}
|
|
}
|
|
|
|
string[] resLines = new string[newLines.Count];
|
|
for (int i = 0; i < newLines.Count; i++)
|
|
{
|
|
resLines[i] = newLines[i];
|
|
}
|
|
|
|
TraceLog.Trace("filePathName = " + filePathName + "当前版本 = " + newVersion + "查询版本 = " + req.SvnRealmListVersion.ToString());
|
|
|
|
//更新到配置文件中
|
|
File.WriteAllLines(filePathName, resLines);
|
|
|
|
//读取游戏服务器开服列表
|
|
RealmlistSvc.ReadRealmListConfig(m_app, filePathName);
|
|
RecommendRealmByIP.OnReloadConfig();
|
|
//上传到svn
|
|
Bash(svnFileName + " upload");
|
|
}
|
|
else
|
|
{
|
|
TraceLog.Trace("filePathName = " + filePathName + "当前版本 = " + newVersion + "查询版本 = " + req.SvnRealmListVersion.ToString());
|
|
res.Code = 1;
|
|
res.Msg.SetString("本地版本与svn版本不一致,修改失败");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TraceLog.Exception(ex);
|
|
res.Code = 1;
|
|
res.Msg.SetString("失败");
|
|
}
|
|
finally
|
|
{
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(serverID, (int)SSMsgID.SsAddRealmRes, ref res, 0);
|
|
}
|
|
}
|
|
|
|
public static void OnRealmOperationReq(uint serverID, StructPacket packet)
|
|
{
|
|
var realmValues = RealmlistSvc.areaDict.Values;
|
|
ref SSRealmOperationReq req = ref packet.GetMessage<SSRealmOperationReq>();
|
|
SSRealmOperationRes res = new SSRealmOperationRes();
|
|
res.Id = req.Id;
|
|
switch (req.OpType)
|
|
{
|
|
case (int)OpRealmType.Add:
|
|
res.Code = RealmlistDBSvc.AddNewRealmFromOp2Cache(ref req);
|
|
break;
|
|
case (int)OpRealmType.Update:
|
|
res.Code = RealmlistDBSvc.UpdateNewRealmFromOp2Cache(ref req);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(res.Code != 0)
|
|
{
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(serverID, (int)SSMsgID.SsRealmOperationRes, ref res, 0);
|
|
}
|
|
}
|
|
public static void SsRealmNewPlayer(uint serverID, StructPacket packet)
|
|
{
|
|
var realmValues = RealmlistSvc.areaDict.Values;
|
|
ref SSRealmNewPlayer req = ref packet.GetMessage<SSRealmNewPlayer>();
|
|
if (RealmlistServerUtils.GetRealmlistServerData().dbRealmConfigs.ContainsKey(req.ReamlId))
|
|
{
|
|
var cfg = RealmlistServerUtils.GetRealmlistServerData().dbRealmConfigs[req.ReamlId];
|
|
cfg.RegNum++;
|
|
RealmlistServerUtils.GetRealmlistServerData().dbRealmConfigs[req.ReamlId] = cfg;
|
|
|
|
SSRealmSavePlayerNum savePlayerNum = new SSRealmSavePlayerNum();
|
|
savePlayerNum.RegNum = cfg.RegNum;
|
|
savePlayerNum.RealmId = cfg.RealmId;
|
|
int instId = (int)ServerIDUtils.GetInstanceID(RealmlistServerUtils.GetApp().ServerID);
|
|
uint DBServerID = ServerIDUtils.GetLevel0ServerIDByType((int)ServerType.Db, instId);
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(DBServerID, (int)SSMsgID.SsRealmSavePlayernum, ref savePlayerNum, 0);
|
|
}
|
|
}
|
|
public static string Bash(this string cmd)
|
|
{
|
|
var escapedArgs = cmd.Replace("\"", "\\\"");
|
|
|
|
var process = new Process()
|
|
{
|
|
StartInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "/bin/bash",
|
|
Arguments = $"-c \"{escapedArgs}\"",
|
|
RedirectStandardOutput = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
}
|
|
};
|
|
process.Start();
|
|
string result = process.StandardOutput.ReadToEnd();
|
|
process.WaitForExit();
|
|
process.Close();
|
|
return result;
|
|
}
|
|
|
|
private static bool HasRoleInArea(ref CSGameListReq req, AreaRealm area)
|
|
{
|
|
for (int i = 0; i < req.CreateRoleRealms.Count; i++)
|
|
{
|
|
int realmId = req.CreateRoleRealms[i];
|
|
if (area.realmIndex.ContainsKey(realmId))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static bool AreaInInvisiableArea(AreaRealmList area, List<AreaRealm> list)
|
|
{
|
|
foreach(var iarea in list)
|
|
{
|
|
if(iarea.areaName == area.areaName)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//获取区域的ip和timezone
|
|
public static List<AreaRealm> GetAllAreaServerIPList(ref CSGameListReq req, string ip, string deviceId, bool checkNewUserInvisibleAreaRule)
|
|
{
|
|
List<AreaRealm> visiableAreaList = new List<AreaRealm>();
|
|
|
|
bool invisibleAreaForNewUser = false;
|
|
var recommendarea = RecommendRealmByIP.GetAreaByIP(ip);
|
|
|
|
if(checkNewUserInvisibleAreaRule && recommendarea != null && recommendarea.invisibleAreaForNewUserList.Count > 0)
|
|
{
|
|
//规则,有任一屏蔽区有角色,则所有区都不屏蔽
|
|
bool hasRoleInInvisibleArea = false;
|
|
foreach (var invisiblearea in recommendarea.invisibleAreaForNewUserList)
|
|
{
|
|
if (HasRoleInArea(ref req, invisiblearea))
|
|
{
|
|
hasRoleInInvisibleArea = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(hasRoleInInvisibleArea == false)
|
|
{
|
|
invisibleAreaForNewUser = true;
|
|
}
|
|
}
|
|
|
|
|
|
foreach (AreaRealmList area in RealmlistSvc.realmListConfig.areaRealmList)
|
|
{
|
|
//如果配置了特殊版本
|
|
if (string.IsNullOrEmpty(area.visibleOnlyCliVersion) == false && area.visibleOnlyCliVersion != ip)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//如果强制配置成ip白名单可见,那么不在名单里的肯定不可见
|
|
if (area.visibleOnlyWhiteList == 1 && !LimitIPList.IsInWhiteList(ip, deviceId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//在不可见列表里?
|
|
if(invisibleAreaForNewUser && AreaInInvisiableArea(area, recommendarea.invisibleAreaForNewUserList))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var areaRealm = RealmlistSvc.areaDict[area.areaName];
|
|
|
|
visiableAreaList.Add(areaRealm);
|
|
}
|
|
|
|
return visiableAreaList;
|
|
}
|
|
|
|
public static void SendAllAreaServerIPList(List<AreaRealm> visiableAreaList, uint remoteAppID, long objectId)
|
|
{
|
|
CSGameAreaServerIPRes res = new CSGameAreaServerIPRes();
|
|
|
|
foreach (var area in visiableAreaList)
|
|
{
|
|
CSAreaServerIPInfo info = new CSAreaServerIPInfo();
|
|
info.AreaName.SetString(area.areaName);
|
|
//info.AreaIP.SetString(area.areaIP);
|
|
info.Timezone = area.timezone;
|
|
|
|
if (area.sortedRealms.Count > 0)
|
|
{
|
|
info.MinRealmId = area.sortedRealms[0].realmId;
|
|
info.MaxRealmId = area.sortedRealms.Last().realmId;
|
|
}
|
|
|
|
res.AreaInfo.Add(ref info);
|
|
}
|
|
|
|
RealmlistServerUtils.GetPacketSender().SendToServerByID(remoteAppID, (int)CSMsgID.GameareaServeripRes, ref res, objectId);
|
|
}
|
|
}
|
|
}
|
|
|