1

背景:我正在开发一个小游戏,并利用玩家的延迟来做延迟补偿。该游戏是开源的,因此目前对系统进行逆向工程并延迟响应时间以人为增加报告的延迟是一项非常容易的任务,从而可能导致不公平的优势。


我当前的延迟检索策略是:

  • 每个固定间隔我都会向玩家发送一条标记为“ping”的消息。(这与ICMP无关)
  • 此 ping 消息由一个特殊的“ping”操作码和一个带有序列号的有效负载组成
  • 一旦客户端收到所述消息,他就会发回一个带有“pong”操作码和具有相同序列号的有效负载
  • 当服务器收到标记为“pong”的消息时,它会计算发送和接收之间经过了多少时间。这是往返时间
  • 我们的延迟是 rtt / 2

在伪代码中

服务器:

function now() {
    return current UTC time in millis
}

i = 0
function nextSequence() {
    return i++
}

sendingTimestamps = []
function onPingEvent() {
    id = nextSequence()
    sendingTimestamps[id] = now()
    sendPingMessage(id)
}

function onPongReceived(id) {
    received = now()
    sent = sendingTimestamps[id]
    rtt = received - sent
    latency = rtt / 2
}

客户:

function onPingReceived(id) {
    sendPongMessage(id)
}

正如你所看到的,客户很容易在他的代码中添加一个延迟来夸大他报告的延迟。

有没有更好的方法来让客户延迟以减少他们作弊的空间?

4

1 回答 1

2

下面的答案是评论中讨论的主题的摘要,以便将它们全部放在一个地方。

延迟补偿应该依赖于事件的精确时间戳,而不是平均数据包延迟

即使对于两个连续的数据包,转换时间也可能会发生巨大变化。测量平均延迟并假设每个接收到的数据包在“延迟”毫秒前发送以进行延迟补偿的建议方法太不准确了。应改为应用以下方案:

服务器开始在其一侧模拟世界并向所有客户端发送命令 START。客户端启动模拟世界并计算其创建的滴答声。每当客户端发生任何事件时,客户端都会将其与时间戳一起发送到服务器。就像“用户在第 183 个刻度上按下了火”。由于数据包转换时间,服务器对游戏的模拟遥遥领先,但服务器可以“及时返回”来处理用户的命令并解决后果。

时间戳和事件仍然可以伪造

AFAIU 验证客户端输入的问题通常是无法解决的。客户端中实现的任何算法都可以重新创建以伪造事件/时间戳/数据包。封闭的代码可以反转,所以它不是一个答案。即使像反恐精英或守望先锋这样的世界范围内流行的游戏也有作弊者,尽管它们是由大公司开发的,我敢打赌,这些公司有单独的部门专注于游戏安全。一些公司开发了类似杀毒软件的模块,这些模块可以检查游戏文件的完整性或部分 RAM 快照的哈希值,但它仍然可以被绕过。

问题是伪造算法所需的努力。需要的努力越多,造假者就越少。简单的时间戳验证如下:

  1. 如果您在事件#1 之后在 TCP 流中收到事件#2,但它的时间戳在事件#1 之前,则它是伪造的。

  2. 如果时间戳远远落后于服务器时间,则警告并踢出严重延迟的玩家。如果是真正的玩家,无论如何游戏对他来说是无法玩的,否则你踢了黑客。如果我没记错的话,CS 服务器会这样做。

于 2017-08-09T14:57:33.517 回答