Ilyialat
27.09.2013, 13:56
Здраствуйте! В этой теме я буду рассматривать создание умного бота на основе библиотеки PW OOG FrameWork ([Ссылки могут видеть только зарегистрированные и активированные пользователи]). Статья разбита на несколько частей, код отдельно от рассуждений.
Надеюсь, что вам понравится!
Часть 1: Рассуждение
Ну, сначала нам надо подумать о том, что мы хотим сделать. Ну хорошо, Вы решили, что это будет не игрок-казино, не игрок-непись, а просто-напросто торговый кот. Ну что же, приступим к размышлениям. Такую программу неплохо было бы создать, а то за такие деньги берут. Представим, что мы её сделали и запустили. Приближается ночь, а комп неприятно шумит. Сразу приходит на ум мысль - разместить кота на каком-нибудь сервере. Тут уже Вы обрадованы своей идеей, но через несколько минут понимаете - сервер стоит где-нибудь в гараже, а то вообще выделенный. Да и если он стоит в гараже, ходить к нему как-то лень. Тут Вы опять возвращаетесь к идее запуска проги на своём компьютере, но только днём. И тут вас посещает неприятная, очень неприятная мысль: Кот стоять будет, но... Чтобы забрать с него деньги, нужно включить ещё один клиент, зайти на персонажа, подождать входа в игру, начать торговлю, а если у вас PW без анфриза, то это очень и очень неудобно делать. И тут Вы объединяете 2 цели - он должен стоять на сервере и должен сам отдавать деньги. Вы вспоминаете про игровой чат и с радостью бежите строчить вашу прогу.
Впринципе, все Вы можно заменить на Я, ну да ладно :)
Часть 2: Структура
Вы бежите писать код, но вспоминаете о главном правиле программиста - лучше потратить немного времени на расписание структуры программы, а после этого столько же времени потратить на написание кода, чем просто писать код не зная о чём, потратив на это времени в 3 раза больше.
Итак, нужно расписать структуру, у нас будет несколько задач:
1. Зайти в игру
2. Подождать конца действия блокировки(чтобы мы могли торговать)
3. Слушаться только хозяина
4. (Немного подумав) Требовать пароль от хозяина
5. (Ещё немного подумав) Требовать пароль от хозяина, если он ничего не писал нам 2 минуты
6. (и т.д.) Выходить из кота и отдавать хозяину деньги
7. 6 => Входить в состояние кота
8. 7 => Получать список того, что есть в инвентаре
На 1-ую статью об использовании библиотеки хватит. Будет развиваться библиотека - будет больше возможностей, и отношение будет другим, а пока это просто пример.
Часть 3: Код
Теперь уже не так радостно, перейдя с бега на ход, мы пишем код.
Предпреждение: Будет развиваться библиотека - будет новая статья об усовершенствовании этого кота, так как пока его возможности и сам код можно оценить на 3 из 5.
Создадим консольное приложение, назовём его PWMiyau.
Объявляем переменные и константы, которые понадобятся:
private static PWClient pw;
private static Timer manageTimer; //Таймер выхода
private static bool isManageAuthorized; //Вошли ли мы
private const string manageNick = "Я"; //Ник того, кто может войти в систему
private const string managePassword = "12333"; //Его пароль
private const string persNick = "персонаж"; //Ник персонажа для выбора
Объявим главный метод бота:
static void Miyau()
{
}
Напишем инициализацию таймера:
manageTimer = new Timer(120000); //Таймер на 2 минуты
manageTimer.Elapsed += (object obj, ElapsedEventArgs e) =>
{
isManageAuthorized = false;
manageTimer.Stop();
};
Подсоединимся к серверу, выберем персонажа:
pw = new PWClient("178.22.90.52:29000", "Login", "Password");
pw.Connect();
pw.WaitLoginResult();
if (!pw.LoginResult)
{
Console.WriteLine("Облом");
return;
}
pw.WaitCharsObtaining();
foreach (var p in pw.Chars)
if (p.Name.StartsWith(persNick))
pw.SelectChar(p);
if (pw.SelectedChar == default(Char))
{
Console.WriteLine("Такого перса нет!");
return;
}
pw.WaitEntryInGame();
pw.Inventory.WaitObtaining();
Подпишемся на получение чата:
pw.ChatMessageReceived += (ChatMessage msg) =>
{
if (msg.Type != ChatMessageType.Private) //Пропускаем локальный и мировой чат
return;
if (!msg.SenderNick.Equals(manageNick)) //Пропускаем всех, кроме управляющего
return;
//Parse
string str = msg.Message;
if (!isManageAuthorized) //Если мы не авторизованы
{
if (!str.Equals(managePassword)) //Если пароль не совпадает - ничего не делаем
return;
isManageAuthorized = true; //Пароль совпал - мы в системе
manageTimer.Start(); //Обратный отсчёт
pw.SendPrivateMessage(manageNick, "Привет, хозяин! :)"); //Поздравление
return;
}
//Перезапуск таймера (сброс отсчёта)
manageTimer.Stop();
manageTimer.Start();
Parse(str); //Эту функцию мы напишем
}
Теперь будем писать функцию обработки команд
static void Parse(string str)
{
var cmd = str.ToLower().Split(' '); //Команда будет разделятся пробелами, сама она будет переведена в нижний регистр
string resp = string.Empty; //Это будет ответом
if (cmd[0].StartsWith("getinv")) //Получаем инвентарь, без комментариев
{
var inv = pw.Inventory;
for (byte i = 0; i < inv.List.Count; i++)
{
var item = inv.List[i];
if (item.IsEmpty) //Пустой слот
continue;
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.AppendFormat("Slot: {0} ", item.Slot);
sb.AppendFormat("Id: {0} ", item.Id);
sb.AppendFormat("Count: {0}", item.Count);
sb.AppendLine();
pw.SendPrivateMessage(manageNick, sb.ToString()); //Выстроится длинная очередь сообщений, которая будет отправлятся полминуты.
}
resp = "Всё, хозяин :)";
}
else if (cmd[0].StartsWith("starttrade")) //Начинаем торговлю, пример starttrade 0_5_99 1_3_888 предмет из слота 0, 5 штук по цене 99 + предмет 1, 3 штуки по цене 888
{
try
{
TradeTerm[] tt = new TradeTerm[cmd.Length - 1];
for (int i = 1; i < cmd.Length; i++) //парсим всё после starttrade
{
var spl = cmd[i].Split('_'); //slot_count_price = слот_количество_цена
tt[i - 1] = new TradeTerm(pw.Inventory.List[byte.Parse(spl[0])], uint.Parse(spl[1]), uint.Parse(spl[2]));
}
if (pw.IsLockActive)
{
resp = string.Format("Подожди, хозяин, осталось {0}c", (pw.UnlockTime - DateTime.Now).TotalSeconds);
goto sResp;
}
resp = "Хозяин, я теперь кот! =)";
pw.Inventory.Trade("Kot", tt);
}
catch //Просто лень
{
resp = "Где-то ошибка, перепроверь всё";
goto sResp;
}
}
else if (cmd[0].StartsWith("endtrade")) //Закрывает лавку
{
pw.CloseTrade();
resp = "Я уже не кот =(";
}
else if (cmd[0].StartsWith("dropgold")) //Выбросить деньги
{
try
{
uint gold = uint.Parse(cmd[1]);
pw.DropGold(gold);
}
catch //Лееееееееень
{
resp = "Где-то ошибка, перепроверь всё.";
goto sResp;
}
}
sResp:
if (resp != string.Empty)
pw.SendPrivateMessage(manageNick, resp);
}
Уффф, это всё.... А нет, есть ещё кое-что:
static void Main(string[] args)
{
Miyau();
while (true)
{
Console.WriteLine("y для завершение");
var key = Console.ReadKey();
if (key.Key == ConsoleKey.Y)
return;
}
}
Работа этого кота полностью протестирована, всё работает отлично. Есть очень много неудобств, но ведь это пример, на который потрачено полчаса.
P.S. Самое интересное то, что, не выложив исходников, я отбил 95% людей, хотя программа полностью расписанная :D
Надеюсь, что вам понравится!
Часть 1: Рассуждение
Ну, сначала нам надо подумать о том, что мы хотим сделать. Ну хорошо, Вы решили, что это будет не игрок-казино, не игрок-непись, а просто-напросто торговый кот. Ну что же, приступим к размышлениям. Такую программу неплохо было бы создать, а то за такие деньги берут. Представим, что мы её сделали и запустили. Приближается ночь, а комп неприятно шумит. Сразу приходит на ум мысль - разместить кота на каком-нибудь сервере. Тут уже Вы обрадованы своей идеей, но через несколько минут понимаете - сервер стоит где-нибудь в гараже, а то вообще выделенный. Да и если он стоит в гараже, ходить к нему как-то лень. Тут Вы опять возвращаетесь к идее запуска проги на своём компьютере, но только днём. И тут вас посещает неприятная, очень неприятная мысль: Кот стоять будет, но... Чтобы забрать с него деньги, нужно включить ещё один клиент, зайти на персонажа, подождать входа в игру, начать торговлю, а если у вас PW без анфриза, то это очень и очень неудобно делать. И тут Вы объединяете 2 цели - он должен стоять на сервере и должен сам отдавать деньги. Вы вспоминаете про игровой чат и с радостью бежите строчить вашу прогу.
Впринципе, все Вы можно заменить на Я, ну да ладно :)
Часть 2: Структура
Вы бежите писать код, но вспоминаете о главном правиле программиста - лучше потратить немного времени на расписание структуры программы, а после этого столько же времени потратить на написание кода, чем просто писать код не зная о чём, потратив на это времени в 3 раза больше.
Итак, нужно расписать структуру, у нас будет несколько задач:
1. Зайти в игру
2. Подождать конца действия блокировки(чтобы мы могли торговать)
3. Слушаться только хозяина
4. (Немного подумав) Требовать пароль от хозяина
5. (Ещё немного подумав) Требовать пароль от хозяина, если он ничего не писал нам 2 минуты
6. (и т.д.) Выходить из кота и отдавать хозяину деньги
7. 6 => Входить в состояние кота
8. 7 => Получать список того, что есть в инвентаре
На 1-ую статью об использовании библиотеки хватит. Будет развиваться библиотека - будет больше возможностей, и отношение будет другим, а пока это просто пример.
Часть 3: Код
Теперь уже не так радостно, перейдя с бега на ход, мы пишем код.
Предпреждение: Будет развиваться библиотека - будет новая статья об усовершенствовании этого кота, так как пока его возможности и сам код можно оценить на 3 из 5.
Создадим консольное приложение, назовём его PWMiyau.
Объявляем переменные и константы, которые понадобятся:
private static PWClient pw;
private static Timer manageTimer; //Таймер выхода
private static bool isManageAuthorized; //Вошли ли мы
private const string manageNick = "Я"; //Ник того, кто может войти в систему
private const string managePassword = "12333"; //Его пароль
private const string persNick = "персонаж"; //Ник персонажа для выбора
Объявим главный метод бота:
static void Miyau()
{
}
Напишем инициализацию таймера:
manageTimer = new Timer(120000); //Таймер на 2 минуты
manageTimer.Elapsed += (object obj, ElapsedEventArgs e) =>
{
isManageAuthorized = false;
manageTimer.Stop();
};
Подсоединимся к серверу, выберем персонажа:
pw = new PWClient("178.22.90.52:29000", "Login", "Password");
pw.Connect();
pw.WaitLoginResult();
if (!pw.LoginResult)
{
Console.WriteLine("Облом");
return;
}
pw.WaitCharsObtaining();
foreach (var p in pw.Chars)
if (p.Name.StartsWith(persNick))
pw.SelectChar(p);
if (pw.SelectedChar == default(Char))
{
Console.WriteLine("Такого перса нет!");
return;
}
pw.WaitEntryInGame();
pw.Inventory.WaitObtaining();
Подпишемся на получение чата:
pw.ChatMessageReceived += (ChatMessage msg) =>
{
if (msg.Type != ChatMessageType.Private) //Пропускаем локальный и мировой чат
return;
if (!msg.SenderNick.Equals(manageNick)) //Пропускаем всех, кроме управляющего
return;
//Parse
string str = msg.Message;
if (!isManageAuthorized) //Если мы не авторизованы
{
if (!str.Equals(managePassword)) //Если пароль не совпадает - ничего не делаем
return;
isManageAuthorized = true; //Пароль совпал - мы в системе
manageTimer.Start(); //Обратный отсчёт
pw.SendPrivateMessage(manageNick, "Привет, хозяин! :)"); //Поздравление
return;
}
//Перезапуск таймера (сброс отсчёта)
manageTimer.Stop();
manageTimer.Start();
Parse(str); //Эту функцию мы напишем
}
Теперь будем писать функцию обработки команд
static void Parse(string str)
{
var cmd = str.ToLower().Split(' '); //Команда будет разделятся пробелами, сама она будет переведена в нижний регистр
string resp = string.Empty; //Это будет ответом
if (cmd[0].StartsWith("getinv")) //Получаем инвентарь, без комментариев
{
var inv = pw.Inventory;
for (byte i = 0; i < inv.List.Count; i++)
{
var item = inv.List[i];
if (item.IsEmpty) //Пустой слот
continue;
StringBuilder sb = new StringBuilder();
sb.AppendLine();
sb.AppendFormat("Slot: {0} ", item.Slot);
sb.AppendFormat("Id: {0} ", item.Id);
sb.AppendFormat("Count: {0}", item.Count);
sb.AppendLine();
pw.SendPrivateMessage(manageNick, sb.ToString()); //Выстроится длинная очередь сообщений, которая будет отправлятся полминуты.
}
resp = "Всё, хозяин :)";
}
else if (cmd[0].StartsWith("starttrade")) //Начинаем торговлю, пример starttrade 0_5_99 1_3_888 предмет из слота 0, 5 штук по цене 99 + предмет 1, 3 штуки по цене 888
{
try
{
TradeTerm[] tt = new TradeTerm[cmd.Length - 1];
for (int i = 1; i < cmd.Length; i++) //парсим всё после starttrade
{
var spl = cmd[i].Split('_'); //slot_count_price = слот_количество_цена
tt[i - 1] = new TradeTerm(pw.Inventory.List[byte.Parse(spl[0])], uint.Parse(spl[1]), uint.Parse(spl[2]));
}
if (pw.IsLockActive)
{
resp = string.Format("Подожди, хозяин, осталось {0}c", (pw.UnlockTime - DateTime.Now).TotalSeconds);
goto sResp;
}
resp = "Хозяин, я теперь кот! =)";
pw.Inventory.Trade("Kot", tt);
}
catch //Просто лень
{
resp = "Где-то ошибка, перепроверь всё";
goto sResp;
}
}
else if (cmd[0].StartsWith("endtrade")) //Закрывает лавку
{
pw.CloseTrade();
resp = "Я уже не кот =(";
}
else if (cmd[0].StartsWith("dropgold")) //Выбросить деньги
{
try
{
uint gold = uint.Parse(cmd[1]);
pw.DropGold(gold);
}
catch //Лееееееееень
{
resp = "Где-то ошибка, перепроверь всё.";
goto sResp;
}
}
sResp:
if (resp != string.Empty)
pw.SendPrivateMessage(manageNick, resp);
}
Уффф, это всё.... А нет, есть ещё кое-что:
static void Main(string[] args)
{
Miyau();
while (true)
{
Console.WriteLine("y для завершение");
var key = Console.ReadKey();
if (key.Key == ConsoleKey.Y)
return;
}
}
Работа этого кота полностью протестирована, всё работает отлично. Есть очень много неудобств, но ведь это пример, на который потрачено полчаса.
P.S. Самое интересное то, что, не выложив исходников, я отбил 95% людей, хотя программа полностью расписанная :D