• <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++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            (搬運工)Mangos代碼閱讀

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

            邏輯層: 類World實現了wow的World,所有的邏輯處理
              MaNGOS 下載,編譯,配置和運行的基本步驟 下載和安裝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進行構造,構造完成后,會得到mangosbinWin32_Debug文件夾 
              編譯scriptdev2我用的是VC9,打開mangoswinscriptdev2VC90.sln進行構造,構造完成后,會得到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數據文件,文件命名規范為map_id(3位) tileY(2位) tileX(2位).map,如文件名為0002035.map,代表的是Azeroth(地圖id為000,tile坐標為(35,20). 注:WOW客戶端的Tile對應mangos中的grid,WOW客戶端的Chunk對應mangos中的cell(1cell = 4 chunk) 
              按照常規流程(包括建立數據庫和配置服務器)把服務器跑起來,使用account create zzh1234567 zzh1234567 創建一個賬號,使用account set gmlevel zzh1234567 3設置為超級用戶 
              配置好客戶端后,運行WOW,順利登陸,呵呵 
              通過安裝UDB來豐富場景FULL DB 9560 : HERE,參考這,在我安裝DB9560的時候,發現Mangos在LoadCreatureAddons的時候,加載creature template addons出錯,Mangos只要求creature template addons有7個字段,而creature template addons有9個字段我現在只是簡單地跳過LoadCreatureAddons的調用 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客 
            運行Mangos (運行Mangos一節過期,是以前我針對國服3.1.3版本進行的安裝配置) ,采用MaNGOS的工具ad從wow的MPQ中抽取map,得到的所有的map數據文件,文件命名規范為map_id(3位) tileY(2位) tileX(2位).map,如文件名為0002035.map,代表的是Azeroth(地圖id為000,tile坐標為(35,20). 注:WOW客戶端的Tile對應mangos中的grid,WOW客戶端的Chunk對應mangos中的cell(1cell = 4 chunk) 
              配置好客戶端后,運行WOW,順利登陸,呵呵 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客 
            Mangos代碼閱讀 
              Mangos有13個工程 
              使用了4個外部工具庫,分別是: 跨平臺的網絡通訊框架The ADAPTIVE Communication Environment (ACE) 
              壓縮庫zlib 
              Socket通信庫 C++ Sockets Library (使用在realmd工程中,和使用在Mangosd工程中的RASocket,負責處理Remote Administration其他地方沒有使用到這個C++ Sockets Library )發現在C++ Sockets Library的TcpSocket::Open中存在一個問題,在n = connect(s, ad, ad);語句執行后,如果n=-1,C++ Sockets Library會檢測是否ERR為WSAEWOULDBLOCK,否則表示成功,但在動態庫中使用TcpSocket的時候,我發現n = connect(s, ad, ad);語句執行后,n=-1,ERR會為0,這個時候連接也是成功了,但TcpSocket::Open會當做不成功處理我發現這個問題,但沒有時間去探究原因,也許并不是一個問題 
              C++的并行編程模板庫Threading Building Blocks (tbb 和 tbbmalloc) 
              Mangos的實現分為:登錄服務器(realmd)和世界服務器(mangosd+game)realmd和mangos共用了Mangos公共庫(shared) 
              工程shared 
              提供了通用功能,包括了數據庫的封裝類,實現了對MySql的訪問,同樣,我們可以編寫派生類來支持其他的數據庫 
              工程script 
              提供了腳本接口,并實現了簡單的幾個腳本,封裝為DLL,提供給game使用,具體可參考:MaNGOS腳本接口 
              通過使用不同的腳本DLL來替換share的這個DLL,可以讓game具有更強的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是世界服務器的管理器,負責初始化工作和啟動世界服務器各層的線程,這些工作主要是由類Master來實現具體是: 使用三個數據庫對象WorldDatabase和CharacterDatabase和loginDatabase,初始化三大數據庫:World Database和Character Database和login Database,并為每個數據庫的訪問都啟動一個DB delay threads具體的數據庫操作功能都是由Mangos公共庫shared來提供 
              調用sWorld.SetInitialWorldSettings,對World進行初始化,包括加載所有的游戲數據和初始化各種更新定時器和郵件定時器,還有些其他的初始化工作類World的成員函數SetInitialWorldSettings調用成員函數LoadConfigSettings解析mangosd.conf,解析后內容放入uint32 m_configs[CONFIG_VALUE_COUNT]中 
              加載的游戲數據有: 
              DBC數據 
              Objects數據 
              Spells數據 
              Pooling數據 
              Game Event數據 
              loot數據 
              技能數據 
              所有其他的游戲數據,包括Waypoints和Trainers等等等 
              腳本數據 
              其他的初始化工作有: 
              初始化MapManager,啟動Map System 
              初始化Battlegrounds,啟動BattleGround System 
              初始化DailyQuestResetTime 
              初始化sGameEventMgr,Starting Game Event system 
              類Master啟動WorldRunnable,開始游戲邏輯Heartbeat for the World,由Master創建,并設置線程為最高優先級 
              類Master啟動CliRunnable:Command Line Interface handling thread,由Master創建CliRunnable運行時候會生成一個WorldDatabase線程,在接收到輸入后會調用sWorld.QueueCliCommand把Cmd放入到World::cliCmdQueue中 
              mangosd的線程總共有(1+3+1+1+1+2 +1 =10)10個線程 主線程Master 
              2個網絡線程ReactorRunnable(可配置數目)(網絡層) 
              一個World線程(邏輯層) 
              三個DB線程(數據層) 
              一個CLI線程(輸入層),運行時候會生成一個WorldDatabase線程 
              一個RA線程(管理層) 
              一個freeze catcher 線程(可選) 
              工程g3dlite:游戲邏輯層的底層庫 
              工程framework:系統框架 
              工程realm 
              負責登陸和選擇游戲服務器,進行負載均衡用到了C++ Sockets Library進行登錄處理,采用select I/O模型實現了Wow, Mangos登錄時的SRP6認證客戶端作為它的client連接到realm server認證和選擇了mangos server就斷開 而mangos server和realm server則不進行連接,只是通過數據庫交互數據:mangos server把自己的狀態和擁有的角色數放入庫中realm server會讀取數據庫中的這些信息來獲知mangos server的狀態 數據庫realm的realmlist表保存了realm的列表 
              realm通過如下事件處理函數來負責登陸和選擇游戲服務器 
              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進行身份認證,并選擇登錄上哪個mangos serveruser登錄到mangos server后,將不再和realm server交互 
              參考: Wow 服務器解析 
              工程game 
              game:是Mangos的核心代碼,網絡層和邏輯層代碼(采用了ACE反應器(Reactor)模式) 
              網絡層: WorldSocket :負責網絡IO,而類WorldSession負責邏輯處理WorldSocket和WorldSession分別在獨立的線程ReactorRunnable和WorldRunnable中運行,使用WorldSession中的消息隊列_recvQueue來進行數據緩沖在WorldSocket接收到網咯輸入后,會調用m_Session->QueuePacket (new_pct);把網絡包放入WorldSession的_recvQueue所以,可以看到WorldSocket 是Mangos game的網絡層,而WorldSession是邏輯處理層WorldSocketMgr是網絡層的一個管理器,它負責指派WorldSocket歸哪個ReactorRunnable管理(Mangos可創建多個ReactorRunnable,缺省是2個) 
              WorldSocketMgr(Manages all sockets connected to peers and network threads)管理所有的連接WorldSocketWorldSocketMgr的WorldSocketMgr::StartNetwork對8085(缺省)端口進行偵聽邏輯處理的循環是在World::Update中循環處理包括: 
              刷新更新定時器 
              刷新游戲定時器和處理游戲關閉 
              處理日常任務 
              處理拍賣 
              刷新SessionsWorld::UpdateSessions會調用所有WorldSession的WorldSession::Update在WorldSession::Update中進行邏輯處理 
              處理天氣 
              刷新uptime table 
              刷新Objects,包括maps,transport,creatures,,,, 
              刷新所有running battlegrounds 
              刷新SqlResultQueue, 邏輯層和數據層是通過Queue來進行異步操作的(用了AsyncPQuery和SqlResultQueue) 
              處理尸體移除 
              處理游戲事件 
              處理 Move all creatures with "delayed move" and remove and delete all objects with "delayed remove" 
              處理InstanceSaveManager的刷新 
              調用World::ProcessCliCommands,處理CLI從cliCmdQueue取得cmd進行解析執行所有有效的Cmd,都可以在ChatHandler::getCommandTable中找到 
              類WorldSession: 類WorldSession負責邏輯處理 
              void WorldSession::SendPacket(WorldPacket const* packet) 負責發包給客戶端,直接發包,沒有輸出緩沖隊列 
              在WorldSession::Update中進行邏輯處理World::UpdateSessions會調用所有WorldSession的WorldSession::Update 
              執行語句OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()];得到opHandle 
              根據得到的opHandle,執行(this->*opHandle.handler)(*packet); 
              WorldSession::HandlePlayerLogin處理玩家登陸游戲 
              構建Player 
              Player::LoadFromDB從數據庫中加載玩家數據在Player::LoadFromDB中會調用SetMap(MapManager::Instance().CreateMap(GetMapId() , this));加載當前player所在的map 
              Player::SetPosition在Player運動的時候,改變位置,保存處理夸區 
              類Map實現了一個state machine,采用state pattern組織了Gid的4個state object:InvalidState;ActiveState;IdleState;RemovalState 
              game中的管理器有: ObjectMgr 
              mMangosStringLocaleMap 關聯到mangos_string table 
              m_scriptNames 關聯到tables: creature_template;gameobject_template;item_templat e;areatrigger_scripts;instance_template 
              mCreatureLocaleMap 關聯到locales_creature table 
              mGameObjectLocaleMap關聯到locales_gameobject table 
              mItemLocaleMap關聯到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進行管理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狀態 
              /// 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) 
              }; 
              生物狀態 
              enum DeathState 
              { 
              ALIVE = 0, 
              JUST_DIED = 1, 
              CORPSE = 2, 
              DEAD = 3, 
              JUST_ALIVED = 4, 
              DEAD_FALLING= 5 
              }; 
              玩家登陸 
              服務器端在連接打開后,會發SMSG_AUTH_CHALLENGE到客戶端客戶端從服務器端發送回來的種子和 SRP6 數據中產生隨機種子,生成 SHA1 字符串,用這些數據生成 CMSG_AUITH_SESSION 數據包,發送給服務端這個過程是沒有經過加密的 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              客戶端發送SMSG_AUTH_SESSION到服務器 
              服務器處理SMSG_AUTH_SESSION 
              服務器發送SMSG_AUTH_RESPONSE給客戶端 
              服務器發送SMSG_ADDON_INFO給客戶端 
              服務器發送SMSG_CLIENTCACHE_VERSION給客戶端 
              服務器發送SMSG_TUTORIAL_FLAGS給客戶端 
              packet結構 SMSG_AUTH_SESSION 是client packet有一個頭部(ClientPktHeader),后面是數據塊 
              SMSG_AUTH_RESPONSE 是server packet有一個頭部(ServicePktHeader),后面是數據塊 
              SMSG_AUTH_RESPONSE 的包組織 
              SMSG_AUTH_RESPONSE 的opcode是01EE,ByteBuffer大小為1 + 4 + 1 + 4 + 1=11一個SMSG_AUTH_RESPONSE 的數據如下: 在構造了SMSG_AUTH_RESPONSE packet后,WorldSocket::SendPacket會根據SMSG_AUTH_RESPONSE packet構造出一個ServerPktHeader,并對ServerPktHeader中的數據header進行加密發送加密采用m_Crypt.EncryptSend ((uint8*)header.header, header.getHeaderLength()); WorldSocket::handle_input_header會對從客戶端接收來的數據進行解密,解密采用m_Crypt.DecryptRecv ((uint8*) m_Header.rd_ptr (), sizeof (ClientPktHeader)); 
              角色枚舉 玩家登上服務器后,從客戶端發送SMSG_CHAR_ENUM到服務器 
              在服務器端 
              根據{ "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode },服務器會調用WorldSession::HandleCharEnumOpcode 
              WorldSession::HandleCharEnumOpcode會調用CharacterDatabase.AsyncPQuery,進行異步查詢后,調用CharacterHandler::HandleCharEnumCallback 
              CharacterHandler::HandleCharEnumCallback會回頭調用session->HandleCharEnum(result); 
              WorldSession::HandleCharEnum根據characters數據庫的查詢結果,調用Player::BuildEnumData,加載角色數據,構造SMSG_CHAR_ENUM返回包,然后發送回客戶端 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客
              角色創建 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客 
              角色的初始化裝備在CharStartOutfit.dbc 
              角色的創建和選擇的設置都在 ChrRaces.dbc 
              角色的創建屬性都在Playercreateinfo,包括出生地和出生屬性 
              playercreateinfo_item表是創建一個新人物時,人物默認帶的所有Item的表 
              playercreateinfo_spell表是創建一個新人物時,人物默認帶的所有Spell的表 
            角色刪除 
              Mangos代碼閱讀 - 陳波 - cp7618@yeah的博客

            色综合久久精品中文字幕首页| 精品综合久久久久久97| 一本一道久久精品综合| 亚洲国产精品久久久久婷婷老年| 国产亚洲精久久久久久无码| 国产精品99久久久久久猫咪 | a高清免费毛片久久| 97超级碰碰碰碰久久久久| 久久亚洲国产成人影院| 国产精品对白刺激久久久| 久久亚洲电影| 国产精品毛片久久久久久久| 久久黄色视频| 精品久久久久久国产| 久久精品国产亚洲av麻豆图片| 香港aa三级久久三级| 亚洲欧美日韩中文久久| 久久亚洲视频| 久久久久久国产a免费观看不卡| 国产精品一久久香蕉国产线看观看| 99久久精品国产综合一区| 久久精品国产99久久无毒不卡| 久久久久无码精品国产app| 久久综合九色综合97_久久久| 囯产精品久久久久久久久蜜桃| 成人精品一区二区久久久| 国产精品久久波多野结衣| 亚洲欧美伊人久久综合一区二区| 理论片午午伦夜理片久久| 9191精品国产免费久久| 久久99国产亚洲高清观看首页| 久久久久99精品成人片欧美 | 久久AV高潮AV无码AV| 人妻精品久久久久中文字幕| 九九久久精品国产| 国产一区二区精品久久凹凸 | 香蕉久久av一区二区三区| 久久精品综合网| 99久久夜色精品国产网站| 一本久久a久久精品综合香蕉 | 国产精品一久久香蕉国产线看观看|