【HLSDK系列】服务端 AddToFullPack 函数
服务端会给客户端发送一些数据,其中两大种类数据是 clientdata_t 和 entity_state_t 这里我们说说 entity_state_t 这个结构体。
你在丢在地上的枪、C4等等是服务端实体(edict_t),并且你能在客户端看到它们(废话),这些实体们是怎样发送到你的客户端的呢?
引擎不可能原原本本地把 edict_t 发送出去的,所以就有了 entity_state_t 这个结构体,它表示了一个可见实体所有必要的数据。
接上面:如果实体不可见,那何必发到客户端呢?:-)
所以 entity_state_t 只保存跟实体显示有关的数据,例如 origin、angles、model 这些,引擎只需要把这些数据发到客户端就行了。
引擎里有一个叫做 FullPack 的包(实际上就是数组),这个包里有全部需要发送给客户端的实体的 entity_state_t。
引擎会逐个检查服务端的所有实体,并且添加到包里,准备发送给客户端。
那引擎是不是默认就把能看见的实体都添加到包里了呢?并不是,因为引擎提供了一个接口让我们自己决定哪些实体可以被添加到包里!
你可以在 mp.dll 的源码里找到 AddToFullPack 这函数,可以看到这样的代码:
int AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet)
{
if ((ent->v.effects == EF_NODRAW) && ent != host)
return ; // 有EF_NODRAW这个标记的实体是不可见的,不添加到包里。 if (!ent->v.modelindex || !STRING(ent->v.model))
return ; // 没有模型的实体是不可见的,不添加到包里。 if ((ent->v.flags & FL_SPECTATOR) && ent != host)
return ; // 观察者也是不可见的,不添加到包里。 // ... if (ent != host)
{
// 在可视范围(PVS)外的实体是看不到的,不添加到包里。
if (!CheckEntityRecentlyInPVS(hostindex, e, gpGlobals->time))
{
if (!ENGINE_CHECK_VISIBILITY((const struct edict_s *)ent, pSet))
{
MarkEntityInPVS(hostindex, e, gpGlobals->time, true);
return ;
} MarkEntityInPVS(hostindex, e, gpGlobals->time);
}
} // ...
}
参数 state 是将要添加到包里的 entity_state_t ,参数 ent 是正在处理的实体,参数 host 是包要发送到的那个玩家(的客户端)!
如果这个函数返回 0 (FALSE)引擎就不会把这个实体添加到包里,这个实体自然也就不会被发送到那个客户端(看不到)。
你甚至可以在这个函数里自定义需要发送的实体的数据!我们可以看到这样的代码:
int AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet)
{
// ... state->number = e;
state->entityType = ENTITY_NORMAL; state->animtime = (int)(1000.0 * ent->v.animtime) / 1000.0; memcpy(state->origin, ent->v.origin, * sizeof(float));
memcpy(state->angles, ent->v.angles, * sizeof(float));
memcpy(state->mins, ent->v.mins, * sizeof(float));
memcpy(state->maxs, ent->v.maxs, * sizeof(float));
memcpy(state->startpos, ent->v.startpos, * sizeof(float));
memcpy(state->endpos, ent->v.endpos, * sizeof(float)); state->impacttime = ent->v.impacttime;
state->starttime = ent->v.starttime;
state->modelindex = ent->v.modelindex;
state->frame = ent->v.frame; // ...
}
你可以看到它从服务端实体(edict_t)抽出必要的数据填充到 entity_state_t 里!
最后返回 1(TRUE)引擎将会把我们填充好的 entity_state_t 添加到包里,发送给客户端。
这个函数真的很有用对吧,我们可以做一些有趣的功能,让一个实体可以被玩家A看到,玩家B却看不到!
我们只需要检查当前正在处理的实体(ent)是那个我们不让玩家B看到的实体,然后判断 host 是不是玩家B,如果是,就返回 0 不让这个实体发送给玩家B!
你甚至可以设置一个玩家(玩家也是实体)不让其它玩家看到!(玩家实体必须被发送,所以如果要隐藏一个玩家,请使用EF_NODRAW这个FLAG)
注意,引擎里的包最多只能容纳 256 个实体!如果超出了这个数量,引擎将会忽略超出部分的实体!
【HLSDK系列】服务端 AddToFullPack 函数的更多相关文章
- 2.live555源码分析----服务端doEventLoop()函数分析
上一篇博客说道,live555服务端main函数做的最后一件事就是调用如下代码陷入死循环: env->taskScheduler().doEventLoop(); // does not ret ...
- 前端学习 node 快速入门 系列 —— 服务端渲染
其他章节请看: 前端学习 node 快速入门 系列 服务端渲染 在简易版 Apache一文中,我们用 node 做了一个简单的服务器,能提供静态资源访问的能力. 对于真正的网站,页面中的数据应该来自服 ...
- Nacos源码系列—服务端那些事儿
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 在上节课中,我们讲解了客户端注册服 ...
- 【HLSDK系列】服务端 UpdateClientData 函数
首先说明下,这个函数是写在 mp.dll 里的. 服务器会给每个客户端发送一些数据,其中两大数据种类就是 clientdata_t 和 entity_state_t 这里要说的是 clientdata ...
- TCP连接建立系列 — 服务端接收ACK段(一)
http://blog.csdn.net/zhangskd/article/details/17923917 分类: Linux TCP/IP Linux Kernel 2014-01-07 09 ...
- 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 ...
- TCP连接建立系列 — 服务端发送SYNACK段
本文主要分析:服务器端如何构造和发送SYNACK段. 内核版本:3.6 Author:zhangskd @ csdn blog 发送入口 tcp_v4_send_synack()用于发送SYNACK段 ...
- 解决有关flask-socketio中服务端和客户端回调函数callback参数的问题(全网最全)
由于工作当中需要用的flask_socketio,所以自己学习了一下如何使用,查阅了有关文档,当看到回调函数callback的时候,发现文档里都描述的不太清楚,最后终于琢磨出来了,分享给有需要的朋友 ...
随机推荐
- 【BZOJ4008】[HNOI2015]亚瑟王
[BZOJ4008][HNOI2015]亚瑟王 题面 bzoj 洛谷 题解 由期望的线性性 可以知道,把所有牌打出的概率乘上它的伤害加起来就是答案 记第$i$张牌打出的概率为$fp[i]$ 则 $$ ...
- 【CF908G】New Year and Original Order
[CF908G]New Year and Original Order 题面 洛谷 题解 设\(f[i][j][k][l]\)表示当前在第\(i\)位有\(j\)位大于等于\(k\),当前有没有卡上界 ...
- MySQL入门篇(七)之Xtrabackup备份与恢复
一.Xtrabackup介绍 MySQL冷备.mysqldump.MySQL热拷贝都无法实现对数据库进行增量备份.在实际生产环境中增量备份是非常实用的,如果数据大于50G或100G,存储空间足够的情况 ...
- Yii2.0 高级模版编写使用自定义组件(component)
翻译自:http://www.yiiframework.com/wiki/760/yii-2-0-write-use-a-custom-component-in-yii2-0-advanced-tem ...
- ps 图层解锁后变成全格子(全透明)的解决方法
其实是因为同时打开了好几个ps文件正在编辑中,所以解决方法就是重启ps,然后单独编辑一个文件,解锁后就不会再出现这种情况能,就能正常编辑了
- GitHub中webhooks的使用
目录 GitHub中的webhooks的配置 对配置的webhooks的进行测试 目前在团队在设计一个应用管理的功能,需要了解到常用代码托管的Webhooks的使用.GitHub中的webhooks首 ...
- python--自定义模块
python模块说明:类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不 ...
- Git生成多个ssh key
在实际的工作中, 有可能需要连接多个远程仓库, 例如我想连接私有仓库.GitLab官网.GitHub官网, 那么同一台电脑就要生成多个ssh key: ssh-keygen -t rsa -C &qu ...
- idea compare功能 之一次bug修复
一次bug修复 最近开发完了一套单点系统,jenkins打包上传到服务器就出问题, 可以启动但是不能正常工作. 首先想到的是环境不一样, 于是把jenkins的jdk和maven都调整和本机大版本相同 ...
- JavaScript设计模式-----命令模式的简单应用
命令模式是最简单和优雅的模式之一,命令模式中的命令(command)是指一个执行某些特定事情的指令. 应用场景:有时候需要向某些对象发送请求,但是并不知道请求的接受者是谁,也不知道被请求的操作是什么, ...