Доступ к готовым решениям

Переход в группу "Пользователь"

300.00
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

FAQ Как подключить MySQL базу с моду

OKStyle

Адвокат по делам семейным
- V I P -
Пользователь
Регистрация
4 Мар 2011
Сообщения
7,088
Лучшие ответы
226
Репутация
2,455
Награды
11
При разработке нового проекта иногда встаёт вопрос об упрощении работы со структурами данных, таких как аккаунты, транспорт, недвижимость и т.п. Одним из вариантов является перевод сервера на базы данных. Из коробки SAMP предлагает использовать SQLite, но в данной статье мы рассмотрим MySQL. Для начала необходимо определиться с версией и автором плагина СУБД, который вы хотите использовать. Советую брать самую актуальную и свежую версию. На сегодняшний момент это от BlueG. Этот плагин можно назвать "лорным", т.к. автором является один из бета-тестеров SA-MP, инклюд по названию схож с остальными САМПовскими, поддерживается и обновляется практически до сих пор.

Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!

ВНИМАНИЕ: дальнейшая инструкция актуальна только для рассматриваемой версии плагина. Работа в любой другой версии не гарантируется, т.к. меняются названия функций, порядок параметров и т.п.

Установка простая:
  • Файл a_mysql.inc кладём в папку pawno/includes/
  • Файл mysql.so/.dll кладём в папку plugins/
  • Файл log-core.so/.dll кладём в корневую папку сервера.
  • Файл libmariadb.dll кладём в корневую папку сервера*.
* .dll только для серверов на ОС Windows.

В конфигурационном файле (server.cfg) прописываем:
PHP:
plugins mysql.so
или добавляем в строку с уже имеющимися у вас плагинами.

Теперь в моде можно (хотя и не обязательно) указать данные для доступа к базе данных в виде дефайнов:
PHP:
#define SQL_HOST "localhost"
#define SQL_USER "пользователь_базы_данных"
#define SQL_DB "имя_базы_данных"
#define SQL_PASS "пароль_пользователя_базы_данных"
Как устанавливать phpmyadmin мы рассматривали в прошлом FAQ, поэтому скажу лишь, что при установке MySQL и PHPMyAdmin в списке баз данных появляются внутренние:
* PERFORMANCE_SCHEMA - обеспечивает способ осмотреть внутреннее выполнение сервера во времени выполнения.
* INFORMATION_SCHEMA - обеспечивает доступ к метаданным базы данных.

И ещё пара: phpmyadmin с настройками надстройки, а также mysql со служебными настройками баз данных в целом.

ВНИМАНИЕ: Если вы не видите служебные базы данных в списке, то для текущего пользователя недостаточно прав доступа, подключитесь под root.

ВНИМАНИЕ: Если вы каким-то образом накосячили и ваши шаловливые ручки почикали системные БД, то не всё потеряно. Команда mysql_upgrade (через PuTTY) восстановит базу данных performance_schema:
Код:
mysql_upgrade --user=root --password=password // или после равно пусто, если не ставили пароль root'у
Далее я буду рассматривать усложнённые варианты работы с базой данных, а через phpmyadmin будем только проверять результат. Метод этот был разработан для одного проекта. Он позволяет не иметь дамп базы данных для запуска сервера. Не хотел публиковать этот мануал, оставив в кулуарах соответствующих междусобойчиков, но попросил тот, кому нельзя отказать )))

Итак, после дефайнов по данным нашей базы данных (вводим туда свои, полученные при покупке хостинга), в OnGameModeInit пишем следующий код.

PHP:
new MySQL:SQL_HANDLE; // наш ID подключения, пригодится в запросах
public OnGameModeInit()
{
    SQL_HANDLE = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS, "MySQL"); // подключаемся к служебной базе данных mysql (регистр букв значения не имеет, по крайней мере на Windows, так что рекомендую писать так, как есть на самом деле, т.е.: mysql, а не как тут)
    mysql_query(SQL_HANDLE, "CREATE DATABASE IF NOT EXISTS "SQL_DB); // запрос создаёт нашу базу данных, если её не существовало ранее (запомните про это условие, потом поймёте почему)
    mysql_close(SQL_HANDLE); // отключаемся от служебной базы данных
    SQL_HANDLE = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS, SQL_DB); // соединяемся с только что созданной базой данных
    mysql_log(); // включаем логи работы с базой, а далее проверяем доступность соединения
    if(!mysql_errno()) print(!"Подключение к базе данных MySQL успешно создано!");
    else print(!"Невозможно подключиться к базе данных MySQL!");
    return 1;
}
Далее нужно создать структуру таблиц, которыми мы будем пользоваться.

Ниже принтов о подключении к БД пишем:
PHP:
mysql_tquery(SQL_HANDLE, !"SHOW TABLES LIKE 'factions'", !"OnFactionsTableExist", ""); // запрос покажет таблицы с названием factions в отдельном паблике
mysql_tquery(SQL_HANDLE, !"SHOW TABLES LIKE 'players'", !"OnPlayersTableExist", ""); // запрос покажет таблицу с названием players в отдельном паблике
Далее введём ещё один дефайн, от которого часто подгорают пуканы хейтеров. Никакие там пабликсы или фпаблики делать не нужно - это бред. У нас есть отличное зарезервированное слово VOID. Да, все, кто связан с другими языками программирования, знают, что оно означает, но поскольку в PAWN оно не используется, но подсвечивается, будем использовать именно его. Потому что я так сказал)

PHP:
#define void%0(%1) forward %0(%1); public %0(%1)
Далее расписываем ответ запроса по фракциям:
PHP:
void OnFactionsTableExist()
{
    new rows;
    if(!cache_get_row_count(rows)) // если в ответе на запрос не вернулось строк с ответом, т.е. таблицы не существует
    {
        mysql_tquery(SQL_HANDLE,
            "CREATE TABLE IF NOT EXISTS `factions`(\
                `ID` int(10) NOT NULL AUTO_INCREMENT, \
                `FactionName` varchar(32) NOT NULL, \
                `FColor` int(11) NOT NULL, \
                `FRank1` varchar(12) NOT NULL, \
                `FRank2` varchar(12) NOT NULL, \
                `FRank3` varchar(12) NOT NULL, \
                `FRank4` varchar(12) NOT NULL, \
                `FRank5` varchar(12) NOT NULL, \
                `FRank6` varchar(12) NOT NULL, \
                `FRank7` varchar(12) NOT NULL, \
                `FRank8` varchar(12) NOT NULL, \
                `FRank9` varchar(12) NOT NULL, \
                `FRank10` varchar(12) NOT NULL, \
            PRIMARY KEY (`ID`))",
        "", ""); // создаём структуру по вашему enum для фракций
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `factions`(\
            `FRank11` varchar(12) NOT NULL, \
            `FRank12` varchar(12) NOT NULL",
        "", ""); // если компилятор старый, и длина строки не позволяет писать всё в одном запросе, делить можно так, поскольку ALTER добавляет столбцы в таблице
        for(new i = 0; i < MAX_FACTIONS; i++)
        {
            Info_Faction[i][fName][0] = EOS; // мой enum по фракциям
            strcat(Info_Faction[i][fName], Names_Faction[i], 24);
            Info_Faction[i][fColor] = Colors_Faction[i]; // массив с цветами фракций
            mysql_tquery(SQL_HANDLE, "INSERT IGNORE INTO `factions` \
            (`FactionName`, `FColor`, `FRank1`, `FRank2`, `FRank3`, `FRank4`, `FRank5`, `FRank6`, `FRank7`, `FRank8`, `FRank9`, `FRank10`, `FRank11`, `FRank12`) VALUES \
            ('%e', '%d', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e')",
                Info_Faction[i][fName], Info_Faction[i][fColor],
                Info_Faction[i][fRank1], Info_Faction[i][fRank2], Info_Faction[i][fRank3], Info_Faction[i][fRank4], Info_Faction[i][fRank5], Info_Faction[i][fRank6],
                Info_Faction[i][fRank7], Info_Faction[i][fRank8], Info_Faction[i][fRank9], Info_Faction[i][fRank10], Info_Faction[i][fRank11], Info_Faction[i][fRank12]
            ); // заполняем базу данных данными из массивов, прописанных в моде
        }
        return 1;
    }
    return 1;
}
То же самое делаем с таблицей игроков. Тут покажу второй метод разделения запросов (по пабликам):
PHP:
void OnPlayersTableExist()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE,
            "CREATE TABLE IF NOT EXISTS `players`(\
                `ID` int(10) NOT NULL AUTO_INCREMENT, \
                `Username` varchar(24) NOT NULL, \
                `Password` varchar(65) NOT NULL, \
                `Email` varchar(128) NOT NULL, \
                `Birth` varchar(12) NOT NULL, \
                `RegDate` varchar(12) NOT NULL, \
                `History` int(5) NOT NULL, \
                `Sex` int(5) NOT NULL, \
                `Country` int(5) NOT NULL, \
                `Skin` int(5) NOT NULL, \
                `Level` int(5) NOT NULL, \
                `Exp` int(5) NOT NULL, \
                `Admin` int(5) NOT NULL, \
                `Interior` int(3) NOT NULL, \
            PRIMARY KEY (`ID`))",
        !"OnDataBaseCreateEnd", "");
        return 1;
    }
    return 1;
}
void OnDataBaseCreateEnd()
{
    new rows;
    if(!cache_get_row_count(rows)) // я думаю это условие можно убрать, т.к. возврат строк был только для главного запроса в OnGameModeInit
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `VirtualWorld` int(6) NOT NULL, \
            ADD `PosX` float NOT NULL, \
            ADD `PosY` float NOT NULL, \
            ADD `PosZ` float NOT NULL, \
            ADD `PosA` float NOT NULL, \
            ADD `Color` int(6) NOT NULL, \
            ADD `PddTest` float NOT NULL, \
            ADD `DrvNum` float NOT NULL, \
            ADD `DrvDateA` varchar(12) NOT NULL, \
            ADD `DrvDateB` varchar(12) NOT NULL, \
            ADD `DrvDateC` varchar(12) NOT NULL, \
            ADD `DrvDateD` varchar(12) NOT NULL, \
            ADD `DrvDateF` varchar(12) NOT NULL",
        !"OnDataBaseCreateEnd2", "");
    }
    return 1;
}
void OnDataBaseCreateEnd2()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `LicA` int(2) NOT NULL, \
            ADD `LicB` int(2) NOT NULL, \
            ADD `LicC` int(2) NOT NULL, \
            ADD `LicD` int(2) NOT NULL, \
            ADD `LicF` int(2) NOT NULL, \
            ADD `Faction` int(2) NOT NULL, \
            ADD `InvDate` varchar(12) NOT NULL, \
            ADD `Rank` int(2) NOT NULL, \
            ADD `Pass` int(2) NOT NULL, \
            ADD `Work` int(2) NOT NULL, \
            ADD `Warn` int(2) NOT NULL, \
            ADD `UnMuteTime` int(2) NOT NULL, \
            ADD `UnBanTime` int(2) NOT NULL, \
            ADD `SDPistol` int(2) NOT NULL",
        !"OnDataBaseCreateEnd3", "");
    }
    return 1;
}
void OnDataBaseCreateEnd3()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `Deagle` int(2) NOT NULL, \
            ADD `Shotgun` int(2) NOT NULL, \
            ADD `MP5` int(2) NOT NULL, \
            ADD `AK47` int(2) NOT NULL, \
            ADD `M4A1` int(2) NOT NULL, \
            ADD `Money` int(2) NOT NULL, \
            ADD `Law` int(2) NOT NULL, \
            ADD `Wanted` int(2) NOT NULL, \
            ADD `Spouse` varchar(24) NOT NULL, \
            ADD `Bank` int(2) NOT NULL, \
            ADD `House` int(2) NOT NULL, \
            ADD `Biz` int(2) NOT NULL, \
            ADD `Flat` int(2) NOT NULL, \
            ADD `Room` int(2) NOT NULL, \
            ADD `BankAccount` int(2) NOT NULL",
        !"OnDataBaseCreateEnd4", "");
    }
    return 1;
}
void OnDataBaseCreateEnd4()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `Hunger` int(2) NOT NULL, \
            ADD `Piss` int(2) NOT NULL, \
            ADD `Hygiene` int(2) NOT NULL",
        "", "");
    }
    return 1;
} // закончили создание параметров аккаунта
Пока остановимся на этих таблицах. Далее рассмотрим реакцию на вход игрока. В OnPlayerConnect:
PHP:
mysql_format(SQL_HANDLE, query, sizeof(query), "SELECT `Password`, `UnBanTime` FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]); // берём пароль, время разбана
mysql_tquery(SQL_HANDLE, query, !"OnPlayerEnter", "i", playerid);
Проверяем пароль и разбан:
PHP:
void OnPlayerEnter(playerid)
{
    new rows;
    if(!cache_get_row_count(rows)) // если аккаунта нет
    {
/*
// рега
        mysql_format(SQL_HANDLE, query, sizeof(query), "INSERT IGNORE INTO `players` (`Username`, `Password`, `Email`, `Birth`, `RegDate`, `History`, `Skin`, `Level`, `Admin`, `Sex`, `Faction`, `Rank`) VALUES ('%e', '%e', '%e', '%e', '%02d/%02d/%04d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
            Info_User[playerid][uName],
            password,
            email,
            birth,
            day,
            month,
            year,
            GetPVarInt(playerid, !"History"),
            GetPVarInt(playerid, !"Skin"),
             GetPVarInt(playerid, !"Level"),
            GetPVarInt(playerid, !"Admin"),
            GetPVarInt(playerid, !"Sex"),
            GetPVarInt(playerid, !"Faction"),
            GetPVarInt(playerid, !"Rank")
        );
        mysql_tquery(SQL_HANDLE, query, "", ""); // вставляем в БД необходимые данные для создания аккаунта
*/
    }
    else
    {
        new btime;
        cache_get_value_name_int(0, !"UnBanTime", btime);
        if(btime > gettime()) return Kick(playerid); // если время разбана не подошло - кикаем
        mysql_format(SQL_HANDLE, query, sizeof(query), "SELECT * FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]);
        mysql_tquery(SQL_HANDLE, query, !"OnPlayerDataLoaded", "i", playerid);
    }
}
Загрузка акка:
PHP:
void OnPlayerDataLoaded(playerid)
{
    new skin; cache_get_value_name_int(0, !"Skin", skin); SetPVarInt(playerid, !"Skin", skin); SetPlayerSkin(playerid, GetPVarInt(playerid, !"Skin"));
    new sex; cache_get_value_name_int(0, !"Sex", sex); SetPVarInt(playerid, !"Sex", sex);
    new admin; cache_get_value_name_int(0, !"Admin", admin); SetPVarInt(playerid, !"Admin", admin);
    new faction; cache_get_value_name_int(0, !"Faction", faction); SetPVarInt(playerid, !"Faction", faction);
    new rank; cache_get_value_name_int(0, !"Rank", rank); SetPVarInt(playerid, !"Rank", rank);
    new pass; cache_get_value_name_int(0, !"Pass", pass); SetPVarInt(playerid, !"Pass", pass);
    new work; cache_get_value_name_int(0, !"Work", work); SetPVarInt(playerid, !"Work", work);
    new law; cache_get_value_name_int(0, !"Law", law); SetPVarInt(playerid, !"Law", law);
    new wanted; cache_get_value_name_int(0, !"Wanted", wanted); SetPVarInt(playerid, !"Wanted", wanted);
    new warn; cache_get_value_name_int(0, !"Warn", warn); SetPVarInt(playerid, !"Warn", warn);
    new unmutetime; cache_get_value_name_int(0, !"UnMuteTime", unmutetime); SetPVarInt(playerid, !"UnMuteTime", unmutetime);
    new unbantime; cache_get_value_name_int(0, !"UnBanTime", unbantime); SetPVarInt(playerid, !"UnBanTime", unbantime);
    new hunger; cache_get_value_name_int(0, !"Hunger", hunger); SetPVarInt(playerid, !"Hunger", hunger);
// и т.д.
// Text
    new spouse[MAX_PLAYER_NAME];
    cache_get_value_name(0, !"Spouse", spouse, sizeof(spouse));
    SetPVarString(playerid, !"Spouse", spouse);
    new regdate[12];
    cache_get_value_name(0, !"RegDate", regdate, sizeof(regdate));
    SetPVarString(playerid, !"RegDate", regdate);
    new birth[12];
    cache_get_value_name(0, !"Birth", birth, sizeof(birth));
    SetPVarString(playerid, !"Birth", birth);
    return 1;
}
Если при регистрации вы сразу пишете данные в БД, как я, то если игрок вышел, не завершив регистрацию, нужно удалить соответствующие данные:
PHP:
public OnPlayerDisconnect(playerid, reason)
{
    if(!GetPVarInt(playerid, !"Spawned")) // если не закончил регу
    {
        mysql_format(SQL_HANDLE, query, sizeof(query), "SELECT `Country` FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]); // если страна не указана - рега не закончена
        mysql_tquery(SQL_HANDLE, query, !"OnPlayerNotComplete", "i", playerid);
        ResetPlayerParams(playerid); // обнуляем pInfo, потому что PVar'ы вам, видите ли, не нравятся (а у меня там только имя, лол, ахахах)
        return 1;
    }
    new Float:x, Float:y, Float:z, Float:a;
    GetPlayerPos(playerid, x, y, z);
    GetPlayerFacingAngle(playerid, a);
    mysql_format(SQL_HANDLE, query, sizeof(query), "UPDATE `players` SET `Interior` = '%d', `VirtualWorld` = '%d', `PosX` = '%.4f', `PosY` = '%0.4f', `PosZ` = '%0.4f', `PosA` = '%0.3f' WHERE `Username` = '%e'", GetPlayerInterior(playerid), GetPlayerVirtualWorld(playerid), x, y, z, a, Info_User[playerid][uName]);
    mysql_tquery(SQL_HANDLE, query, "", ""); // обновляем место последнего положения для спавна на нём при следующем входе
    ResetPlayerParams(playerid); // обнуляем pInfo ваши любимые, супер-оптимизированные
    return 1;
}
И обработка запроса:
PHP:
void OnPlayerNotComplete(playerid)
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_format(SQL_HANDLE, query, sizeof(query), "DELETE FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]);
        mysql_tquery(SQL_HANDLE, query, "", "");
        ResetPlayerParams(playerid); // тут обнуляется pInfo
        return 1;
    }
    return 1;
}
Через PHPMyAdmin можно отслеживать этапы обработки запросов, что я категорически рекомендую. При ошибках в запросах читаем mysql_log.txt в директории с сервером и исправляем ошибки.

P.S. Для блондинок по жизни, да и брюнеток, которые просто хотят быть уверены в правильности своих действий, полный листинг кода я закинул под спойлер.

ВНИМАНИЕ: данный код не является работоспособной регистрацией, а только показывает порядок работы с базой данных

PHP:
#define SQL_HOST "localhost"
#define SQL_USER "root"
#define SQL_DB "weiland"
#define SQL_PASS ""

#define void%0(%1) forward %0(%1); public %0(%1)

#define MAX_FACTIONS 10

new MySQL:SQL_HANDLE;

enum uData
{
    uName[MAX_PLAYER_NAME],
    uDrvDateA[12],
    uDrvDateB[12],
    uDrvDateC[12],
    uDrvDateD[12],
    uDrvDateF[12]
};
new Info_User[MAX_PLAYERS][uData];

enum fData
{
    fName[32],
    fColor,
    fRank1[12],
    fRank2[12],
    fRank3[12],
    fRank4[12],
    fRank5[12],
    fRank6[12],
    fRank7[12],
    fRank8[12],
    fRank9[12],
    fRank10[12],
    fRank11[12],
    fRank12[12]
};
new Info_Faction[MAX_FACTIONS][fData];
new Names_Faction[MAX_FACTIONS][24] = {!"Фракция 1", !"Фракция 2", !"Автошкола", !"Армия", !"ЛСПД", !"Фракция 6", !"Фракция 7", !"Фракция 8", !"Фракция 9", !"Фракция 10"};
new Colors_Faction[MAX_FACTIONS] = {0xFFFFFFAA, 0xFFFFFFAA, 0x3366FFAA, 0x006600AA, 0xFFFFFFAA, 0xFFFFFFAA, 0xFFFFFFAA, 0xFFFFFFAA, 0xFFFFFFAA, 0xFFFFFFAA};
static query[2048];
public OnGameModeInit()
{
    SQL_HANDLE = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS, "MySQL");
    mysql_tquery(SQL_HANDLE, "CREATE DATABASE IF NOT EXISTS"SQL_DB, "", "");
    mysql_close(SQL_HANDLE);

    SQL_HANDLE = mysql_connect(SQL_HOST, SQL_USER, SQL_PASS, SQL_DB);
    mysql_log();
    if(!mysql_errno()) print(!"Подключение к базе данных MySQL успешно создано!");
    else print(!"Невозможно подключиться к базе данных MySQL!");

    mysql_tquery(SQL_HANDLE, !"SHOW TABLES LIKE 'factions'", !"OnFactionsTableExist", "");
    mysql_tquery(SQL_HANDLE, !"SHOW TABLES LIKE 'players'", !"OnPlayersTableExist", "");

    strcat(Info_Faction[0][fName], !"Отсутствует", 32);
    return 1;
}
public OnPlayerConnect(playerid)
{
    GetPlayerName(playerid, Info_User[playerid][uName], MAX_PLAYER_NAME);
// # Account
    mysql_format(SQL_HANDLE, query, sizeof(query), "SELECT `Password`, `UnBanTime` FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]);
    mysql_tquery(SQL_HANDLE, query, !"OnPlayerEnter", "i", playerid);
    return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
    if(!GetPVarInt(playerid, !"Spawned"))
    {
        mysql_format(SQL_HANDLE, query, sizeof(query), "SELECT `Country` FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]);
        mysql_tquery(SQL_HANDLE, query, !"OnPlayerNotComplete", "i", playerid);
        ResetPlayerParams(playerid);
        return 1;
    }
    new Float:x, Float:y, Float:z, Float:a;
    GetPlayerPos(playerid, x, y, z);
    GetPlayerFacingAngle(playerid, a);
    mysql_format(SQL_HANDLE, query, sizeof(query), "UPDATE `players` SET `Interior` = '%d', `VirtualWorld` = '%d', `PosX` = '%.4f', `PosY` = '%0.4f', `PosZ` = '%0.4f', `PosA` = '%0.3f' WHERE `Username` = '%e'", GetPlayerInterior(playerid), GetPlayerVirtualWorld(playerid), x, y, z, a, Info_User[playerid][uName]);
    mysql_tquery(SQL_HANDLE, query, "", "");
    ResetPlayerParams(playerid);
    return 1;
}
stock ResetPlayerParams(playerid)
{
    Info_User[playerid][uName][0] = EOS;
    return 1;
}
// MySQL Func
void OnFactionsTableExist()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE,
            "CREATE TABLE IF NOT EXISTS `factions`(\
                `ID` int(10) NOT NULL AUTO_INCREMENT, \
                `FactionName` varchar(32) NOT NULL, \
                `FColor` int(11) NOT NULL, \
                `FRank1` varchar(12) NOT NULL, \
                `FRank2` varchar(12) NOT NULL, \
                `FRank3` varchar(12) NOT NULL, \
                `FRank4` varchar(12) NOT NULL, \
                `FRank5` varchar(12) NOT NULL, \
                `FRank6` varchar(12) NOT NULL, \
                `FRank7` varchar(12) NOT NULL, \
                `FRank8` varchar(12) NOT NULL, \
                `FRank9` varchar(12) NOT NULL, \
                `FRank10` varchar(12) NOT NULL, \
            PRIMARY KEY (`ID`))",
        "", "");
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `factions`(\
            `FRank11` varchar(12) NOT NULL, \
            `FRank12` varchar(12) NOT NULL",
        "", "");
        for(new i = 0; i < MAX_FACTIONS; i++)
        {
            Info_Faction[i][fName][0] = EOS;
            strcat(Info_Faction[i][fName], Names_Faction[i], 24);
            Info_Faction[i][fColor] = Colors_Faction[i];
            mysql_tquery(SQL_HANDLE, "INSERT IGNORE INTO `factions` \
            (`FactionName`, `FColor`, `FRank1`, `FRank2`, `FRank3`, `FRank4`, `FRank5`, `FRank6`, `FRank7`, `FRank8`, `FRank9`, `FRank10`, `FRank11`, `FRank12`) VALUES \
            ('%e', '%d', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e', '%e')",
                Info_Faction[i][fName], Info_Faction[i][fColor],
                Info_Faction[i][fRank1], Info_Faction[i][fRank2], Info_Faction[i][fRank3], Info_Faction[i][fRank4], Info_Faction[i][fRank5], Info_Faction[i][fRank6],
                Info_Faction[i][fRank7], Info_Faction[i][fRank8], Info_Faction[i][fRank9], Info_Faction[i][fRank10], Info_Faction[i][fRank11], Info_Faction[i][fRank12]
            );
        }
        return 1;
    }
    return 1;
}
void OnPlayersTableExist()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE,
            "CREATE TABLE IF NOT EXISTS `players`(\
                `ID` int(10) NOT NULL AUTO_INCREMENT, \
                `Username` varchar(24) NOT NULL, \
                `Password` varchar(65) NOT NULL, \
                `Email` varchar(128) NOT NULL, \
                `Birth` varchar(12) NOT NULL, \
                `RegDate` varchar(12) NOT NULL, \
                `History` int(5) NOT NULL, \
                `Sex` int(5) NOT NULL, \
                `Country` int(5) NOT NULL, \
                `Skin` int(5) NOT NULL, \
                `Level` int(5) NOT NULL, \
                `Exp` int(5) NOT NULL, \
                `Admin` int(5) NOT NULL, \
                `Interior` int(3) NOT NULL, \
            PRIMARY KEY (`ID`))",
        !"OnDataBaseCreateEnd", "");
        return 1;
    }
    return 1;
}
void OnDataBaseCreateEnd()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `VirtualWorld` int(6) NOT NULL, \
            ADD `PosX` float NOT NULL, \
            ADD `PosY` float NOT NULL, \
            ADD `PosZ` float NOT NULL, \
            ADD `PosA` float NOT NULL, \
            ADD `PddTest` float NOT NULL, \
            ADD `DrvNum` float NOT NULL, \
            ADD `DrvDateA` varchar(12) NOT NULL, \
            ADD `DrvDateB` varchar(12) NOT NULL, \
            ADD `DrvDateC` varchar(12) NOT NULL, \
            ADD `DrvDateD` varchar(12) NOT NULL, \
            ADD `DrvDateF` varchar(12) NOT NULL",
        !"OnDataBaseCreateEnd2", "");
    }
    return 1;
}
void OnDataBaseCreateEnd2()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `LicA` int(2) NOT NULL, \
            ADD `LicB` int(2) NOT NULL, \
            ADD `LicC` int(2) NOT NULL, \
            ADD `LicD` int(2) NOT NULL, \
            ADD `LicF` int(2) NOT NULL, \
            ADD `Faction` int(2) NOT NULL, \
            ADD `InvDate` varchar(12) NOT NULL, \
            ADD `Rank` int(2) NOT NULL, \
            ADD `Pass` int(2) NOT NULL, \
            ADD `Work` int(2) NOT NULL, \
            ADD `Warn` int(2) NOT NULL, \
            ADD `UnMuteTime` int(2) NOT NULL, \
            ADD `UnBanTime` int(2) NOT NULL, \
            ADD `SDPistol` int(2) NOT NULL",
        !"OnDataBaseCreateEnd3", "");
    }
    return 1;
}
void OnDataBaseCreateEnd3()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `Deagle` int(2) NOT NULL, \
            ADD `Shotgun` int(2) NOT NULL, \
            ADD `MP5` int(2) NOT NULL, \
            ADD `AK47` int(2) NOT NULL, \
            ADD `M4A1` int(2) NOT NULL, \
            ADD `Money` int(2) NOT NULL, \
            ADD `Law` int(2) NOT NULL, \
            ADD `Wanted` int(2) NOT NULL, \
            ADD `Spouse` varchar(24) NOT NULL, \
            ADD `Bank` int(2) NOT NULL, \
            ADD `House` int(2) NOT NULL, \
            ADD `Biz` int(2) NOT NULL, \
            ADD `Flat` int(2) NOT NULL, \
            ADD `Room` int(2) NOT NULL, \
            ADD `BankAccount` int(2) NOT NULL",
        !"OnDataBaseCreateEnd4", "");
    }
    return 1;
}
void OnDataBaseCreateEnd4()
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_tquery(SQL_HANDLE, "ALTER TABLE `players` \
            ADD `Hunger` int(2) NOT NULL, \
            ADD `Piss` int(2) NOT NULL, \
            ADD `Hygiene` int(2) NOT NULL",
        "", "");
    }
    return 1;
}
void OnPlayerNotComplete(playerid)
{
    new rows;
    if(!cache_get_row_count(rows))
    {
        mysql_format(SQL_HANDLE, query, sizeof(query), "DELETE FROM `players` WHERE `Username` = '%e' LIMIT 1", Info_User[playerid][uName]);
        mysql_tquery(SQL_HANDLE, query, "", "");
        ResetPlayerParams(playerid);
        return 1;
    }
    return 1;
}
void OnPlayerEnter(playerid)
{
    new rows;
    if(!cache_get_row_count(rows))
    {
// регистрация
        return 1;
    }
    else
    {
        new btime;
        cache_get_value_name_int(0, !"UnBanTime", btime);
        if(btime > gettime()) return Kick(playerid);
// логин
    }
    return 1;
}
void OnPlayerDataLoaded(playerid)
{
    new skin; cache_get_value_name_int(0, !"Skin", skin); SetPVarInt(playerid, !"Skin", skin); SetPlayerSkin(playerid, GetPVarInt(playerid, !"Skin"));
    new sex; cache_get_value_name_int(0, !"Sex", sex); SetPVarInt(playerid, !"Sex", sex);
    new admin; cache_get_value_name_int(0, !"Admin", admin); SetPVarInt(playerid, !"Admin", admin);
    new faction; cache_get_value_name_int(0, !"Faction", faction); SetPVarInt(playerid, !"Faction", faction);
    new rank; cache_get_value_name_int(0, !"Rank", rank); SetPVarInt(playerid, !"Rank", rank);
    new pass; cache_get_value_name_int(0, !"Pass", pass); SetPVarInt(playerid, !"Pass", pass);
    new work; cache_get_value_name_int(0, !"Work", work); SetPVarInt(playerid, !"Work", work);
    new law; cache_get_value_name_int(0, !"Law", law); SetPVarInt(playerid, !"Law", law);
    new wanted; cache_get_value_name_int(0, !"Wanted", wanted); SetPVarInt(playerid, !"Wanted", wanted);
    new warn; cache_get_value_name_int(0, !"Warn", warn); SetPVarInt(playerid, !"Warn", warn);
    new unmutetime; cache_get_value_name_int(0, !"UnMuteTime", unmutetime); SetPVarInt(playerid, !"UnMuteTime", unmutetime);
    new unbantime; cache_get_value_name_int(0, !"UnBanTime", unbantime); SetPVarInt(playerid, !"UnBanTime", unbantime);
    new hunger; cache_get_value_name_int(0, !"Hunger", hunger); SetPVarInt(playerid, !"Hunger", hunger);
// и т.д.
// Text
    new spouse[MAX_PLAYER_NAME];
    cache_get_value_name(0, !"Spouse", spouse, sizeof(spouse));
    SetPVarString(playerid, !"Spouse", spouse);
    new regdate[12];
    cache_get_value_name(0, !"RegDate", regdate, sizeof(regdate));
    SetPVarString(playerid, !"RegDate", regdate);
    new birth[12];
    cache_get_value_name(0, !"Birth", birth, sizeof(birth));
    SetPVarString(playerid, !"Birth", birth);
    return 1;
}
 
Сверху Снизу