Активный
- Тема Автор
- #1
MySQL позволяет хранить данные игроков в базе данных. Разберем подключение и использование.
Подключение библиотеки
Подключение к базе данных
Выполнение запросов
Колбэки запросов
Сохранение данных игрока
Безопасность: экранирование строк
Асинхронные запросы
Пример: система регистрации
Важные моменты:
- Всегда экранируйте пользовательский ввод
- Используйте mysql_tquery для асинхронности
- Проверяйте ошибки подключения
- Закрывайте кеш после использования (cache_delete)
- Используйте индексы для ускорения запросов
MySQL обеспечивает надежное хранение данных!
Подключение библиотеки
Код:
#include <a_mysql>
#include <mysql>
Подключение к базе данных
Код:
new MySQL:g_SQL;
public OnGameModeInit()
{
g_SQL = mysql_connect("localhost", "user", "password", "database");
if(g_SQL == MYSQL_INVALID_HANDLE || mysql_errno(g_SQL) != 0)
{
print("Ошибка подключения к MySQL");
SendRconCommand("exit");
return 1;
}
print("Подключение к MySQL успешно");
// Создание таблиц
mysql_query(g_SQL, "CREATE TABLE IF NOT EXISTS players (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(24), money INT, level INT)");
return 1;
}
public OnGameModeExit()
{
mysql_close(g_SQL);
return 1;
}
Выполнение запросов
Код:
// Простой запрос без результата
mysql_query(g_SQL, "UPDATE players SET money = 1000 WHERE name = 'Player1'");
// Запрос с обработкой результата
mysql_query(g_SQL, "SELECT * FROM players WHERE name = 'Player1'", "OnPlayerDataLoaded", "i", playerid);
Колбэки запросов
Код:
forward OnPlayerDataLoaded(playerid);
public OnPlayerDataLoaded(playerid)
{
new rows = cache_num_rows();
if(rows > 0)
{
new name[24], money, level;
cache_get_value_name(0, "name", name);
cache_get_value_name_int(0, "money", money);
cache_get_value_name_int(0, "level", level);
PlayerInfo[playerid][pMoney] = money;
PlayerInfo[playerid][pLevel] = level;
SendClientMessage(playerid, -1, "Данные загружены");
}
else
{
// игрок не найден, создаем нового
CreateNewPlayer(playerid);
}
cache_delete();
return 1;
}
Сохранение данных игрока
Код:
SavePlayerData(playerid)
{
new query[256], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(query, sizeof(query),
"UPDATE players SET money = %d, level = %d WHERE name = '%e'",
GetPlayerMoney(playerid),
PlayerInfo[playerid][pLevel],
name);
mysql_query(g_SQL, query);
}
CreateNewPlayer(playerid)
{
new query[256], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(query, sizeof(query),
"INSERT INTO players (name, money, level) VALUES ('%e', %d, %d)",
name,
GetPlayerMoney(playerid),
PlayerInfo[playerid][pLevel]);
mysql_query(g_SQL, query);
}
LoadPlayerData(playerid)
{
new query[128], name[MAX_PLAYER_NAME];
GetPlayerName(playerid, name, sizeof(name));
format(query, sizeof(query),
"SELECT * FROM players WHERE name = '%e'",
name);
mysql_query(g_SQL, query, "OnPlayerDataLoaded", "i", playerid);
}
Безопасность: экранирование строк
Код:
// Используйте '%e' вместо '%s' для экранирования
format(query, sizeof(query), "SELECT * FROM players WHERE name = '%e'", name);
// Или используйте mysql_escape_string
new escaped_name[48];
mysql_escape_string(name, escaped_name, g_SQL);
format(query, sizeof(query), "SELECT * FROM players WHERE name = '%s'", escaped_name);
Асинхронные запросы
Код:
// Используйте mysql_tquery вместо mysql_query для асинхронности
mysql_tquery(g_SQL, query, "OnPlayerDataLoaded", "i", playerid);
// Это не блокирует основной поток сервера
Пример: система регистрации
Код:
CMD:register(playerid, params[])
{
if(PlayerInfo[playerid][pLoggedIn])
{
SendClientMessage(playerid, -1, "Вы уже зарегистрированы");
return 1;
}
new password[64];
if(sscanf(params, "s[64]", password))
{
SendClientMessage(playerid, -1, "Использование: /register [пароль]");
return 1;
}
if(strlen(password) < 6)
{
SendClientMessage(playerid, -1, "Пароль должен быть не менее 6 символов");
return 1;
}
new query[256], name[MAX_PLAYER_NAME], hash[129];
GetPlayerName(playerid, name, sizeof(name));
// Хеширование пароля (используйте bcrypt или другой алгоритм)
WP_Hash(hash, sizeof(hash), password);
format(query, sizeof(query),
"INSERT INTO players (name, password, money, level) VALUES ('%e', '%e', 1000, 1)",
name, hash);
mysql_tquery(g_SQL, query, "OnPlayerRegistered", "i", playerid);
return 1;
}
forward OnPlayerRegistered(playerid);
public OnPlayerRegistered(playerid)
{
if(mysql_errno(g_SQL) != 0)
{
SendClientMessage(playerid, -1, "Ошибка регистрации");
return 1;
}
PlayerInfo[playerid][pLoggedIn] = true;
SendClientMessage(playerid, -1, "Регистрация успешна!");
return 1;
}
Важные моменты:
- Всегда экранируйте пользовательский ввод
- Используйте mysql_tquery для асинхронности
- Проверяйте ошибки подключения
- Закрывайте кеш после использования (cache_delete)
- Используйте индексы для ускорения запросов
MySQL обеспечивает надежное хранение данных!