Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 2 1 2 ПоследняяПоследняя
Показано с 1 по 10 из 13
  1. #1
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±

    Синхронизация в SA:MP (Перевод)

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



    Я заметил, что куча багов и проблем возникает у скриптеров из-за отсутствия знаний в этой области. Надеюсь, у меня получится разъяснить для вас некоторые вещи в этой статье.

    Содержание:
    • Скрипт выполняется в одном потоке.
    • Обновление данных об игроках.
    • Влияние игрока на функции сервера.
    • Синхронизация клавиш.
    • Потеря пакетов.
    • Смешивание пакетов.


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

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

    Серверу придётся ждать, пока выполнятся все эти действия, поэтому старайтесь делать ваш код как можно более производительным.

    Преимущества однопоточности:
    Преимущество работы сервера в одном потоке (на мой взгляд) - полный контроль над потоком информации на сервере. Вы всегда будете обрабатывать каждое событие на сервере, как только оно произойдёт. Если бы сервер был многопоточным, то информация об игроке могла бы обновиться во время выполнения вашего кода. И, если честно, я не думаю, что так было бы лучше.[/INDENT]


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

    С помощью скриптинга можно отследить практически все изменения при вызове OnPlayerUpdate.

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

    Примечание: Я не уверен на все 100%, что анимация обновляется в тот же момент, что и статус нажатия клавиш.

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

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

    Хороший пример:
    Этот код не позволит игроку перемещаться/стрелять, когда он заморожен. Больше не будет "призрачной стрельбы", или как вы там это называли.
    PHP код:
    public OnPlayerUpdateplayerid )
    {
        static 
    // Я использую здесь статистические переменные, чтобы они не создавались каждый раз заново
            
    s_Keys,
            
    s_UpDown,
            
    s_LeftRight
        
    ;

        
    GetPlayerKeysplayerids_Keyss_UpDowns_LeftRight ); // Получаем нажатые в настоящее время клавиши

        
    if ( g_IsPlayerFrozeplayerid ] && ( s_Keys || s_UpDown || s_LeftRight ) ) // Если любые клавиши нажаты, не синхронизируем данные
            
    return 0;

        return 
    1;
    }

    // Используем 2 функции для заморозки/разморозки игрока

    stock FreezePlayerplayerid )
    {
        
    g_IsPlayerFrozeplayerid ] = true// Теперь сервер запомнит игрока, как "замороженного"

        
    TogglePlayerControllableplayeridfalse );
    }

    stock UnfreezePlayerplayerid )
    {
        
    g_IsPlayerFrozeplayerid ] = false// То же самое, но наоборот

        
    TogglePlayerControllableplayeridtrue );


    Плохой пример:

    Ниже в конце функции нет return 1, из-за чего ни один игрок не будет синхронизироваться.
    Примечание (DC): если в функции не возвращать никаких значений, она по умолчанию вернёт 0.
    PHP код:
    public OnPlayerUpdateplayerid )
    {
        if ( 
    GetPlayerWeaponplayerid ) == WEAPON_MINIGUN )
            
    Banplayerid );

    Лучше сделать так:
    PHP код:
    public OnPlayerUpdateplayerid )
    {
        if ( 
    GetPlayerWeaponplayerid ) == WEAPON_MINIGUN )
            
    Banplayerid );

        return 
    1;


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

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


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

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

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

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


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

    Как же избежать потери пакетов вызванную ошибкой в скрипте?

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

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


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


    Смешивание пакетов
    Смешивание пакетов происходит, когда отправленные пакеты не получены в том же порядке, в котором они были отправлены.

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

    1. Игрок 1 сражается с кем-то.
    2. Игрок 1 дважды получает урон, сначала на 10 hp, потом на 20 hp. Два пакета данных с обновленной броней отправляются на сервер.
    3. Пакеты перемешаны. Сервер сначала получает данные о том, что у игрока есть 55 брони (85 - 10 - 20).
    4. Первый пакет приходит на сервер после второго, там броня игрока - 75.
    5. Сервер думает, что игрок читом восстановил броню и банит его.


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





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



    Оригинал: http://forum.sa-mp.com/showthread.php?t=184118
    Автор статьи: Slice
    Перевод: wAx, Daniel_Cortez
    Отдельное спасибо DeimoS за помощь.
    Последний раз редактировалось Daniel_Cortez; 11.08.2016 в 20:16. Причина: update

  2. 18 пользователя(ей) сказали cпасибо:
    Alexander (18.12.2014) codeo (15.06.2014) Daniel_Cortez (11.06.2014) DeimoS (15.05.2014) Dima_Khar (11.06.2014) kushichka (03.07.2016) L0ndl3m (15.05.2014) MacMailler (15.05.2014) Osetin (15.05.2014) Salvacore (29.05.2014) Smile (16.08.2015) Sp1ke (03.01.2016) Spectrum (24.07.2014) vovandolg (11.08.2016) XemyL (11.06.2014) [ForD] (16.05.2014) Копюшон (15.05.2014)
  3. #2
    Аватар для wAx
    ¯\_(ツ)_/¯

    Статус
    Оффлайн
    Регистрация
    13.12.2013
    Сообщений
    377
    Репутация:
    146 ±
    обновил

  4. #3
    Аватар для Caypen
    Пользователь

    Статус
    Оффлайн
    Регистрация
    25.03.2014
    Сообщений
    90
    Репутация:
    16 ±
    PHP код:
    Предотвращаем это:

    Сообщаем админами начисляем игроку +1 к подозрению в читерствеЕсли таких подозрений будет более 3наказываем.
    Не применяйте наказание в ближайшие 2-3 обновления.
    Примените наказаниетолько в том случае если броня >= 100
    Ну или же можно переменными действовать, т.е. типо SetPlayerArmourAC в нутри которого будет инфа о том сколько брони дали,таким образом синхра будет не при чем.
    Захожу на pro-pawn.ru - чувствую себя обычным пользователем
    Захожу на gawno-info.ru - чувствую себя самым великим гением
    (С) Caypen

  5. #4
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,369
    Репутация:
    113 ±
    PHP код:
    if ( g_IsPlayerFrozeplayerid ] && ( s_Keys || s_UpDown || s_LeftRight ) ) // Если любые клавиши нажаты, не синхронизируем данные
            
    return 0
    Я вот тут момента не понял, статус заморозки в проверке лишний?
    Ибо нам надо проверять клавиши, а не клавиши+статус нажатия так ведь?
    Когда игрок заморожен он и так не че не сделает поэтому и синхрон не нужен там..не?
    _________________
    Так ведь?
    PHP код:
    if (!s_Keys && !s_UpDown && !s_LeftRight) return 0
    Последний раз редактировалось vovandolg; 11.08.2016 в 00:51.
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

  6. #5
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Провёл ревизию статьи, исправил ошибки и неточности. Кое-где даже были пропущены отрывки из оригинала: например, о том, что может занимать много времени на выполнение, или список параметров, при изменении которых клиент отправит на сервер информацию об обновлении. Эти отрывки я тоже вернул.
    Изменений реально много, поэтому если вы читали эту статью ранее, советую на всякий случай прочесть её заново.


    Цитата Сообщение от vovandolg Посмотреть сообщение
    Я вот тут момента не понял, статус заморозки в проверке лишний?
    Ибо нам надо проверять клавиши, а не клавиши+статус нажатия так ведь?
    Так и задумано: если игрок заморожен, возвращается 0, чтобы у других игроков не нажимались клавиши.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  7. Пользователь сказал cпасибо:
    vovandolg (11.08.2016)
  8. #6
    Аватар для vovandolg
    Пользователь

    Статус
    Оффлайн
    Регистрация
    17.11.2015
    Адрес
    Stavropol
    Сообщений
    1,369
    Репутация:
    113 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Провёл ревизию статьи, исправил ошибки и неточности. Кое-где даже были пропущены отрывки из оригинала: например, о том, что может занимать много времени на выполнение, или список параметров, при изменении которых клиент отправит на сервер информацию об обновлении. Эти отрывки я тоже вернул.
    Изменений реально много, поэтому советую на всякий случай прочесть статью заново.



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

    - - - Добавлено - - -

    Очепятка кстате)
    Код:
    Обновление данных об игроках.
    [INDENT]Когда любой из этих параметров изменяется
    [Anticheat]___Invisible Fly Hack
    [Anticheat]____Weapon/Ammo Hack
    [Function]______ResetPlayerWeaponSlot
    [Function]_______FIX_SetPlayerAmmo
    [ServerMod]______TDM | Zombie Apokalypse

  9. #7
    Аватар для Elrmrnt-Kritik
    Пользователь

    Статус
    Оффлайн
    Регистрация
    05.11.2017
    Сообщений
    136
    Репутация:
    10 ±
    То есть, когда срабатывает OnPlayerUpdate, изменения в игроке (например, стало 50 хп) обновляются для других игроков? Таким образом, OnPlayerUpdate обновляет информацию об игроке для других игроков?

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

    Да и смешивание пакетов тоже так себе описано. Вроде смешались, а почему - кто его знает... Потому что пакеты что ли однотипные (изменение одного и того же параметра)?

  10. #8
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    То есть, когда срабатывает OnPlayerUpdate, изменения в игроке (например, стало 50 хп) обновляются для других игроков? Таким образом, OnPlayerUpdate обновляет информацию об игроке для других игроков?
    Не совсем так. Коллбэки на сервере являются лишь следствием тех или иных действий, а не первопричиной. В случае с OnPlayerUpdate, вызов происходит тогда, когда игрок присылает данные, которые нужно обновить для всех. После того, как сервер получил данные, он сообщает скриптеру об этом, путём вызова OnPlayerUpdate и проверяет какое значение вернул коллбэк, дабы позволить скриптеру контролировать обновление данных.



    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    И этот пример какой-то неудачный. Можно, пожалуйста, его разжевать?
    Что именно тут не понятно?

    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Да и смешивание пакетов тоже так себе описано. Вроде смешались, а почему - кто его знает... Потому что пакеты что ли однотипные (изменение одного и того же параметра)?
    Нет, причин может быть много, но основные:
    1) Плохой интернет-канал, когда игрок поочереди отправил 2 разных пакета, но один где-то затерялся из-за нагруженности канала провайдера игрока, а второй прошёл нормально. Если первый пакет так и не дойдёт до сервера, то это будет потеря пакетов. Если же дойдёт - смешивание.
    2) Игрок намеренно смешивает пакеты, дабы получить какой-то профит от этого
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  11. Пользователь сказал cпасибо:
    Elrmrnt-Kritik (05.04.2018)
  12. #9
    Аватар для Elrmrnt-Kritik
    Пользователь

    Статус
    Оффлайн
    Регистрация
    05.11.2017
    Сообщений
    136
    Репутация:
    10 ±
    Ну, купил игрок броню, отправил запрос (пакет) на обновление денежных средств и брони, а пакет-то куда делся?

  13. #10
    Аватар для Nexius_Tailer
    Пользователь

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±
    Цитата Сообщение от Elrmrnt-Kritik Посмотреть сообщение
    Ну, купил игрок броню, отправил запрос (пакет) на обновление денежных средств и брони, а пакет-то куда делся?
    Не дошёл. Нужно ж понимать, что передача данных по интернету имеет как задержку (пинг), так и иногда плохое качество связи, из-за которого какие-то данные не доходят. Хз что может быть хорошим примером в этом плане, но попробуй поиграть где-нибудь на очень забитом вайфае в интернет-кафе, я думаю там будет хорошо ощущаться и первое и второе.
    Не хотите постоянно проверять обновления моих скриптов?
    Подключите его последним, после всех остальных
    Nexius's Update Checker

  14. Пользователь сказал cпасибо:
    Elrmrnt-Kritik (05.04.2018)
 

 
Страница 1 из 2 1 2 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •