Skip to content

Synchronization

1NS edited this page Jul 14, 2026 · 2 revisions

[<<<Wiki]

Vehicle Synchronization
[Video]SA-MP vs MTA movement comparison
Работа с RakNet хуками с помощью SAMPFUNCS

Скрипт выполняется в одном потоке - любое действие на сервере происходит только после завершения предыдущего действия. К примеру, если у вас есть код, который выполняется за 3 секунды в OnPlayerConnect (одна из старых версий плагина GeoIP, например), то сервер будет ждать, пока выполнится этот код, прежде чем начать выполнять что-либо ещё.

Что может занять много времени: Работа с длинными строками. Перебор игроков и выполнение действий над ними. Чтение и запись информации в большое количество файлов. Серверу придётся ждать, пока выполнятся все эти действия, поэтому старайтесь делать ваш код как можно более производительным.

Обновление данных об игроках. Когда любой из параметров изменяется, клиент будет отправлять информацию на сервер и сервер будет вызывать OnPlayerUpdate:

  • Здоровье / броня.
  • HP автомобиля / повреждения / цвет / тюнинг.
  • Смерть.
  • Скорость.
  • Позиция / поворот.
  • Анимация.
  • Нажатые клавиши.
  • Оружие / боеприпасы.
  • Положение камеры (при наведении, съемке, если такого действия нет, обновляется раз в 2 секунды).

Что происходит, когда игрок перемещает камеру, начинает двигаться или нажимает на клавиши? Если игрок целился или стрелял, угол поворота камеры и поворота игрока будут отправлены в этом же обновлении и будет вызван коллбэк OnPlayerUpdate. Если же игрок не целился и не стрелял, OnPlayerUpdate может и не вызваться. OnPlayerUpdate вызывается при нажатии кнопок. OnPlayerKeyStateChange не вызывается, если нажаты клавиши ходьбы/движения (вправо/влево/вперед/назад). Анимация игрока будет обновлена до вызова OnPlayerUpdate, если она была изменена мгновенно.

Что произойдёт, если вернуть 0 в OnPlayerUpdate? OnPlayerUpdate вызывается до того как сервер посылает обновлённую информацию игрокам. Если в этой функции вернуть 0 (как из фильтрскрипта, так и из мода), обновлённая информация просто не будет передана.

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

Функции сервера, влияюшие на игрока Такие функции, как SetPlayerHealth, GivePlayerMoney, PutPlayerInVehicle и т.д., передают данные с сервера только тому игроку, которого они затрагивают (за исключением SetPlayerVirtualWorld).

Что же это значит? К примеру, если у игрока 73 ХП и вы используете SetPlayerHealth для установки здоровья в 100 ХП, происходит следующее:SetPlayerHealth(playerid, 100.0) -> сервер отправляет игроку сообщение о том, что у него должно обновиться ХП.Клиент на данный момент приостановлен, поэтому сообщение отправляется в "очередь". Как только клиент продолжит работу, он обработает все сообщения из очереди в порядке их поступления.Таймер в моде использует GetPlayerHealth на игроке и получает 73.Теперь клиент возобновлен и все запросы в очереди обрабатываются.ХП изменено для клиента.Обновление отправлено на сервер.Вызвана функция OnPlayerUpdate. Информация о новом количестве ХП отправлена другим игрокам на сервере, теперь они тоже видят у того игрока 100 ХП.

Синхронизация клавиш

SA:MP синхронизируется путем получения статуса нажатия ваших клаквиш и отправки этого статуса другим клиентам. Если вы нажмете клавиши прицела и стрельбы, данные об этом получат и другие клиенты. Это означает, что, даже если вы стреляете на вашем экране, вы можете стоять перед разсинхронизированной машиной или быть зарезаным/убитым от взрыва автомобиля на экранах других клиентов. Это называется рассинхронизацией.

Как исправить рассинхронизированного игрока
Чтобы исправить проблему с синхронизацией игрока, следует либо переместить игрока из зоны стрима другого игрока и обратно, либо заново зареспавнить игрока. Перемещение в/из зоны стрима занимает около секунды, поэтому респавн является самым универсальным решением.

Отправке данных о нажатии клавиш на сервер
Некоторые могут думать, что если нажать клавишу очень быстро, сервер не получит данные о нажатии. Ошибаетесь! Например, если нажать и отпустить клавишу "огонь", сервер получит 2 обновления: вы нажали клавишу и вы отпустили клавишу.

Потеря пакетов Иногда, когда клиент отправляет обновленные данные на сервер, они теряются. Это может привести к ошибкам и проблемам в скриптах, поэтому нужно быть готовым к потере пакетов! Как же избежать потери пакетов вызванную ошибкой в скрипте?

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

Игрок 1 имеет 50 брони. Сервер оснащен супер-новым античитом на броню, основанным на обновлениях игрока! Античит сработает, если броня игрока изменилась, но деньги его остались прежними (т.е. он не купил её в магазине оружия).

Игрок 1 идет в магазин оружия. Сервер узнает это из-за вызова OnPlayerInteriorChange. Игрок покупает новую броню, отправляет на сервер обновлённую информацию и платит $240. Игрок отправляет пакет с информацией на сервер; пакет потерян! Игрок 1 начинает передвигаться, тем самым отправляя на сервер данные о позиции, но сервер понятия не имеет о броне и о $240. В игрока 1 стреляют, на сервер отправляются данные о новой броне, но данные о $240 - утеряны. Античит всё это видит и банит игрока по причине чита на броню.

Предотвращаем бан по ошибке:
Сообщаем админам и начисляем игроку +1 к подозрению в читерстве. Если таких подозрений будет более 3, наказываем. Даем игроку $1 и ждем новых данных о деньгах игрока. Возможно также снять броню и вернуть ее, только если новые данные о деньгах будут получены в следующих 1-3 обновлениях.

Смешивание пакетов
Смешивание пакетов происходит, когда отправленные пакеты не получены в том же порядке, в котором они были отправлены. Пример такого сценария: Игрок 1 имеет 85 брони. Сервер оснащен супер-новым античитом на броню, основанным на обновлениях игрока! Античит сработает, если броня игрока изменилась, но деньги его остались прежними (т.е. он не купил её в магазине оружия). Игрок 1 сражается с кем-то. Игрок 1 дважды получает урон, сначала на 10 hp, потом на 20 hp. Два пакета данных с обновленной броней отправляются на сервер. Пакеты перемешаны. Сервер сначала получает данные о том, что у игрока есть 55 брони (85 - 10 - 20). Первый пакет приходит на сервер после второго, там броня игрока - 75. Сервер думает, что игрок читом восстановил броню и банит его.

Предотвращаем бан по ошибке:
Сообщаем админам и начисляем игроку +1 к подозрению в читерстве. Если таких подозрений будет более 3, наказываем. Не применяйте наказание в ближайшие 2-3 обновления, только делайте предупреждения, как в предыдущем пункте. Принимайте меры только если у игрока 100 или более ед. брони.

Перевод статьи написанной Slice на офф.форуме самп

[<<<Wiki]

Clone this wiki locally