Manual Обсуждение API плагинов, теория, примеры кода

zhorzh78

Администратор
Сообщения
3,060
Решения
21
Реакции
1,214
Баллы
113
Данная тема создана для обсуждения использования API (Application Programming Interface) плагинов, размещенных на данном форуме. Плагины с API имеют довольно обширные возможности, но ввиду отсутствия примеров, их использование становится не особо понятным. К сожалению, те кто сталкивается с вопросами, предпочитают "забить", чем спросить. Целью данного обсуждения является раскрытие возможностей использования функций для создания собственных дополнений к существующим плагинам без изменения кода основных плагинов. Также, будет удобнее предоставлять примеры ссылкой на пост, чем объяснять каждому, кто пишет в личные сообщения.
Предлагаю в теме задавать вопросы, возникающие при использовании API плагинов. В свободное время и по мере поступления вопросов, будут публиковаться участки кода, конкретные примеры использования нативов и форвардов. Если задача не может быть решена с использованием имеющихся возможностей, будет рассмотрен вопрос о добавлении функций в основные плагины.


Пример создания кошелька для перевода аммопаков между игроками в ZP4.3
 
Последнее редактирование:
Использую cmsapi_get_user_services(id, "", "_priva_1", 0) чтоб получить наличие нужной мне услуги, но столкнулся с проблемой при попытке удалить её с помощью cmsapi_remove_user_service, удаление будет происходить только при присутствий игрока на сервере, поэтому не смог разобрать как именно мне получить iServiceId нужной мне услуги.
 
при попытке удалить её с помощью cmsapi_remove_user_service, удаление будет происходить только при присутствий игрока на сервере,
А разве для cmsapi_get_user_services(id..
не нужен игрок на сервере?
Не улавливаю весь замысел. Приведите пример, желательно с кодом.
 
Код:
if(cmsapi_get_user_services(id, "", _priva_1, 0)) {
// Тут делаем нужные вещи
cmsapi_remove_user_service(id, _priva_1, .bUpdateDB = true);
}

При использования примера выше, выходят следующие ошибки в консоль1667309121072.png
 
Последнее редактирование:
Пример создания кошелька для перевода аммопаков между игроками в ZP4.3

Требования:
ZP 4.3
Gaming Transfer System

C++:
#include <amxmodx>
#include <gaming_transfer_system>
//#include <gamecms5>
#include <zombieplague>

new g_iPurseIndex

public plugin_cfg()
{
    //создаем ключи для словаря (или добавляем их в словарь плагина)
    AddTranslation("ru", CreateLangKey("GTS_CURRENCY_AMMO43_NAME"), "[\wАммопаки\y]");
    AddTranslation("ru", CreateLangKey("GTS_CURRENCY_AMMO43_SIGN"), "\w%d \y[\wштук\y]");
    
    //создаем кошелек для перевода
    g_iPurseIndex = GTSCreatePurse("ammo43", "GTS_CURRENCY_AMMO43_NAME", "GTS_CURRENCY_AMMO43_SIGN", .iOpenTime = 3);
    //.iOpenTime = 3 - доступ к переводу с 3-го раунда, или через 3 минуты, если мод CSDM
}

public OnGTSPurseBalanceRequestPre(id, iPurseIndex, eBalanceAction:iActionSet, iValue)
{
    //если это наш кошелек
    if(iPurseIndex == g_iPurseIndex)
    {
        //получаем баланс
        if(iActionSet == GET_BALANCE)
            return zp_get_user_ammo_packs(id);
        else
        {
            //устанавливаем баланс
            zp_set_user_ammo_packs(id, zp_get_user_ammo_packs(id) + iValue);
            return PLUGIN_HANDLED;
        }
    }

    return PLUGIN_CONTINUE;
}
 
1. OnAPIAdminConnected вызывается стабильно всегда до client_putinserver? или бывают моменты, что может прийти позже?

2. OnAPIMemberConnected вызывается только для зарегистрированного игрока, есть ли подобный форвард, который будет вызван один раз при коннекте любого игрока который укажет успешное получение всех данных с базы gcms? Что бы можно было работать со всеми остальными нативами для получения данных даже если игрок не зарегистрирован. Думал поможет OnAPIAdminsLoaded но в нем не нашел id игрока который зашел, а iAdminIndex мне постоянно 0 возвращает.

3. Есть cmsapi_set_user_flags для установки, а нету натива для отбирания флагов? Нужно, что бы в дальнейшем был так же вызван OnAPIAdminConnected ну и OnAPIPreAdminCheck и OnAPIPostAdminCheck соответственно как и при установки

4. Как я понял OnAPIAdminConnected вызывается всегда при коннекте игрока, когда тот получил флаги, а так же каждый раз при cmsapi_set_user_flags если набор флагов не совпал, это верное утверждение?

5. Как работает gcms api он каждый коннект игрока идет в базу для получение данных или раз при старте карты загружает все данные об услугах? Этот аспект мне тоже важен, что бы понять может ли OnAPIAdminConnected вызываться позже client_authorized например

6. Если в client_connect я добавлю свои флаги игроку, фактически api еще не начнет проверять его из базы, то OnAPIAdminConnected заменит их на те, что были в базе или просто добавит их к существующим? И если просто добавит, то, флаг z не будет ли добавлен? К примеру если у игрока не было флагов в базе еще
Добавлено:

7. Как получить все флаги игрока, то есть оригинальные, которые были в базе, не те, что измененные на лету по типу OnAPIPreAdminCheck, OnAPIPostAdminCheck или выданные cmsapi_set_user_flags и так далее?

8. В чем разница между cmsapi_reload_wallet и cmsapi_add_user_money, разве cmsapi_add_user_money не обновит информацию в базе данных? Или это как-то временно работает. Не совсем понимаю смысл.
Добавлено:

9. Верно ли мое утверждение? Для того, что бы при заходе игрока, не важно, зарегистрированный он или нет, мы хотим добавить один или несколько флагов к числу уже имеющихся, а так же, убрать один или несколько флагов из числа имеющихся достаточно заюзать
OnAPIPostAdminCheck где перезаписать szFlags? Тогда в OnAPIAdminConnected мы получим уже флаги с учетом изменений выше

10. Верно ли мое утверждение? Что кейс выше не сработает если я использую OnAPIPreAdminCheck, так-как при исполнение PLUGIN_HANDLED он не продолжит добавлять другие флаги из базы? То есть фактически мы не добавим флаги, а просто присвоим, получается, если конечно в client_connect не имелось иных флагов
Добавлено:

11. Как я понимаю, в 9 вопросе оно удалит все флаги у игрока и заменит уже готовый список szFlags в get_user_flags для актуализации флагов
 
Последнее редактирование:
5. Как работает gcms api он каждый коннект игрока идет в базу для получение данных или раз при старте карты загружает все данные об услугах? Этот аспект мне тоже важен, что бы понять может ли OnAPIAdminConnected вызываться позже client_authorized например
При установке связи с БД после загрузки плагина "раз при старте карты загружает все данные об услугах"
Если квар cms_use_group_flags //использовать группы пользователей для выдачи флагов доступа = 0, то авторизация (проверка услуг) игрока произойдет в client_authorized
Если квар = 1, то авторизация будет после client_putinserver, т.е после загрузки информации об игроке, как пользователе сайта. после этого будут выданы флаги группы и остальные услуги, если имеются.

1. OnAPIAdminConnected вызывается стабильно всегда до client_putinserver? или бывают моменты, что может прийти позже?
Вызывается после авторизации игрока. Когда происходит авторизация описано выше и получается, что до client_putinserver она будет только если cms_use_group_flags = 0

4. Как я понял OnAPIAdminConnected вызывается всегда при коннекте игрока, когда тот получил флаги, а так же каждый раз при cmsapi_set_user_flags если набор флагов не совпал, это верное утверждение?
Да

3. Есть cmsapi_set_user_flags для установки, а нету натива для отбирания флагов? Нужно, что бы в дальнейшем был так же вызван OnAPIAdminConnected ну и OnAPIPreAdminCheck и OnAPIPostAdminCheck соответственно как и при установки
C++:
* @return                индекс ячейки, добавленной в массив админов (Array:cmsapi_get_all_services)
                        -1 - если услуга с этими флагами уже есть.
*/
native cmsapi_set_user_flags(index, const szFlags[], iTime = -1, const szServiceName[] = "", bAuthorize = true);

/**
* Получение данных всех имеющихся на сервере услуг
*
* @return        New array handle or Invalid_Array if empty
*/
native Array:cmsapi_get_all_services();

/**
* Динамическая перепроверка прав доступа у игрока
*
* @param id    Индекс игрока
*
* @noreturn
*/
native cmsapi_reaccess_admin(id);

C++:
//выдать
new iIndex = cmsapi_set_user_flags(index, const szFlags[], iTime = -1, const szServiceName[] = "", bAuthorize = true);

//удалить (грубый пример без проверок на размер массива и корректный индекс)
ArrayDeleteItem(cmsapi_get_all_services(), iIndex);
cmsapi_reaccess_admin(index);
Добавлено:

2. OnAPIMemberConnected вызывается только для зарегистрированного игрока,
Только для зарегистрированного.

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

Думал поможет OnAPIAdminsLoaded но в нем не нашел id игрока который зашел, а iAdminIndex мне постоянно 0 возвращает.
C++:
/**
* Выполняется после успешной загрузки данных об услугах из базы
*
* @param eQueryStatus:status    Статус загрузки списка (LOAD_ALL- загрузка, RELOAD - перезагрузка)
* @param iAdminIndex            Индекс админа (0, если статус LOAD_ALL)
* @noreturn
*/
forward OnAPIAdminsLoaded(eQueryStatus:status, iAdminIndex);

Индекс админа (0, если статус LOAD_ALL)
Если производится перезагрузка одного админа, например, игрок купил услугу на сайте или удалена истекшая услуга, или выдана/ удалена услуга нативами, то будет индекс админа, с которым проводилась операция. Индекс админа-`id`.`admins__services`
Добавлено:

6. Если в client_connect я добавлю свои флаги игроку, фактически api еще не начнет проверять его из базы, то OnAPIAdminConnected заменит их на те, что были в базе или просто добавит их к существующим? И если просто добавит, то, флаг z не будет ли добавлен? К примеру если у игрока не было флагов в базе еще
Обычная авторизация...
- начало авторизации (из любого места)..
- функция Пре, если она есть в сторонних плагинах
- поиск по загруженным услугам
- функция Пост, если она есть в сторонних плагинах
- авторизация с выдачей флагов.

Если у игрока уже имеются флаги, отличные от тех, которые приготовлены для выдачи, то они будут удалены, будут выданы новые и вызван форвард OnAPIAdminConnected.
Т.е. если у игрока в базе есть флаги "abc", но вы выдали их раньше авторизации игрока, то OnAPIAdminConnected не будет вызван, т.к. вызывается только при установке флагов, отличных от имеющихся.
Если у игрока нет флагов в базе, то будут использованы флаги amx_default_access, т.е ваши ранее выданные будут заменены.
Этот процесс можно корректировать в форвардах.
Добавлено:

7. Как получить все флаги игрока, то есть оригинальные, которые были в базе, не те, что измененные на лету по типу OnAPIPreAdminCheck, OnAPIPostAdminCheck или выданные cmsapi_set_user_flags и так далее?
Услуг может быть несколько. Флаги в них могут дублироваться, но при итоговой выдаче все дубли будут удалены и получится набор флагов от всех услуг. Здесь сложно по данному набору определить оригинальные от конкретной услуги из базы. Нужно точнее понимать задачу, для чего это нужно.
Возможно, для этого подойдет список услуг cmsapi_get_user_services и работа с ними по отдельности
Добавлено:

8. В чем разница между cmsapi_reload_wallet и cmsapi_add_user_money, разве cmsapi_add_user_money не обновит информацию в базе данных? Или это как-то временно работает. Не совсем понимаю смысл.
cmsapi_add_user_money обновить баланс на сайте и только после выхода игрока с сервера, либо после перезагрузки данных о нем
cmsapi_reload_wallet обновит баланс не только на сайте, но и на сервере. Например, игрок не выходя с сервера пополнил баланс на сайте и хочет им воспользоваться на серере. Более информативно можно описывать только на конкретных примерах.
C++:
cmsapi_reload_wallet(.full_update = false) выгрузит данные в базу (как cmsapi_add_user_money)
cmsapi_reload_wallet(.full_update = true) выгрузит данные в базу и загрузит новое значение. Игрок на сервере потратил, а на сайте пополнил. По сути, синхронизация балансов сайта и сервера.
 
Последнее редактирование:
10. Верно ли мое утверждение? Что кейс выше не сработает если я использую OnAPIPreAdminCheck, так-как при исполнение PLUGIN_HANDLED он не продолжит добавлять другие флаги из базы? То есть фактически мы не добавим флаги, а просто присвоим, получается, если конечно в client_connect не имелось иных флагов
Здесь тоже много применений, нужно разбирать на конкретном примере. Не важно, были уже присвоены флаги или нет. Вы можете сами их добавить/ удалить/ оставить и т.д. Смысл в том, что поиска по базе не будет и не будет OnAPIPostAdminCheck.
Добавлено:

9. Верно ли мое утверждение? Для того, что бы при заходе игрока, не важно, зарегистрированный он или нет, мы хотим добавить один или несколько флагов к числу уже имеющихся, а так же, убрать один или несколько флагов из числа имеющихся достаточно заюзать
OnAPIPostAdminCheck где перезаписать szFlags? Тогда в OnAPIAdminConnected мы получим уже флаги с учетом изменений выше
szFlags - флаги, которые были приготовлены для выдачи. Да, их можно поменять в форварде.
11. Как я понимаю, в 9 вопросе оно удалит все флаги у игрока и заменит уже готовый список szFlags в get_user_flags для актуализации флагов
Да.
 
Последнее редактирование:
Посему есть натив для получения данных cmsapi_get_user_data, но нет для их редактирования?
 
Потомусто не было такой необходимости.
Есть список данных, которые можно получить с сайта.
C++:
enum _:eMemberData
{
    MemberId,
    MemberLogin[MAX_NAME_LENGTH],
    MemberName[MAX_NAME_LENGTH*2],
    MemberBirth[MAX_INT_LEN + 1],
    MemberNick[MAX_NAME_LENGTH],
    Float:MemberMoney,
    Float:MemberMoneySaved,
    MemberGameTime,
    MemberPrefix[MAX_STRING_LEN],
    MemberGameMoney,
    MemberGameMoneySaved,
    MemberMessages,
    MemberGroup,
    MemberGroupName[MAX_NAME_LENGTH*2],
    MemberThanks,
    MemberAnswers,
    MemberRaiting,
    MemberRegDate[MAX_STRING_LEN],
    MemberLastActivity[MAX_INT_LEN],
    MemberDiscount
};
Сначала, для работы с ними были созданы нативы
C++:
native cmsapi_get_forum_data(id, szData[4], szName[]="", iLen=0);
native cmsapi_get_user_nick(id, szNick[], iLen);
native cmsapi_get_user_group(id, szGroup[] = "", iLen = 0);
и т.п..
Чтобы не создавать отдельный натив для работы с каждым элементом, был создан один универсальный.
А менять какие-то данные, созданные на сайте не было необходимости, да и удобство для администрирования, по сравнению с работой на сайте, сомнительное.
 
zhorzh78, Я вот хочу изменить MemberRaiting, но мне никак это не сделать без доп натива
 
steelzzz, Потому что он рассчитывается по формуле, которая придумана автором движка.
C++:
function collect_reit($thanks, $answers) {
    //thanks - количество спасибок
    //answers - количество ответов
    $reit = $thanks * 5 + $answers;
    return $reit;
}
Не вижу оснований лезть в работу сайта серверными плагинами. Изменение рейтинга напрямую мешает работе данной функции сайта. Да и переподсчет рейтинга на сайте вернет все ваши изменения. Мало того, я даже практического применения этому не вижу. А как можно сделать то, не знаю что.. вопрос риторический.
 
Последнее редактирование:
steelzzz, Я предполагал обсуждение существующих возможностей и реальных потребностей, а не абстрактных примеров.
 
Если я в client_putinserver пытаюсь узнать id юзера на сайте через cmsapi_is_user_member(id), не всегда может прийти id. После смены карты особенно большая вероятность что придет 0. Не успевает связаться вовремя с бд? И если да, как лучше тогда поступить?
 
Но насколько я понял, оно выполняется только для тех, кто зарегистрирован. Мне нужно на этапе putinserver выполнять код отдельно для обычного игрока и отдельно для зарегистрированного..
 
как лучше тогда поступить?
В OnAPIAdminsLoaded проверяешь, загрузились-ли данные. Если загрузились, то можно с плагином работать. Если нет, то нельзя. Решается простой булевой.
 
В OnAPIAdminsLoaded проверяешь, загрузились-ли данные. Если загрузились, то можно с плагином работать. Если нет, то нельзя. Решается простой булевой.
Нужно чтобы точно загрузились данные об игроке, а не возвращало 0 для зарегистрированного как сейчас бывает. Этот натив только для зарегистрированных и не подходит.

У меня один код выполняется для обычных игроков и другой код для тех кто с сайта на этапе client_putinserver.
 
Ещё раз повторяю, необходимо для начала узнать, подключился-ли плагин к базе. Проще всего это сделать через OnAPIAdminsLoaded.
В putinserver же проверяешь, плагин подключился к БД(через булевую, значение которой меняешь в вышеупомянутом OnAPIAdminsLoaded)или нет. Если подключился, то выполняешь свой код. Если нет, то не выполняешь код(зачем выполнять код, когда плагин ещё не подключился к БД?).
 
Назад
Сверху