我们来了解一下引擎是怎么管理实体的吧!我们这里就说说服务端的实体(edict_t)

服务端用 edict_t 这个结构体来保存一个实体,可以说一个 edict_t 就是一个 服务端实体,下文简称实体。

我们在 mp.dll 的源码里经常看到的那些 CBaseXXX 又和 edict_t 有什么关系呢?

引擎只管理小部分实体的功能,更多功能需要我们自己写代码去实现,这里就引入了 实体控制类 这个东西(就是那些 CBaseXXX),类就是C++的那个类。下文简称控制类。

接下来我们就分析 edict_t 到底是怎么跟 控制类 挂上勾的。

我们通常用 CREATE_NAMED_ENTITY( MAKE_STRING("weapon_mp5") ); 来创建一个 weapon_mp5 的武器实体,那我们就来分析这个函数到底做了什么吧!

1. 用户调用 CREATE_NAMED_ENTITY。

2. 引擎在 mp.dll (的导出函数)里查找名为“weapon_mp5”的函数。(你可能会有疑问:我从来没写过这个函数啊?别急,下文分析)

3. 引擎调用“weapon_mp5”函数来创建出一个CMP5类实例。“weapon_mp5”还调用了 CREATE_ENTITY 来创建出一个 edict_t。(用数学老师的话说:CMP5就是实体weapon_mp5的控制类)

4. 引擎把类实例的指针赋值到 edict_t 的 pvPrivateData 成员变量里。

5. 引擎返回 edict_t 给用户。

看了上面的步骤,你一定注意到非常关键的一步,“weapon_mp5”函数到底是怎么一回事。

打开 mp5.cpp 你会发现有一行

LINK_ENTITY_TO_CLASS( weapon_mp5, CMP5 );

这行就是关键,它会生成一个函数,这个函数起了类似如下代码的作用:

注:实际上不是这么简单的,只是为了更容易理解。

CMP5 *weapon_mp5()
{
return new CMP5();
}

再往回看上面的步骤3和4,能理解了吧。

引擎先创建一个 edict_t 然后又 new CMP5 把指针存到 pvPreivateData 这个变量里,到此一个实体就创建出来了。

然后我们还要了解控制类是怎么工作的。首先请你打开 cbase.cpp 你会看到一堆 Dispatch 开头的函数,下文简称派遣函数。

派遣函数用来干嘛呢?当一个实体要 Think 的时候,引擎就会调用 mp.dll 里的 DispatchThink 这个函数,它有一个参数 edict_t *pent 就是要 Think 的实体!

接着才是关键!

我们来看 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 变量,你一定还记得这个变量是怎么来的吧!不记得请马上往回看!

没错,之前引擎创建实体的时候,把 控制类 的 指针 存这变量里了,我们这里就把这个 控制类 拿出来而已!

接着它检查了一下 控制类 是不是 NULL,然后它在 if 里面调用了 控制类 的 Think 函数!

整个过程就是这样的:引擎 -> 派遣函数 -> 控制类 也就是说,引擎是不管 控制类 的,为让 控制类 工作,我们还需要在派遣函数里写东西(虽然HLSDK已经写好了,但是你一定要去看看他是怎么写的)。

如果你写过 AMXX 你肯定会认识 FM_Think FM_Spawn 这些东西,它们就是HOOK了这些派遣函数!

本来还想仔细讲解 LINK_ENTITY_TO_CLASS 的,留到下一篇文章吧!

【HLSDK系列】服务端实体 edict_t 和 控制类的更多相关文章

  1. 前端学习 node 快速入门 系列 —— 服务端渲染

    其他章节请看: 前端学习 node 快速入门 系列 服务端渲染 在简易版 Apache一文中,我们用 node 做了一个简单的服务器,能提供静态资源访问的能力. 对于真正的网站,页面中的数据应该来自服 ...

  2. Nacos源码系列—服务端那些事儿

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 在上节课中,我们讲解了客户端注册服 ...

  3. TCP连接建立系列 — 服务端接收ACK段(一)

      http://blog.csdn.net/zhangskd/article/details/17923917 分类: Linux TCP/IP Linux Kernel 2014-01-07 09 ...

  4. TCP连接建立系列 — 服务端发送SYNACK段

    本文主要分析:服务器端如何构造和发送SYNACK段. 内核版本:3.6 Author:zhangskd @ csdn blog 发送入口 tcp_v4_send_synack()用于发送SYNACK段 ...

  5. TCP连接建立系列 — 服务端接收SYN段

    本文主要分析:服务器端接收到SYN包时的处理路径. 内核版本:3.6 Author:zhangskd @ csdn blog 接收入口 1. 状态为ESTABLISHED时,用tcp_rcv_esta ...

  6. TCP连接建立系列 — 服务端接收ACK段(二)

    本文主要分析:三次握手中最后一个ACK段到达时,服务器端的处理路径. 内核版本:3.6 Author:zhangskd @ csdn blog 创建新sock 协议族相关的操作函数,我们要看的是TCP ...

  7. 【HLSDK系列】服务端 AddToFullPack 函数

    服务端会给客户端发送一些数据,其中两大种类数据是 clientdata_t 和 entity_state_t 这里我们说说 entity_state_t 这个结构体. 你在丢在地上的枪.C4等等是服务 ...

  8. 【HLSDK系列】HL引擎入门篇

    如果你打算拿HL的源码(也就是HLSDK)来改出一个自己的游戏,那你就非常有必要理解一些HL引擎的工作方式. HL引擎分成两个部分,服务端和客户端.服务端管理所有玩家的状态和游戏规则,客户端负责显示U ...

  9. cocos2d-lua ARPG手机游戏《烈焰遮天》(客户端+服务端+数据库)发布说明

    服务器发布流程及其规范1,环境准备        a, mvn命令行:从\\10.21.210.161\share\tools\apache-maven-3.1.1-bin.tar.gz取出安装包,  ...

随机推荐

  1. OpenCV中Mat操作clone() 与copyto()的区别

    OpenCV中Mat操作clone() 与copyto()的区别 // Mat is basically a class with two data parts: the matrix header ...

  2. P3368 【模板】树状数组 2(区间增减,单点查询)

    P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表 ...

  3. spring源码-aop动态代理-5.3

    一.动态代理,这是一个很强大的东西哦.研发过程中我们会常用很多业务类,但是存在一个问题.如何在不修改源码逻辑的情况下,加入自己的相关逻辑.比如异常处理,日志记录等! 二.Java动态代理的两种方式JD ...

  4. Python接口测试实战2 - 使用Python发送请求

    如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...

  5. tensorflow中tensor与数组之间的转换

    # 主要是两个方法: # 1.数组转tensor:数组a, tensor_a=tf.convert_to_tensor(a) # 2.tensor转数组:tensor b, array_b=b.eva ...

  6. 转载-找圆算法((HoughCircles)总结与优化-霍夫变换

    原文链接: http://www.opencv.org.cn/forum.php?mod=viewthread&tid=34096   找圆算法((HoughCircles)总结与优化 Ope ...

  7. Linux建立互信关系(ssh公钥登录)

    Linux有多种登录方式,比如telnet.ssh.支持ssh登录方式:口令登录和公钥登录 ssh登录方式:ssh [-l login_name] [-p port] [user@]hostname ...

  8. Hibernate入门篇<1>hibernate.cfg.xml学习小结

    Hibernate配置文件主要用于配置数据库连接和Hibernate运行时所需的各种属性,这个配置文件应该位于应用程序或Web程序的类文件夹 classes中.Hibernate配置文件支持两种形式, ...

  9. os模块大全详情

    python常用模块目录 一:os模块分类: python os.walk详解 二:os模块大全表 序号 方法 方法 1 os.access(path, mode) 检验权限模式 2 os.chdir ...

  10. linux 的 awk 使用

    linux中awk命令对文本内容进行操作,其功能十分强大 1.如:查看一个有几百万行内容的文件中第3列数字内容(不重复) cat test.csv | awk -F ',' '{print $3}' ...