Русское сообщество по скриптингу

Работа с куками через MOTD окно

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

Работа с куками через MOTD окно

Сообщение Nixon133 » 13 фев 2014, 18:08

Автор: Internal

Введение.
В этой статье я постараюсь объяснить как можно дать бан(блокировку какую-либо) по кукам через МОТД окно клиента. На STEAM клиенте может не работать! Для примера возьмём пермаментный бан. Для тестирования нам понадобится web-сервер с поддержкой PHP и MYSQL.
Как будет работать блокировка? При бане открываем игроку MOTD окно, вместо обычной странички показываем ему свою с баном. При последующем подключение, будет идти проверка так же через MOTD окно(со своим скриптом), если кука отсутствует(нету бана) значит всё хорошо, если есть значит игрок забанен и кикаем его. Ну и так, думаю начнём. :acute:

Сначала обычное подключение библиотек:

[pawn]
  1.  

  2. #include <amxmodx>

  3. #include <sqlx>

  4.  
[/pawn]

Теперь нужно хукнуть MOTD окно:

[pawn]
  1.  

  2. public plugin_init () {

  3.         // Регистрируем нужное событие

  4.         register_message (get_user_msgid ("MOTD"),"start_motd")

  5. }
[/pawn]

Создадим булевую, с помощью неё будем отсеивать все хукнутые MOTD окна(нам нужен только первый)

[pawn]
  1. static bool: g_bMotdStatus[33]
[/pawn]

Создаём подключения к Mysql серверу:

[pawn]
  1.  

  2. static Handle: g_hSql

  3. static Handle: g_hSqlConnect
[/pawn]

Подключаемся к Mysql:

[pawn]
  1.  

  2. public plugin_init () {

  3.         // Через секунду подключаемся

  4.         set_task (1.0,"mysql_integration")

  5. }
[/pawn]

Здесь само подключение :crazy: :

[pawn]
  1.  

  2. public mysql_integration () {

  3.         // Переменные под возможные ошибки

  4.         new sError[64];

  5.         new iError;

  6.         // Подключаемя к mysql

  7.         g_hSql = SQL_MakeDbTuple("localhost","root","","database");

  8.         g_hSqlConnect = SQL_Connect(g_hSql,iError,sError,127);

  9.         // Если неудача - выводим сообщение об ошибке

  10.         if (g_hSqlConnect == Empty_Handle) server_print ("Error #%d (%s)",iError,sError);

  11.         // Иначе информируем об успешном подключении

  12.         else server_print ("Successfully connected to database");

  13. }
[/pawn]

Во время подключения игрока, обнуляем переменную:

[pawn]
  1.  

  2. public client_connect (id) {

  3.         // Обнуляем переменную статуса показа мотд

  4.         g_bMotdStatus[id] = false;

  5. }
[/pawn]

Теперь показ MOTD окна игроку. Инфа о клиенте будет отсылаться на web-сервер, отсылаются его userid методом get:

[pawn]
  1.  

  2. public start_motd(const iMsg, const iMsgDest, const iEnt) {

  3.         // Если начальное мотд-окно уже поазывалось - выходим из подпрограммы

  4.         if (g_bMotdStatus[iEnt] == true) return PLUGIN_CONTINUE;

  5.         // Формируем url к скрипту

  6.         new sBuffer[256];

  7.         format (sBuffer,255,"http://localhost/check.php?id=%d",sBuffer,get_user_userid (iEnt));

  8.         // Показываем игроку мотд

  9.         show_motd (iEnt,sBuffer,"Counter-Strike server");

  10.         g_bMotdStatus[iEnt] = true;

  11.         // Блокируем стандартное окно

  12.         return PLUGIN_HANDLED;

  13. }
[/pawn]

С этим вроде всё, но еще вернёмся!
Теперь web-сервер.

Файл check.php - его задача проверить игрока на куку отвечающую за бан и внести в mysql таблицу индекс кука.
Но так как у нас идеализированный пример мы поступим проще - в таблице будет только одно поле и оно будет называться userid, в это поле попадет индекс игрока в случае наличии куки.

Подключаемся к БД:

[pawn]
  1.  

  2. <?php

  3.  

  4. // Подключаемся к mysql (хост, пользователь, пароль)

  5. $connect = mysql_connect ("localhost","root","");

  6. // В случае неудачи выводим на экран ошибки

  7. if (!$connect) die ('Error: '.mysql_error());

  8. // Подключаемся к базе данных (название бд, указатель на подключение)

  9. $database = mysql_select_db ("database",$connect);

  10. // В случае неудачи выводим на экран ошибки

  11. if (!$database) die ('Error: '.mysql_error());

  12.  

  13. ?>

  14.  
[/pawn]

Если же кука есть, то вносим индекс в таблицу:

[pawn]
  1. <?php

  2.  

  3. if (strlen ($_COOKIE['ban_info'])) {

  4.         // Формируем запрос к бд

  5.         $buffer =

  6.         "INSERT INTO table (userid)

  7.         VALUES (".$_GET['id'].")";

  8.         // Вносим новый индекс в мускуль-таблицу

  9.         $query = mysql_query ($buffer);

  10. }

  11.  

  12. ?>

  13.  
[/pawn]

Опять к серверной части. Через три секунды после показа MOTD окна запускаем проверку на индекс в БД:

[pawn]
  1. set_task (3.0,"check_user_ban_info",iEnt)
[/pawn]

Запрос к Mysql:

[pawn]
  1. public check_user_ban_info (id) {

  2.         // Переменная под возможные ошибки

  3.         new sError[64];

  4.         // Подготавливаем запрос к бд

  5.         new Handle: hQuery = SQL_PrepareQuery (g_hSqlConnect,"SELECT * FROM table WHERE id = '%d'",get_user_userid (id));

  6.         if (!SQL_Execute (hQuery)) {

  7.                 // Если неудача - выводим информацию об ошибках

  8.                 SQL_QueryError (hQuery,sError,127);

  9.                 server_print ("Error: %s",sError);

  10.         }

  11.         else {

  12.                 // Иначе если такой индекс присутствует - значит игрок в бане

  13.                 if (SQL_NumResults (hQuery)) server_cmd ("kick #%d",get_user_userid (id));

  14.         }

  15.         SQL_FreeHandle(hQuery);

  16. }

  17.  
[/pawn]

Теперь нужно создать алгоритм блокировки.
Для этого будем показывать MOTD окно по команде /banme

Регистрация команды:

[pawn]
  1. register_clcmd ("say /banme","ban_action");
[/pawn]

Алгоритм блокировки:

[pawn]
  1. public ban_action (id) {

  2.         // Показываем motd с алгоритмом бана

  3.         show_motd (id,"http://localhost/ban.php","You are banned!");

  4.         // Через 4 секунды выкидываем забаненного игрока с сервера

  5.         set_task (4.0,"kick_banned_player",id);

  6. }

  7.  
[/pawn]

И в конце кик игрока:

[pawn]
  1. public kick_banned_player (id) {

  2.         server_cmd ("kick #%d",get_user_userid (id));

  3. }

  4.  
[/pawn]

Теперь опять к web части.
Файл ban.php - устанавливает клиенту куку.

[pawn]
  1. <?php

  2.  

  3. // Устанавливаем куку

  4. setcookie ("ban_info","true",time () + 999999);

  5.  

  6. ?>

  7.  
[/pawn]

На серверной стороне отключаемся от Mysql, на всякий случай :acute:

[pawn]
  1. public plugin_end () {

  2.         // При смене карты разрываем соединение с mysql

  3.         if (g_hSqlConnect != Empty_Handle) {

  4.                 SQL_FreeHandle (g_hSql);

  5.                 SQL_FreeHandle (g_hSqlConnect);

  6.         }

  7.         return PLUGIN_HANDLED;

  8. }

  9.  
[/pawn]

Так же обработка таймеров при отключение игрока:

[pawn]
  1. public client_disconnect (id) {

  2.         // Если есть таймеры связанные с отключающимся клиентом - отменить их

  3.         if (task_exists (id)) remove_task (id);

  4. }
[/pawn]

Обязательно при старте сервера / смене карты очищать таблицу, т.к. индексы пойдут по второму кругу:

[pawn]
  1. // Готовим запрос для очистки таблицы

  2. new Handle: hQuery = SQL_PrepareQuery (g_hSqlConnect,"DELETE FROM test");

  3. if (!SQL_Execute (hQuery)) {

  4.         // Если неудача - информируем об ошибках

  5.         SQL_QueryError (hQuery,sError,127);

  6.         server_print ("[BAN SYSTEM] Error: %s",sError);

  7. }

  8. else SQL_FreeHandle(hQuery);

  9.  
[/pawn]


Ну а теперь готовые кодики:

Серверная часть:

[pawn]
  1. #include <amxmodx>

  2. #include <sqlx>

  3.  

  4. static bool: g_bMotdStatus[33];

  5.  

  6. static Handle: g_hSql;

  7. static Handle: g_hSqlConnect;

  8.  

  9. public plugin_init () {

  10.         register_message (get_user_msgid ("MOTD"),"start_motd");

  11.         set_task (1.0,"mysql_integration");

  12.         register_clcmd ("say /banme","ban_action");

  13. }

  14.  

  15. public mysql_integration () {

  16.         new sError[64];

  17.         new iError;

  18.         g_hSql = SQL_MakeDbTuple("localhost","root","","database");

  19.         g_hSqlConnect = SQL_Connect(g_hSql,iError,sError,127);

  20.         if (g_hSqlConnect == Empty_Handle) server_print ("Error #%d (%s)",iError,sError);

  21.         else server_print ("Successfully connected to database");

  22.         new Handle: hQuery = SQL_PrepareQuery (g_hSqlConnect,"DELETE FROM test");

  23.         if (!SQL_Execute (hQuery)) {

  24.                 SQL_QueryError (hQuery,sError,127);

  25.                 server_print ("[BAN SYSTEM] Error: %s",sError);

  26.         }

  27.         else SQL_FreeHandle(hQuery);

  28. }

  29.  

  30. public start_motd(const iMsg, const iMsgDest, const iEnt) {

  31.         if (g_bMotdStatus[iEnt] == true) return PLUGIN_CONTINUE;

  32.         new sBuffer[256];

  33.         format (sBuffer,255,"http://localhost/check.php?id=%d",sBuffer,get_user_userid (iEnt));

  34.         show_motd (iEnt,sBuffer,"Counter-Strike server");

  35.         g_bMotdStatus[iEnt] = true;

  36.         set_task (3.0,"check_user_ban_info",iEnt);

  37.         return PLUGIN_HANDLED;

  38. }

  39.  

  40. public client_connect (id) {

  41.         g_bMotdStatus[id] = false;

  42. }

  43.  

  44. public check_user_ban_info (id) {

  45.         new sError[64];

  46.         new Handle: hQuery = SQL_PrepareQuery (g_hSqlConnect,"SELECT * FROM table WHERE id = '%d'",get_user_userid (id));

  47.         if (!SQL_Execute (hQuery)) {

  48.                 SQL_QueryError (hQuery,sError,127);

  49.                 server_print ("Error: %s",sError);

  50.         }

  51.         else {

  52.                 if (SQL_NumResults (hQuery)) server_cmd ("kick #%d",get_user_userid (id));

  53.         }

  54.         SQL_FreeHandle(hQuery);

  55. }

  56.  

  57. public ban_action (id) {

  58.         show_motd (id,"http://localhost/ban.php","You are banned!");

  59.         set_task (4.0,"kick_banned_player",id);

  60. }

  61.  

  62. public kick_banned_player (id) {

  63.         server_cmd ("kick #%d",get_user_userid (id));

  64. }

  65.  

  66. public plugin_end () {

  67.         if (g_hSqlConnect != Empty_Handle) {

  68.                 SQL_FreeHandle (g_hSql);

  69.                 SQL_FreeHandle (g_hSqlConnect);

  70.         }

  71.         return PLUGIN_HANDLED;

  72. }

  73.  

  74. public client_disconnect (id) {

  75.         if (task_exists (id)) remove_task (id);

  76. }

  77.  
[/pawn]

Файл check.php(проверка на куку)

[pawn]
  1. <?php

  2.  

  3. $connect = mysql_connect ("localhost","root","");

  4. if (!$connect) die ('Error: '.mysql_error());

  5. $database = mysql_select_db ("database",$connect);

  6. if (!$database) die ('Error: '.mysql_error());

  7. if (strlen ($_COOKIE['ban_info'])) {

  8.         $buffer =

  9.         "INSERT INTO table (userid)

  10.         VALUES (".$_GET['id'].")";

  11.         $query = mysql_query ($buffer);

  12. }

  13.  

  14. ?>
[/pawn]

Файл ban.php(устанавливает куку)

[pawn]
  1. <?php

  2.  

  3. setcookie ("ban_info","true",time () + 999999);

  4.  

  5. ?>

  6.  
[/pawn]

PS. Статью не я придумал, она писалась на другом сайте.(если нужно могу оставить линк, без проблем)
Статью писал для ознакомления и новичков. :zzz:
скуйп - legaalize
Аватара пользователя
Nixon133
 
Сообщения: 476
Зарегистрирован: 13 ноя 2012, 12:20
Благодарил (а): 107 раз.
Поблагодарили: 56 раз.
Опыт программирования: Больше трех лет
Языки программирования: C, Pawn

Re: Работа с куками через MOTD окно

Сообщение Maped » 08 мар 2014, 05:09

Аватара пользователя
Maped
 
Сообщения: 98
Зарегистрирован: 06 июл 2010, 21:02
Откуда: Hu>KHuu HoBropog
Благодарил (а): 42 раз.
Поблагодарили: 1 раз.

Re: Работа с куками через MOTD окно

Сообщение caesar2k » 14 ноя 2014, 22:29

Подниму старую тему.
Имею очень поверхностные знания по скриптингу,и возникает 2 вопроса по коду ТСа.
1. Срабатывает ли функция public client_connect (id) { g_bMotdStatus[id] = false; } при смене карты, т.е. игроки действительно коннектятся заново? и если да...
2. Как стабильно сработает данный код с подключением и выборкой из БД, если после смены карты будет 32 обращения единовременно.
Аватара пользователя
caesar2k
 
Сообщения: 10
Зарегистрирован: 15 авг 2013, 23:38
Благодарил (а): 2 раз.
Поблагодарили: 0 раз.
Опыт программирования: Меньше месяца
Языки программирования: Counter-Strike 1.6

Re: Работа с куками через MOTD окно

Сообщение Safety1st » 15 ноя 2014, 04:07

1. Срабатывает.
2. Будет фриз, насколько ощутимый - зависит от задержки при общении с БД.


Не забывайте, что
Nixon133 писал(а):Статью писал для ознакомления и новичков
Другими словами - код максимально прост и функционал примитивен.
GoldSrc Gaming Community
Аватара пользователя
Safety1st
 
Сообщения: 1958
Зарегистрирован: 08 окт 2011, 05:41
Откуда: Moscow
Благодарил (а): 1690 раз.
Поблагодарили: 933 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

Re: Работа с куками через MOTD окно

Сообщение caesar2k » 15 ноя 2014, 11:32

Safety1st писал(а):1. Срабатывает.
2. Будет фриз, насколько ощутимый - зависит от задержки при общении с БД.


Тогда подскажите как оптимизировать эту часть кода. ведь бессмысленно проверять игроков на новой карте, если они были проверены на прошлой.
Первое что пришло на ум, использовать userid, т.к. не меняется при реконнекте, но тогда у меня получатся тысячи ненужных переменных...
Второе, если userid не меняется при реконнекте, то мб есть функции которые срабатывают при коннекте, и НЕ срабатывают при РЕконнекте, и заменить client_connect() на нее.
Аватара пользователя
caesar2k
 
Сообщения: 10
Зарегистрирован: 15 авг 2013, 23:38
Благодарил (а): 2 раз.
Поблагодарили: 0 раз.
Опыт программирования: Меньше месяца
Языки программирования: Counter-Strike 1.6

Re: Работа с куками через MOTD окно

Сообщение Polarhigh » 15 ноя 2014, 11:38

если использовать асинхронные запросы, то фризов не будет
Аватара пользователя
Polarhigh
 
Сообщения: 1006
Зарегистрирован: 04 май 2010, 17:41
Благодарил (а): 131 раз.
Поблагодарили: 388 раз.
Опыт программирования: Больше трех лет

Re: Работа с куками через MOTD окно

Сообщение caesar2k » 20 ноя 2014, 15:40

Да, наверное я бред спросил. Функции только для рекконнекта клиента видимо нет.
Но все-таки, как можно лишний раз не производить проверку, если у игрока не сменился userid. Подскажите алгоритм.


PolarHIGH писал(а):если использовать асинхронные запросы, то фризов не будет

Спс. Взял на заметку, но вышестоящая задача все равно актуальна(для меня).
Аватара пользователя
caesar2k
 
Сообщения: 10
Зарегистрирован: 15 авг 2013, 23:38
Благодарил (а): 2 раз.
Поблагодарили: 0 раз.
Опыт программирования: Меньше месяца
Языки программирования: Counter-Strike 1.6

Пред.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6

cron