【HLSDK系列】服务端实体 edict_t 和 控制类
我们来了解一下引擎是怎么管理实体的吧!我们这里就说说服务端的实体(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 和 控制类的更多相关文章
- 前端学习 node 快速入门 系列 —— 服务端渲染
其他章节请看: 前端学习 node 快速入门 系列 服务端渲染 在简易版 Apache一文中,我们用 node 做了一个简单的服务器,能提供静态资源访问的能力. 对于真正的网站,页面中的数据应该来自服 ...
- Nacos源码系列—服务端那些事儿
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 在上节课中,我们讲解了客户端注册服 ...
- TCP连接建立系列 — 服务端接收ACK段(一)
http://blog.csdn.net/zhangskd/article/details/17923917 分类: Linux TCP/IP Linux Kernel 2014-01-07 09 ...
- TCP连接建立系列 — 服务端发送SYNACK段
本文主要分析:服务器端如何构造和发送SYNACK段. 内核版本:3.6 Author:zhangskd @ csdn blog 发送入口 tcp_v4_send_synack()用于发送SYNACK段 ...
- TCP连接建立系列 — 服务端接收SYN段
本文主要分析:服务器端接收到SYN包时的处理路径. 内核版本:3.6 Author:zhangskd @ csdn blog 接收入口 1. 状态为ESTABLISHED时,用tcp_rcv_esta ...
- TCP连接建立系列 — 服务端接收ACK段(二)
本文主要分析:三次握手中最后一个ACK段到达时,服务器端的处理路径. 内核版本:3.6 Author:zhangskd @ csdn blog 创建新sock 协议族相关的操作函数,我们要看的是TCP ...
- 【HLSDK系列】服务端 AddToFullPack 函数
服务端会给客户端发送一些数据,其中两大种类数据是 clientdata_t 和 entity_state_t 这里我们说说 entity_state_t 这个结构体. 你在丢在地上的枪.C4等等是服务 ...
- 【HLSDK系列】HL引擎入门篇
如果你打算拿HL的源码(也就是HLSDK)来改出一个自己的游戏,那你就非常有必要理解一些HL引擎的工作方式. HL引擎分成两个部分,服务端和客户端.服务端管理所有玩家的状态和游戏规则,客户端负责显示U ...
- cocos2d-lua ARPG手机游戏《烈焰遮天》(客户端+服务端+数据库)发布说明
服务器发布流程及其规范1,环境准备 a, mvn命令行:从\\10.21.210.161\share\tools\apache-maven-3.1.1-bin.tar.gz取出安装包, ...
随机推荐
- Servlet——web.xml的配置
<servlet>: <servlet-name>: 名称 <servlet-class>: 类名 <init-param>: 初始化参数(只有本ser ...
- day5 if while for
.注意点: ctrl + n 自动补全 18行报错,直接定位18行 逻辑运算符and or not 复合赋值运算符 += .if-elif 判断星期几 猜拳游戏 .while循环 )3大执行流程 )什 ...
- django使用流程
1.安装django包 (命令行)>pip install django # conda install django 2.安装成功后,可以新建django项目 1(命令行)>django ...
- 一个奇怪的JS函数
今天在分析一个jQuery插件源码的时候,发现了一个奇怪的函数. 这个函数的目的是为数字补零,如传入7,输出07,传入12输出12.由于是对时间补零,只截取后两位. // add leading ze ...
- STM32L431驱动带UC1698芯片调试记录
1, 数据线连接方式,这次使用的是8080格式的接口,如下 2. 主要是信号和数据引脚 DATA0-DATA7 并口的数据 RST 复位信号 WR 写信号 RD 读信号 C/D 数据还是命令 CS片 ...
- springmvc @Valid 接收实体类时出现bean为null的问题
这是因为传到后端之后,全部以全小写形式处理了 所以前端也需要把name设置为全小写,否则后端不识别,导致接收不到,导致为null
- JavaScript 中函数的参数
functionName(parameter1, parameter2, parameter3) { // 要执行的代码…… } 参数规则 JavaScript 函数定义时形参没有指定数据类型. Ja ...
- JavaScript查找元素的方法
1.根据id获取元素 document.getElementById("id属性的值"); 2.根据标签名字获取元素 document.getElementsByTagName(& ...
- Linux 安装Redis<集群版>(使用Mac远程访问)
阅读本文需要先阅读安装Redis<准备> 一 架构细节 所有的redis节点彼此互联(PING-PONG机制) 内部使用二进制协议优化传输速度和带宽 节点的fail是通过集群中超过半数的节 ...
- GitHub 多人协作开发 三种方式:
GitHub 多人协作开发 三种方式: 一.Fork 方式 网上介绍比较多的方式(比较大型的开源项目,比如cocos2d-x) 开发者 fork 自己生成一个独立的分支,跟主分支完全独立,pull代码 ...