Когда я только начинал писать свой первый "недо код" Появилась проблема с mysql и регистрацией(авторизацией).
Эту тему создал специально для новичков, я постараюсь объяснить все понятно если будут вопросы обращайтесь, ну что же начнём,
1. База данных :
Если у вас есть хост с Phpmyadmin, можете исполосовать его, что бы запустить на локалки есть программа Denwer >>Скачать<<
Установка проста, ну или чекайте в инете ибо я ленивый
2.Система аккаунтов:
1. Выбераем бд в которой будем создавать таблицу (клик по создать таблицу) и вводим данные о таблице:
В поле "Имя таблицы" вводим "accounts"
В поле "Количество столбцов" вводим "3"
2. Структуру новой таблицы заполняем следующим образом:
Эту тему создал специально для новичков, я постараюсь объяснить все понятно если будут вопросы обращайтесь, ну что же начнём,
1. База данных :
Если у вас есть хост с Phpmyadmin, можете исполосовать его, что бы запустить на локалки есть программа Denwer >>Скачать<<
Установка проста, ну или чекайте в инете ибо я ленивый
2.Система аккаунтов:
1. Выбераем бд в которой будем создавать таблицу (клик по создать таблицу) и вводим данные о таблице:
В поле "Имя таблицы" вводим "accounts"
В поле "Количество столбцов" вводим "3"
2. Структуру новой таблицы заполняем следующим образом:
Первый столбец
- Имя столбца: id
- Тип столбца: INT
- Длина/значения: 11
Все остальные значения, кроме A_I, не трогаем. Находим A_I (Auto Increment) и ставим галочку.
Идентификаторов не может быть больше одного в таблице. Да оно и не нужно =)
Второй столбец
- Имя столбца: player_name
- Тип столбца: VARCHAR
- Длина/значения: 24 (так как длина ника в SA-MP не может превышать 24 символа)
Все остальные значения не трогаем.
Третий столбец
- Имя столбца: password
- Тип столбца: VARCHAR
- Длина/значения: 30 (Я ограничу длину пароля игрока 30-ю символами. Вы можете сделать меньше/больше)
3.Запускаем pawno:
1. Данные для подключения
В начало нашего скрипта (под "#include ") добавим:
#include <a_mysql>
#define MYSQL_HOST "localhost"//Адрес, по которому расположен MySQL-Сервер
#define MYSQL_USER "root"//Имя пользователя, на которого была создана база данных
#define MYSQL_DATABASE "sa-mp"// Имя базы данных
#define MYSQL_PASSWORD ""//Пароль для доступа к серверу MySQL
new MySQL:mysql_connect_ID;
#include <a_mysq> - подключаем инклюд, в котором хранится объявление всех функций для работы с плагином.
#define MYSQL_HOST "localhost" - Этот макрос хранит в себе адрес хостинга, где хранится база данных (мы будем запускать на ПК, поэтому указываем адрес локальной сети).
#define MYSQL_USER "root" - Этот макрос хранит в себе имя пользователя, у которого имеется доступ к базе данных (так как мы запускаем мод на ПК, у нас это администратор. Когда будете запускать мод на хостинге, Вам выдадут особое имя)
#define MYSQL_DATABASE "first_database" - Этот макрос содержит в себе имя базы данных. Если при создании БД Вы прописывали имя отличное от моего, измените его на то, что указали Вы.
#define MYSQL_PASSWORD "" -- Этот макрос хранит в себе пароль, который требуется для подключения к базе данных
new mysql_connect_ID;
Это целочисленная переменная, в которой мы будем хранить ID подключения, которое потребуется для работы большинства функций.
2. Подключение к базе данных
В OnGameModeInIt
mysql_connect_ID = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
Данная функция возвращает ID подключения, который мы и записали в переменную.
3. Ко всем enum
enum e_PLAYER_INFO
{
pID,
pName[MAX_PLAYER_NAME],
pPassword[31]
};
new pInfo[MAX_PLAYERS][e_PLAYER_INFO];
enum e_PLAYER_INFO -enum - англ. Enumeration (Перечисление) - это тип, состоящий из набора целочисленных констант
pID, - Первый член перечисления, а по совместительству и ячейка, в которой будет хранится ID аккаунта игрока.
pName[MAX_PLAYER_NAME], - Второй член перечисления, а по совместительству и ячейка, в которой будет хранится имя аккаунта.
pPassword[31] - Третий член массива, а по совместительству и ячейка, в которой будет хранится пароль от аккаунта.
new pInfo[MAX_PLAYERS][e_PLAYER_INFO]; - Массив, через который мы будем обращаться у нужному нам члену перечисления за данными.
4. Поиск игрока в базе данных и запись ника в массив
GetPlayerName(playerid, pInfo[playerid][pName], MAX_PLAYER_NAME);
new query_string[49+MAX_PLAYER_NAME-4];
format(query_string, sizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'", pInfo[playerid][pName]);
mysql_tquery(mysql_connect_ID, query_string, "FindPlayerInTable","i", playerid);
Так же нам нужно эти данные записать в наш массив.
forward FindPlayerInTable(playerid);
public FindPlayerInTable(playerid)
{
new rows;
cache_get_row_count(rows);
if(!rows)
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "Введите пароль для регистрации нового аккаунта:", "Регистрация", "Выход");
}
else
{
ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "Введите пароль от аккаунта для того, чтоб продолжить игру:", "Вход", "Выход");
cache_get_value_name(0, "password", pInfo[playerid][pPassword], 31);
}
return 1;
}
5. Создание действий для диалогов
Сначала нам нужно вспомнить о себе любимых и упростить работу с диалогами, создав ещё одно перечисление, которое будет позволять писать нам на месте ID диалога какие-то слова, намекающие нам на предназначение этого диалога, а не обычные числа. Ведь согласитесь, "dRegister" гораздо сильнее намекает нам на то, что этот диалог является диалогом регистрации, нежели просто "0", "1" или какое-либо ещё число. Но перечисление не только даст нам возможность более лучше понимать предназначение диалога по его ID, но и избавит нас от страха того, что ID диалогов могут перепутаться, ведь перечисление само определит свободный ID и установит его.
Чтоб создать такое перечисление, находим наше перечисление с данными игроков и выше него создадим ещё одно:
enum e_DIALOG_IDs
{
dKickMessage,//Автоматически займёт ID 0
dRegister,//ID 1
dLogin//ID 2
};
Всё =) Теперь достаточно придумывать имя каждому новому диалогу, дописывать его в этот список и тогда Вы точно никогда не запутаетесь при создании новых диалогов.
switch(dialogid)
{
case dRegister:
{
if(!response)
{
ShowPlayerDialog(playerid, dKickMessage, DIALOG_STYLE_MSGBOX, "Оповещение", "{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от регистрации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат", "Выход", "");
return Kick(playerid);
}
if(!strlen(inputtext)) return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить регистрацию не введя пароль!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
else if(strlen(inputtext) < 4) return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Пароль слишком короткий!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
else if(strlen(inputtext) > 30) return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Пароль слишком длинный!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
for(new i = strlen(inputtext)-1; i != -1; i--)
{
switch(inputtext)
{
case '0'..'9', 'а'..'я', 'a'..'z', 'А'..'Я', 'A'..'Z': continue;
default: return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
}
}
pInfo[playerid][pPassword][0] = EOS;
strins(pInfo[playerid][pPassword], inputtext, 0);
CreateNewAccount(playerid, pInfo[playerid][pPassword]);
return 1;
}
case dLogin:
{
if(!response)
{
ShowPlayerDialog(playerid, dKickMessage, DIALOG_STYLE_MSGBOX, "Оповещение", "{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от авторизации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат", "Выход", "");
return Kick(playerid);
}
if(!strlen(inputtext)) return ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить авторизацию не введя пароль!\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
for(new i = strlen(inputtext)-1; i != -1; i--)
{
switch(inputtext)
{
case '0'..'9', 'а'..'я', 'a'..'z', 'А'..'Я', 'A'..'Z': continue;
default: return ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Введённый пароль содержит запрещённые символы!\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
}
}
if(!strcmp(pInfo[playerid][pPassword], inputtext))
{
new query_string[49+MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'", pInfo[playerid][pName]);
mysql_tquery(mysql_connect_ID, query_string, "UploadPlayerAccount","i", playerid);
}
else
{
switch(GetPVarInt(playerid, "WrongPassword"))
{
case 0: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 3 попытки.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
case 1: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 2 попытки.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
case 2: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 1 попытка.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
case 3: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталась последняя попытка, после чего Вас кикнет.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
default:
{
ShowPlayerDialog(playerid, dKickMessage, DIALOG_STYLE_MSGBOX, "Оповещение", "{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Превышен лимит попыток на ввод пароля.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат", "Выход", "");
return Kick(playerid);
}
}
SetPVarInt(playerid, "WrongPassword", GetPVarInt(playerid, "WrongPassword")+1);
}
return 1;
}
}
6. Создание/загрузка аккаунта игрока
В самый конец мода вставим этот stock:
stock CreateNewAccount(playerid, password[])
{
new query_string[66+MAX_PLAYER_NAME-4+30];
format(query_string, sizeof(query_string), "INSERT INTO `accounts` (`player_name`, `password`) VALUES ('%s', '%s')", pInfo[playerid][pName], password);
mysql_tquery(mysql_connect_ID, query_string, "UploadPlayerAccountNumber", "i", playerid);
format(query_string, sizeof(query_string), "Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!", pInfo[playerid][pName]);
SendClientMessage(playerid, 0xFFFFFF00, query_string);
SpawnPlayer(playerid);
return 1;
}
А вот и сам коллбэк, который вернёт ID аккаунта:
forward UploadPlayerAccountNumber(playerid);
public UploadPlayerAccountNumber(playerid) pInfo[playerid][pID] = cache_insert_id();
Загрузка аккаунта:
forward UploadPlayerAccount(playerid);
public UploadPlayerAccount(playerid)
{
cache_get_value_name_int(0, "id", pInfo[playerid][pID]);
SendClientMessage(playerid, 0xFFFFFF00, "Вы успешно авторизировались!");
SpawnPlayer(playerid);
return 1;
}
7. Сохранение аккаунта
Так же, в самом конце, добавим новый stock
stock SaveAccount(playerid)
{
new query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)] = "UPDATE `accounts` SET";
format(query_string, sizeof(query_string), "%s `player_name` = '%s',", query_string, pInfo[playerid][pName]);
format(query_string, sizeof(query_string), "%s `password` = '%s'", query_string, pInfo[playerid][pPassword]);
format(query_string, sizeof(query_string), "%s WHERE `id` = '%d'", query_string, pInfo[playerid][pID]);
mysql_tquery(mysql_connect_ID, query_string, "", "");
return 1;
}
И в OnPlayerDisconnect
SaveAccount(playerid);
8. Отключение от базы данных
Так же нужно не забыть добавить запрос к плагину MySQL на отключение от нашей базы данных. Делается это просто.
В OnGameModeExit
mysql_close(mysql_connect_ID);
9. Обнуление массива с данными
Это действие требуется для того, чтоб данные одного игрока не перемешались с данными другого в случае, если один игрок вышел и второй зашёл на тот же слот.
Делается это просто. Сначала в OnPlayerDisconnect, после "SaveAccount(playerid);" добавим:
RemovePlayerInfo(playerid);
А после в конец скрипта:
stock RemovePlayerInfo(playerid)
{
pInfo[playerid][pID] = 0;
pInfo[playerid][pName][0] = EOS;
pInfo[playerid][pPassword][0] = EOS;
return 1;
}
10. Проверка на авторизацию игрока
В начало мода, к переменным, добавим следующий массив:
new player_is_authorized[MAX_PLAYERS char];
Теперь в UploadPlayerAccount/CreateNewAccount, перед SpawnPlayer, добавить
player_is_authorized{playerid} = 1;
В OnPlayerText добавляем следующее:
if(!player_is_authorized{playerid})
{
SendClientMessage(playerid, -1, "Вы не авторизировались и не можете писать в чат!");
return 0;
}
В начало OnPlayerCommandText
if(!player_is_authorized{playerid}) return SendClientMessage(playerid, -1, "Вы не авторизировались и не можете использовать команды!");
Автор DeimoS
- Имя столбца: id
- Тип столбца: INT
- Длина/значения: 11
Все остальные значения, кроме A_I, не трогаем. Находим A_I (Auto Increment) и ставим галочку.
Идентификаторов не может быть больше одного в таблице. Да оно и не нужно =)
Второй столбец
- Имя столбца: player_name
- Тип столбца: VARCHAR
- Длина/значения: 24 (так как длина ника в SA-MP не может превышать 24 символа)
Все остальные значения не трогаем.
Третий столбец
- Имя столбца: password
- Тип столбца: VARCHAR
- Длина/значения: 30 (Я ограничу длину пароля игрока 30-ю символами. Вы можете сделать меньше/больше)
3.Запускаем pawno:
1. Данные для подключения
В начало нашего скрипта (под "#include ") добавим:
#include <a_mysql>
#define MYSQL_HOST "localhost"//Адрес, по которому расположен MySQL-Сервер
#define MYSQL_USER "root"//Имя пользователя, на которого была создана база данных
#define MYSQL_DATABASE "sa-mp"// Имя базы данных
#define MYSQL_PASSWORD ""//Пароль для доступа к серверу MySQL
new MySQL:mysql_connect_ID;
#include <a_mysq> - подключаем инклюд, в котором хранится объявление всех функций для работы с плагином.
#define MYSQL_HOST "localhost" - Этот макрос хранит в себе адрес хостинга, где хранится база данных (мы будем запускать на ПК, поэтому указываем адрес локальной сети).
#define MYSQL_USER "root" - Этот макрос хранит в себе имя пользователя, у которого имеется доступ к базе данных (так как мы запускаем мод на ПК, у нас это администратор. Когда будете запускать мод на хостинге, Вам выдадут особое имя)
#define MYSQL_DATABASE "first_database" - Этот макрос содержит в себе имя базы данных. Если при создании БД Вы прописывали имя отличное от моего, измените его на то, что указали Вы.
#define MYSQL_PASSWORD "" -- Этот макрос хранит в себе пароль, который требуется для подключения к базе данных
new mysql_connect_ID;
Это целочисленная переменная, в которой мы будем хранить ID подключения, которое потребуется для работы большинства функций.
2. Подключение к базе данных
В OnGameModeInIt
mysql_connect_ID = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE);
Данная функция возвращает ID подключения, который мы и записали в переменную.
3. Ко всем enum
enum e_PLAYER_INFO
{
pID,
pName[MAX_PLAYER_NAME],
pPassword[31]
};
new pInfo[MAX_PLAYERS][e_PLAYER_INFO];
enum e_PLAYER_INFO -enum - англ. Enumeration (Перечисление) - это тип, состоящий из набора целочисленных констант
pID, - Первый член перечисления, а по совместительству и ячейка, в которой будет хранится ID аккаунта игрока.
pName[MAX_PLAYER_NAME], - Второй член перечисления, а по совместительству и ячейка, в которой будет хранится имя аккаунта.
pPassword[31] - Третий член массива, а по совместительству и ячейка, в которой будет хранится пароль от аккаунта.
new pInfo[MAX_PLAYERS][e_PLAYER_INFO]; - Массив, через который мы будем обращаться у нужному нам члену перечисления за данными.
4. Поиск игрока в базе данных и запись ника в массив
GetPlayerName(playerid, pInfo[playerid][pName], MAX_PLAYER_NAME);
new query_string[49+MAX_PLAYER_NAME-4];
format(query_string, sizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'", pInfo[playerid][pName]);
mysql_tquery(mysql_connect_ID, query_string, "FindPlayerInTable","i", playerid);
Так же нам нужно эти данные записать в наш массив.
forward FindPlayerInTable(playerid);
public FindPlayerInTable(playerid)
{
new rows;
cache_get_row_count(rows);
if(!rows)
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "Введите пароль для регистрации нового аккаунта:", "Регистрация", "Выход");
}
else
{
ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "Введите пароль от аккаунта для того, чтоб продолжить игру:", "Вход", "Выход");
cache_get_value_name(0, "password", pInfo[playerid][pPassword], 31);
}
return 1;
}
5. Создание действий для диалогов
Сначала нам нужно вспомнить о себе любимых и упростить работу с диалогами, создав ещё одно перечисление, которое будет позволять писать нам на месте ID диалога какие-то слова, намекающие нам на предназначение этого диалога, а не обычные числа. Ведь согласитесь, "dRegister" гораздо сильнее намекает нам на то, что этот диалог является диалогом регистрации, нежели просто "0", "1" или какое-либо ещё число. Но перечисление не только даст нам возможность более лучше понимать предназначение диалога по его ID, но и избавит нас от страха того, что ID диалогов могут перепутаться, ведь перечисление само определит свободный ID и установит его.
Чтоб создать такое перечисление, находим наше перечисление с данными игроков и выше него создадим ещё одно:
enum e_DIALOG_IDs
{
dKickMessage,//Автоматически займёт ID 0
dRegister,//ID 1
dLogin//ID 2
};
Всё =) Теперь достаточно придумывать имя каждому новому диалогу, дописывать его в этот список и тогда Вы точно никогда не запутаетесь при создании новых диалогов.
switch(dialogid)
{
case dRegister:
{
if(!response)
{
ShowPlayerDialog(playerid, dKickMessage, DIALOG_STYLE_MSGBOX, "Оповещение", "{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от регистрации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат", "Выход", "");
return Kick(playerid);
}
if(!strlen(inputtext)) return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить регистрацию не введя пароль!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
else if(strlen(inputtext) < 4) return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Пароль слишком короткий!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
else if(strlen(inputtext) > 30) return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Пароль слишком длинный!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
for(new i = strlen(inputtext)-1; i != -1; i--)
{
switch(inputtext)
{
case '0'..'9', 'а'..'я', 'a'..'z', 'А'..'Я', 'A'..'Z': continue;
default: return ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, "Регистрация нового пользователя", "{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).", "Регистрация", "Выход");
}
}
pInfo[playerid][pPassword][0] = EOS;
strins(pInfo[playerid][pPassword], inputtext, 0);
CreateNewAccount(playerid, pInfo[playerid][pPassword]);
return 1;
}
case dLogin:
{
if(!response)
{
ShowPlayerDialog(playerid, dKickMessage, DIALOG_STYLE_MSGBOX, "Оповещение", "{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от авторизации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат", "Выход", "");
return Kick(playerid);
}
if(!strlen(inputtext)) return ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить авторизацию не введя пароль!\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
for(new i = strlen(inputtext)-1; i != -1; i--)
{
switch(inputtext)
{
case '0'..'9', 'а'..'я', 'a'..'z', 'А'..'Я', 'A'..'Z': continue;
default: return ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Введённый пароль содержит запрещённые символы!\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
}
}
if(!strcmp(pInfo[playerid][pPassword], inputtext))
{
new query_string[49+MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'", pInfo[playerid][pName]);
mysql_tquery(mysql_connect_ID, query_string, "UploadPlayerAccount","i", playerid);
}
else
{
switch(GetPVarInt(playerid, "WrongPassword"))
{
case 0: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 3 попытки.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
case 1: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 2 попытки.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
case 2: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 1 попытка.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
case 3: ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, "Авторизация", "{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталась последняя попытка, после чего Вас кикнет.\nВведите пароль от аккаунта для входа на сервер:", "Вход", "Выход");
default:
{
ShowPlayerDialog(playerid, dKickMessage, DIALOG_STYLE_MSGBOX, "Оповещение", "{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Превышен лимит попыток на ввод пароля.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат", "Выход", "");
return Kick(playerid);
}
}
SetPVarInt(playerid, "WrongPassword", GetPVarInt(playerid, "WrongPassword")+1);
}
return 1;
}
}
6. Создание/загрузка аккаунта игрока
В самый конец мода вставим этот stock:
stock CreateNewAccount(playerid, password[])
{
new query_string[66+MAX_PLAYER_NAME-4+30];
format(query_string, sizeof(query_string), "INSERT INTO `accounts` (`player_name`, `password`) VALUES ('%s', '%s')", pInfo[playerid][pName], password);
mysql_tquery(mysql_connect_ID, query_string, "UploadPlayerAccountNumber", "i", playerid);
format(query_string, sizeof(query_string), "Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!", pInfo[playerid][pName]);
SendClientMessage(playerid, 0xFFFFFF00, query_string);
SpawnPlayer(playerid);
return 1;
}
А вот и сам коллбэк, который вернёт ID аккаунта:
forward UploadPlayerAccountNumber(playerid);
public UploadPlayerAccountNumber(playerid) pInfo[playerid][pID] = cache_insert_id();
Загрузка аккаунта:
forward UploadPlayerAccount(playerid);
public UploadPlayerAccount(playerid)
{
cache_get_value_name_int(0, "id", pInfo[playerid][pID]);
SendClientMessage(playerid, 0xFFFFFF00, "Вы успешно авторизировались!");
SpawnPlayer(playerid);
return 1;
}
7. Сохранение аккаунта
Так же, в самом конце, добавим новый stock
stock SaveAccount(playerid)
{
new query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)] = "UPDATE `accounts` SET";
format(query_string, sizeof(query_string), "%s `player_name` = '%s',", query_string, pInfo[playerid][pName]);
format(query_string, sizeof(query_string), "%s `password` = '%s'", query_string, pInfo[playerid][pPassword]);
format(query_string, sizeof(query_string), "%s WHERE `id` = '%d'", query_string, pInfo[playerid][pID]);
mysql_tquery(mysql_connect_ID, query_string, "", "");
return 1;
}
И в OnPlayerDisconnect
SaveAccount(playerid);
8. Отключение от базы данных
Так же нужно не забыть добавить запрос к плагину MySQL на отключение от нашей базы данных. Делается это просто.
В OnGameModeExit
mysql_close(mysql_connect_ID);
9. Обнуление массива с данными
Это действие требуется для того, чтоб данные одного игрока не перемешались с данными другого в случае, если один игрок вышел и второй зашёл на тот же слот.
Делается это просто. Сначала в OnPlayerDisconnect, после "SaveAccount(playerid);" добавим:
RemovePlayerInfo(playerid);
А после в конец скрипта:
stock RemovePlayerInfo(playerid)
{
pInfo[playerid][pID] = 0;
pInfo[playerid][pName][0] = EOS;
pInfo[playerid][pPassword][0] = EOS;
return 1;
}
10. Проверка на авторизацию игрока
В начало мода, к переменным, добавим следующий массив:
new player_is_authorized[MAX_PLAYERS char];
Теперь в UploadPlayerAccount/CreateNewAccount, перед SpawnPlayer, добавить
player_is_authorized{playerid} = 1;
В OnPlayerText добавляем следующее:
if(!player_is_authorized{playerid})
{
SendClientMessage(playerid, -1, "Вы не авторизировались и не можете писать в чат!");
return 0;
}
В начало OnPlayerCommandText
if(!player_is_authorized{playerid}) return SendClientMessage(playerid, -1, "Вы не авторизировались и не можете использовать команды!");
Автор DeimoS
Последнее редактирование модератором: