Вводный блок с комментариями
Лучшее место комментариев к плагину это самое его начало, в комментарий желательно поместить всю необходимую информацию о палгине, такую как:
- Что он делает
- Настройки
- Команды для игроков и администраторов
- Журнал изменений
- ...
Блок комментариев можно и пропустить, если вы не собираетесь выкладывать в паблик свой плагн, но даже для себя его лучше сделать, смотрится как кто солиднее.
copyleft уведомление является ненужным, но хорошо бы по чаще напоминать людям, что все плагины AMXX – распространяются под лицензий GPL'd.
Вот пример, не плохого на мой взгляд вводного комментария:
/***********************************************
* Access.ini for players (example: "nick or ip" "pass" "flags")
* Denied.ini for subnets (example: "ip" "mask" "flags")
*
* if #define SUBNET_REVERSE is comment then
* Access.ini list of nicks,who can join from banned subnets
* Denied.ini list of banned subnets
*
* if #define SUBNET_REVERSE is uncomment then
* Access.ini list of nicks,who can't join from access subnets
* Denied.ini list of access subnets,others are banned
*
* ATTENTION!!! HELP for BAN (for that who don't know)
* copyleft http://ipcalc.dewil.ru/
*
************************************************
*
* CREATE TABLE bansubnets (
* id int(11) NOT NULL auto_increment,
* subipaddr VARCHAR(32) NOT NULL,
* bitmask VARCHAR(2) NOT NULL,
* flags VARCHAR(32) NOT NULL,
* comment TEXT NOT NULL,
* PRIMARY KEY (id));
*
************************************************/
Макросы и Препроцессор
Честно говоря, сам не до конца понимаю все что с этим связано, по этому буквально в двух словах об этом разделе.
После комментариев логичнее всего сразу же включить в плагин все необходимые вам инклюды
#include <amxmodx>А так же константы:
#define MAX_ITEMS 10Обратите внимание, что константы записывать лучше заглавными буквами, что бы не путать их с переменными.
Единственное исключение для макро-функциональных определений:
#define MyNewIsUserAlive(%1) is_user_alive( %1 )Это является приемлемым, потому что макрос по существу действует как функция.
Добавление отступов
Весь плагин состоит из функций, в некоторых функциях есть условия, в нутрии этих условий циклы и такое вложение может быть многократным, что бы это все было наглядно видно, принято делать отступ для каждой вложенной функции или условия, ниже приведу 2 примера для наглядности:
Код без отступов:
public client_connect(id) {
if (is_user_bot(id) || access(id, ADMIN_RESERVATION) || is_user_hltv(id)) {
return PLUGIN_HANDLED
} else {
if (sql == Empty_Handle) {
server_print(NotConnectMSG, Tag, error)
if (file_exists(AccessFile)) {
new Areaddata[101], Alen, Apos = 0
if (!file_size(AccessFile, 0)) {
Denied(id)
server_print(EmptyPlMSG, Tag)
} else {
while(read_file(AccessFile, Apos++, Areaddata, 100, Alen)) {
if (Areaddata[0] == ';' || !Alen)
continue
parse(Areaddata, Ident, 31, Apass, 31, UFlags, 21)
if (equal(Ident, name) || equal(Ident, ip)) {
plrAccess(id)
}
}
}
}
}
}
}
И код с отступами:
public client_connect(id)
{
if (is_user_bot(id) || access(id, ADMIN_RESERVATION) || is_user_hltv(id))
{
return PLUGIN_HANDLED
} else
{
if (sql == Empty_Handle)
{
server_print(NotConnectMSG, Tag, error)
if (file_exists(AccessFile))
{
new Areaddata[101], Alen, Apos = 0
if (!file_size(AccessFile, 0))
{
Denied(id)
server_print(EmptyPlMSG, Tag)
} else
{
while(read_file(AccessFile, Apos++, Areaddata, 100, Alen))
{
if (Areaddata[0] == ';' || !Alen)
continue
parse(Areaddata, Ident, 31, Apass, 31, UFlags, 21)
if (equal(Ident, name) || equal(Ident, ip))
{
plrAccess(id)
}
}
}
}
}
}
}
Теперь думаю, вы наглядно увидели разницу и преимущество отступов.
А так же с отступами легче уследить за всеми кавычками, с которыми у новичков очень много проблем.
Просто возьмите себе за правило, весь код заключенный межу кавычками { code }
Должен имеет отступ, если в нутрии этого кода появились еще такие же кавычки, то этот код будет уже с двойным отступом и так по мере вложенности.
А так же, что бы открывающая и закрывающая кавычки были на одном уровне, что облегчит вам поиск незакрытой кавычки и сделает еще более понятным код.
Название для функций.
Что бы код был как можно более легко читаемый, все функции должны иметь, понятные названия и при этом красиво написаны.
Вот пример красивой и понятной функции:
public EventDeathMsg()
А могло бы быть так:
public deathmsg()
В первом варианте сразу видно, что это за функция, а во втором? Тоже видно, но не так очевидно и не красиво.
Добавление префикса типа переменной.
Если плагин меньше 100 строк, то в принципе ни каких особых проблем не будет, а вот если более 1000, сможете ли вы запомнить все переменные? А их тип? Сомневаюсь…
Для начала выделим глобальные переменные префиксом g
new gMyVariable
Или
new g_MyVariable
Объявлять глобальные переменные лучше каждую отдельно, это облегчит поиск в случае необходимости.
new g_MyVariable
new g_MyOtherVariable
в место
new g_MyVariable, g_MyOtherVariable
Для глобальных переменных я бы рекомендовал второй способ.
"Венгерская запись" типов переменных (HN).
Некоторые люди также тегируют свои имена переменных их типом:
- g или g_ - глобальные переменные
- p или p_ pointers
- i - целые числа/ячейки
- f или fl – дробные числа
- sz - строки
- b – bools Булевые переменные
- h - дескрипторы
- v - векторы (не стандарт к HN, но все еще полезный)
- fn – функция
Вот несколько примеров тегированных переменных:
// a global cell
new g_iKills
// a global float
new Float:g_flSpeed
// a bool
new bool:bFlag
// a function
public fnEventResetHUD()
// a pointer
new g_pCvar
В сложных плагинах это поможет вам не запутаться в огромном количестве переменных и массивов.
Комментарии.
Комментарии к коду очень важны, даже если вы не следуете ни каким правилам или системе по называнию переменных и функций, но ваши комментарии хорошо описывают каждый блок, то и вам самим и другим пользователям вашего кода, будет доставлять наслаждение работать с вашим плагином.
Комментарии бывают 2х видов
Многострочный
/*
this is a nested comment
this is a nested comment
this is a nested comment
*/
И однострочный
// this is a nested comment
Главное запомните что PAWN не поддерживает вложенные комментарии:
/*
this is the first comment
/* this is a nested comment */
*/
Обратили внимание на то, что последние закрывающие комментарий символы */ подсвечены зеленым? Это кА КрАЗ из за того что не поддерживаются вложенные комментарии, будьте внимательны!
Пробелы или пустые строки
Что бы код был легко читаем, он должен быть разбит на блоки, вы скажете что он и так разбит на функции и условия, но и тут не все так просто, можно еще немного разбить, вот пример:
MyFunction()
{
new id = random_num( 1, 13 )
user_kill( id )
set_pcvar_num( p_MyCvar, 9 )
}
Как видно в функции MyFunction происходит 2 не зависящих друг от друга дела, но к первому дело еще необходимо создать переменную, так как эти две строчки напрямую взаимосвязаны они и стоят в плотную, а вот следующая функция не связанна с ними ни как и стоит через пустую стоку, что визуально делит код на части.
В заключении хотел сказать, что у каждого человека есть свой индивидуальный стиль, но если каждый будет следовать общепринятым стилям, то разбираться в чужом коде всем станет легче. Все что выше было изложено, не является, каким либо правилом или законом, это всего лишь рекомендации. Поверьте, они написаны не от балды, а по опыту и вам же будет легче, если вы с самого начала будете писать плагины правильно.
Это что-то вроде урока чистописания.