最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

wow魔獸世界服務(wù)端主體結(jié)構(gòu)

2023-02-08 19:39 作者:馳網(wǎng)科技idc-艾西  | 我要投稿

??服務(wù)端主要由三大塊組成,數(shù)據(jù)庫(kù)、服務(wù)端邏輯、腳本。數(shù)據(jù)庫(kù)用的MySQL,這里不是很關(guān)鍵暫且不說(shuō)。腳本有自己的腳本引擎,簡(jiǎn)單的任務(wù)、戰(zhàn)斗等都可以通過數(shù)據(jù)庫(kù)配置相應(yīng)條目來(lái)完成,復(fù)雜的戰(zhàn)斗AI等在腳本庫(kù)中由C++直接寫成,這個(gè)腳本庫(kù)是要被編譯為機(jī)器代碼的,執(zhí)行效率相當(dāng)高效,例如巫妖王的戰(zhàn)斗比較復(fù)雜就用C++寫,其它簡(jiǎn)單的就配置在數(shù)據(jù)庫(kù)中由腳本引擎來(lái)驅(qū)動(dòng)執(zhí)行。AZ服務(wù)端是一個(gè)多線程、邏輯單線程的服務(wù)端。每個(gè)線程內(nèi)部都采用循環(huán)結(jié)構(gòu),主線程啟動(dòng)后將創(chuàng)建多個(gè)工作線程,主要包括負(fù)責(zé)游戲世界運(yùn)作的核心線程,具有處理用戶請(qǐng)求,執(zhí)行定時(shí)器的能力。其它幾個(gè)工作線程還有網(wǎng)絡(luò)Io,該線程啟動(dòng)后其內(nèi)部將使用線程池進(jìn)行網(wǎng)絡(luò)Io操作,不間斷地接收數(shù)據(jù)包,并存儲(chǔ)到相關(guān)玩家的消息隊(duì)列中,由世界線程進(jìn)行處理,其它幾個(gè)工作線程先不討論,看mangos的源代碼.務(wù)端啟動(dòng)后這些線程將永不停息地工作。世界線程是服務(wù)器的核心,負(fù)責(zé)處理所有玩家操作請(qǐng)求,定時(shí)器、AI等。以下是世界線程啟動(dòng)后執(zhí)行的代碼:

///?Heartbeat for the Worldvoid?WorldRunnable::run()

{

????///- Init new SQL thread for the world database

????WorldDatabase.ThreadStart(); ???????????????????????????// let thread do safe mySQL requests (one connection call enough)????sWorld.InitResultQueue();

?

????uint32 realCurrTime = 0;

????uint32 realPrevTime = WorldTimer::tick();

?

????uint32 prevSleepTime = 0; ??????????????????????????????// used for balanced full tick time length near WORLD_SLEEP_CONST

?

????///- While we have not World::m_stopEvent, update the world

????while?(!World::IsStopped())

????{

????????++World::m_worldLoopCounter;

????????realCurrTime = WorldTimer::getMSTime();

?

????????uint32 diff = WorldTimer::tick();

?

????????sWorld.Update(diff);

????????realPrevTime = realCurrTime;

?

????????// diff (D0) include time of previous sleep (d0) + tick time (t0)

????????// we want that next d1 + t1 == WORLD_SLEEP_CONST

????????// we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement

????????// d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0

????????if?(diff <= WORLD_SLEEP_CONST + prevSleepTime)

????????{

????????????prevSleepTime = WORLD_SLEEP_CONST + prevSleepTime - diff;

????????????ACE_Based::Thread::Sleep(prevSleepTime);

????????}

????????else

????????????prevSleepTime = 0;

?

#ifdef WIN32

????????if?(m_ServiceStatus == 0) World::StopNow(SHUTDOWN_EXIT_CODE);

????????while?(m_ServiceStatus == 2) Sleep(1000);#endif

????}

?

????sWorld.CleanupsBeforeStop();

?

????sWorldSocketMgr->StopNetwork();

?

????MapManager::Instance().UnloadAll(); ????????????????????// unload all grids (including locked in memory)

?

????///- End the database thread

????WorldDatabase.ThreadEnd(); ?????????????????????????????// free mySQL thread resources

}

這里先作一下說(shuō)明,這是世界線程的根循環(huán)結(jié)構(gòu),在while(!World::IsStopped())內(nèi)部只有一個(gè)核心函數(shù)調(diào)用,其他都是一些控制更新時(shí)間之類的代碼,不用太關(guān)注:

sWorld.Update(diff);

sWorld是單一實(shí)例的World對(duì)象,它代表了整個(gè)游戲世界,和多數(shù)MMORPG一樣,啟動(dòng)后進(jìn)入根循環(huán),在運(yùn)行內(nèi)部一直調(diào)用更新整個(gè)游戲世界的Update函數(shù),服務(wù)端不停的Update游戲世界,每次Update能在100毫秒內(nèi)完成,則客戶端會(huì)感到非常流暢。在根循環(huán)退出后,清理服務(wù)器相關(guān)資源,線程結(jié)束被回收。

到這里僅僅需要關(guān)注一個(gè)函數(shù)了,就是World的Update方法內(nèi)部到底在干什么?

void?World::Update(uint32 diff)

{

????///- Update the different timers

????for?(int?i = 0; i < WUPDATE_COUNT; ++i)

????{

????????if?(m_timers[i].GetCurrent() >= 0)

????????????m_timers[i].Update(diff);

????????else

????????????m_timers[i].SetCurrent(0);

????}

????///- Update the game time and check for shutdown time????_UpdateGameTime();

????///-Update mass mailer tasks if any????sMassMailMgr.Update();

????///?Handle daily quests reset time

????if?(m_gameTime > m_NextDailyQuestReset)

????????ResetDailyQuests();

????///?Handle weekly quests reset time

????if?(m_gameTime > m_NextWeeklyQuestReset)

????????ResetWeeklyQuests();

????///?Handle monthly quests reset time

????if?(m_gameTime > m_NextMonthlyQuestReset)

????????ResetMonthlyQuests();

????///?Handle monthly quests reset time

????if?(m_gameTime > m_NextCurrencyReset)

????????ResetCurrencyWeekCounts();

????///?<ul><li>?Handle auctions when the timer has passed

????if?(m_timers[WUPDATE_AUCTIONS].Passed())

????{

????????m_timers[WUPDATE_AUCTIONS].Reset();

????????///- Update mails (return old mails with item, or delete them)

????????//(tested... works on win)

????????if?(++mail_timer > mail_timer_expires)

????????{

????????????mail_timer = 0;

????????????sObjectMgr.ReturnOrDeleteOldMails(true);

????????}

????????///- Handle expired auctions????????sAuctionMgr.Update();

????}

?

????///?<li>?Handle AHBot operations

????if?(m_timers[WUPDATE_AHBOT].Passed())

????{

????????sAuctionBot.Update();

????????m_timers[WUPDATE_AHBOT].Reset();

????}

?

????///?<li>?Handle session updates????UpdateSessions(diff);

?

????///?<li>?Handle weather updates when the timer has passed

????if?(m_timers[WUPDATE_WEATHERS].Passed())

????{

????????///- Send an update signal to Weather objects

????????for?(WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end();)

????????{

????????????///- and remove Weather objects for zones with no player

????????????// As interval > WorldTick

????????????if?(!itr->second->Update(m_timers[WUPDATE_WEATHERS].GetInterval()))

????????????{

????????????????delete itr->second;

????????????????m_weathers.erase(itr++);

????????????}

????????????else

????????????????++itr;

????????}

?

????????m_timers[WUPDATE_WEATHERS].SetCurrent(0);

????}

????///?<li>?Update uptime table

????if?(m_timers[WUPDATE_UPTIME].Passed())

????{

????????uint32 tmpDiff = uint32(m_gameTime - m_startTime);

????????uint32 maxClientsNum = GetMaxActiveSessionCount();

?

????????m_timers[WUPDATE_UPTIME].Reset();

????????LoginDatabase.PExecute("UPDATE uptime SET uptime = %u, maxplayers = %u WHERE realmid = %u AND starttime = "?UI64FMTD, tmpDiff, maxClientsNum, realmID, uint64(m_startTime));

????}

?

????///?<li>?Handle all other objects

????///- Update objects (maps, transport, creatures,...)????sMapMgr.Update(diff);

????sBattleGroundMgr.Update(diff);

????sOutdoorPvPMgr.Update(diff);

?

????///- Delete all characters which have been deleted X days before

????if?(m_timers[WUPDATE_DELETECHARS].Passed())

????{

????????m_timers[WUPDATE_DELETECHARS].Reset();

????????Player::DeleteOldCharacters();

????}

?

????// execute callbacks from sql queries that were queued recently????UpdateResultQueue();

?

????///- Erase corpses once every 20 minutes

????//每20分鐘清除尸體

????if?(m_timers[WUPDATE_CORPSES].Passed())

????{

????????m_timers[WUPDATE_CORPSES].Reset();

?

????????sObjectAccessor.RemoveOldCorpses();

????}

?

????///- Process Game events when necessary

????//處理游戲事件

????if?(m_timers[WUPDATE_EVENTS].Passed())

????{

????????m_timers[WUPDATE_EVENTS].Reset(); ??????????????????// to give time for Update() to be processed

????????uint32 nextGameEvent = sGameEventMgr.Update();

????????m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);

????????m_timers[WUPDATE_EVENTS].Reset();

????}

?

????///?</ul>

????///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"????sMapMgr.RemoveAllObjectsInRemoveList();

????// update the instance reset times????sMapPersistentStateMgr.Update();

????// And last, but not least handle the issued cli commands????ProcessCliCommands();

????// cleanup unused GridMap objects as well as VMaps????sTerrainMgr.Update(diff);

}

這是World::Update函數(shù)的全部代碼,服務(wù)器循環(huán)執(zhí)行這些代碼,每一次執(zhí)行就能更新一次游戲世界。這個(gè)函數(shù)看似比較長(zhǎng),實(shí)際上不算很長(zhǎng),其中的關(guān)鍵之處在于首先是根據(jù)定時(shí)器來(lái)執(zhí)行特定的任務(wù),而執(zhí)行這些任務(wù)則是通過調(diào)用各個(gè)模塊的Manager來(lái)完成,比如游戲世界里面的尸體每20分鐘清除一次,就檢測(cè)相關(guān)的定時(shí)器是否超時(shí),超時(shí)則清理尸體,然后重置定時(shí)器。通過這些定時(shí)器,來(lái)執(zhí)行游戲中由服務(wù)器主動(dòng)完成的任務(wù),這些任務(wù)基本上是通過定時(shí)器來(lái)啟動(dòng)的。游戲中的天氣系統(tǒng)、PvP系統(tǒng)、地形系統(tǒng)等等都根據(jù)定時(shí)器指定的頻率進(jìn)行更新。除了更新各個(gè)模塊之外,其中還有個(gè)非常重要的調(diào)用:

UpdateSessions(diff);

如果翻譯過來(lái)就是更新所有會(huì)話,服務(wù)器端為每一個(gè)客戶端建立一個(gè)Session,即會(huì)話,它是客戶端與服務(wù)端溝通的通道,取數(shù)據(jù)、發(fā)數(shù)據(jù)都得通過這條通道,這樣客戶端和服務(wù)端才能溝通。在mangos的構(gòu)架中,Session的作用非常重要,但其功能不僅僅取客戶端發(fā)過來(lái)的數(shù)據(jù)、將服務(wù)端數(shù)據(jù)發(fā)給客戶端那么簡(jiǎn)單,后面會(huì)繼續(xù)結(jié)束這個(gè)Session,很關(guān)鍵的東西,下面是UpdateSessions的具體實(shí)現(xiàn):

void?World::UpdateSessions(uint32 diff)

{

????///- Add new sessions

????WorldSession* sess;

????while?(addSessQueue.next(sess))

????????AddSession_(sess);

?

????///- Then send an update signal to remaining ones

????for?(SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)

????{

????????next = itr;

????????++next;

????????///- and remove not active sessions from the list

????????WorldSession* pSession = itr->second;

????????WorldSessionFilter updater(pSession);

?

????????if?(!pSession->Update(updater))

????????{

????????????RemoveQueuedSession(pSession);

????????????m_sessions.erase(itr);

????????????delete pSession;

????????}

????}

}

其內(nèi)部結(jié)構(gòu)簡(jiǎn)單,主要遍歷所有會(huì)話,移除不活動(dòng)的會(huì)話,并調(diào)用每個(gè)Session的Update函數(shù),達(dá)到更新所有Session的目的,有1000玩家在線就會(huì)更新1000個(gè)會(huì)話,前面提到了Session,每個(gè)會(huì)話的內(nèi)部都掛載有一個(gè)消息隊(duì)列,這里隊(duì)列存儲(chǔ)著從客戶端發(fā)過來(lái)的數(shù)據(jù)包,1000個(gè)會(huì)話就會(huì)有1000個(gè)數(shù)據(jù)包隊(duì)列,隊(duì)列是由網(wǎng)絡(luò)模塊收到數(shù)據(jù)包后,將其掛載到相應(yīng)Sesson的接收隊(duì)列中,客戶端1發(fā)來(lái)的數(shù)據(jù)包被掛載到Session1的隊(duì)列,客戶端2的就掛載到Session2的隊(duì)列中。mangos的架構(gòu)中Session不止是收發(fā)數(shù)據(jù)的入口,同樣也是處理客戶端數(shù)據(jù)的入口,即處理客戶端請(qǐng)求的調(diào)度中心。每次Update Session的時(shí)候,這個(gè)Update 函數(shù)的內(nèi)部會(huì)取出隊(duì)列中所有的請(qǐng)求數(shù)據(jù),循環(huán)地對(duì)每一個(gè)數(shù)據(jù)包調(diào)用數(shù)據(jù)包對(duì)應(yīng)的處理代碼,即根據(jù)數(shù)據(jù)包的類型(操作碼OpCode)調(diào)用相應(yīng)的函數(shù)進(jìn)行處理,而這些“相應(yīng)的函數(shù)”是Session內(nèi)部的普通成員函數(shù),以HandleXXXXXX開頭,為了便于理解,將Session的Update函數(shù)主體核心代碼寫在這里:

bool?WorldSession::Update(PacketFilter& updater)

{

????///- Retrieve packets from the receive queue and call the appropriate handlers

????///?not process packets if socket already closed

????WorldPacket* packet = NULL;

????while?(m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater))

????{

????????OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];

????????ExecuteOpcode(opHandle, packet);

????}

}

這樣看起了比較清楚了,Session在Update的時(shí)候,取出所有數(shù)據(jù)包,每個(gè)數(shù)據(jù)包都有一個(gè)操作碼,opcode,魔獸模擬器有1600多個(gè)操作碼,玩家或者服務(wù)器的每個(gè)操作都有一個(gè)對(duì)應(yīng)的操作碼,比如攻擊某個(gè)目標(biāo)、拾取一件東西、使用某個(gè)物品都有操作碼,被追加到數(shù)據(jù)包頭部,這樣每次取數(shù)據(jù)包的操作碼,就可以查找相應(yīng)的處理代碼來(lái)處理這個(gè)數(shù)據(jù)包。

?


wow魔獸世界服務(wù)端主體結(jié)構(gòu)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
江华| 湖北省| 怀柔区| SHOW| 桑日县| 炉霍县| 隆安县| 分宜县| 紫阳县| 四川省| 松阳县| 岳池县| 台东市| 辽宁省| 乐亭县| 怀集县| 商水县| 浦县| 丹寨县| 固始县| 龙里县| 宁德市| 吴旗县| 嘉祥县| 利川市| 静乐县| 扎兰屯市| 砀山县| 随州市| 鄂托克旗| 峨眉山市| 资溪县| 嵊泗县| 涡阳县| 德保县| 长白| 永泰县| 娄烦县| 济阳县| 泽库县| 边坝县|