- Регистрация
- 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"
]
}
или альтернативный и самый простой вариант заменяющий два последних шага:
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
PHP:
#include <YSI_Coding\y_hooks>
hook OnPlayerConnect(playerd)
{
// ваш код
return Y_HOOKS_CONTINUE_RETURN_1;
}
Многократное использование обратных вызовов
gamemodes/new.pwn
PHP:
// выше include ваших плагинов, библиотек и т.п.
#include "src/players/player_module1.inc"
#include "src/players/player_module2.inc"
// module1, module2 - может быть что угодно, данная статья не про архитектуру проекта, используется в качестве примера
// ниже ваш любой другой код в моде
PHP:
#include <YSI_Coding\y_hooks>
hook OnPlayerConnect(playerd)
{
// ваш какой то код, инициализация переменных, запрос в игрока в БД и т.д.
return Y_HOOKS_CONTINUE_RETURN_1; // возвращает 1, продолжает вызов следующих функций
}
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;
}
P.S. статья писалась ночью, могут быть какие то ошибки или не точности, вы всегда можете оставить свое пожелание и предложение и оно будет учтено.
Последнее редактирование модератором: