6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) + game logic (GameFix/GameDAL/ServerData) + network layer (NetWorkMessage) + data layer (ObjectModel) + utilities (MrWu/Core/Config/CloudAPI/dll) + adapters (zyxAdapter/base) .NET 8.0 C# solution, 16 projects, 958 source files
846 lines
25 KiB
C#
846 lines
25 KiB
C#
/*
|
|
* 由SharpDevelop创建。
|
|
* 用户: Administrator
|
|
* 日期: 2018-09-13
|
|
* 时间: 17:14
|
|
*
|
|
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
|
|
*/
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using GameData;
|
|
using MrWu.Debug;
|
|
using MrWu.RabbitMQ;
|
|
using Server.Data.Module;
|
|
using Server.DB.Redis;
|
|
using Server.DB.Sql;
|
|
using Server.MQ;
|
|
using Server.Pack;
|
|
using Server.Config;
|
|
using Server.Core;
|
|
using Server.Net;
|
|
|
|
namespace Server
|
|
{
|
|
/// <summary>
|
|
/// 全局管理
|
|
/// </summary>
|
|
public abstract partial class GlobalManager : ITimerProcessor, IServer
|
|
{
|
|
/// <summary>
|
|
/// 是否需要重新加载配置
|
|
/// </summary>
|
|
public bool IsReloadTable;
|
|
|
|
/// <summary>
|
|
/// 服务器单元工厂
|
|
/// </summary>
|
|
public static ServerUtilFactory Factory;
|
|
|
|
private static GlobalManager mInstance;
|
|
|
|
/// <summary>
|
|
/// 每个服务器只能管理一个服务,单例模式
|
|
/// </summary>
|
|
public static GlobalManager instance
|
|
{
|
|
get
|
|
{
|
|
if (mInstance == null)
|
|
mInstance = Factory.GetGlobalManager();
|
|
return mInstance;
|
|
}
|
|
}
|
|
|
|
#region 数据
|
|
|
|
/// <summary>
|
|
/// 是否自杀
|
|
/// </summary>
|
|
public bool isKill { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 是否可以开战,关闭服务器前先禁止,然后再关闭服务器
|
|
/// </summary>
|
|
public bool IsCanWar = true;
|
|
|
|
/// <summary>
|
|
/// 客户端要得到的配置
|
|
/// </summary>
|
|
public ConfigHead ClientConfig;
|
|
|
|
/// <summary>
|
|
/// 服务器信息
|
|
/// </summary>
|
|
protected ServerInfo m_serverinfo;
|
|
|
|
/// <summary>
|
|
/// 服务器信息
|
|
/// </summary>
|
|
public virtual ServerInfo serverinfo
|
|
{
|
|
get
|
|
{
|
|
if (m_serverinfo == null)
|
|
m_serverinfo = new ServerInfo();
|
|
return m_serverinfo;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 获取配置头
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected virtual ConfigHead GetConfigHead()
|
|
{
|
|
ConfigHead cfh = new ConfigHead();
|
|
cfh.style = 1;
|
|
cfh.id = ServerConfigManager.Instance.NodeId;
|
|
cfh.num = ServerConfigManager.Instance.NodeNum;
|
|
cfh.maxSVer = ServerConfigManager.Instance.MaxVer;
|
|
cfh.minSVer = ServerConfigManager.Instance.MinVer;
|
|
cfh.maxCver = ServerConfigManager.Instance.MaxCVer;
|
|
cfh.minCver = ServerConfigManager.Instance.MinCVer;
|
|
return cfh;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置系统时间间隔
|
|
/// </summary>
|
|
/// <param name="t"></param>
|
|
[DllImport("winmm")]
|
|
protected static extern void timeBeginPeriod(int t);
|
|
|
|
/// <summary>
|
|
/// 恢复系统时间间隔
|
|
/// </summary>
|
|
/// <param name="t"></param>
|
|
[DllImport("winmm")]
|
|
protected static extern void timeEndPeriod(int t);
|
|
|
|
/// <summary>
|
|
/// 定时器管理
|
|
/// </summary>
|
|
private TimerManager timermgr;
|
|
|
|
/// <summary>
|
|
/// 更新服务器信息的时间
|
|
/// </summary>
|
|
public int updateServerInfo_time;
|
|
|
|
/// <summary>
|
|
/// 更新服务器信息
|
|
/// </summary>
|
|
protected virtual void UpdateServerInfo(bool isStart = false)
|
|
{
|
|
timeBeginPeriod(1);
|
|
|
|
serverinfo.moduleId = myUtil.id;
|
|
serverinfo.nodenum = myUtil.nodeNum;
|
|
if (isStart)
|
|
serverinfo.startTime = DateTime.Now;
|
|
|
|
serverinfo.serverName = ServerName;
|
|
serverinfo.dopackCnt = 0;
|
|
serverinfo.minfps = minfps;
|
|
serverinfo.fps = Fps;
|
|
serverinfo.maxRuntime = maxruntiming;
|
|
serverinfo.ConnectCnt = UserSessionsInfo.GetAllSessionCount();
|
|
serverinfo.BindConnectCnt = UserSessionsInfo.GetBindSessionCount();
|
|
|
|
updateServerInfo_time = ServerConfigManager.Instance.UpdateServerInfoTime;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新
|
|
/// </summary>
|
|
protected virtual void Update()
|
|
{
|
|
TimeInfo.Instance.Update();
|
|
// long key = Debug.StartTiming();
|
|
GameNetDispatcher.Instance.Update();
|
|
GlobalDispatcher.Instance.Update();
|
|
GameDispatcher.Instance.Update();
|
|
|
|
// double runtime = Debug.GetRunTime(key);
|
|
// if (runtime > 200)
|
|
// {
|
|
// Debug.Error($"Update: 处理慢:{runtime}");
|
|
// }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动数据
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected virtual bool Init()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
private void DayChange()
|
|
{
|
|
GameDispatcher.Instance.Dispatch(GameMsgId.DayChange);
|
|
}
|
|
|
|
/// <summary>
|
|
/// fps计数
|
|
/// </summary>
|
|
private int fpscount = -1;
|
|
|
|
/// <summary>
|
|
/// 帧率
|
|
/// </summary>
|
|
public int Fps { get; protected set; }
|
|
|
|
private int m_minfps = -1;
|
|
|
|
/// <summary>
|
|
/// 最小fps
|
|
/// </summary>
|
|
public int minfps
|
|
{
|
|
get { return m_minfps; }
|
|
protected set { m_minfps = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 最大运行时间
|
|
/// </summary>
|
|
public double maxruntiming { get; protected set; }
|
|
|
|
private System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
|
|
|
|
/// <summary>
|
|
/// 发送配置包裹
|
|
/// </summary>
|
|
protected virtual void SendConfigPack()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 处理模块死亡信号
|
|
/// </summary>
|
|
/// <param name="node"></param>
|
|
/// <param name="nodenum"></param>
|
|
protected void DoModuleDieSign(object param)
|
|
{
|
|
if (param is ServerNode serverNode)
|
|
{
|
|
Debug.Info("模块死亡包处理!");
|
|
|
|
PackHead head = PackHead.Create();
|
|
head.packlx = ServerPackAgreement.ModuleDie;
|
|
Message msg = GlobalMQ.CreateMessage(head, serverNode);
|
|
GlobalMQ.instance.AddMessage(msg);
|
|
head.Dispose();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发送开启节点包
|
|
/// </summary>
|
|
protected virtual void SendOpenNode()
|
|
{
|
|
//注册模块
|
|
PackHead head = PackHead.Create();
|
|
head.packlx = ServerPackAgreement.openNode;
|
|
var data = this.myType != ModuleType.WatchDog ? MonitoringAppInfo : null;
|
|
GlobalMQ.instance.DeliveryAll(GlobalMQ.CreateMessage(head, data), true);
|
|
head.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发送关闭节点包
|
|
/// </summary>
|
|
protected void SendCloseNode()
|
|
{
|
|
PackHead head = PackHead.Create();
|
|
head.packlx = ServerPackAgreement.closeNode;
|
|
var data = this.myType != ModuleType.WatchDog ? MonitoringAppInfo : null;
|
|
|
|
GlobalMQ.instance.DeliveryAll(GlobalMQ.CreateMessage(head, data), true);
|
|
head.Dispose();
|
|
}
|
|
|
|
//自身主机信息应该是不变的。 暂存这个信息
|
|
MonitoringAppInfo MonitoringAppInfo =>
|
|
MonitoringAppInfo.GetCurrentApplicateInfo(this.myUtil.onlyId, this.myUtil.id, this.myUtil.nodeNum);
|
|
|
|
/// <summary>
|
|
/// 退出游戏
|
|
/// </summary>
|
|
public virtual void Quit()
|
|
{
|
|
state = ServerState.Stoping;
|
|
}
|
|
|
|
#region ITimerProcessor
|
|
|
|
/// <summary>
|
|
/// 100毫秒定时器
|
|
/// </summary>
|
|
public virtual void OnTime(int Interval)
|
|
{
|
|
//Debug.Log("秒级定时器:" + "," + System.DateTime.Now.Ticks);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 记录天
|
|
/// </summary>
|
|
int Day = 0;
|
|
|
|
/// <summary>
|
|
/// 秒级定时器
|
|
/// </summary>
|
|
public virtual void SecondTime()
|
|
{
|
|
updateServerInfo_time--;
|
|
|
|
if (updateServerInfo_time == 0)
|
|
{
|
|
UpdateServerInfo();
|
|
}
|
|
|
|
DoFps();
|
|
|
|
if (Day != DateTime.Now.Day)
|
|
{
|
|
Day = DateTime.Now.Day;
|
|
DayInit();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 每一天初始化一次
|
|
/// </summary>
|
|
public virtual void DayInit()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 处理Fps的赋值
|
|
/// </summary>
|
|
protected virtual void DoFps()
|
|
{
|
|
if (minfps < 0 || minfps > fpscount)
|
|
{
|
|
minfps = fpscount;
|
|
//Debug.Warning("fps最低记录:" + minfps);
|
|
}
|
|
|
|
Fps = fpscount;
|
|
fpscount = 0;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 缓存变化
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
protected virtual void CacheChange(WaitBeMsg msg)
|
|
{
|
|
var head = msg.head;
|
|
if (head.otherString == null || head.otherString.Length == 0)
|
|
return;
|
|
Debug.Info("处理缓存更新!" + head.otherString[0]);
|
|
CaCheManager.instance.UpdateKeyAsync(head.otherString[0]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 处理其他
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
/// <returns></returns>
|
|
protected virtual bool HandleOtherServerPack(WaitBeMsg msg) => false;
|
|
|
|
/// <summary>
|
|
/// 处理模块死亡信号——意外死亡
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
protected virtual void ModuleDie(WaitBeMsg msg)
|
|
{
|
|
var data = JsonPack.GetData<ServerNode>(msg.jsondata);
|
|
if (data == null)
|
|
Debug.Error("数据错误!");
|
|
else
|
|
Debug.Warning("模块死亡信号:" + data.id + "," + data.nodeNum);
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
protected virtual void Ping(PackHead head, string jsondata)
|
|
{
|
|
ModuleUtile util = JsonPack.GetData<ModuleUtile>(jsondata);
|
|
if (util == null)
|
|
Debug.Error("收到网络监测包数据为空!");
|
|
head.packlx = ServerPackAgreement.Pong;
|
|
GlobalMQ.instance.DeliveryOne(new ServerNode(util.id, util.nodeNum), GlobalMQ.CreateMessage(head, myUtil),
|
|
true);
|
|
|
|
Debug.Info("发送探测包:" + myUtil.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="head"></param>
|
|
/// <param name="jsondata"></param>
|
|
protected virtual void Pong(PackHead head, string jsondata)
|
|
{
|
|
ModuleUtile util = JsonPack.GetData<ModuleUtile>(jsondata);
|
|
if (util == null)
|
|
Debug.Error("收到网络探测回包数据为空!");
|
|
else
|
|
Debug.Info("Pong : " + util.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 心跳处理包
|
|
/// </summary>
|
|
/// <param name="msg">消息</param>
|
|
protected virtual void Heart(WaitBeMsg msg)
|
|
{
|
|
PackHead head = msg.head;
|
|
ServerNode node = head.sendutil;
|
|
if (node == null)
|
|
{
|
|
Debug.Error("心跳包错误,没有发送者的描述!");
|
|
return;
|
|
}
|
|
|
|
if (node.Equals(myUtil)) //自己的包不处理
|
|
return;
|
|
|
|
//ServerHeart.instanece.DoHeartAsync(node.id, node.nodeNum);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 节点开启信号
|
|
/// </summary>
|
|
/// <param name="msg">消息</param>
|
|
[System.Diagnostics.DebuggerNonUserCode]
|
|
protected virtual void RecvOpenNode(WaitBeMsg msg)
|
|
{
|
|
PackHead head = msg.head;
|
|
ModuleUtile node = head.sendutil;
|
|
if (node == null)
|
|
{
|
|
Debug.Error("节点开启信号包错误,没有发送者的描述!");
|
|
return;
|
|
}
|
|
|
|
if (node.Equals(myUtil))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//Debug.Info($"接收到模块开启:{node.ToString()}");
|
|
|
|
RountingManager.instance.AddModule(node.id, node.name);
|
|
|
|
if (node.id == (int)ModuleType.ConfigModule)
|
|
{
|
|
SendConfigPack();
|
|
}
|
|
|
|
if (head.otherString == null || head.otherString.Length == 0 || head.otherString[0] != "ok")
|
|
{
|
|
head.packlx = ServerPackAgreement.openNode;
|
|
head.otherString = new string[] { "ok" };
|
|
var data = this.myType != ModuleType.WatchDog ? MonitoringAppInfo : null;
|
|
var sendmsg = GlobalMQ.CreateMessage(head, data, null, -1, -1, null, null);
|
|
GlobalMQ.instance.DeliveryOne(node, sendmsg, true);
|
|
}
|
|
|
|
ServerHeart.instanece.AddModule(node.id, node.name, node.nodeNum);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 节点关闭信号_正常关闭
|
|
/// </summary>
|
|
/// <param name="msg">消息</param>
|
|
protected virtual void RecvCloseNode(WaitBeMsg msg)
|
|
{
|
|
ModuleUtile node = msg.head.sendutil;
|
|
|
|
if (node == null)
|
|
{
|
|
Debug.Error("收到节点关闭信号,没有发送者的描述!");
|
|
return;
|
|
}
|
|
|
|
if (node.Equals(myUtil))
|
|
{
|
|
//是本模块
|
|
if (node.onlyId != myUtil.onlyId)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (state == ServerState.Runing)
|
|
{
|
|
//检测到已经死了
|
|
//直接退出
|
|
Debug.Error("收到死完包!直接退出!");
|
|
state = ServerState.Error;
|
|
return;
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
//模块死亡信号
|
|
ServerHeart.instanece.RemoveDie(node.id, node.nodeNum, true);
|
|
Debug.Warning("收到模块关闭信号:" + node);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 处理命令
|
|
/// </summary>
|
|
protected virtual void DoCommand(WaitBeMsg msg)
|
|
{
|
|
string[] cmds = msg.head.otherString;
|
|
if (cmds == null || cmds.Length <= 0)
|
|
return;
|
|
|
|
Debug.Info("收到命令" + cmds[0]);
|
|
|
|
switch (cmds[0])
|
|
{
|
|
case "exit":
|
|
Quit();
|
|
break;
|
|
case "test":
|
|
break;
|
|
case "onlineModules": //在线的所有模块
|
|
Debug.Log("所有的在线模块");
|
|
break;
|
|
|
|
case "redislocktest":
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// DistributedLock
|
|
/// </summary>
|
|
protected DistributedLock dtl { get; } = new DistributedLock(1000);
|
|
|
|
#region IServer
|
|
|
|
/// <summary>
|
|
/// 服务器状态
|
|
/// </summary>
|
|
public ServerState state { get; set; } = ServerState.Close;
|
|
|
|
/// <summary>
|
|
/// 服务器名称
|
|
/// </summary>
|
|
public string ServerName
|
|
{
|
|
get
|
|
{
|
|
return ServerConfigManager.Instance.ServerName;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 我的模块单元
|
|
/// </summary>
|
|
public ModuleUtile myUtil { get; protected set; }
|
|
|
|
private ModuleType mMyType;
|
|
|
|
/// <summary>
|
|
/// 模块类型
|
|
/// </summary>
|
|
public ModuleType myType
|
|
{
|
|
get { return mMyType; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 消息处理器
|
|
/// </summary>
|
|
public MessageProcessor msgProcessor;
|
|
|
|
/// <summary>
|
|
/// 其他配置初始化
|
|
/// </summary>
|
|
public virtual void OtherConfigInit()
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
for (int i = 0; i < 50; i++)
|
|
{
|
|
stringBuilder.Append('0');
|
|
}
|
|
|
|
if (ServerConfigManager.Instance.GameConfig != null)
|
|
{
|
|
ServerConfigManager.Instance.GameConfig.GameGz = stringBuilder.ToString();
|
|
|
|
if (ServerConfigManager.Instance.TingCnt > 0)
|
|
{
|
|
foreach (var ting in ServerConfigManager.Instance.Tings)
|
|
{
|
|
ting.TingGz = stringBuilder.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 检查配置表是否有问题
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public virtual bool CheckConfig()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动
|
|
/// </summary>
|
|
public bool Start()
|
|
{
|
|
//启动中
|
|
state = ServerState.Starting;
|
|
|
|
mMyType = (ModuleType)ServerConfigManager.Instance.NodeId;
|
|
|
|
myUtil = new ModuleUtile(ServerConfigManager.Instance.NodeId,
|
|
ServerConfigManager.Instance.NodeNum,
|
|
Enum.GetName(myType.GetType(), myType),
|
|
ServerConfigManager.Instance.MaxVer);
|
|
|
|
TimeInfo.Instance.DayChange += DayChange;
|
|
|
|
//序列化预热
|
|
PreLoadMessagePack();
|
|
|
|
GlobalDispatcher.Instance.Dispatch(GlobalMsgId.GameNameReadSuccess, ServerConfigManager.Instance.ServerName);
|
|
Debug.Info($"Start ServerName:{ServerConfigManager.Instance.ServerName}");
|
|
|
|
//数据库初始化
|
|
GameDB.Instance.Init(SqlConfigCategory.Instance.GetDBSqlConfig());
|
|
|
|
//redis启动
|
|
redisManager.Start();
|
|
|
|
ClientConfig = GetConfigHead();
|
|
|
|
//存储自己的模块信息
|
|
if (!redisManager.db.HashExists(RedisDictionary.moduleNames, ServerConfigManager.Instance.NodeId.ToString()))
|
|
redisManager.db.HashSet(RedisDictionary.moduleNames, ServerConfigManager.Instance.NodeId, myUtil.name);
|
|
|
|
//心跳开始,并检查模块是否在线
|
|
if (!ServerHeart.instanece.Start(myType, ServerConfigManager.Instance.NodeNum))
|
|
{
|
|
Debug.ImportantLog("启动失败,模块在线!");
|
|
return false;
|
|
}
|
|
|
|
MessagePool.tag = "" + myUtil.id + "-" + myUtil.nodeNum + "-" + myUtil.ver + "-" + myUtil.name;
|
|
|
|
//模块死亡事件监听
|
|
GlobalDispatcher.Instance.AddListener(GlobalMsgId.ModuleNodeDie, DoModuleDieSign);
|
|
|
|
//创建消息处理
|
|
Factory.CreateGlobalMQFactory().CreateGlobalMQ();
|
|
|
|
//启动rabbit
|
|
if (!GlobalMQ.instance.StartModule(RabbitConfigCategory.Instance.GetRabbitMQConfig(), myUtil))
|
|
{
|
|
Debug.Error("启动失败:A71134F4-EA97-44C0-A305-E35966622FEB");
|
|
return false;
|
|
}
|
|
|
|
msgProcessor = Factory.CreateMessageProcessor();
|
|
|
|
new UserSessionsManager().Register();
|
|
//重要数据启动
|
|
if (!Init())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Debug.ImportantLog("init over!!!");
|
|
//发送开启信号
|
|
SendOpenNode();
|
|
|
|
//定时器管理
|
|
timermgr = new TimerManager(ServerConfigManager.Instance.OnTime);
|
|
timermgr.Start();
|
|
|
|
//更改状态为运行中
|
|
state = ServerState.Runing;
|
|
|
|
//更新服务器信息
|
|
UpdateServerInfo(true);
|
|
|
|
//开始发送心跳包
|
|
ServerHeart.instanece.BeginHeart(Factory.CreateHeartPack(myUtil));
|
|
|
|
return true;
|
|
}
|
|
|
|
private StringBuilder logs = new StringBuilder();
|
|
|
|
private int GcCount = 0;
|
|
|
|
/// <summary>
|
|
/// 预热 MessagePack
|
|
/// </summary>
|
|
protected virtual void PreLoadMessagePack()
|
|
{
|
|
|
|
}
|
|
|
|
private void ReLoadTable()
|
|
{
|
|
TableManager.Instance.ReLoadTableData();
|
|
|
|
try
|
|
{
|
|
ReLoadTableInit();
|
|
Debug.ImportantLog("配置重新加载成功!");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Error("重载配置出错!" + e.Message);
|
|
TableManager.Instance.RollBack();
|
|
}
|
|
}
|
|
|
|
protected virtual void ReLoadTableInit()
|
|
{
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// 主线程
|
|
/// </summary>
|
|
public void Loop()
|
|
{
|
|
if (state == ServerState.Runing)
|
|
{
|
|
try
|
|
{
|
|
logs.Clear();
|
|
watch.Restart();
|
|
//watch.Restart();
|
|
|
|
if (IsReloadTable)
|
|
{
|
|
IsReloadTable = false;
|
|
ReLoadTable();
|
|
}
|
|
|
|
if (timermgr.GetMillScoend())
|
|
{
|
|
#if DEBUG
|
|
var key = Debug.StartTiming();
|
|
logs.AppendLine($"GlobalManager Loop DoTime begin");
|
|
#endif
|
|
OnTime(timermgr.Interval);
|
|
#if DEBUG
|
|
logs.AppendLine($"GlobalManager Loop DoTime end, time: {Debug.GetRunTime(key)}");
|
|
#endif
|
|
}
|
|
|
|
if (timermgr.GetSecoend())
|
|
{
|
|
#if DEBUG
|
|
var key = Debug.StartTiming();
|
|
logs.AppendLine($"GlobalManager Loop DoTimeSecond begin");
|
|
#endif
|
|
SecondTime();
|
|
#if DEBUG
|
|
logs.AppendLine($"GlobalManager Loop DoTimeSecond end, time: {Debug.GetRunTime(key)}");
|
|
#endif
|
|
}
|
|
|
|
//消息处理
|
|
msgProcessor.Run(logs);
|
|
|
|
#if DEBUG
|
|
var updateKey = Debug.StartTiming();
|
|
#endif
|
|
fpscount++;
|
|
Update();
|
|
#if DEBUG
|
|
logs.AppendLine($"Update Loop time:{Debug.GetRunTime(updateKey)}");
|
|
#endif
|
|
watch.Stop();
|
|
double runtime = watch.ElapsedMilliseconds; //.ElapsedMilliseconds;
|
|
|
|
if (runtime >= 100)
|
|
{
|
|
logs.AppendLine(
|
|
$"GlobalManager Loop end, now: {DateTime.Now}, runtime: {runtime} / {watch.Elapsed.TotalMilliseconds}");
|
|
|
|
Debug.Error($"Loop runtime warning: " + logs.ToString());
|
|
}
|
|
|
|
if (runtime > maxruntiming)
|
|
maxruntiming = runtime;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.Error("主线程错误:" + e.ToString());
|
|
}
|
|
}
|
|
else if (state == ServerState.Stoping)
|
|
{
|
|
Close();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 阻塞检查,直到正常退出
|
|
/// </summary>
|
|
public virtual void Close()
|
|
{
|
|
UUIDManager.Instance.Close();
|
|
UserSessionsManager.Instance.Dispose();
|
|
timermgr.Stop();
|
|
|
|
SendCloseNode();
|
|
ServerHeart.instanece.Close();
|
|
//ServerManager.instance.Close();
|
|
if (GlobalMQ.instance != null)
|
|
GlobalMQ.instance.Close();
|
|
|
|
//保存道具日志
|
|
PropManager.Instance.Dispose();
|
|
state = ServerState.Stop;
|
|
|
|
Debug.Log("模块正常退出!");
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// 收到获取在线人数的请求
|
|
/// </summary>
|
|
/// <param name="msg"></param>
|
|
protected virtual void ReportPlayerOnLineData(WaitBeMsg msg)
|
|
{
|
|
}
|
|
}
|
|
} |