【HLSDK系列】服务端实体 edict_t 和 控制类
我們來了解一下引擎是怎么管理實(shí)體的吧!我們這里就說說服務(wù)端的實(shí)體(edict_t)
服務(wù)端用 edict_t 這個(gè)結(jié)構(gòu)體來保存一個(gè)實(shí)體,可以說一個(gè) edict_t 就是一個(gè) 服務(wù)端實(shí)體,下文簡稱實(shí)體。
我們在 mp.dll 的源碼里經(jīng)常看到的那些 CBaseXXX 又和 edict_t 有什么關(guān)系呢?
引擎只管理小部分實(shí)體的功能,更多功能需要我們自己寫代碼去實(shí)現(xiàn),這里就引入了 實(shí)體控制類 這個(gè)東西(就是那些 CBaseXXX),類就是C++的那個(gè)類。下文簡稱控制類。
接下來我們就分析 edict_t 到底是怎么跟 控制類 掛上勾的。
我們通常用 CREATE_NAMED_ENTITY( MAKE_STRING("weapon_mp5") ); 來創(chuàng)建一個(gè) weapon_mp5 的武器實(shí)體,那我們就來分析這個(gè)函數(shù)到底做了什么吧!
1. 用戶調(diào)用 CREATE_NAMED_ENTITY。
2. 引擎在 mp.dll (的導(dǎo)出函數(shù))里查找名為“weapon_mp5”的函數(shù)。(你可能會有疑問:我從來沒寫過這個(gè)函數(shù)啊?別急,下文分析)
3. 引擎調(diào)用“weapon_mp5”函數(shù)來創(chuàng)建出一個(gè)CMP5類實(shí)例。“weapon_mp5”還調(diào)用了 CREATE_ENTITY 來創(chuàng)建出一個(gè) edict_t。(用數(shù)學(xué)老師的話說:CMP5就是實(shí)體weapon_mp5的控制類)
4. 引擎把類實(shí)例的指針賦值到 edict_t 的 pvPrivateData 成員變量里。
5. 引擎返回 edict_t 給用戶。
看了上面的步驟,你一定注意到非常關(guān)鍵的一步,“weapon_mp5”函數(shù)到底是怎么一回事。
打開 mp5.cpp 你會發(fā)現(xiàn)有一行
LINK_ENTITY_TO_CLASS( weapon_mp5, CMP5 );這行就是關(guān)鍵,它會生成一個(gè)函數(shù),這個(gè)函數(shù)起了類似如下代碼的作用:
注:實(shí)際上不是這么簡單的,只是為了更容易理解。
CMP5 *weapon_mp5() {return new CMP5(); }再往回看上面的步驟3和4,能理解了吧。
引擎先創(chuàng)建一個(gè) edict_t 然后又 new CMP5 把指針存到 pvPreivateData 這個(gè)變量里,到此一個(gè)實(shí)體就創(chuàng)建出來了。
?
然后我們還要了解控制類是怎么工作的。首先請你打開 cbase.cpp 你會看到一堆?Dispatch 開頭的函數(shù),下文簡稱派遣函數(shù)。
派遣函數(shù)用來干嘛呢?當(dāng)一個(gè)實(shí)體要 Think 的時(shí)候,引擎就會調(diào)用 mp.dll 里的?DispatchThink 這個(gè)函數(shù),它有一個(gè)參數(shù)?edict_t *pent 就是要 Think 的實(shí)體!
接著才是關(guān)鍵!
我們來看 DispatchThink 的源碼:
void DispatchThink( edict_t *pent ) {CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);if (pEntity){// ...pEntity->Think();} }順便還有 GET_PRIVATE 的源碼:
inline void *GET_PRIVATE( edict_t *pent ) {if ( pent )return pent->pvPrivateData;return NULL; }我們可以看到它獲取了 edict_t 里面的 pvPrivateData 變量,你一定還記得這個(gè)變量是怎么來的吧!不記得請馬上往回看!
沒錯(cuò),之前引擎創(chuàng)建實(shí)體的時(shí)候,把 控制類 的 指針 存這變量里了,我們這里就把這個(gè) 控制類 拿出來而已!
接著它檢查了一下 控制類 是不是 NULL,然后它在 if 里面調(diào)用了 控制類 的 Think 函數(shù)!
整個(gè)過程就是這樣的:引擎 -> 派遣函數(shù) -> 控制類 也就是說,引擎是不管 控制類 的,為讓 控制類 工作,我們還需要在派遣函數(shù)里寫東西(雖然HLSDK已經(jīng)寫好了,但是你一定要去看看他是怎么寫的)。
如果你寫過 AMXX 你肯定會認(rèn)識 FM_Think FM_Spawn 這些東西,它們就是HOOK了這些派遣函數(shù)!
?
本來還想仔細(xì)講解?LINK_ENTITY_TO_CLASS 的,留到下一篇文章吧!
轉(zhuǎn)載于:https://www.cnblogs.com/crsky/p/6881146.html
總結(jié)
以上是生活随笔為你收集整理的【HLSDK系列】服务端实体 edict_t 和 控制类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于程序员35岁的坎:年龄不是挡板,图灵
- 下一篇: webmagic+selenium模拟浏