个人觉得要防住外挂,最好的方案就是一切走服务器来验证。尤其是一些关键性的数据,比如血条,装备和位置。
这里我以位置来举例,如果什么时候都要把数据同步给服务器来验证后再移动,除了可能的丢包之外,来回的开销也会让客户端玩起来像PPT一样。当然回合制的游戏,比如卡牌之类可以考虑这种方案。如果是对实时性要求比较高的FPS游戏,肯能就无法忍受这种方案了。
模型思路
有一种比较实用的方案是:由于“位置”这个信息比较敏感,客户端会不停地反复更新它。肯定是需要服务器校验的。所以可以去掉客户端的直接写它的权利,转而做一个“位置副本”。客户端对于位置的更新都给予这个“位置副本”,包括读和写。这样由于操作都在客户端所以游戏的流畅感会好很多。
对于原来的“位置”数据,客户端只保留了读的权利。相反,服务器将拥有“位置”数据的读和写权利,但对于“位置副本”却只有读的权利。
那么当客户端不断的操作“位置副本”,并且不停地将信息同步给服务器的时候。服务器可以拿“位置”数据和它进行交叉对比。如果发现符合算法条件的下移动,则可以拿“位置副本”更新“位置”数据。相反,如果发现异常:比如一下子穿墙之类,服务器就不会更新“位置”数据。并且异步告知客户端需要修正它的“位置副本”。
通常客户端是只要关注“位置副本”数据的,一旦收到服务器的“位置”异常信息。则需要立马修正自己的“位置副本”到上一个正确的“位置”数据。这样就达到了一个既能保证流畅性又能完成校验的目的了。
服务器预估
那么服务器如何判定客户端的“位置副本”正确性呢?
首先, 服务器需要一份地图数据(这份地图数据有可能也需要实时更新,比如在一些可以破坏地形的场景中)。同时他需要保存一份所有玩家的“位置”信息。这样服务器就知道玩家某个时刻在地图的哪个位置了。当它收到客户端的“位置副本”数据更新信息后,除了做一些常规的校验外。最终要的是去匹配当前值是否和“预估位置”值。如果符合,则可以更新。
那么这个“预估位置”如何得到呢?这里会涉及比较多的因素: 比如玩家的三维值,环境值之类。基本上的思路是基于上一个“位置”数据,然后穷尽游戏内所有可以对移动产生的作用的因素,并把它转化成许多个对应的“向量”,然后进行相加就可以获得“预估位置”了。
当然基于现实情况的复杂性,要求“位置副本”和“预估位置”严格相等是显然不现实的。所以还要容忍一定的“合理误差”。
客户端呢?
由于我不是客户端出生,所以思路有可能比较局限。现在想到的方案有,进行包混淆可以一定层度的减少被破解。然后一些敏感的“位置”信息相关的逻辑可以欺骗性的用字符串而不是常规的数字,这样就可以避免被内存定位到之类。当然肯定不止这些方案。。。