《CS2》零基础外挂开发教程 02:单双向链表

文摘   社会   2025-01-10 00:00   广西  
在本期教程开始之前,为了更好地吸引大家的学习兴趣,还有就是想让大家知道上次我不仅仅只讲了理论,还有实践。并且,实践出来的效果应该还算是比较满意。所以我会先把这个最后我们可以实现的一个效果放出来供大家观赏一下。
欢迎来到以《CS2》为例剖析游戏外挂原理并实现的第二期教程。本期教程,在讲解之前,首先来看一下上期教程的一些反馈。关于大家所提的意见,关于这个“我是来看实践的,原理关我什么事情”的问题,首先要搞清楚一件事情,那就是你要实践,你必须弄懂它的原理才行,况且本系列教程还是以“零基础”冠名的。否则的话,我讲的所有东西都只是一个操作步骤,你照着步骤来是肯定可以的。就是对于CS2这款游戏是可以的,但你换到另外一款游戏呢,其他游戏,其他引擎的游戏呢,如果你搞清楚了原理,任何游戏其实都是可以按照这一套理论来进行实践的。所以可能我原理讲的稍微冗杂了一点,后面我会尽量精简一点。
所以说,要看实践的,不要慌,后面会有实践的,而且实践的会非常精彩。首先,我们上期教程已经讲完了重要的相关知识,结构体的本质和人物属性,结构体的关系,以及指针的概念。
本期我们将深入学习图的概念,包括图的拓展,如双向列表和单向列表。接下来,我们将使用CE来实践,寻找CSGO的一个NT体,即实体数组地址,并将所有实体对象的基本属性打印到控制台上。在之后的几期中,我们将探讨两种实现复数的基本方法:编写动态链接库(DLL)注入游戏,以及直接使用外部方法。我将演示通过外部方法注入游戏,并分析两种方法的优劣。
在巩固好基础技能后,我们将通过实战绘制人物方块,使用外部绘制方法,并介绍"word to screen"方法。此外,我会简要介绍矩阵乘法的理论,无需事先学习矩阵乘法,因为它只是一个理论概念,你可以完全记住。我们还将学习如何寻找视角矩阵,获取人物坐标数据并绘制方框,这是进阶的初步内容。再之后,我将补充讨论有关VANTG(如VAC)反作弊机制的检测方法,以及其他反作弊措施,如TP等,并探讨如何避免检测问题。
图这个概念可以用一个简单的例子来说明。在我们的生活中,有许多类似图的关系,比如我们的QQ好友关系。假设你是自己,有一些好友,比如CE,假设我们只有三个好友。我们可以用箭头表示我们拥有哪些好友,指向他们。因为QQ好友是双向确认的,所以你也是别人的好友,有一个箭头指回你。同样,你的好友也有自己的好友,我们可以继续指出去。
举个例子,就像这样。我们用圆圈表示一个顶点,它是图中的一个元素,用箭头或边表示元素之间的关系。这种双向箭头的图称为无向图,即没有方向的图,简写为没有箭头的图。在生活中,除了无向图,还有有向图,比如男一号喜欢女一号,女一号喜欢男二号,男二号喜欢男一号,构成了一个三角形。这样的图称为有向图,箭头不能指回。
在游戏中,为什么要介绍图的概念呢?因为游戏中所有实体的存储实际上也涉及图这一数据结构。我们把存储图的一种方式称为链表,除了链表,还有其他存储方式,比如邻接矩阵或向量内存。在游戏中,我们主要介绍了双向列表和单向列表。双向链表对应无向图,因为它是双向的,可以从任意一个元素出发遍历整个列表。
单向列表其实就是双向链表去掉了一个方向的连接,变成了只有一个方向的链表。比如,假设有一个元素AE,它只有一个指向下一个元素的连接,即直接指向下一个。如果我们从A2进入,就无法到达A1,只能向下走,直到A3或A4。同样,它可以只向下指,也可以只向上指,只要所有连接都是一个方向的,就是单向链表。
在程序中,我们如何存储这种关系呢?假设我们有一个双向链表,现在要移除其中的某个元素,比如A2,该怎么做呢?实际上,我们首先找到A2的下一个元素是谁,发现是A3;然后找到A2的上一个元素是谁,发现是A1。为了移除A2,我们只需断开A2与其上下两个元素的连接,并建立起上下两个元素的新连接。形式化来说,就是将A1的下一个指向A2的下一个,即A3,然后将A3的上一个指向A2的上一个,即A1。这样就移除了A2,当我们从A4往上走时,就只能从A3直接走到A1,无法再到达A2。
但是要注意,虽然A2从逻辑上被移除了,但在程序内存中并没有真正消失。这就是双向链表的优势:减少了清空内存或移动内存的时间损失。但它也有代价,就是列表必须是顺序访问,无法进行随机访问。
现在来讲一下单向列表的实现。首先,单向列表比较简单,我们可以将每个表项看作一个结构体,每个结构体有自己的存储值(val),以及指向下一个元素的连接。这样,我们就有一个结构体命名为item,表示列表中的一个元素。

除了存储本身的data以外,我们还需要存储指向下一个表项的信息,也就是它所指向的下一个表项是谁。因此,我们需要一个next指针来表示它的下一项。为什么上节课要讲这个指针的概念呢?因为实际上,这个next就是一个item类型的指针,它指向的是一个内存地址,而这个内存地址存储的就是它所指向的下一个表项的内存空间的地址。因此,在单项链表中,我们可以通过item来遍历链表,从而获取每个表项的值,同时,每个表项的data也是可以访问的。

双向列表仅仅在结构体上多维护了一个prev,表示它的前一个表项是谁。比如,A1的后一个是A2,A2的前一个是A1,那么它的prev实际上就指向了A1,它的next指向了A2,这就是双向链表。具体在程序中实现时,我们通过item的next来往下走,通过prev来往上走,这样就能遍历整个链表。

在游戏中,双向列表和单向列表的意义是什么呢?比如在CS2中,所有的玩家和游戏中的物品,比如枪、手榴弹、C4等,都可以看作是一个一个的对象。因为在CS中,它们都是一个个的物品,只是功能和属性不同。游戏需要存储整个地图中的所有物品,通过双向列表来实现。比如,在游戏中,需要时刻了解每个玩家的状态,通过遍历自身的状态并通过双向列表不断地往前往后遍历,就可以遍历出所有玩家和物品的状态。制作辅助时,也就是通过找到自身的地址,然后通过拟合出的结构来辨别地图中的所有物品的属性,从而实现读取它们属性的目的。

暮色的狐
这是一只高强度上网冲浪、高质量输出内容的狐狸。主打ACGN杂谈、技术干货分享、第九艺术鉴赏、网梗百科解析、情感树洞鸡汤、正能量价值观~
 最新文章