PDA

Просмотр полной версии : [Руководство] Делаем своего "умного" OOG Кота


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

Благодарный
05.11.2013, 13:10
Ilyialat, отличная тема! Спасибо. Если из этого действительно можно сложить рабочего кота, то просто здорово! Тогда смогу этот код взять за основу для изучения и проб сварганить что-нибудь своё.

А на каком языке это написано?) Я не очень разбираюсь...)) Похоже на C++

Hilling
09.11.2013, 00:05
Смешно, конечно, но у меня не компилируется.. Ругается на строчку "if (pw.SelectedChar == default(Char))"
Error 1 Operator '==' cannot be applied to operands of type 'PWOOGFrameWork.Char' and 'PWOOGFrameWork.Char'

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); //Эту функцию мы напишем
};


}
:confused:

Ilyialat
11.11.2013, 17:15
Hilling, замените на if (pw.SelectedChar.Equals(default(PWOOGFrameWork.Cha r)))

DeadMaus_XD
15.12.2013, 10:28
Блин) Не опытному человеку тяжеловато зделать)

LOL MOUSE!!111
15.12.2013, 16:15
А на каком языке это написано?) Я не очень разбираюсь...)) Похоже на C++

Библиотека,как и программа написаны на языке C#.

Добавлено через 2 часа 36 минут
Собрал программу,начал отладку,авторизовался на сервере,но программа при попытке выбрать персонажа выдает,что персонажа нету.Проверял аккаунт и данные в программе,все валид.
В чем может быть проблема?

lileeth
17.12.2013, 21:15
LOL MOUSE!!111, гугли ip-адрес своего сервера, и меняй его в программе

DeadMaus_XD, тяжко не значит невозможно) несколько ненапряжных дней чтения самоучителей, и я собрал прогу, при том, что опыт в программировании на C# нулевой. Всё работает, автору спасибо. Даже зародилось несколько идей, но для их реализации придется курить маны дальше.

LOL MOUSE!!111
17.12.2013, 22:58
LOL MOUSE!!111, гугли ip-адрес своего сервера, и меняй его в программе


Спасибо.

Кстати,вот нашел лист с доменами всех серверов

Орион link1.pwonline.ru
Вега link2.pwonline.ru
Сириус link3.pwonline.ru
Мира link4.pwonline.ru
Таразед link5.pwonline.ru
Альтаир link6.pwonline.ru
Процион link7.pwonline.ru
Астра link8.pwonline.ru
Пегас link9.pwonline.ru
Антарес link10.pwonline.ru
Кассиопея link12.pwonline.ru
Лиридан link13.pwonline.ru
Андромеда link14.pwonline.ru
Омега link15.pwonline.ru
PVP1 pvplink1.pwonline.ru
PVP2 pvplink2.pwonline.ru
PVP3 pvplink3.pwonline.ru
PVP4 pvplink4.pwonline.ru

larin74
27.01.2014, 12:04
Очень жаль, что все это для меня - темный лес... так хотелось бы себе такого котобота)

может кто сможет сделать уже работающий и функционирующий exe файл со всеми функциями?)

Ilyialat
27.01.2014, 21:00
Очень жаль, что все это для меня - темный лес... так хотелось бы себе такого котобота)

может кто сможет сделать уже работающий и функционирующий exe файл со всеми функциями?)
NitroCat на форуме где-то есть, там и картинки предметов есть, и дизайн хороший, и всё рабочее :)

larin74
28.01.2014, 01:34
NitroCat на форуме где-то есть, там и картинки предметов есть, и дизайн хороший, и всё рабочее :)

пользуюсь) но здесь описан процесс создания бота, который ещё и деньги передаёт хозяину без входа на клиент)

ToRcH2565
28.01.2014, 19:25
:bayan: И такое сделано уже давно) только денег стоит) за удобство трэбэ платить)) или пользовать то что есть

Добавлено через 2 минуты
Кстати да, автору надо спасибку тыкнуть) именно благодоря этой статье я таки решился разобратся в ООГ, и сделать свою либу)) еслиб не тот кривой кусок не читающий 0х00 контейнеры... мне бы было лень переписать все на свой язык)))

FriendsKenny
01.02.2014, 17:09
Как поставить вещи на продажу?

Смотрел пакет, на каждый продаваемый предмет добавляется:

4 байта ид предмета, 4 байта хз чего, 4 байта количество и 4 байта цена

5F 21 00 00 FF FF 00 00 01 00 00 00 02 00 00 00

То что выделено красным, что туда записывается?

Ilyialat
01.02.2014, 18:10
Как поставить вещи на продажу?

Смотрел пакет, на каждый продаваемый предмет добавляется:

4 байта ид предмета, 4 байта хз чего, 4 байта количество и 4 байта цена

5F 21 00 00 FF FF 00 00 01 00 00 00 02 00 00 00

То что выделено красным, что туда записывается?
pkt.AddUInt32(item.Item.Id);
pkt.AddUInt32((uint)item.Item.Slot);
pkt.AddUInt32(item.Count);
pkt.AddUInt32(item.Price);
Если не ошибаюсь, то если предмет ставится на покупку, то слот как раз ставится FF FF, что есть UInt16.MaxValue или 65535.

_DVD_
23.04.2014, 12:33
А кто подскажет для данного примера вариант реализации проверки на разрыв связи и релог?)
И еще не нашел как логиниться усиленно.

sined1994111
05.05.2014, 21:03
все хорошо, но данный кот только ставит на продажу, а как же его дописать, что бы он еще и скупку ставил?

hangen
26.06.2014, 19:33
Народ помогите плизз, если этот код залить google apps engine, его можно будет использовать?

ToRcH2565
27.06.2014, 17:41
конечно можно) вы получите клиент пв прямо на гугловских серверах, он даже будет с графикой блек джеком и шлюхами)

thetester
25.07.2014, 18:16
У этого примера трейдера есть 1 нюанс, когда все предметы проданы, кот не выходит из режима торга, так и сидит с пустыми списками :)

Nursultan5
21.03.2015, 00:06
Почему я не вижу класса PWClient?

Kitsune
22.03.2015, 23:29
Почему я не вижу класса PWClient?
Подключи неймспейс PWOOGFrameWork.

Nursultan5
12.04.2015, 00:01
Подключи неймспейс PWOOGFrameWork.

using PWOOGFrameWork;

Это есть.
Но у меня есть класс private static Client pw.
А в примере выше есть использование такого класса как PWClient

и конструктора pw = new PWClient("178.22.90.52:29000", "Login", "Password");

Как получить доступ именно к этому классу?

Ololowa35
02.05.2015, 01:37
private static Client pw - Ты сам ответил на свой вопрос

skiritsa555
28.08.2016, 22:37
Кто-нибудь может помочь разобраться, как сейчас, с помощью oog, залогиниться(после введения иц способ из первого поста не работает).

_Wolf_
19.09.2016, 16:47
В ветке есть топик по авторизации без ИЦ (он правда на Delphi) и ничего сложного там нет.
Нововведение в том что, если в раннем клиенте надо было отправлять HMAC_MD5, то в данном случае лишь токен, который прислал тебе сервер.