[FAQ] Мой первый плагин. По-Perl-о.

FAQ. Ответы на часто задаваемые вопросы.

Модератор: 4epT

Правила форума
Этот раздел является руководством и тут разрешено оставлять сообщения лишь для уточнения и внесения корректив в существующие материалы. Для вопросов существует ряд других разделов.
Аватара пользователя
DeniZka
Разработчик
Сообщения: 410
Зарегистрирован: Ср ноя 15, 2006 6:36 pm
Сервер RO:: rRO AsgardRO
Откуда: Mos-Cow Citadel
Контактная информация:

[FAQ] Мой первый плагин. По-Perl-о.

Сообщение DeniZka »

Пишем свой первый плагин под OpenKore.

Если вы осилили язык макросов и хотите выжимать из OpenKore больше соков то эта статья для вас.

Сам я не сильный оратор и правописание местами хромает, поэтому статья будет держаться в ключе "Меньше теории и больше практики".

Немного Perl. Начало.
Начинаем написание плагина с создания MyFirstPlugin.pl файла в папке plugins OpenKore.
Открываем файл текстовым редактором и вводим следующие строки:

package MyFirstPlugin;
print "Hello World\n";

\n - это символ перевода каретки на новую строку, всеравно что [Enter] нажать при вводе текста.
Сохраняем, запускаем OpenKore и глядим первые строки загрузки и таинственно улыбаемся.

Переменные.
Hello World - это статичное слово, давайте сделаем его более динамичным. Введем переменные (они начинаются с символа $ ). Попробуем применить к ним разные операции и отобразить их по-разному.

Код: Выделить всё

package MyFirstPlugin; 
my $var1 = 'Hello';
my $Var1 = 'World';
my $count1 = 2;
my $count2 = '3';

my $summ = $count1 + $count2;
$summ = 'Itogo: ' . $summ;

print "$var1 not equal $Var1\n";
print '$var1 not equal '.$Var1."\n";
print $summ."\n";
Создание новой локальной переменной начинается с my. При использовании её в дальнейшем my больше не нужен.
Запустив OpenKore с этим примером вы увидите много интересных вещей
1) переменная $var1 и $Var1 - совсем разные
2) ковычки "" и '' содержат текст, но отбражают содержимое текста по разному.
3) знак . - Знак конкатинации строчек (объединения строки)
4) Переменная $count2 сначала была строкой, а затем, при подсчете суммы, превратилась в число. А переменная $summ сначала была числом, а потом превратилась в строку.
Складывая буквы через + вы получите ошибку.

Массивы.
Массив - это индексированная очередь переменных. Обозначаются массивы префиксом @.

Код: Выделить всё

package MyFirstPlugin; 
my @mass = ('Hello', 'World', '4', 7);
print @mass."\n";
print "@mass\n";
my $count = $mass[2] + $mass[3];
print "$mass[0] $mass[1], $count\n";
pop @mass;
pop @mass;
push @mass, 'again';
print "@mass\n";
первый print рапечатает нам число элементов в массиве, второй - сам массив, третий - отдельные элементы массива
pop - выдергивает последний элемент массива, push добавляет еще один элемент.


Хэши.
Хеши - это ассоциативные массивы. В отличии от обычных массивов для доступа к содержимому используются ключи а не индексы. Объявляются хеши через знак %

Код: Выделить всё

package MyFirstPlugin; 
my %data = (
	'var1' => 12,
	'var2' => 2,
	'massiv' => ['World', 'Hello'],
);
my $count = $data{var1} / $data{var2};
print "$data{massiv}[1] $data{massiv}[0], $count\n"

Ну вот. Базовые вещи, которыми я пользуюсь, вроде рассмотрены.

Едем глубже.
Как вы, наверное, заметили, плагин исполняется сразу, как только перл его загрузил и в этот момент сделать нам ничего особенного не удастся. Для того, чтобы плагин срабатывал в нужное время, в OpenKore предусмотрены дырки для крюков плагина(Вызов Hook-а). Найти эти дырки можно в .pm файлах папки \src и выглядят они как Plugins::callHook(<Параметры для плагина>).
За какую дырку цепляться зависит от поставленной задачи.

Давайте поставим две простенькие задачи:
1) В основном цикле (в конце) программы выводить уже заезженную фразу "Hello World";
2) Зарегистрировать новую комманду "shutup_now". И при её вызове остановить вывод;

И так, для начала найдем то место, куда мы закинем крюк плагина.
в \src\functions.pl находим следующее:
Plugins::callHook('mainLoop_post');
main - есть главнй, Loop - есть цикл. Похоже это то что нам надо. Сюда и будем кидать Хук.

Создается он следующей коммандой:
my $hook = Plugins::addHook('куда_цепляем', \&НАЗВАНИЕ_ПРОЦЕДУРЫ);
-> В созданную переменную $hook записывается дескриптор хука. Дескриптор - это уникальный идентификационный номер, который регистрируется в OpenKore. Имея в зубах эту переменную Хук можно вызвать или отрубить или еще какую-нить пакость сделать.(Выглядит как многоцифирчатое число)
-> 'куда_цепляем' - в нашем случае мы цепляем хук на 'mainLoop_post'
-> \& - этот символ отсылает нас на код подпрограммы выоплнения хука с называнием "НАЗВАНИЕ_ПРОЦЕДУРЫ"

Положим, что хук создали мы, а че в нем делается не написали. Так сделаем это:
sub НАЗВАНИЕ_ПРОЦЕДУРЫ {
<код подпрограммы>
}
Вот и все.

Теперь реализуем первую часть задачи:

Код: Выделить всё

package ShutUP;
my $hook = Plugins::addHook('mainLoop_post', \&ShowPhraseInLoop);
sub ShowPhraseInLoop {
	print "Hello World\n";
}
Давайте введем теперь творческого безобразия:
Будем использовать функцию vocalString, которая находится в Utils.pm. Она генерит случайную фразу заданной длинны.
Поскольку мы будем использовать нестандартную процедуру находящуюся в другом файле. Этот файл нам нужно подключить в наш плагин. Делается это коммандой use.

Код: Выделить всё

package ShutUP;
use Utils;
my $hook = Plugins::addHook('mainLoop_post', \&ShowPhraseInLoop);
sub ShowPhraseInLoop {
	my $mystring = vocalString(10);
	print "$mystring\n";
}
Есть альтернативный способ использования комманды из другого файла без use
my $mystring = Utils::vocalString(10);

Вот, наша программа несет какую-то ахинею в консоль, теперь это надо прекращать как-то. Реализуем задачу номер два. Куда ставить хук? Так как мы собираемся добавлять новую комманду, то ищем вызов хука в разделе комманд src\Commands.pm. Вродь логично. Но там отсутствует callHook на регистрацию комманды. Да. Зато там есть процедура позваляющая добавить новую комманду. Называется она register. Бааа, там даже есть указание как её пристроить! Ну поехали.
В предыдущем варианте плагина вы наверное заметили что в консоль что-либо ввести почти не возможно. Мешает комманда print. Меняем её на комманду message из Log.pm. При это м Log нужно добавить в раздел use.

Код: Выделить всё

package ShutUP;
use Utils;
use Log qw(message);

my $hook = Plugins::addHook('mainLoop_post', \&ShowPhraseInLoop);
my $cmdhook = Commands::register(['shutup_now', "The way to shutup vocalsting", \&RunCommand]);

sub ShowPhraseInLoop {
	my $mystring = vocalString(10);
	message "$mystring\n";
}

sub RunCommand {
	Plugins::delHook($hook);
}
Я аккуратненько все отсортировал

Сверху используемые файлы
Потом дескрипторы хуков
а потом уже подпрограммы этих хуков

Вот и все, вот и получился наш первый плагин.

Пожалуй расскажу еще пару вещей из Perl. Это надо знать

Код: Выделить всё

my $var1;
sub Procedure {
	$var1 доступен
	$var2 не доступен
	my $var2;
	$var2 доступен
	{	my $var3
		$var1, $var2 доступны
	}
	$var3 не доступен
}
$var1 доступен
$var2, $var3 не доступен
И так далее. Вешняя часть не видит внутренние действия. А внутренняя видит внешние.

Про define и undef
1) if(defined $var) тоже, что и if($var), if($var != 0), if($var ne ""), if($var eq любые символы), if($var == любые цифры)
2) if(!defined $var) тоже, что и if(!$var), if($var == 0), if($var eq ""), if($var ne любые символы), if($var != любые цифры)
define - значит переменная(массив, хеш) несет в себе какие-то данные. в числовом выражении - не ноль. В строковом не пустая строка
undef - наоборот В числовом выражении - ноль, в строковом -пустая строка
Вложения
perl.zip
Учебник по Perl. Не особо в удобном формате, но оч приятный на восприятие.
(1.02 МБ) 301 скачивание
Последний раз редактировалось DeniZka Чт янв 24, 2008 8:23 pm, всего редактировалось 1 раз.
Изображение
1t 1$ t00 900d d4y 2 d1e

?(???)?(???)?( ?Д?)?
Аватара пользователя
piroJOKE
Модератор
Сообщения: 8205
Зарегистрирован: Сб ноя 04, 2006 2:20 am
Сервер RO:: localhost
Откуда: Molvania

Сообщение piroJOKE »

Определения у тебя конешно для начинающих самое оно. Цытирую:
"Массив - это куча переменных"
"Хеши - это сложные струтуры которые могут содержать (...) все че хочешь"

:ROFL:
Use brain against brain, ai against ai... · как правильно задавать вопросы · faq · download
Аватара пользователя
Click
Разработчик
Сообщения: 1564
Зарегистрирован: Сб ноя 04, 2006 11:30 pm
Сервер RO:: clickro.sytes.net
Откуда: Великий Новгород
Контактная информация:

Сообщение Click »

:good:
Аватара пользователя
Kissa2k
Профессионал
Сообщения: 1304
Зарегистрирован: Пн дек 04, 2006 8:33 pm

Сообщение Kissa2k »

Хеши это ассоциативные массивы :)
Аватара пользователя
piroJOKE
Модератор
Сообщения: 8205
Зарегистрирован: Сб ноя 04, 2006 2:20 am
Сервер RO:: localhost
Откуда: Molvania

Сообщение piroJOKE »

DInvalid писал(а):В перле хэш - это таблица, к полям которой обращаются по ключам. И это самый нормальный способ работать с изменяемым списком различных данных. {но при переборе всех значений} хэша его ключи возвращаются не в порядке занесения а в его внутреннем порядке...
Use brain against brain, ai against ai... · как правильно задавать вопросы · faq · download
Аватара пользователя
Kissa2k
Профессионал
Сообщения: 1304
Зарегистрирован: Пн дек 04, 2006 8:33 pm

Сообщение Kissa2k »

Ну просто кто изучал PHP, тому понятнее термин ассоциативный массив.
Аватара пользователя
DeniZka
Разработчик
Сообщения: 410
Зарегистрирован: Ср ноя 15, 2006 6:36 pm
Сервер RO:: rRO AsgardRO
Откуда: Mos-Cow Citadel
Контактная информация:

Сообщение DeniZka »

Спокойстви граждане.
Новичку главное что? Новичку главное наглядность.
Я думаю с этим я справился.
Изображение
1t 1$ t00 900d d4y 2 d1e

?(???)?(???)?( ?Д?)?
excellent
Энтузиаст
Сообщения: 66
Зарегистрирован: Ср янв 03, 2007 4:20 am

Сообщение excellent »

У меня появился вопросик. Мне надо чтобы при определённых условиях плагин отключал АИ. Я сделал чтобы срабатывала команда:
print "GM near! AI off\n";

И написал автомакрос:

automacro GMnear {
console /GM near! AI off/
call {
do c param pam pam
pause 1
do eval Utils::Win32::playSound('E:\Games\Ragnarok\Bots\beep.wav');
do ai off
}
}

При имитации определённых условий надпись GM near! AI off в консоле пишется, но автомакрос её не улавливает. Если с какого левого чара боту написать GM near! AI off, то автомакрос сработает.

Не подскажите, как прямо с плагина отключить АИ или почему макрос не улавливает консоль при использовании print?
Аватара пользователя
Kissa2k
Профессионал
Сообщения: 1304
Зарегистрирован: Пн дек 04, 2006 8:33 pm

Сообщение Kissa2k »

Можно использовать функцию run() из пространства имен Commands.
Например:
Commands::run("ai of");
excellent
Энтузиаст
Сообщения: 66
Зарегистрирован: Ср янв 03, 2007 4:20 am

Сообщение excellent »

Kissa2k
Спасибо большое, всё здорово, всё работает! Только "ai off" с 2 "f" =)
Аватара пользователя
4epT
macro-маньячина
Сообщения: 2792
Зарегистрирован: Чт дек 21, 2006 1:23 pm
Сервер RO:: 4game
Discord: ya4ept#8494
Контактная информация:

Сообщение 4epT »

excellent у тя проблемы с макросом или же с плагом? о_О
Быстро и качественно напишу конфиг (макрос)! Стучи!
¤ Свежий бот ¤ Config checker ¤ Manual ¤
Изображение
Изображение
excellent
Энтузиаст
Сообщения: 66
Зарегистрирован: Ср янв 03, 2007 4:20 am

Сообщение excellent »

Вообще я правил Receive.pm... Я просто хотел узнатть можно ли отключить АИ бота прямо с кода, если нет то почему не работает макрос. Мне сказали как выключить прямо с кода, поэтому макрос не понадобился =)
Ответить