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

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

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

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

Как написать плагин?

Tracker1

Эксперт
Пользователь
Регистрация
1 Июл 2011
Сообщения
1,752
Лучшие ответы
0
Репутация
871
Вступление

Это не форум по C++.
Хорошие сайты по изучению языка:

cprogramming.com
cplusplus.com
learncpp.com

Если у вас возникли проблемы во время написания кода на С++, то вы можете получить поддержку здесь:

dreamincode.net
stackoverflow.com


Часто задаваемые вопросы.

Вопрос: Как же делают плагины?
Ответ: Плагины делаются на C/++ с помощью SDK. Этот FAQ подразумевает, что вы знаете C/++ и лишь доводит до вашего сведения информацию по использованию SDK

Вопрос: Можно ли создать плагин не на C/++?
Ответ: Теоретически - да, практически - нет

Вопрос: Я хочу чтобы мой плагин запускался везде (На линуксе и виндоусе)?
Ответ: Linux и Windows - АБСОЛЮТНО разные операционные системы со своими структурами(далее фреймворками). Для того чтобы сделать так, чтобы ваш плагин запускался под обеими ОСями вам необходимо писать Платформо-Независимый-Код. После написания такого кода, вам всеголишь необходимо скомпилировать его на желаемых осях. В итоге вы получите .so и .dll версию плагина.

Вопрос: Можно мне подменять память серверного демона?
Ответ: Честно говоря, это уже относится к андерграунду и кодингу уровня Евгена 1137. Использовать хаки памяти для того чтобы отлавливать Коллбэки вполне нормально, но подменять память сервера, это уже что-то выходящее за рамки.

Вопрос: Возможно ли сделать плагин который будет делать ______ ?
Ответ: В 90% случаев - ДА. Возможно плагину потребуется отдельное приложение для работы, но это не меняет суть ответа. Не стоит задавать такие вопросы.

Вопрос: Какую Среду разработки(далее IDE)/компилятор я должен использовать для ______ ?
Ответ: Выбор каждого. Лично я советую VS2010 для Windows и g++ для Linux

Вопрос: Что такое файл сведений о модулях DLL (.def)?
Ответ: файл сведений о модулях DLL это специальный файл который сообщает линкеру IDE VS2010 о компилируемой программе. Когда речь идет о плагинописании, мы лишь используем "EXPORTS" которая предоставляет компилятору информацию о наших экспортируемых функциях. В статье мы обсудим это

Вопрос: Когда я выпускаю плагин, я должен выкладывать исходники?
Ответ: Если вы выпускаете хоть что-нибудь на этом форуме, вы обязаны прикладывать исходники. Плагины не исключение.

Начало

Начнем с того, что если вы знаете язык, это не значит что вы знаете как двигаться по IDE. VS2010 IDE может показаться очень неуютным местом для новеньких. Я думаю, что это нечестно - давать вам SDK без объяснения IDE.

Заметка: Если вы выбрали другую IDE для Windows, то вам НЕВЕЗЕТ! Судя по-всему, единственный способ экспортировать функции - это использование файла сведений о модулях DLL (.DEF). Другие методы, основывающиеся на использовании __declspec(dllexport), провальны, потому что вызов __stdcall просто напросто коверкает их имена (Заметка: код Kyosaur'a ).

Вам понадобится:

Visual C++ 2010 express:
SDK:

Первым делом следует создать новый проект. Нажимаем file -> new -> project
Выберите Win32 проект. Введите имя проекта и нажмите ОК.
Нажимаем Continue
Выбираем DLL и отмечаем empty project
Далее мы идем в Solution Explorer. Обычно он слева, но если его нет то следует нажать CTRL+SHIFT+L. Нажмите ПКМ на ваш проект и выберите properties
После открытия настроек идем в Configuration properties->Linker->Input в левой части. Так как вы здесь, значит мы хотим создать .def файл. Называйте его как хотите, главное чтобы .def был на конце. После того, как вы дали ему имя, нажмите ОК
Остается только добавить файлы. Это выполняется через ПКМ по названию вашего проекта и ADD-New item. Сначало добавляем наш .def файл. Но в списке нету .def типа. Выбираем .cpp тип, но в названии файла в конце обязательно ставим .def. Как справитесь, добавьте .cpp файл с вашим названием.(большинство называют его main.cpp)
Прежде, чем мы сможем заполнять наши два пустых файла, мы должны подключить SDK к нашему проекту. Скачав, SDK из ссылки сверху следует распаковать. После этого создаем фильтр в проекте со своим названием(в данном примере SDK)
Затем просто добавляем все из SDK\amx\ в ваш фильтр.

Время компиляции плагина! Если у вас все получилось, то у вас должно быть в проекте 2 пустых файла. Копируйте следующий код в соотвествующие файлы

.cpp файл
PHP:
#include "SDK\amx\amx.h"
#include "SDK\plugincommon.h"


typedef void (*logprintf_t)(char* format, ...);


logprintf_t logprintf;
extern void *pAMXFunctions;


cell AMX_NATIVE_CALL HelloWorld(AMX* amx, cell* params)
{
    logprintf("This was printed from the Test plugin! Yay!");
    return 1;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() 
{
    return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) 
{
    pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t) ppData[PLUGIN_DATA_LOGPRINTF];

    logprintf(" * Test plugin was loaded.");
    return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
    logprintf(" * Test plugin was unloaded.");
}

AMX_NATIVE_INFO PluginNatives[] =
{
    {"HelloWorld", HelloWorld},
    {0, 0}
};

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx ) 
{
    return amx_Register(amx, PluginNatives, -1);
}


PLUGIN_EXPORT int PLUGIN_CALL AmxUnload( AMX *amx ) 
{
    return AMX_ERR_NONE;
}
.def файл
PHP:
EXPORTS
    Supports
    Load
    Unload
    AmxLoad
    AmxUnload
Рассмотрим код

Теперь вас никто не держит за ручку. Дальнейшая часть будет рассматривать структуры, функции, дефайны, которые есть в SDK. Объяснение будет только касательно SDK. Подразумевается понимание С++.

.def файл

Что же такое .def файл? Да, да это эксклюзивная фича Visual Studio, но... что он делает? Все просто. Он сообщает линкеру о том, какой код нужно связать. Все просто

Что за "Exports"?

Export это оператор, который экспортирует материал в нашу программу. Если мы не экспортируем материал, то для нашего плагина он останется в private.

Экспортированные функции:

Всего есть 6 функции которые необходимо экспортировать. Мы, в нашем проекте. используем всего 5. Не беспокойтесь об PLUGIN_EXPORT, и PLUGIN_CALL, в этой теме ничего не останется без внимания.

Supports() - Эта функция говорит о том, на каких возможностях будет построен наш плагин. Обычно мы используем 3 суппорт флага в плагинах: SUPPORTS_VERSION, SUPPORTS_AMX_NATIVES, и SUPPORTS_PROCESS_TICK.

Load(void**) Функция LOAD довольно проста. вызывается когда плагин получает команду загрузки от сервера и получает список адресов для работы. Два индекса для использования PLUGIN_DATA_AMX_EXPORTS, и PLUGIN_DATA_LOGPRINTF.

Unload() Вызывается когда плагин выгружается. (сервер выключается).

AmxLoad(AMX*) Вызывается когда новая абстрактная машина подгружается на сервер. Вызывается при каждой загрузке фс или гм! Поэтому не самая лучшая идея хранить 1 экземпляр АМХ на весь плагин, используйте очередь/вектор/лист. В этой функции мы также задаем НАТИВЫ, которые позже снабжают PAWN.

AmxUnload(AMX*) Вызывается когда гм или фс выгружается. Если вы храните экземпляр AMX следует, то его удалить. Иначе у вас будет экземпляр с несуществующими гмами/фсами.

ProcessTick() Функция, которая вызывается каждый раз, когда серверный цикл проходит итерацию


Дефайны и структуры

Веселье начинается ЗДЕСЬ! Вы наверное заметили что мы использовали МАССУ структур и прочих определений. Если вы раньше не писали плагины для SA-MP, то вам этот код покажется тяжелым. Самое время пролить свет на это.

cell Ячейка - это синоним для простоты использования. PAWN предлагает поддержку 16bit, 32bit, и 64bit целых чисел. Синоним "ячейка" будет всегда верным размером, в то время как целое число(int) может и не быть. Обычно, в плагинах SA-MP это синоним 32bit целых чисел


AMX Имя все объясняет - экземпляр AMX. Эта структура хранит массу информации касающейся данных и другую амх информацию. Эта структура должна быть представлена во всех нативных функциями с указателем на данные, что она передает; Без этой информации мы не сможем понять, какой скрипт вызвал нативную функцию, а темболее какие параметры передал.

PLUGIN_EXPORT читай как "PLUGIN_EXTERN_C".

PLUGIN_EXTERN_C Если вы используете С++ компилятор, то это что-то вроде "дополнительный С". Все это для совместимости с С. Когда это определение используется, С++ использует С линковку.

PLUGIN_CALL Это определение сообщает С/++ какое соглашение вызова следует использовать в экспортированной фнукции. Если вы делаете для windows, то это определяется как __stdcall, в других случаях просто как ничего или стандартное соглашение вызова.

SUPPORTS_VERSION Это определение используется в бит-маске, которую возвращает функция Supports(). Этот флаг определяет какие версии сервера поддерживаются

SUPPORTS_AMX_NATIVES Еще одно определение, которое возвращает функция "Supports()". Любой плагин, который использует функции встроенной абстрактной машины должен использовать этот флаг. Иначе будет ошибка

SUPPORTS_PROCESS_TICK Последний флаг. Если вы собираетесь использовать функцию "ProcessTick()" то вы должны указать это в бит-маске.

PLUGIN_DATA_AMX_EXPORTS Это используется как индекс в мульти-мерных массивах. Индекс передается в Load. Фактически содержит таблицу функции АМХ. Все плагины должны использовать этот индекс чтобы работать с таблицей функции pAMXFunctions.

PLUGIN_DATA_LOGPRINTF Другой индекс, который мы получаем в Load. Этот индекс содержит адресс функции logprintf, аналог printf в pawn.

AMX_NATIVE_INFO Эта структура используется в смеси с amx_Register. В ней содержится стринг - название новой натив функции и указатель на ее адресс.

АМХ функции.

Функции хорошо описаны в pawn-implementers-guide, который можно скачать тут . Вместо того, чтобы описывать каждую функции своими словами, я просто переведу нужные для плагинописания

Если тема будет популярна, оформлю этот раздел.
 
Сверху Снизу