• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 311, comments - 0, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            (搬運(yùn)工)Mangos代碼閱讀

            Posted on 2016-12-16 11:28 點點滴滴 閱讀(1706) 評論(0)  編輯 收藏 引用 所屬分類: 19 源碼收集

            邏輯層: 類World實現(xiàn)了wow的World,所有的邏輯處理
              MaNGOS 下載,編譯,配置和運(yùn)行的基本步驟 下載和安裝msysgit,用于代碼管理我使用的是Git-1.6.5.1-preview20091022.exe 
              下載和安裝tortoisegit,用于代碼管理我使用的是TortoiseGit-1.3.2.0-32bit.msi 
              使用git://github.com/mangos/mangos.git,從github提取mangos代碼 
              采用Git GUI工具的Clone Existing Repository,得到 mangos代碼(我的是9560,安裝UDB參考這) 
              使用git://github.com/scriptdev2/scriptdev2.git,從github提取scriptdev2代碼 
              采用Git GUI工具的Clone Existing Repository,得到 scriptdev2代碼. 
              編譯mangos我用的是VC9,打開mangoswinmangosdVC90.sln進(jìn)行構(gòu)造,構(gòu)造完成后,會得到mangosbinWin32_Debug文件夾 
              編譯scriptdev2我用的是VC9,打開mangoswinscriptdev2VC90.sln進(jìn)行構(gòu)造,構(gòu)造完成后,會得到scriptdev2binWin32_Debug文件夾也可參考 
              pandore 
              拷貝mangossrcmangosd目錄下的mangosd.conf.dist.in為mangosbinWin32_Debugmangosd.conf 
              拷貝mangossrcrealmd目錄下的realmd.conf.dist.in為mangosbinWin32_Debugrealmd.conf 
              從http://www.wowtaiwan.com.tw/下載和安裝臺服WOW,并升級到最新版本我使用的是臺服WOW 3.3.2 build 11403 
              ,采用MaNGOS的工具ad從wow的MPQ中抽取map,得到的所有的map數(shù)據(jù)文件,文件命名規(guī)范為map_id(3位) tileY(2位) tileX(2位).map,如文件名為0002035.map,代表的是Azeroth(地圖id為000,tile坐標(biāo)為(35,20). 注:WOW客戶端的Tile對應(yīng)mangos中的grid,WOW客戶端的Chunk對應(yīng)mangos中的cell(1cell = 4 chunk) 
              按照常規(guī)流程(包括建立數(shù)據(jù)庫和配置服務(wù)器)把服務(wù)器跑起來,使用account create zzh1234567 zzh1234567 創(chuàng)建一個賬號,使用account set gmlevel zzh1234567 3設(shè)置為超級用戶 
              配置好客戶端后,運(yùn)行WOW,順利登陸,呵呵 
              通過安裝UDB來豐富場景FULL DB 9560 : HERE,參考這,在我安裝DB9560的時候,發(fā)現(xiàn)Mangos在LoadCreatureAddons的時候,加載creature template addons出錯,Mangos只要求creature template addons有7個字段,而creature template addons有9個字段我現(xiàn)在只是簡單地跳過LoadCreatureAddons的調(diào)用 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客 
            運(yùn)行Mangos (運(yùn)行Mangos一節(jié)過期,是以前我針對國服3.1.3版本進(jìn)行的安裝配置) ,采用MaNGOS的工具ad從wow的MPQ中抽取map,得到的所有的map數(shù)據(jù)文件,文件命名規(guī)范為map_id(3位) tileY(2位) tileX(2位).map,如文件名為0002035.map,代表的是Azeroth(地圖id為000,tile坐標(biāo)為(35,20). 注:WOW客戶端的Tile對應(yīng)mangos中的grid,WOW客戶端的Chunk對應(yīng)mangos中的cell(1cell = 4 chunk) 
              配置好客戶端后,運(yùn)行WOW,順利登陸,呵呵 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客 
            Mangos代碼閱讀 
              Mangos有13個工程 
              使用了4個外部工具庫,分別是: 跨平臺的網(wǎng)絡(luò)通訊框架The ADAPTIVE Communication Environment (ACE) 
              壓縮庫zlib 
              Socket通信庫 C++ Sockets Library (使用在realmd工程中,和使用在Mangosd工程中的RASocket,負(fù)責(zé)處理Remote Administration其他地方?jīng)]有使用到這個C++ Sockets Library )發(fā)現(xiàn)在C++ Sockets Library的TcpSocket::Open中存在一個問題,在n = connect(s, ad, ad);語句執(zhí)行后,如果n=-1,C++ Sockets Library會檢測是否ERR為WSAEWOULDBLOCK,否則表示成功,但在動態(tài)庫中使用TcpSocket的時候,我發(fā)現(xiàn)n = connect(s, ad, ad);語句執(zhí)行后,n=-1,ERR會為0,這個時候連接也是成功了,但TcpSocket::Open會當(dāng)做不成功處理我發(fā)現(xiàn)這個問題,但沒有時間去探究原因,也許并不是一個問題 
              C++的并行編程模板庫Threading Building Blocks (tbb 和 tbbmalloc) 
              Mangos的實現(xiàn)分為:登錄服務(wù)器(realmd)和世界服務(wù)器(mangosd+game)realmd和mangos共用了Mangos公共庫(shared) 
              工程shared 
              提供了通用功能,包括了數(shù)據(jù)庫的封裝類,實現(xiàn)了對MySql的訪問,同樣,我們可以編寫派生類來支持其他的數(shù)據(jù)庫 
              工程script 
              提供了腳本接口,并實現(xiàn)了簡單的幾個腳本,封裝為DLL,提供給game使用,具體可參考:MaNGOS腳本接口 
              通過使用不同的腳本DLL來替換share的這個DLL,可以讓game具有更強(qiáng)的AIScriptDev2 就是一個這樣的庫ScriptDev2 is a replacement for the Script Library that comes with MaNGOS( http://www.getmangos.com ) written in C++ and is compatible with Windows and Linux. It provides scripts for NPCs, Boss events, and Items currently. Once ScriptDev2 is compiled it is automatically run by MaNGOS on server startup. 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客

            工程mangosd 
              mangos是世界服務(wù)器的管理器,負(fù)責(zé)初始化工作和啟動世界服務(wù)器各層的線程,這些工作主要是由類Master來實現(xiàn)具體是: 使用三個數(shù)據(jù)庫對象WorldDatabase和CharacterDatabase和loginDatabase,初始化三大數(shù)據(jù)庫:World Database和Character Database和login Database,并為每個數(shù)據(jù)庫的訪問都啟動一個DB delay threads具體的數(shù)據(jù)庫操作功能都是由Mangos公共庫shared來提供 
              調(diào)用sWorld.SetInitialWorldSettings,對World進(jìn)行初始化,包括加載所有的游戲數(shù)據(jù)和初始化各種更新定時器和郵件定時器,還有些其他的初始化工作類World的成員函數(shù)SetInitialWorldSettings調(diào)用成員函數(shù)LoadConfigSettings解析mangosd.conf,解析后內(nèi)容放入uint32 m_configs[CONFIG_VALUE_COUNT]中 
              加載的游戲數(shù)據(jù)有: 
              DBC數(shù)據(jù) 
              Objects數(shù)據(jù) 
              Spells數(shù)據(jù) 
              Pooling數(shù)據(jù) 
              Game Event數(shù)據(jù) 
              loot數(shù)據(jù) 
              技能數(shù)據(jù) 
              所有其他的游戲數(shù)據(jù),包括Waypoints和Trainers等等等 
              腳本數(shù)據(jù) 
              其他的初始化工作有: 
              初始化MapManager,啟動Map System 
              初始化Battlegrounds,啟動BattleGround System 
              初始化DailyQuestResetTime 
              初始化sGameEventMgr,Starting Game Event system 
              類Master啟動WorldRunnable,開始游戲邏輯Heartbeat for the World,由Master創(chuàng)建,并設(shè)置線程為最高優(yōu)先級 
              類Master啟動CliRunnable:Command Line Interface handling thread,由Master創(chuàng)建CliRunnable運(yùn)行時候會生成一個WorldDatabase線程,在接收到輸入后會調(diào)用sWorld.QueueCliCommand把Cmd放入到World::cliCmdQueue中 
              mangosd的線程總共有(1+3+1+1+1+2 +1 =10)10個線程 主線程Master 
              2個網(wǎng)絡(luò)線程ReactorRunnable(可配置數(shù)目)(網(wǎng)絡(luò)層) 
              一個World線程(邏輯層) 
              三個DB線程(數(shù)據(jù)層) 
              一個CLI線程(輸入層),運(yùn)行時候會生成一個WorldDatabase線程 
              一個RA線程(管理層) 
              一個freeze catcher 線程(可選) 
              工程g3dlite:游戲邏輯層的底層庫 
              工程framework:系統(tǒng)框架 
              工程realm 
              負(fù)責(zé)登陸和選擇游戲服務(wù)器,進(jìn)行負(fù)載均衡用到了C++ Sockets Library進(jìn)行登錄處理,采用select I/O模型實現(xiàn)了Wow, Mangos登錄時的SRP6認(rèn)證客戶端作為它的client連接到realm server認(rèn)證和選擇了mangos server就斷開 而mangos server和realm server則不進(jìn)行連接,只是通過數(shù)據(jù)庫交互數(shù)據(jù):mangos server把自己的狀態(tài)和擁有的角色數(shù)放入庫中realm server會讀取數(shù)據(jù)庫中的這些信息來獲知mangos server的狀態(tài) 數(shù)據(jù)庫realm的realmlist表保存了realm的列表 
              realm通過如下事件處理函數(shù)來負(fù)責(zé)登陸和選擇游戲服務(wù)器 
              const AuthHandler table[] = 
              { 
              { AUTH_LOGON_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleLogonChallenge }, 
              { AUTH_LOGON_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleLogonProof }, 
              { AUTH_RECONNECT_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleReconnectChallenge}, 
              { AUTH_RECONNECT_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleReconnectProof }, 
              { REALM_LIST, STATUS_AUTHED, &AuthSocket::_HandleRealmList }, 
              { XFER_ACCEPT, STATUS_CONNECTED, &AuthSocket::_HandleXferAccept }, 
              { XFER_RESUME, STATUS_CONNECTED, &AuthSocket::_HandleXferResume }, 
              { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } 
              }; 登錄處理: 
              user登錄到realm server進(jìn)行身份認(rèn)證,并選擇登錄上哪個mangos serveruser登錄到mangos server后,將不再和realm server交互 
              參考: Wow 服務(wù)器解析 
              工程game 
              game:是Mangos的核心代碼,網(wǎng)絡(luò)層和邏輯層代碼(采用了ACE反應(yīng)器(Reactor)模式) 
              網(wǎng)絡(luò)層: WorldSocket :負(fù)責(zé)網(wǎng)絡(luò)IO,而類WorldSession負(fù)責(zé)邏輯處理WorldSocket和WorldSession分別在獨立的線程ReactorRunnable和WorldRunnable中運(yùn)行,使用WorldSession中的消息隊列_recvQueue來進(jìn)行數(shù)據(jù)緩沖在WorldSocket接收到網(wǎng)咯輸入后,會調(diào)用m_Session->QueuePacket (new_pct);把網(wǎng)絡(luò)包放入WorldSession的_recvQueue所以,可以看到WorldSocket 是Mangos game的網(wǎng)絡(luò)層,而WorldSession是邏輯處理層WorldSocketMgr是網(wǎng)絡(luò)層的一個管理器,它負(fù)責(zé)指派WorldSocket歸哪個ReactorRunnable管理(Mangos可創(chuàng)建多個ReactorRunnable,缺省是2個) 
              WorldSocketMgr(Manages all sockets connected to peers and network threads)管理所有的連接WorldSocketWorldSocketMgr的WorldSocketMgr::StartNetwork對8085(缺省)端口進(jìn)行偵聽邏輯處理的循環(huán)是在World::Update中循環(huán)處理包括: 
              刷新更新定時器 
              刷新游戲定時器和處理游戲關(guān)閉 
              處理日常任務(wù) 
              處理拍賣 
              刷新SessionsWorld::UpdateSessions會調(diào)用所有WorldSession的WorldSession::Update在WorldSession::Update中進(jìn)行邏輯處理 
              處理天氣 
              刷新uptime table 
              刷新Objects,包括maps,transport,creatures,,,, 
              刷新所有running battlegrounds 
              刷新SqlResultQueue, 邏輯層和數(shù)據(jù)層是通過Queue來進(jìn)行異步操作的(用了AsyncPQuery和SqlResultQueue) 
              處理尸體移除 
              處理游戲事件 
              處理 Move all creatures with "delayed move" and remove and delete all objects with "delayed remove" 
              處理InstanceSaveManager的刷新 
              調(diào)用World::ProcessCliCommands,處理CLI從cliCmdQueue取得cmd進(jìn)行解析執(zhí)行所有有效的Cmd,都可以在ChatHandler::getCommandTable中找到 
              類WorldSession: 類WorldSession負(fù)責(zé)邏輯處理 
              void WorldSession::SendPacket(WorldPacket const* packet) 負(fù)責(zé)發(fā)包給客戶端,直接發(fā)包,沒有輸出緩沖隊列 
              在WorldSession::Update中進(jìn)行邏輯處理World::UpdateSessions會調(diào)用所有WorldSession的WorldSession::Update 
              執(zhí)行語句OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()];得到opHandle 
              根據(jù)得到的opHandle,執(zhí)行(this->*opHandle.handler)(*packet); 
              WorldSession::HandlePlayerLogin處理玩家登陸游戲 
              構(gòu)建Player 
              Player::LoadFromDB從數(shù)據(jù)庫中加載玩家數(shù)據(jù)在Player::LoadFromDB中會調(diào)用SetMap(MapManager::Instance().CreateMap(GetMapId() , this));加載當(dāng)前player所在的map 
              Player::SetPosition在Player運(yùn)動的時候,改變位置,保存處理夸區(qū) 
              類Map實現(xiàn)了一個state machine,采用state pattern組織了Gid的4個state object:InvalidState;ActiveState;IdleState;RemovalState 
              game中的管理器有: ObjectMgr 
              mMangosStringLocaleMap 關(guān)聯(lián)到mangos_string table 
              m_scriptNames 關(guān)聯(lián)到tables: creature_template;gameobject_template;item_templat e;areatrigger_scripts;instance_template 
              mCreatureLocaleMap 關(guān)聯(lián)到locales_creature table 
              mGameObjectLocaleMap關(guān)聯(lián)到locales_gameobject table 
              mItemLocaleMap關(guān)聯(lián)到locales_item table 
              mQuestLocaleMap –> locales_quest 
              mNpcTextLocaleMap –> locales_npc_text 
              mPageTextLocaleMap –> locales_page_text 
              mGossipMenuItemsLocaleMap –> locales_gossip_menu_option 
              mPointOfInterestLocaleMap –> locales_points_of_interest 
              … 
              對象類層次 
              對象的類層次如下,所有的Object都由ObjectMgr進(jìn)行管理ObjectMgr以GUID方式,管理了characters,creature,item_instance,gameobject,auctionhouse,mail,item_text,corpse,arena_team,character_equipmentsets 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客

            Player狀態(tài) 
              /// Player state 
              enum SessionStatus 
              { 
              STATUS_AUTHED = 0, ///< Player authenticated (_player==NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage) 
              STATUS_LOGGEDIN, ///< Player in game (_player!=NULL, m_GUID == _player->GetGUID(), inWorld()) 
              STATUS_TRANSFER, ///< Player transferring to another map (_player!=NULL, m_GUID == _player->GetGUID(), !inWorld()) 
              STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, ///< _player!= NULL or _player==NULL && m_playerRecentlyLogout, m_GUID store last _player guid) 
              STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) 
              }; 
              生物狀態(tài) 
              enum DeathState 
              { 
              ALIVE = 0, 
              JUST_DIED = 1, 
              CORPSE = 2, 
              DEAD = 3, 
              JUST_ALIVED = 4, 
              DEAD_FALLING= 5 
              }; 
              玩家登陸 
              服務(wù)器端在連接打開后,會發(fā)SMSG_AUTH_CHALLENGE到客戶端客戶端從服務(wù)器端發(fā)送回來的種子和 SRP6 數(shù)據(jù)中產(chǎn)生隨機(jī)種子,生成 SHA1 字符串,用這些數(shù)據(jù)生成 CMSG_AUITH_SESSION 數(shù)據(jù)包,發(fā)送給服務(wù)端這個過程是沒有經(jīng)過加密的 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              客戶端發(fā)送SMSG_AUTH_SESSION到服務(wù)器 
              服務(wù)器處理SMSG_AUTH_SESSION 
              服務(wù)器發(fā)送SMSG_AUTH_RESPONSE給客戶端 
              服務(wù)器發(fā)送SMSG_ADDON_INFO給客戶端 
              服務(wù)器發(fā)送SMSG_CLIENTCACHE_VERSION給客戶端 
              服務(wù)器發(fā)送SMSG_TUTORIAL_FLAGS給客戶端 
              packet結(jié)構(gòu) SMSG_AUTH_SESSION 是client packet有一個頭部(ClientPktHeader),后面是數(shù)據(jù)塊 
              SMSG_AUTH_RESPONSE 是server packet有一個頭部(ServicePktHeader),后面是數(shù)據(jù)塊 
              SMSG_AUTH_RESPONSE 的包組織 
              SMSG_AUTH_RESPONSE 的opcode是01EE,ByteBuffer大小為1 + 4 + 1 + 4 + 1=11一個SMSG_AUTH_RESPONSE 的數(shù)據(jù)如下: 在構(gòu)造了SMSG_AUTH_RESPONSE packet后,WorldSocket::SendPacket會根據(jù)SMSG_AUTH_RESPONSE packet構(gòu)造出一個ServerPktHeader,并對ServerPktHeader中的數(shù)據(jù)header進(jìn)行加密發(fā)送加密采用m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength()); WorldSocket::handle_input_header會對從客戶端接收來的數(shù)據(jù)進(jìn)行解密,解密采用m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr (), sizeof (ClientPktHeader)); 
              角色枚舉 玩家登上服務(wù)器后,從客戶端發(fā)送SMSG_CHAR_ENUM到服務(wù)器 
              在服務(wù)器端 
              根據(jù){ "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode },服務(wù)器會調(diào)用WorldSession::HandleCharEnumOpcode 
              WorldSession::HandleCharEnumOpcode會調(diào)用CharacterDatabase.AsyncPQuery,進(jìn)行異步查詢后,調(diào)用CharacterHandler::HandleCharEnumCallback 
              CharacterHandler::HandleCharEnumCallback會回頭調(diào)用session->HandleCharEnum(result); 
              WorldSession::HandleCharEnum根據(jù)characters數(shù)據(jù)庫的查詢結(jié)果,調(diào)用Player::BuildEnumData,加載角色數(shù)據(jù),構(gòu)造SMSG_CHAR_ENUM返回包,然后發(fā)送回客戶端 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              角色創(chuàng)建 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客 
              角色的初始化裝備在CharStartOutfit.dbc 
              角色的創(chuàng)建和選擇的設(shè)置都在 ChrRaces.dbc 
              角色的創(chuàng)建屬性都在Playercreateinfo,包括出生地和出生屬性 
              playercreateinfo_item表是創(chuàng)建一個新人物時,人物默認(rèn)帶的所有Item的表 
              playercreateinfo_spell表是創(chuàng)建一個新人物時,人物默認(rèn)帶的所有Spell的表 
            角色刪除 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客

            伊人久久大香线蕉亚洲五月天| 日日噜噜夜夜狠狠久久丁香五月| 国产精品久久网| 99精品久久久久久久婷婷| 国产综合成人久久大片91| 日本欧美国产精品第一页久久| 一本一本久久a久久精品综合麻豆| 久久成人国产精品免费软件| 色综合久久久久网| 女人高潮久久久叫人喷水| 国产精品久久波多野结衣| 欧美亚洲另类久久综合婷婷| avtt天堂网久久精品| 伊人 久久 精品| www亚洲欲色成人久久精品| 伊人久久大香线蕉av不卡| 国产伊人久久| 欧美精品一区二区精品久久| 亚洲精品无码久久一线| 久久久久婷婷| 国产精品无码久久四虎| 性欧美大战久久久久久久久| 亚洲国产高清精品线久久 | 国产精品久久成人影院| 亚洲精品乱码久久久久久不卡| 国产一区二区精品久久| 久久精品a亚洲国产v高清不卡| 国产精品gz久久久| 久久久久久综合一区中文字幕| 久久久亚洲欧洲日产国码aⅴ| 伊人久久大香线蕉AV一区二区 | 久久影院亚洲一区| 欧美日韩中文字幕久久伊人| 99久久精品国内| 亚洲国产精品一区二区久久| 国产精品久久国产精品99盘 | 久久亚洲国产最新网站| 性做久久久久久久久| 亚洲精品无码久久久| 国产一区二区久久久| 久久久久久国产a免费观看黄色大片 |