服务端会给客户端发送一些数据,其中两大种类数据是 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 函数的更多相关文章

  1. 2.live555源码分析----服务端doEventLoop()函数分析

    上一篇博客说道,live555服务端main函数做的最后一件事就是调用如下代码陷入死循环: env->taskScheduler().doEventLoop(); // does not ret ...

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

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

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

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

  4. 【HLSDK系列】服务端 UpdateClientData 函数

    首先说明下,这个函数是写在 mp.dll 里的. 服务器会给每个客户端发送一些数据,其中两大数据种类就是 clientdata_t 和 entity_state_t 这里要说的是 clientdata ...

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

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

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

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

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

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

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

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

  9. 解决有关flask-socketio中服务端和客户端回调函数callback参数的问题(全网最全)

    由于工作当中需要用的flask_socketio,所以自己学习了一下如何使用,查阅了有关文档,当看到回调函数callback的时候,发现文档里都描述的不太清楚,最后终于琢磨出来了,分享给有需要的朋友 ...

随机推荐

  1. 苏州Uber优步司机奖励政策(4月11日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. Hbase单机安装及使用hbase shell进行简单操作

    一,配置环境变量 在etc/prifile中加入java环境变量及hbase环境变量: #set java environment JAVA_HOME=/usr/local/lhc/jdk1.8.0_ ...

  3. DSP5509项目之用FFT识别钢琴音调(2)

    1. 本节主要是学习TLV320AIC32这个音频芯片,Easy5509 开发板上有一个语音编解码芯片 TLV320AIC23.TLV320AIC23 是一个高性能的多媒体数字语音编解码器,它的内部 ...

  4. Django-建立网页

    进入cmd模式做 django-admin startproject helloworld创建一个project,并命名helloworld,新生成的文件结构如下   输入python manage. ...

  5. MySQL5.6.14从安装到启动全过程

    1.下载 地址:http://dev.mysql.com/downloads/mysql/ 这里选择的是Linux-Generic平台,下载了MySQL-5.6.14-1.linux_glibc2.5 ...

  6. 谈谈你对Java异常处理机制的理解

    先谈谈我的理解:异常处理机制可以说是让我们编写的程序运行起来更加的健壮,无论是在程序调试.运行期间发生的异常情况的捕获,都提供的有效的补救动作,任何业务逻辑都会存在异常情况,这时只需要记录这些异常情况 ...

  7. dalao自动报表邮件2.0

    经过昨天的修改优化后,dalao收到了不是“木马”的邮件,欣慰地点了点头,“不错,不错,这几张表设计的简洁明了,看着有货!不过呀,,,这些表的数据太多了一点,十几天的数据一大溜,能不能再简洁一点,做一 ...

  8. Pycharm实现服务器端代码的远程调试

     Pycharm是很多人在学习机器学习时的常用IDE.但是,当代码需要庞大计算资源的时候,我们往往需要借助远程服务器的GPU资源.很多人都是将代码拷贝到服务器,然后运行,但是当修改调试的时候,很不方便 ...

  9. HttpServlet 详解(基础)

    HttpServlet详解 大家都知道Servlet,但是不一定很清楚servlet框架,这个框架是由两个Java包组成:javax.servlet和javax.servlet.http. 在java ...

  10. scrum立会报告+燃尽图(第二周第三次)

    此作业要求参考: https://edu.cnblogs.com/campus/nenu/2018fall/homework/2248 一.小组介绍 组名:杨老师粉丝群 组长:乔静玉 组员:吴奕瑶.公 ...