服务端会给客户端发送一些数据,其中两大种类数据是 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 0;    // 有EF_NODRAW这个标记的实体是不可见的,不添加到包里。if (!ent->v.modelindex || !STRING(ent->v.model))return 0;    // 没有模型的实体是不可见的,不添加到包里。if ((ent->v.flags & FL_SPECTATOR) && ent != host)return 0;    // 观察者也是不可见的,不添加到包里。// ...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 0;}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, 3 * sizeof(float));memcpy(state->angles, ent->v.angles, 3 * sizeof(float));memcpy(state->mins, ent->v.mins, 3 * sizeof(float));memcpy(state->maxs, ent->v.maxs, 3 * sizeof(float));memcpy(state->startpos, ent->v.startpos, 3 * sizeof(float));memcpy(state->endpos, ent->v.endpos, 3 * 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 个实体!如果超出了这个数量,引擎将会忽略超出部分的实体!

转载于:https://www.cnblogs.com/crsky/p/6881052.html

【HLSDK系列】服务端 AddToFullPack 函数相关推荐

  1. Netty 源码解析系列-服务端启动流程解析

    netty源码解析系列 Netty 源码解析系列-服务端启动流程解析 Netty 源码解析系列-客户端连接接入及读I/O解析 五分钟就能看懂pipeline模型 -Netty 源码解析 1.服务端启动 ...

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

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

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

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

  4. LinuxC++:网络编程(一)最原始服务端及客户端代码实现和函数释义

    前言:学习编程一定要敲,接着测试,然后查资料,最后总结!!! 一.socket这个单词在C++网络编程中的含义 socket中文就是插座.运行在计算机中的两个程序通过socket建立起一个通道,数据在 ...

  5. 客户端呼叫Flash Medis Server3服务端入门

    当你不仅仅只想用FLEX来做纯业务数据的管理时,或者当你的项目有视频,音频,多客户端数据或消息同步,数据即时共享,或者你要做网络游戏,互动社区等等更多要求时,学习FMS将刻不容缓,因为FMS是ADOB ...

  6. cocos2d-x3.2与服务端框架Firefly的网络编程(初级网络通讯)

    好久没写东西,最近在研究服务端框架Firefly和Pomelo,身为菜鸟的我的确花了很大功夫才看懂一些源代码.原来打算玩下Pomelo,不过我不得不说这东西真的是给专业开发者准备的,我搞了半天libp ...

  7. vue服务端渲染——基础

    文章目录 vue服务端渲染(基础) Nuxt框架 文件目录结构 项目启动.打包 生命周期 SSR nuxtserverInit middleware 中间件 全局中间件 页面级中间件 validate ...

  8. Vue SSR之服务端渲染

    目录 准备工作 开始折腾 1. 首先安装 ssr 支持 2. 增加路由test与页面 3. 在src目录下创建两个js: 4. 修改router配置. 5. 改造main.js 6. entry-cl ...

  9. thrift 大list序列化过慢引发的客户端耗时记录和服务端不一致问题

    一.问题背景 最近在工作上遇到了一个问题,客户端说我们服务的返回长尾太长了,经常40+ms.找了一个trace发现,我们服务端记录这个trace从开始到返回,总共才花了6ms.多试了几个trace发现 ...

最新文章

  1. Concurrency 学习 (Mac iphone)
  2. /etc/profile /etc/profile .bash_profile .bashrc解释
  3. Windows APC学习笔记(二)—— 挂入过程执行过程
  4. 3DSlicer18:Layouts
  5. 经典面试题(39):以下代码将输出的结果是什么?
  6. golang切片转为字符串,字符串转切片
  7. Zabbix 神器——自动发现
  8. 你真的会php,你真的会PHP吗?
  9. Java十进制数和二进制数之间的相互转换
  10. No matching configuration of project :libusb was found.
  11. Zookeeper集群leader选举机制
  12. ESX无法感知VM的心跳
  13. 单例模式的懒汉模式跟恶汉模式的区别
  14. 【直播】陈安东,马琦钧:赛题Baseline讲解以及语音识别基础知识介绍
  15. 使用 Fail2ban 防止 ssh 暴力破解攻击
  16. 微信网页小游戏网站源码带后台+可后台添加游戏+推荐到微信
  17. [LeetCode-java实现]3. 无重复字符的最长子串
  18. 图片服务架构演进及云存储的优势
  19. nopi 缩小字体填充_我在超市里改字体
  20. 挚爱身影渐隐。素绞无意世情狠

热门文章

  1. linux新硬盘分区及格式化和挂载分区到目录的方法
  2. linux touch
  3. Linux时间子系统(十六) clockevent
  4. Redis事务和分布式锁
  5. android activity 窗口 样式
  6. Espcms 注册或登录提示Can not connect to MySQL server
  7. 聚合天气--ajax 通过城市名取数据
  8. 反编译工具Reflector ILSpy
  9. linux下,查找命令的使用
  10. PAT1070. 结绳