Как принять во внимание различия в задержке при проверке различий в местоположении с помощью отметок времени (анти-мошенничество)? - PullRequest
4 голосов
/ 01 ноября 2009

Если у вас есть многопользовательская игра, в которой сервер получает информацию о перемещении (местоположении) от клиента, вы хотите проверить эту информацию в качестве меры против обмана.

Это можно сделать так:

maxPlayerSpeed = 300; // = 300 pixels every 1 second
if ((1000 / (getTime() - oldTimestamp) * (newPosX - oldPosX)) > maxPlayerSpeed)
{
   disconnect(player); //this is illegal!
}

Это простой пример, учитывающий только координаты X. Проблема здесь в том, что oldTimestamp сохраняется, как только последнее обновление местоположения было получено сервером. Это означает, что если в это время был скачок задержки, старая временная метка будет получена намного позже относительно нового обновления местоположения сервером. Это означает, что разница во времени не будет точной.

Пример:

  1. Клиент говорит: я сейчас на позиции 5х10
  2. Пик задержки: сервер получает это сообщение с отметкой времени 500 (обычно оно должно достигать 30)
  3. .... 1 секунда движения ...
  4. Клиент говорит: я сейчас на позиции 20х15
  5. Без скачка задержки: сервер получает сообщение с отметкой времени 1530

Сервер теперь будет думать, что разница во времени между этими двумя местоположениями равна 1030. Однако разница в реальном времени равна 1500. Это может привести к тому, что обнаружение анти-мошенничества будет считать, что 1030 недостаточно, что пинает клиента.

Возможное решение : разрешить клиенту отправлять временную метку при отправке, чтобы сервер мог использовать эти временные метки вместо

Проблема: проблема с этим решением состоит в том, что игрок мог манипулировать клиентом, чтобы отправить временную метку, которая не является законной, поэтому античитерская система не сработает. Это не хорошо решение.

Также возможно просто разрешить maxPlayerSpeed ​​* 2 speed (например), однако это в основном позволяет повысить скорость хакерства вдвое быстрее, чем обычно. Это тоже не очень хорошее решение.

Итак: есть ли у вас какие-либо предложения о том, как решить эту проблему с «отметкой времени и задержкой сервера», чтобы мои меры по борьбе с мошенничеством оправдывали себя?

Ответы [ 3 ]

4 голосов
/ 02 ноября 2009

Нет, нет, нет ... при всем уважении, это все неправильно, и как НЕ делать этого.

Средство защиты не доверять вашим клиентам . Не заставляйте клиентов отправлять свои позиции, заставляйте их отправлять свои состояния кнопок! Просматривайте состояния кнопок как запросы, когда клиенты говорят «Я двигаюсь вперед, если вы не возражаете». Если клиент отправляет сообщение «продвижение вперед» и не может двигаться вперед, сервер может игнорировать это или делать все, что ему нравится, для обеспечения согласованности. В этом случае клиент только обманывает себя.

Что касается скоростных взломов, которые стали возможны при переполнении пакетов, сохраните счетчик пакетов. Удалите клиентов, которые отправляют больше пакетов в течение определенного периода времени, чем допустимые параметры. Клиенты должны отправлять один пакет за такт / кадр / мировой временной шаг. Удобно называть пакеты, основанные на времени, в целых приращениях. Избыточные пакеты одного и того же временного шага могут быть затем идентифицированы и проигнорированы. Обратите внимание, что отправка одного и того же пакета несколько раз является хорошей идеей при использовании UDP, чтобы предотвратить потерю пакета.

Опять же, никогда не доверяй клиенту. Это не может быть подчеркнуто достаточно.

2 голосов
/ 06 ноября 2009

Независимо от мнения о подходе, вы ищете порог скорости, который считается "обманом". Учитывая расстояние и приращение времени, вы можете легко увидеть, переместились ли они «слишком далеко» в зависимости от вашего порога обмана.

time = thisTime - lastTime;
speed = distance / time;
If (speed > threshold) dudeIsCheating();

Время, используемое для измерения, - это время приема пакета сервером. Хотя это кажется тривиальным, оно рассчитывает расстояние для каждого движения персонажа, что может оказаться очень дорогим. Лучший маршрут - это сервер, рассчитывающий позицию на основе скорости, и это позиция персонажа. Клиент никогда не сообщает позицию или абсолютную скорость, вместо этого клиент отправляет «процент от максимальной» скорости.


уточнить: Это было только для проверки на обман. Ваш код имеет возможность задержки или длительной обработки на сервере повлиять на ваш результат. Формула должна быть:

maxPlayerSpeed = 300; // = 300 pixels every 1 second
if (maxPlayerSpeed < 
    (distanceTraveled(oldPos, newPos) / (receiveNewest() - receiveLast()))
{
   disconnect(player); //this is illegal!
}

Сравнивает скорость перемещения игроков с максимальной скоростью перемещения. Метки времени определяются тем, когда вы получаете пакет, а не тем, когда вы обрабатываете данные. Вы можете использовать любой метод, который вам нужен, чтобы определить, какие обновления следует отправлять клиентам, но для порогового метода, который вы хотите использовать для определения мошенничества, задержка не повлияет на вышеуказанный.

Прием пакета 1 в секунду 1: символ в позиции 1

Прием пакета 2 в секунду 100: символ в позиции 3000

пройденное расстояние = 2999

время = 99

ставка = 30

Обмана не было.

Прием пакета 3 в секунду 101: символ в позиции 3301

пройденное расстояние = 301

время = 1

ставка = 301

Обман обнаружен.

То, что вы называете «скачком задержки», - это очень высокая задержка при доставке пакетов. Но это не имеет значения, поскольку вы не проходите мимо, когда обрабатываются данные, вы проходите мимо, когда каждый пакет был получен. Если вы оставляете вычисления времени независимыми от обработки игровых тиков (как и должно быть, как происходило во время этого «тика»), высокая и низкая задержки влияют только на то, насколько точно сервер находится в позиции персонажа, что вы используете для разрешения интерполяции + экстраполяции .

Если клиент не синхронизирован настолько, чтобы он не получил каких-либо исправлений к своему положению и совершенно не синхронизирован с сервером, существует значительная потеря пакетов и высокая задержка, которую ваша проверка на мошенничество не сможет учитывать. Вы должны учитывать это на более низком уровне с обработкой реальных сетевых коммуникаций.

Для любых игровых данных идеальным методом является запуск всех систем, кроме сервера, на 100-200 мс. Скажем, у вас есть запланированное обновление каждые 50 мс. Клиент получает первое и второе. У клиента нет данных для отображения, пока он не получит второе обновление. В течение следующих 50 мс он показывает прогресс изменений, как он уже произошел (т. Е. Воспроизведение происходит с очень небольшой задержкой). Клиент отправляет свои состояния кнопки на сервер. Локальный клиент также прогнозирует движение, эффекты и т. Д. На основе этих нажатий кнопок, но только отправляет серверу «состояние кнопки» (поскольку существует конечное число кнопок, существует конечное число битов, необходимых для представления каждого состояния, который позволяет более компактный формат пакета).

Сервер - это авторитетная симуляция, определяющая фактические результаты. Сервер отправляет обновления каждые, скажем, 50 мс клиентам. Вместо того чтобы интерполировать между двумя известными кадрами, сервер вместо этого экстраполирует позиции и т. Д. Для любых пропущенных данных. Сервер знает, какой была последняя реальная позиция. Когда он получает обновление, следующий пакет, отправляемый каждому из клиентов, включает в себя обновленную информацию. Затем клиент должен получить эту информацию до достижения этого момента времени, и игроки реагируют на нее по мере ее появления, не видя никаких странных прыжков, потому что он никогда не отображал неправильную позицию.

Возможно, клиент может быть авторитетным для некоторых вещей, или чтобы клиент выступал в качестве авторитетного сервера. Ключом является определение степени влияния доверия на клиента.


Клиент должен отправлять обновления регулярно, скажем, каждые 50 мс. Это означает, что 500-миллисекундный «пик задержки» (задержка при приеме пакетов), либо все пакеты, отправленные в течение периода задержки, будут задержаны на такую ​​же величину, либо пакеты будут приняты не в порядке. Базовая сеть должна корректно обрабатывать эти задержки (отбрасывая пакеты с чрезмерно большой задержкой, обеспечивая порядок доставки пакетов и т. Д.). Конечный результат заключается в том, что при надлежащей обработке пакетов ожидаемые проблемы не должны возникать. Кроме того, не получая явного расположения символов от клиента и вместо этого имея сервер явно исправлять клиента и получать только состояния управления от клиента, предотвратит эту проблему.

2 голосов
/ 01 ноября 2009

Сглаживание пиков отставания путем фильтрации. Или, говоря иначе, вместо того, чтобы всегда сравнивать их новую позицию с предыдущей, сравните ее с позицией нескольких обновлений назад. Таким образом, любой кратковременный джиттер усредняется. В вашем примере сервер может посмотреть на позицию перед скачком задержки и увидеть, что в целом игрок движется с разумной скоростью.

Для каждого игрока вы можете просто удерживать последние позиции X, или вы можете держать много недавних позиций плюс некоторые более старые позиции (например, 2, 3, 5, 10 секунд назад).

Как правило, вы будете выполнять интерполяцию / экстраполяцию на сервере в любом случае в пределах нормальных скоростей движения, чтобы скрыть дрожание от других игроков - все, что вы делаете, это распространяете и на свой механизм проверки читов. Все законные ускорения наступят после очевидного замедления, и интерполяция помогает скрыть такого рода ошибки.

...