Доступ к готовым решениям

Переход в группу "Пользователь"

300.00
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

[YSI] y_hooks 5.x

Alisa_Mey

Начинающий
Пользователь
Регистрация
8 Мар 2019
Сообщения
44
Лучшие ответы
2
Репутация
10
Приветствуем всех пользователей и гостей портала, в данной статье мы разберем обновленную версию библиотеки y_hooks из YSI 5.x.​

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

Классическая установка

1. Скачиваем исходный код из официального репозитория на github (Зеленая кнопка Clone or download)
2. Распаковываем архив в папку pawno/include нашего проекта (мода, сервера и т.д.)
3. Подключаем библиотеку #include <YSI_Coding\y_hooks> (Кто использовал YSI старой версии, вариант <YSI\y_hooks> больше не работает)

Современный способ

1. Устанавливаем sampctl (Инструкция: https://pawno-info.ru/threads/318341)
2. Создаем проект sampctl package init (Инструкция: https://pawno-info.ru/threads/318326)
3. Добавляем зависимость от библиотек pawn-lang/YSI-Includes в файл проекта pawn.json

Пример pawn.json:
PHP:
{
    "user": "yourname",
    "repo": "yourproject",
    "entry": "gamemodes/new.pwn",
    "output": "gamemodes/new.amx",
    "dependencies": [
        "sampctl/samp-stdlib",
        "pawn-lang/YSI-Includes"
    ]
}
4. Обновляем зависимости sampctl package ensure

или альтернативный и самый простой вариант заменяющий два последних шага:

PHP:
sampctl package install pawn-lang/YSI-Includes
Собственно установка на этом закончена, можем переходить к следующему этапу, но для начала все же нужно объяснить для чего необходима данная библиотека.

Если вы уже продвинутый PAWN-разработчик, то наверняка задавались вопросом, почему бы не разбить мой код написанный в одном большом .pwn файле на несколько модулей или include, как принято это называть. Данная библиотека как-раз позволяет решить некоторые проблемы, при разделении вашего мода на такие куски, связанные с обратными вызовами вашего мода, т.е. те самые public.

Например, в нашем новом файле gamemodes/src/players/player_register.inc в который мы решили вынести регистрацию игрока, нам нужно, чтобы сработал обратный вызов OnPlayerConnect(playerid).

PHP:
public OnPlayerConnect(playerid)
{
    // ваш код

    return 1;
}

Если вы вызовите непосредственно сам каллбэк в вашем файле и он также вызывается непосредственно в самом моде или другом аналогичном файле, компиляция завершиться с ошибкой symbol already defined: "OnPlayerConnect", т.е. функция уже была определена раньше. Чтобы решить данную проблемы обычно используют макросы, для "подмены" названия каллбэка на любое другое, например:

PHP:
public OnPlayerConnect(playerid)
{
     // ваш код

    #if defined Register_OnPlayerConnect
        return Register_OnPlayerConnect(playerid);
    #else
        return 1;
    #endif
}
#if defined _ALS_OnPlayerConnect
    #undef OnPlayerConnect
#else
    #define _ALS_OnPlayerConnect
#endif

#define OnPlayerConnect Register_OnPlayerConnect
#if defined Register_OnPlayerConnect
    forward Register_OnPlayerConnect(playerid);
#endif
Согласитесь, код стал очень громоздким, а что будет если мы уже где то раньше использовали название Register_OnPlayerConnect и уже забыли об этом? Тут, то нам на помощь и приходит y_hooks, давайте посмотрим, как теперь будет выглядеть наш код:

PHP:
#include <YSI_Coding\y_hooks>

hook OnPlayerConnect(playerd)
{
    // ваш код

    return Y_HOOKS_CONTINUE_RETURN_1;
}
Теперь намного лучше, не правда ли? По сути, y_hooks делает тоже самое что и наш макрос с ALS, переименовывая функция, добавляя в ее название @1, @2, @3 и т.д. Вызываться соответственно они будет по очереди, начиная с последней добавленный функции т.е. например сначала будет вызван OnPlayerConnect@3(playerid), OnPlayerConnect@2(playerid) и последним OnPlayerConnect@1(playerid) - это нужно учитывать при проектировании архитектуры проекта. На этом наше большое вступление закончено, перейдем к примерам.

Многократное использование обратных вызовов

gamemodes/new.pwn

PHP:
// выше include ваших плагинов, библиотек и т.п.

#include "src/players/player_module1.inc"
#include "src/players/player_module2.inc"

// module1, module2 - может быть что угодно, данная статья не про архитектуру проекта, используется в качестве примера
// ниже ваш любой другой код в моде
gamemodes/src/players/player_module1.inc

PHP:
#include <YSI_Coding\y_hooks>

hook OnPlayerConnect(playerd)
{
    // ваш какой то код, инициализация переменных, запрос в игрока в БД и т.д.

    return Y_HOOKS_CONTINUE_RETURN_1; // возвращает 1, продолжает вызов следующих функций
}
gamemodes/src/players/player_module2.inc

PHP:
#include <YSI_Coding\y_hooks> // да нужно подключать в каждом файле, для генерация уникального названия функции

hook OnPlayerConnect(playerd)
{
    if (IsBlocked(playerid)
    {
        // любая ваша проверка, в данном случае проверка блокировки игрока
        // если игрок заблокирован, кикнем его и прервем вызов следующих функций
        Kick(playerid);
        return Y_HOOKS_BREAK_RETURN_1;
    }
    // если игрок не заблокирован продолжим вызов следующих функций
    return Y_HOOKS_CONTINUE_RETURN_1;
}

// Y_HOOKS_CONTINUE_RETURN_1 - вернет 1, продолжит выполнение функций в моде
// Y_HOOKS_CONTINUE_RETURN_0 - вернет 0, продолжит выполнение функций в моде, но заблокирует вызов некоторых функций в FS
// Y_HOOKS_BREAK_RETURN_1 - вернет 1, но заблокирует выполнение функций в моде, но не заблокирует вызов некоторых функций в FS
// Y_HOOKS_BREAK_RETURN_0 - вернет 0, но заблокирует выполнение функций в моде и FS
Пользовательские возвращаемые результаты по умолчанию

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

PHP:
#include <YSI_Coding\y_hooks>

DEFINE_HOOK_RETURN__(OnMyCustomEvent, 0);

forward OnMyCustomEvent(playerid);

hook OnMyCustomEvent(playerid)
{
    // ваш код
    // в конце return не указываем, наша функция вернет 0 по умолчанию как мы и указали выше.
}

hook OnPlayerConnect(playerid)
{
    // в стандартных вызовах тоже можем не указывать, значения уже прописаны в самой библиотеки
}
Сокращенные названия функций

Еще одна проблема с которой мы можем столкнуться, это длинные названия наших функций, при компиляции название нашей функции будет обрезано до 31 символа и будет выведено соответствующее предупреждение, например symbol "@yH_OnPlayerPickUpDynamicPickup" is truncated to 31 characters.

Это решается объявлением макроса с сокращенным названием, например:

PHP:
DEFINE_HOOK_REPLACEMENT__(DynamicCP , DynamicCP);

// OnPlayerPickUpDynamicCP вместо OnPlayerPickUpDynamicPickup
hook OnPlayerPickUpDynamicCP(playerid, pickupid)
{
    // ...
}
Для всех стандартных и некоторых популярных плагинов, для удобства сокращенные названия уже прописаны в самой библиотеку.

Хуки функций

Еще одно из нововведений в новой версии, это хуки для обычных и нативных функций.

Например:

PHP:
#include <YSI_Coding\y_hooks>

hook function CreateVehicle(vehicletype, Float:x, Float:y, Float:z, Float:rotation, color1, color2, respawn_delay, addsiren=0)
{
    // ваш любой код
    return continue(vehicletype, x, y, z, rotation, color1, color2, respawn_delay, addsiren);
}
Так же мы можем сначала вызвать саму функцию и получить результат ее выполнения, а потом уже провести какие то манипуляции.

PHP:
#include <YSI_Coding\y_hooks>

hook function CreateVehicle(vehicletype, Float:x, Float:y, Float:z, Float:rotation, color1, color2, respawn_delay, addsiren=0)
{
    new ret = continue(vehicletype, x, y, z, rotation, color1, color2, respawn_delay, addsiren);

    // ваш любой код

    return ret;
}
Никогда не вызывайте, саму функцию внутри вашего хука, иначе это вызовет рекурсию, ваш код зациклиться на одном месте.

PHP:
#include <YSI_Coding\y_hooks>

hook function CreateVehicle(vehicletype, Float:x, Float:y, Float:z, Float:rotation, color1, color2, respawn_delay, addsiren=0)
{
    new ret = CreateVehicle(vehicletype, x, y, z, rotation, color1, color2, respawn_delay, addsiren); // так делать нельзя

    // ваш любой код

    return ret;
}
На этой ноте, мы можем завершить нашу статью, если вам понравиться данный материал, мы можем продолжить освещать возможности YSI и дальше.

P.S. статья писалась ночью, могут быть какие то ошибки или не точности, вы всегда можете оставить свое пожелание и предложение и оно будет учтено.
 
Последнее редактирование модератором:
Сверху Снизу