• GS初始化


    开启GameServer模式
    init函数,现在看看这个大函数干什么的
    //这个init也是GameServerUI里面调的,这个线程其实就做了一些初始化的工作,其实这里面没有什么主不主线程,都是在一个进程里面的
    void __stdcall GameServer::init()
    {
        ///设置最大连接数,现在还不知这个到底干啥的
        Share::SetMaxGcNumb(12000); //指定本GS支持的最大数量
        
        ///log日志,现在服务器写日志,在服务器报错的时候可以查看日志,还有报错时生成dump文件,然后上传ftp服务器,到时可以调试这个dump文件也可以知道在哪里报错
        // Log记录,全局单例,支持多线程。
        m_spLog = NEWSP(Log);
        std::string strLogDir = safe::wcstombs(Plug::GetCurrentPath()) + "Log";
        m_spLog->Init(strLogDir.c_str());
        SetPlug("Log", m_spLog.get());
        
        ///这个usbdog现在我不知道干啥的
        I_USBDog* pDog = NEW(USBDog);
        msg_assertex(pDog,"usb dog 创建失败!"); 
        std::string str = (char*)Plug::GetApp()->m_app_shared;
        if(str != "USBDog")
            return ;
    
        ///主要是一些配置文件的拷贝,只要模板然后拷贝一份你可以配置
        std::wstring wstrCurPath = Plug::GetCurrentPath();
        CheckFileAndCopy(wstrCurPath + L"option.xml", wstrCurPath + L"option模板.xml");
        CheckFileAndCopy(wstrCurPath + L"DBline.xml", wstrCurPath + L"DBline模板.xml");
        CheckFileAndCopy(wstrCurPath + L"centerOption.xml", wstrCurPath + L"centerOption模板.xml");
    
        ///在程序中开启控制打印,看变量的值
    //#define ALLOC_CONSOLE
    #ifdef ALLOC_CONSOLE
        AllocConsole();                        // 开辟控制台 释放:FreeConsole();
        SetConsoleTitle(L"Debug Output");      // 设置控制台窗口标题
        freopen("CONOUT$","w",stdout);         // 重定向输出
        printf("hello!
    ");
    #endif
    
        ////为进程指定CPU
        //SetProcessAffinityMask(GetCurrentProcess(), 1L);
        
        ///连接中心服务器,天龙里面是世界服务器,我们这个可以说没啥用,天龙那个是架构的一部分,没咋看天龙那个世界服务器
        /*连接centerServer*/
        m_spCenterTcpLink = NEWSP(CenterTcpLink);
        std::shared_ptr<I_SaveOption> spSaveOpt = NEWSP(SaveOption);
        spSaveOpt->openFile((Plug::GetCurrentPath() + L"centerOption.xml").c_str());
        std::string strIP = safe::wcstombs(spSaveOpt->getStr(L"root.ip"));
        int nPort = spSaveOpt->getInt(L"root.port");
        int nIP = ntohl(inet_addr(strIP.c_str()));
        if (!m_spCenterTcpLink->Connect(nIP, nPort))
        {
            MessageBox(NULL, L"centerServer连接失败!", L"Error!", MB_ICONERROR);
            ::TerminateProcess(::GetCurrentProcess(), 0);
        }
    
        //获取GameServer端口号
        spSaveOpt->openFile((Plug::GetCurrentPath() + L"option.xml").c_str());
        m_nPort = spSaveOpt->getInt(L"root.port");
    
        /*    初始化数据库    */
        m_spAsynDBC = NEWSP(asynDBCenter);///主要是mongo数据库的指针和加载任务等级信息,用于创建角色使用
    
        spSaveOpt->openFile((Plug::GetCurrentPath() + L"DBline.xml").c_str());
        std::string strDBIP =  safe::wcstombs(spSaveOpt->getStr(L"root.ip"));
        std::string strAcountDBName = safe::wcstombs(spSaveOpt->getStr(L"root.AccountDBName"));
        std::string strActorDBName = safe::wcstombs(spSaveOpt->getStr(L"root.ActorDBName"));
    
        ///这个主要是数据库字段数组的初始化,这个数组的值就是对应到数据库里面的字段的,后面数据库的存取都用到这个数组,类似下面的形式
        {//其中是根绝数组直接定位的
            m_pConfigName[eAccountTable_INC] = "T_INC";
            m_pConfigName[eAccountTable_User] = "T_UserInfo";
            m_pConfigName[eServerTable_INC] = "T_INC";
            m_pConfigName[eServerTable_Actor] = "T_ActorInfo";
            m_pConfigName[eServerTable_Guild] = "T_GuildInfo";
            m_pConfigName[eServerTable_Prop] = "T_PropInfo";
        }
        if(!m_spAsynDBC->Init(true))
        {
            MessageBoxA(GetTopWindow(NULL), "数据库初始化失败!", "Error!", MB_ICONERROR);
            ::TerminateProcess(GetCurrentProcess(), 0);
        }
        ///这个登录过程主要是连接mongo和认证,然后就是保证一些表的存在,数据库现在主要分为账号数据库和角色数据库,这里用suerperamdmin登录,其他数据库也能使用了
        if(!m_spAsynDBC->Login(strDBIP.c_str(), 27017, ShuiHu::eServerDB_AoShiQianXiong, "SuperAdmin", "123456"))
        {
            MessageBoxA(GetTopWindow(NULL), "数据库连接失败!", "Error!", MB_ICONERROR);
            ::TerminateProcess(GetCurrentProcess(), 0);
        }
        ///在ui上显示数据库线程id方便压测的
        OnThreadId(m_spAsynDBC->GetThrID(), L"数据库");
    
        ///对于长时间没有收到心跳包的客户端会被放入队列中,到时会释放,其实这个没咋看
        I_TimerFactory* pTimeFactory = NEW(TimerFactory);
        SetPlug("TimerFactory", pTimeFactory);
        m_FreeQueueTimer.reset(pTimeFactory->createTimer());
        m_FreeQueueTimer->regTimer(std::bind(&GameServer::FreeQueueTimer, this));
        m_FreeQueueTimer->setInterval(30 * 1000);//(30 * 1000);
        m_FreeQueueTimer->start();
        
        ///定时保存帮会信息,1min
        m_SaveGuildInfoTimer.reset(pTimeFactory->createTimer());
        m_SaveGuildInfoTimer->regTimer(std::bind(&DBSaveTiming::OnSaveGuildInfo, &m_DBSaveTiming));
        m_SaveGuildInfoTimer->setInterval(1 * 60 * 1000);
    
        ///定时保存道具信息,从道具管理器里面读取,然后保存到数据库,是整个服务器的道具定时存储
        m_SavePropInfoTimer.reset(pTimeFactory->createTimer());
        m_SavePropInfoTimer->regTimer(std::bind(&DBSaveTiming::OnSavePropInfo, &m_DBSaveTiming));
        m_SavePropInfoTimer->setInterval(1 * 60 * 1000);
    
        ///添加DataLayer单例好像gamemap里面也会用到,最后被废弃了,随后看看
        m_spDataLayer = NEWSP(DataLayer);
        add_singleton("DataLayer", m_spDataLayer.get());
        //m_spDataLayer = NEWSP(GatwayData);
        
        ///网络初始化,就是双向的共享内存的初始化
        if(!m_spDataLayer->Init())
        {
            Plug::PlugMessageBox(L"初始化网络失败!");
            ::TerminateProcess(::GetCurrentProcess(), 0);
        }
    
        ShareInit(m_spDataLayer.get());
        m_DBSaveTiming.SetAsynDBCPtr(m_spAsynDBC);
        m_DBSaveTiming.SetPropMgrPtr(m_spPropManager);
        m_DBSaveTiming.SetGuildOptPtr(m_spGuildOpt);
        //获取帮会信息
        m_fnGetGuildInfo = std::bind(&GameServer::ProcessGetGuildInfo, this, ph::_1, ph::_2);
        m_spAsynDBC->GetGuildInfos(&m_fnGetGuildInfo);
        //道具信息
        m_funGetUserProp = std::bind(&GameServer::ProcessGetPropInfo, this, ph::_1, ph::_2);
        m_spAsynDBC->GetPropInfos(&m_funGetUserProp);
    
        m_LiveMgr.m_fnTimeOutDisconnect = std::bind(&GameServer::TimeOutDisconnect, this, ph::_1);
        m_LiveMgr.Init(GetMaxGcNumb());
    
        m_vecChannel.resize(GetMaxGcNumb());
        m_spThread.reset(new std::thread(std::bind(&GameServer::ProcessThread, this)));//创建一个线程,就是常说的GS线程,其实很多工作都是在这个线程里面做的
        OnThreadId(m_spThread->get_id(), L"GS线程");
    }
    //可以看出主线程
    void Share::ShareInit(I_DataLayer* data_layer)//share是管理所有地图信息的,非常重要
    {
        // 加载xls表
        if(!LoadnBodyId())
            Plug::PlugMessageBox("加载nBodyID表失败啊!");//三种职业,两种性别,nbodyid大概就代表地图资源
        if(!LoadLevelInfo())
            Plug::PlugMessageBox("加载角色等级信息失败!");//三种职业,71个等级的等级信息
        if(!LoadMapData())
            Plug::PlugMessageBox("加载地图数据失败!");//现在就有7张地图
    
        /*地图数量*/
    
        for(auto itMap : m_mapDataTable)
        {
            auto& pMap = m_mapMap[itMap.first] = NEW(Map);//m_mapMap是地图id对应一个地图指针信息
            pMap->Init(GetMaxGcNumb(), itMap.second.map_path.c_str());//地图的初始化
            pMap->m_fnGetLevelInfo = std::bind(&Share::TGetLevelInfo, this, ph::_1, ph::_2, ph::_3);
    
            pMap->m_nMapId = itMap.first;
            std::wstring name = L"地图";
            name += boost::lexical_cast<std::wstring>(pMap->m_nMapId);
            OnThreadId(pMap->GetThreadId(), name); //获取线程ID
        }
    
        m_pDataLayer = data_layer;
        //初始化 跨地图操作模块
        InitAcrossMapOpt();
        InitAcrossManager();
    }
    
    
    void Map::Init(int max_gc_numb,  const char* res_path)
    {
        m_pLog = GetPlug(Log);//全局log单例
        msg_assert(m_pLog);
    
        m_vecPlayerChannel.resize(max_gc_numb);//m_vecPlayerChannel代表了一个地图上的所有玩家
        
        InitTimer();//map里面各种定时器的初始化
        InitOpt();//主要是地图内的一些操作,帮会,组队,关系,交易,npc交互,将这给些给分开有利于模块的独立
        InitMapInfoXml(res_path);//主要是地图的加载,块的划分,格子,2d人物通知都是用的格子,听说3d用的九宫格,只是听说
        InitPropXml();//道具信息的读取
        InitOrnamemtal();//这个不知干啥的
        InitMonsterTypeInfoTable();//怪物信息记载
        InitRegions();//区域的加载(安全区,战斗区)
        InitSkillLevelInfoTable();//技能等级信息
        InitMonsterDropRuleTable();//怪物掉落
        InitPlayerDropRuleTable();//人物掉落
        InitPetArrributeTable();//宠物属性
        InitSkillRestrictInfoTable();//限制技能读取
    
        InitSkillScript();//技能脚本
        InitMission();//任务
        InitMgr();//管理加载
    
        Start();//map线程启动
    }
  • 相关阅读:
    VS2019项目打开遇到的问题
    访问修饰符
    缩写
    PHP invoke函数使用
    json中有中文
    Walmart SKU空格问题
    error和exception的
    phpunit的安装
    curl注意
    关于学习
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4107111.html
Copyright © 2020-2023  润新知