Продолжение статьи про mysql. В этой статье я вам расскажу, как отправлять и получать данные для определенного игрока
Описание:
В данной статье мы рассмотрим технику отправки и получение данных для определенного игрока на сервере. Для того, чтобы вы поняли о чем речь для начала прочитайте ЭТО
Нам потребуется:
1. Игровой сервер
2. Хостинг с mysql на борту
3. Мозг
4. 2 руки ( Желательно )
Приступаем:
Приступаем:
1. Создаем пустой *sma файл и вставляем туда начальный шаблон
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "password")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
}
Как вы помните – мы делали это в прошлом уроке и мы будем работать именно с ним, чтобы не терять время.
2. Создаем необходимые массивы для данных. В нашем случаи их будет 3.
new g_ActiveMysql //Будет хранить в себе информацию о подключении к базе данных
new szPlayerData[33] //Будет хранить в себе данные которые мы будет отправлять/получать
new szPlayerMysql[33] //Будет хранить в себе данные, что игрок присутствует в базе
В итоге наш код должен выглядеть так:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
new g_ActiveMysql
new szPlayerData[33]
new szPlayerMysql[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "password")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
}
3. Как вы поняли – массив g_ActiveMysql создан не просто так. Он поможет нам определить совершилось из подключение к базе или нет. Если этого массива не будет, то будут ошибки при подключении игроков к серверу, ведь игроки подключаются к серверу быстрее, чем база. Для этого нам нужно в функцию MYSQL_Load добавить в самый конец g_ActiveMysql = true
браузерные игры – разновидность онлайн игр, не требующих установки на компьютер и работающих непосредственно через браузер.
В итоге наш код должен выглядеть так:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
new g_ActiveMysql
new szPlayerData[33]
new szPlayerMysql[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "password")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
g_ActiveMysql = true
}
4. Далее мы приступает к получению данных. Получать их мы будет во время коннекта игрока. Поэтому создаем функцию коненкта игрока. Выглядит она так
public client_connect(id) //Игрок подключается к серверу
{
if(!is_user_bot(id) || !is_user_hltv(id)) //Если игрок не бот и не хлтв
{
set_task(1.0, "CheckPlayer", id) //Запускаем функцию проверки его в базе через секунду
}
}
В итоге наш код должен выглядеть так:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
new g_ActiveMysql
new szPlayerData[33]
new szPlayerMysql[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "password")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
g_ActiveMysql = true
}
public client_connect(id)
{
if(!is_user_bot(id) || !is_user_hltv(id))
{
set_task(1.0, "CheckPlayer", id)
}
}
5. Ну вот мы создали функцию коннекта игрока, теперь нужно создать сам обработчик. Выглядеть он будет так
public CheckPlayer(id)
{
if(!g_ActiveMysql) //Если ещё нет коннекта
{
set_task(1.0, "PlayerCheck", id) //Пробуем через секунду
}
new szError[512] //Массив, который будет содержать ошибки
new szName[32], szMYSQLName[32] //Данные для хранение ников из базы и сервера
new Handle:szSelect //Массив отправки запроса в базу
szSelect = SQL_PrepareQuery(MYSQL_Connect, "SELECT * FROM players")
//SELECT - означает, что мы узнаем
//* - получаем все данные
//FROM - Откуда
//players - название таблицы
if(!SQL_Execute(szSelect)) //Если во время отправки произошла ошибка
{
SQL_QueryError(szSelect, szError, charsmax( szError )) //Узнаем ошибку
set_fail_state( szError ) //Отключаем плагин с указанной ошибкой
}
get_user_name(id, szName, charsmax( szName )) //Узнаем имя, записываем в массив
while(SQL_MoreResults(szSelect)) //Получаем данные из mysql
{
SQL_ReadResult(szSelect, 1, szMYSQLName, charsmax( szMYSQLName )) //Узнаем ник через mysql
if(equal(szMYSQLName, szName)) //Если ник совпадает
{
szPlayerData[id] = SQL_ReadResult(szSelect, 2) //Записываем в массив данные, которые получили
szPlayerMysql[id] = true //Говорим, что игрок есть в базе
break //Заканчиваем цикл
}else{ //А если совпадение не было
SQL_NextRow(szSelect) //Переходим к следующей строчке
}
}
if(!szPlayerMysql[id]) //Если игрока нет в базе, то создаем его
{
new Handle:szInsert //Массив отправки запроса в базу
szInsert = SQL_PrepareQuery(MYSQL_Connect, "INSERT INTO `players` (`name`, `data`) VALUES ('%s', '0');", szName) //Отправляем в базу его ник
if(!SQL_Execute(szInsert)) //Если во время отправки произошла ошибка
{
SQL_QueryError(szInsert, szError, charsmax( szError )) //Узнаем ошибку
set_fail_state( szError ) //Отключаем плагин с указанной ошибкой
}
szPlayerMysql[id] = true //Говорим, что игрок есть в базе
}
}
В итоге наш код должен выглядеть так:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
new g_ActiveMysql
new szPlayerData[33]
new szPlayerMysql[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "password")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
g_ActiveMysql = true
}
public client_connect(id)
{
if(!is_user_bot(id) || !is_user_hltv(id))
{
set_task(1.0, "CheckPlayer", id)
}
}
public CheckPlayer(id)
{
if(!g_ActiveMysql)
{
set_task(1.0, "PlayerCheck", id)
}
new szError[512]
new szName[32], szMYSQLName[32]
new Handle:szSelect
szSelect = SQL_PrepareQuery(MYSQL_Connect, "SELECT * FROM players")
if(!SQL_Execute(szSelect))
{
SQL_QueryError(szSelect, szError, charsmax( szError ))
set_fail_state( szError )
}
get_user_name(id, szName, charsmax( szName ))
while(SQL_MoreResults(szSelect)) //Получаем данные из mysql
{
SQL_ReadResult(szSelect, 1, szMYSQLName, charsmax( szMYSQLName ))
if(equal(szMYSQLName, szName))
{
szPlayerData[id] = SQL_ReadResult(szSelect, 2)
szPlayerMysql[id] = true
break
}else{
SQL_NextRow(szSelect)
}
}
if(!szPlayerMysql[id])
{
new Handle:szInsert
szInsert = SQL_PrepareQuery(MYSQL_Connect, "INSERT INTO `players` (`name`, `data`) VALUES ('%s', '0');", szName)
if(!SQL_Execute(szInsert))
{
SQL_QueryError(szInsert, szError, charsmax( szError ))
set_fail_state( szError )
}
szPlayerMysql[id] = true
}
}
Ну чтож. Мы сделали всё, для получение данных из базы.Но ведь данным нужно туда как-то попасть, поэтому нам нужна ещё функция отправки данных. Разумеется вы можете этого не делать и добавлять данные прямиком в базе. Всё зависит, что вы собираетесь делать.
6. Создаем функцию сохранение. Для наглядности мы будет сохранять убийства игрока. Разумеется мы можете сохранять любое другое значение. Сохранять будет во время дисконнекта. Выглядеть это будет так
public client_disconnect(id)
{
new szError[512] //Массив, который будет содержать ошибки
new szName[32] //Данные для хранение ника
new Handle:szUpdate //Массив отправки запроса в базу
get_user_name(id, szName, charsmax( szName )) //Узнаем ник
szPlayerData[id] = szPlayerData[id] + get_user_frags(id) //Записываем фраги игрока в массив
szUpdate = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `data` = '%i' WHERE `players`.`name` = '%s';", szPlayerData[id], szName)
//UPDATE - означает, что мы обновляем данные
//`players` - Где будем обновлять
//`data` = '%i' - Что будем обновлять
//WHERE - Кому
//`players`.`name` = '%s' - Нашему игроку по имени
//, szPlayerData[id], szName - Данные, которые отправятся
if(!SQL_Execute(szUpdate)) //Если во время отправки произошла ошибка
{
SQL_QueryError(szUpdate, szError, charsmax( szError )) //Узнаем ошибку
set_fail_state( szError ) //Отключаем плагин с указанной ошибкой
}
}
В итоге наш код должен выглядеть так:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
new g_ActiveMysql
new szPlayerData[33]
new szPlayerMysql[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "password")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
g_ActiveMysql = true
}
public client_connect(id)
{
if(!is_user_bot(id) || !is_user_hltv(id))
{
set_task(1.0, "CheckPlayer", id)
}
}
public CheckPlayer(id)
{
if(!g_ActiveMysql)
{
set_task(1.0, "PlayerCheck", id)
}
new szError[512]
new szName[32], szMYSQLName[32]
new Handle:szSelect
szSelect = SQL_PrepareQuery(MYSQL_Connect, "SELECT * FROM players")
if(!SQL_Execute(szSelect))
{
SQL_QueryError(szSelect, szError, charsmax( szError ))
set_fail_state( szError )
}
get_user_name(id, szName, charsmax( szName ))
while(SQL_MoreResults(szSelect)) //Получаем данные из mysql
{
SQL_ReadResult(szSelect, 1, szMYSQLName, charsmax( szMYSQLName ))
if(equal(szMYSQLName, szName))
{
szPlayerData[id] = SQL_ReadResult(szSelect, 2)
szPlayerMysql[id] = true
break
}else{
SQL_NextRow(szSelect)
}
}
if(!szPlayerMysql[id])
{
new Handle:szInsert
szInsert = SQL_PrepareQuery(MYSQL_Connect, "INSERT INTO `players` (`name`, `data`) VALUES ('%s', '0');", szName)
if(!SQL_Execute(szInsert))
{
SQL_QueryError(szInsert, szError, charsmax( szError ))
set_fail_state( szError )
}
szPlayerMysql[id] = true
}
}
public client_disconnect(id)
{
new szError[512]
new szName[32]
new Handle:szUpdate
get_user_name(id, szName, charsmax( szName ))
szPlayerData[id] = szPlayerData[id] + get_user_frags(id)
szUpdate = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `data` = '%i' WHERE `players`.`name` = '%s';", szPlayerData[id], szName)
if(!SQL_Execute(szUpdate))
{
SQL_QueryError(szUpdate, szError, charsmax( szError ))
set_fail_state( szError )
}
}
7. Ну и заключающий штрихом нашего плагина будет функция, чтобы узнать общее количество наших фрагов. Выглядит это так
public ShowData(id)
{
client_print(id, print_chat, "you all frags = %i", szPlayerData[id]) //Выводим игроку в чат данные
}
Ну и создаем команду.в plugin_init добавляем
register_clcmd("say /showdata", "ShowData")
В итоге наш код должен выглядеть так:
#include <amxmodx>
#include <amxmisc>
#include <sqlx>
#define PLUGIN "MYSQL(ya-cs.ru)"
#define VERSION "1.0"
#define AUTHOR "CrAsH"
new Handle:MYSQL_Tuple
new Handle:MYSQL_Connect
new g_Cvar[5]
new g_ActiveMysql
new szPlayerData[33]
new szPlayerMysql[33]
public plugin_init()
{
register_plugin(PLUGIN, VERSION, AUTHOR)
g_Cvar[1] = register_cvar("amx_mysql_hostname", "127.0.0.1")
g_Cvar[2] = register_cvar("amx_mysql_username", "root")
g_Cvar[3] = register_cvar("amx_mysql_password", "vertigo")
g_Cvar[4] = register_cvar("amx_mysql_database", "testmysql")
register_clcmd("say /showdata", "ShowData")
set_task(1.0, "MYSQL_Load")
}
public MYSQL_Load()
{
new szHostname[30], szUsername[30], szPassword[30], szDatabase[30]
new szError[512], szErr
get_pcvar_string(g_Cvar[1], szHostname, charsmax( szHostname ))
get_pcvar_string(g_Cvar[2], szUsername, charsmax( szUsername ))
get_pcvar_string(g_Cvar[3], szPassword, charsmax( szPassword ))
get_pcvar_string(g_Cvar[4], szDatabase, charsmax( szDatabase ))
MYSQL_Tuple = SQL_MakeDbTuple(szHostname, szUsername, szPassword, szDatabase)
MYSQL_Connect= SQL_Connect(MYSQL_Tuple, szErr, szError, charsmax( szError ))
if(MYSQL_Connect == Empty_Handle)
set_fail_state( szError )
g_ActiveMysql = true
}
public client_connect(id)
{
if(!is_user_bot(id) || !is_user_hltv(id))
{
set_task(1.0, "CheckPlayer", id)
}
}
public CheckPlayer(id)
{
if(!g_ActiveMysql)
{
set_task(1.0, "PlayerCheck", id)
}
new szError[512]
new szName[32], szMYSQLName[32]
new Handle:szSelect
szSelect = SQL_PrepareQuery(MYSQL_Connect, "SELECT * FROM players")
if(!SQL_Execute(szSelect))
{
SQL_QueryError(szSelect, szError, charsmax( szError ))
set_fail_state( szError )
}
get_user_name(id, szName, charsmax( szName ))
while(SQL_MoreResults(szSelect)) //Получаем данные из mysql
{
SQL_ReadResult(szSelect, 1, szMYSQLName, charsmax( szMYSQLName ))
if(equal(szMYSQLName, szName))
{
szPlayerData[id] = SQL_ReadResult(szSelect, 2)
szPlayerMysql[id] = true
break
}else{
SQL_NextRow(szSelect)
}
}
if(!szPlayerMysql[id])
{
new Handle:szInsert
szInsert = SQL_PrepareQuery(MYSQL_Connect, "INSERT INTO `players` (`name`, `data`) VALUES ('%s', '0');", szName)
if(!SQL_Execute(szInsert))
{
SQL_QueryError(szInsert, szError, charsmax( szError ))
set_fail_state( szError )
}
szPlayerMysql[id] = true
}
}
public client_disconnect(id)
{
new szError[512]
new szName[32]
new Handle:szUpdate
get_user_name(id, szName, charsmax( szName ))
szPlayerData[id] = szPlayerData[id] + get_user_frags(id)
szUpdate = SQL_PrepareQuery(MYSQL_Connect, "UPDATE `players` SET `data` = '%i' WHERE `players`.`name` = '%s';", szPlayerData[id], szName)
if(!SQL_Execute(szUpdate))
{
SQL_QueryError(szUpdate, szError, charsmax( szError ))
set_fail_state( szError )
}
}
public ShowData(id)
{
client_print(id, print_chat, "you all frags = %i", szPlayerData[id]) //Выводим игроку в чат данные
}
Ну вот. Мы закончили с плагином. Осталось лишь создать таблицу и попробывать. Как сделать импорт данных в базу вы сможете узнать в прошлой статье. Я лишь приведу структуру таблицы. Выглядит она так
CREATE TABLE `players`
(
`id` INT NOT NULL AUTO_INCREMENT , //Присваиваем идентификатор каждому запросу
`name` VARCHAR( 32 ) NOT NULL , //Ячейка записи ника
`data` VARCHAR( 32 ) NOT NULL , //Ячейка для записи данных
PRIMARY KEY ( `id` ) //Говорим, что идентификатором является ячейка id
);
Статья написана специально для сайта ya-cs.ru
Ром ответь в лс или зайди с скайп или аську
Ответь мне лучше в скайп , я уже написал тебе
ром я щас 14:21 в скайп зашел , зайди тоже в скайп или icq
[b2. Хостинг с mysql на борту]crash94[/b], Зачем? если есть Denwer то можно и на компе Mysql сделать
Хорошая статья))) Serg.elit за денвер +1