Перейти к содержанию
Авторизация  
Vladimir_Kulkov

Оригинальная система регистрации [MySQL R39-7]

Рекомендуемые сообщения

Vladimir_Kulkov

Представляю вашему вниманию оригинальную систему регистрации.
Подобного вида система используется на RP-Gameworld. Уверен, данная система внесет каплю разнообразия на ваш сервер.

Демонстрационное видео

https://youtu.be/p2fO49fx5Fo

 

 

Описание
Каждый пункт динамичен и выполнен в виде переключателя. С помощью этой системы вы сможете собрать в одном месте все поля для ввода данных, которые вам необходимо получить от игрока (к примеру, email, код безопасности, раса и т.д., и т.п.)
Скрипт тестировался на чистом проекте, который я приложу в конце темы и создавался с ориентиром на использование его в модах типа "с нуля". Но приложив совсем чуть-чуть усилий, его можно с легкостью адаптировать под любой мод.
К некоторым строкам в коде добавлено описание для пучшего понимания.

Урок

 

Для начала нам необходимо создать базу данных. Для этого откройте панель управления базой и с помощью запросов импортируйте таблицу:

Сама база:

CREATE DATABASE `newmod` DEFAULT CHARACTER SET cp1251 COLLATE cp1251_general_ci;
USE `newmod

 

 

CREATE TABLE IF NOT EXISTS `accounts` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Nickname` varchar(32) NOT NULL,
`Password` varchar(64) NOT NULL,
`Level` int(11) NOT NULL DEFAULT '1',
`Sex` int(11) NOT NULL,
`Referal` varchar(64) NOT NULL DEFAULT 'No',
`Admin` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251 AUTO_INCREMENT=1;

 

 

http://image.prntscr.com/image/9877f4bfe98c44799c13172b8299fb1c.png

 

 

Подключаем mysql плагин. Как указано в шапке темы, для этой системы я использовал mysql от blueg версии R39-7

#include

 

 

#define REG_DIALOG 555
#define LOG_DIALOG 777
#define TABLE_ACCOUNTS "accounts" //название таблицы с аккаунтами
#define SQL_HOST "localhost" //хост базы
#define SQL_USER "root" //имя пользователя
#define SQL_DB "newmod" //имя базы, к которой мы подключаемся
#define SQL_PASS "" //пароль
#define SQL_PORT 3306 //порт соединения
#define SQL_RECONNECT true //переподключение в случае ошибок
#define SQL_POOLSIZE 10 //максимальное к-лво одновременных подключений (необходимо для mysql_pquery)
#define MIN_PASS_LENGTH 6 //минимальная длинна пароля
#define MAX_PASS_LENGTH 64 //максимальная длинна пароля
#define ENCRYPT_PASS 1 //Значение 1 включает шифрование пароля в диалоге. Т.е. при пароле 123123 будет, к примеру ***123

 

 

/* Данные */
enum regdata
{
pAcceptRules,
pSex,
pReferal[32+1],
pPassword[64]
}
new RegData[MAX_PLAYERS][regdata]; //хранение информации при регистрации

enum player_data
{
pDatabaseID,
pName[MAX_PLAYER_NAME+1],
pPassword[64],
pReferal[32+1],
pLevel,
pSex,
pAdmin,
bool:pLogged
}
new pData[MAX_PLAYERS][player_data]; //хранение информации авторизованого игрока
new WrongPass[MAX_PLAYERS];
new TextStr[512]; //массив для форматирования самого диалога регистрации

/* MYSQL */
new MySQL; //для записи connection handle (номер соединения)

 

 

/* Форварды */
forward IsValidAccount(playerid);
forward OnPlayerRegister(playerid);
forward LoadPlayerAccount(playerid)

 

 

public LoadPlayerAccount(playerid)
{
if(cache_get_row_count(MySQL) == 1)
{
/* Грузим данные из БД на сервер */
pData[playerid][pDatabaseID] = cache_get_field_content_int(0, "ID", MySQL);
cache_get_field_content(0, "Referal", pData[playerid][pReferal], MySQL, 64);
pData[playerid][pLevel] = cache_get_field_content_int(0, "Level", MySQL);
pData[playerid][pSex] = cache_get_field_content_int(0, "Sex", MySQL);
pData[playerid][pAdmin] = cache_get_field_content_int(0, "Admin", MySQL);

pData[playerid][pLogged] = true; //авторизуем
SendClientMessage(playerid, -12, "Данные успешно загружены. Приятной игры!");
SpawnPlayer(playerid);

/* Тестовые функции для првоерки загрузки */
print("\n\n============================================== ===");
printf("Nickname: %s", pData[playerid][pName]);
printf("DB: %i", pData[playerid][pDatabaseID]);
printf("Referal: %s", pData[playerid][pReferal]);
printf("Level: %d", pData[playerid][pLevel]);
printf("Sex: %d", pData[playerid][pSex]);
printf("Admin: %d", pData[playerid][pAdmin]);
print("=================================================\ n\n");
}
return 1;
}

public IsValidAccount(playerid)
{
if(cache_get_row_count(MySQL) == 1) //если нашло 1 нужный нам аккаунт
{
cache_get_row(0, 2, pData[playerid][pPassword], MySQL, 64); //заправшиваем пароль для проверки

SendClientMessage(playerid, -1, "Ваш аккаунт успешно найден в базе данных. Пройдите пожалуйста авторизацию");
ShowPlayerDialog(playerid, LOG_DIALOG, DIALOG_STYLE_INPUT, "Авторизация", "Ваш аккаунт найден в базе данных\nПожалуйста, авторизуйтесь..", ">>", "Выход");
}
else //если 1 нужный нам аккаунт не найден
{
SendClientMessage(playerid, -1, "Ваш аккаунт не найден в базе данных. Пройдите пожалуйста регистрацию");
ResetRegData(playerid); //обнуляем данные
ShowRegisterDialog(playerid);
}
return 1;
}
public OnPlayerRegister(playerid)
{
pData[playerid][pDatabaseID] = cache_insert_id(); //записываем ид аккаунта в базе. По нему мы будем сохранять аккаунт. В БД он добавляется автоматически
pData[playerid][pLevel] = 1;
pData[playerid][pAdmin] = 0;

pData[playerid][pLogged] = true; //авторизуем

SpawnPlayer(playerid);
SendClientMessage(playerid, -1, "Поздравляем с успешной регистрацией!!!");
return 1;
}

 

 

stock ResetRegData(playerid)
{
RegData[playerid][pAcceptRules] = 0;
RegData[playerid][pSex] = 0;
RegData[playerid][pReferal] = EOS;
RegData[playerid][pPassword] = EOS;
return 1;
}
stock RemovePlayerData(playerid)
{
pData[playerid][pLevel] = 1;
pData[playerid][pSex] = 0;
pData[playerid][pAdmin] = 0;
pData[playerid][pLogged] = false;
WrongPass[playerid] = 0;
return 1;
}

stock UpdatePlayerData(playerid)
{
if(!pData[playerid][pLogged]) return 1; //не сохраняем, если игрок не авторизован

new save_query[512]; //замените этот массив на свой массив, который вы используете для запросов, если он есть
new str_q[128];

format(str_q, sizeof str_q, "UPDATE `"TABLE_ACCOUNTS"` SET "), strcat(save_query, str_q);

format(str_q, sizeof str_q, "`Nickname` = '%s',", pData[playerid][pName]), strcat(save_query, str_q);
format(str_q, sizeof str_q, "`Password` = '%s',", pData[playerid][pPassword]), strcat(save_query, str_q);
format(str_q, sizeof str_q, "`Level` = '%d',", pData[playerid][pLevel]), strcat(save_query, str_q);
format(str_q, sizeof str_q, "`Sex` = '%d',", pData[playerid][pSex]), strcat(save_query, str_q);
format(str_q, sizeof str_q, "`Referal` = '%s',", pData[playerid][pReferal]), strcat(save_query, str_q);
format(str_q, sizeof str_q, "`Admin` = '%d'", pData[playerid][pAdmin]), strcat(save_query, str_q);

format(str_q, sizeof str_q," WHERE `ID` = '%i'", pData[playerid][pDatabaseID]), strcat(save_query, str_q);
mysql_tquery(MySQL, save_query, "", "");
return 1;
}
stock ShowRegisterDialog(playerid)
{
new str_local[64], switch_str[32];
TextStr = "\0"; //предварительно очищаем

switch(RegData[playerid][pAcceptRules]) //тут мы просто проверяем, сколько страниц правил просмотрел игрок
{
case 0,1: switch_str = "Не ознакомлены";
default: switch_str = "Ознакомлены";
}
format(str_local, sizeof(str_local), "Правила сервера\t{86a366}%s\n", switch_str), strcat(TextStr, str_local);

switch(RegData[playerid][pSex]) //тут мы просто проверяем, сколько страниц правил просмотрел игрок
{
case 1: switch_str = "Мужской";
case 2: switch_str = "Женский";
default: switch_str = "Не указан";
}
format(str_local, sizeof(str_local), "Пол персонажа\t{86a366}%s\n", switch_str), strcat(TextStr, str_local);

/*
Что до пункта реферал, то тут уж можете доделывать, либо заменить на какой угодно параметр
Я же для наглядности просто буду проверять длинну никнейма
*/
if(strlen(RegData[playerid][pReferal]) {
format(str_local, sizeof(str_local), "Реферал\t{86a366}Не указан\n"), strcat(TextStr, str_local);
}
else format(str_local, sizeof(str_local), "Реферал\t{86a366}%s\n", RegData[playerid][pReferal]), strcat(TextStr, str_local);

if(strlen(RegData[playerid][pPassword]) MAX_PASS_LENGTH)
{
format(str_local, sizeof(str_local), "Пароль\t{86a366}Не указан\n"), strcat(TextStr, str_local);
}
else //если пароля подходит по длинне
{
#if ENCRYPT_PASS

new encrypt_pass[64];
strcat(encrypt_pass, RegData[playerid][pPassword], 64); //лублируем текст, чтобы над ним можно было совершать манипуляции
strdel(encrypt_pass, 0, strlen(encrypt_pass)-3); //удаляем все символы, кроме 3 последних
for(new s; s
format(str_local, sizeof(str_local), "Пароль\t{86a366}%s\n", encrypt_pass), strcat(TextStr, str_local); //тут необходимо показать измененную строчку

#else

/*
Тут мы не используем шифрование, поэтому вставляем RegData[playerid][pPassword]
*/
format(str_local, sizeof(str_local), "Пароль\t{86a366}%s\n", RegData[playerid][pPassword]), strcat(TextStr, str_local);

#endif
}
format(str_local, sizeof(str_local), "Завершить регистрацию >>"), strcat(TextStr, str_local);

ShowPlayerDialog(playerid, REG_DIALOG, DIALOG_STYLE_TABLIST, "Регистрация", TextStr, ">>", "");
return 1;
}

 

 

LoadPlayerAccount(playerid) - загружает данные игрока после успешной авторизации
IsValidAccount(playerid) - проверяет, существует ли в базе данных аккаунт
OnPlayerRegister(playerid) - вызывается после самой регистрации и добавления аккаунта в базу данных
ResetRegData(playerid) - обнуляет переменные, которые мы использовали для заполнения полей при регистрации
RemovePlayerData(playerid) - обнуляет переменные, используемые для хранения данных игрока (необходимо использовать как минимум при коннекте или дисконнекте)
UpdatePlayerData(playerid) - сохраняет данные авторизованного игрока

 

 

']В паблик OnGameModeInit добавляем код, который соединит сервер с нашей базой данных

MySQL = mysql_connect(SQL_HOST, SQL_USER, SQL_DB, SQL_PASS, SQL_PORT, SQL_RECONNECT, SQL_POOLSIZE);
mysql_log(LOG_ALL, LOG_TYPE_HTML);
if(mysql_errno() != 0) print("[-] MYSQL Connection does not exist");
else
{
print("[+] MYSQL Connection accepted ");
mysql_query(MySQL, "SET NAMES 'cp1251'",false);
mysql_set_charset("cp1251", MySQL);
}

 

 

mysql_close(); //закрываем соединение

 

 

if(!pData[playerid][pLogged]) return 0;

 

 

new db_str[128]; //создаем массив для формирования запроса
RemovePlayerData(playerid); //очищаем данные энуменатора player_data

GetPlayerName(playerid, pData[playerid][pName], MAX_PLAYER_NAME); //запрашиваем имя

/* форматируем и отправляем запрос */
mysql_format(MySQL, db_str, sizeof(db_str), "SELECT * FROM `"TABLE_ACCOUNTS"` WHERE `Nickname` = '%e'", pData[playerid][pName]);
mysql_pquery(MySQL, db_str, "IsValidAccount", "d", playerid);

SetSpawnInfo(playerid, 0, 222, 1128.9762,-1488.1531,22.7690,360.0000, 0, 0, 0, 0, 0, 0); //устанавливаем данные для спавна (необходимо для теста)

 

 

case LOG_DIALOG:
{
new wrong_pass[8];
new load_query[512];
if(!response)
{
/*
Тут необходимо указать действие при отказе ввода
я для наглядности поставлю кик
*/
Kick(playerid);
return 1;
}
if(strlen(pData[playerid][pPassword]) MAX_PASS_LENGTH)
{
ShowPlayerDialog(playerid, LOG_DIALOG, DIALOG_STYLE_INPUT, "Авторизация", "Неправильная длинна пароля! Попробуйте ещё раз", ">>", "Выход");
return 1;
}
if(!strcmp(pData[playerid][pPassword], inputtext, true))
{
mysql_format(MySQL, load_query, 512, "SELECT * FROM `"TABLE_ACCOUNTS"` WHERE `Nickname` = '%s' AND `Password` = '%s'", pData[playerid][pName], pData[playerid][pPassword]);
mysql_tquery(MySQL, load_query, "LoadPlayerAccount", "d", playerid);
SendClientMessage(playerid, -12, "Идет загрузка данных игрока...");
}
else
{
WrongPass[playerid] ++;
if(WrongPass[playerid] > 2) //если больше двух ошибок, то всё!!!
{
/*
Тут необходимо указать действие при трёхкратном введении неправильного пароля
я опять же для наглядности поставлю кик
*/
Kick(playerid);
return 1;
}
ShowPlayerDialog(playerid, LOG_DIALOG, DIALOG_STYLE_INPUT, "Авторизация", "Вы ввели неправильный пароль!!! Попробуйте ещё раз", ">>", "Выход");
format(wrong_pass, 8, "~r~%d/3", WrongPass[playerid]);
GameTextForPlayer(playerid, wrong_pass, 3000, 6);
}
return 1;
}
case REG_DIALOG:
{
switch(listitem)
{
case 0: //правила
{
if(RegData[playerid][pAcceptRules] > 1) //если прочитал все страницы правил
{
SendClientMessage(playerid, -1, "Вы ознакомилены с правилами");
ShowRegisterDialog(playerid);
return 1;
}
ShowPlayerDialog(playerid, REG_DIALOG+1, DIALOG_STYLE_MSGBOX, "Правила сервера", "Правило #1 Не наруйшай правил\nПравило #2 Будь паинькой", ">>", "");
RegData[playerid][pAcceptRules] = 1; //игрок посмотрел первую страницу
}
case 1: //пол персонажа
{
ShowPlayerDialog(playerid, REG_DIALOG+2, DIALOG_STYLE_MSGBOX, "Выбор пола персонажа", "Выберите пол вашего персонажа", "Мужской", "Женский");
}
case 2:
{
ShowPlayerDialog(playerid, REG_DIALOG+3, DIALOG_STYLE_INPUT, "Реферал", "Введите имя игрока, который пригласил вас на сервер", ">>", "Назад");
}
case 3:
{
ShowPlayerDialog(playerid, REG_DIALOG+4, DIALOG_STYLE_INPUT, "Пароль", "Придумайте пароль для вашего аккаунта", ">>", "Назад");
}
case 4: //завершение регистрации
{
if(RegData[playerid][pAcceptRules] if(!RegData[playerid][pSex]) return SendClientMessage(playerid, -1, "Ошибка: Вы не указали пол персонажа!"), ShowRegisterDialog(playerid);
if(strlen(RegData[playerid][pPassword]) MAX_PASS_LENGTH) return SendClientMessage(playerid, -1, "Ошибка: Вы не указали пароль!"), ShowRegisterDialog(playerid);

new add_db[512]; //замените этот массив на свой массив, который вы используете для запросов, если он есть

/* Переносим введенные данные в конструкцию для хранения информации об аккаунте */

format(pData[playerid][pReferal], 64, RegData[playerid][pReferal]);
format(pData[playerid][pPassword], 64, RegData[playerid][pPassword]);
RegData[playerid][pSex] = pData[playerid][pSex];

/* Отправляем запрос на добавление аккаунта в базу */

mysql_format(MySQL, add_db, 512, "INSERT INTO `"TABLE_ACCOUNTS"` (`Nickname`, `Password`, `Level`, `Sex`, `Referal`, `Admin`) VALUES ('%s', '%s', 1, '%d', '%s', 0)", pData[playerid][pName], pData[playerid][pPassword], pData[playerid][pSex], pData[playerid][pReferal]);
mysql_pquery(MySQL, add_db, "OnPlayerRegister", "d", playerid);

ResetRegData(playerid); //обнуляем даныне регистрации

/*
Запрос на внесение аккаунта в базу добавлен.
В паблике OnPlayerRegister внесутся стандартные данные и произойдет спавн игрока
*/
}
}
return 1;
}
case REG_DIALOG+1:
{
if(RegData[playerid][pAcceptRules] > 1)
{
SendClientMessage(playerid, -1, "Вы успешно ознакомились с правилами сервера");
ShowRegisterDialog(playerid);
return 1;
}
ShowPlayerDialog(playerid, REG_DIALOG+1, DIALOG_STYLE_MSGBOX, "Правила сервера", "Правило #3 Не флуди\nПравило #4 Не вреди", ">>", "");
RegData[playerid][pAcceptRules] = 2;
return 1;
}
case REG_DIALOG+2:
{
if(response) RegData[playerid][pSex] = 1;
else RegData[playerid][pSex] = 2;
SendClientMessage(playerid, -1, "Пол успешно установлен");

ShowRegisterDialog(playerid);
return 1;
}
case REG_DIALOG+3:
{
if(!response) return ShowRegisterDialog(playerid);

if(strlen(inputtext) 32)
{
SendClientMessage(playerid, -1, "Имя реферала должно содержать минимум 3 и максимум 32 символа");
ShowPlayerDialog(playerid, REG_DIALOG+3, DIALOG_STYLE_INPUT, "Реферал", "Введите имя игрока, который пригласил вас на сервер", ">>", "Назад");
return 1;
}
format(RegData[playerid][pReferal], 32, inputtext);
SendClientMessage(playerid, -1, "Реферал успешно указан");

ShowRegisterDialog(playerid);
return 1;
}
case REG_DIALOG+4:
{
/*
Тут вы можете поизвращаться над паролем: добавляйте мд5, проверяйте пароль на символы/кириллицу и т.д. и т.п. на ваш взгляд
Это базовая версия системы регистрации, поэтому я не буду добавлять никаких проверок, а оставлю это удовольствие вам! :)
*/
if(strlen(inputtext) MAX_PASS_LENGTH)
{
SendClientMessage(playerid, -1, "Недопустимая длинна пароля");
ShowPlayerDialog(playerid, REG_DIALOG+4, DIALOG_STYLE_INPUT, "Пароль", "Придумайте пароль для вашего аккаунта", ">>", "Назад");
return 1;
}
format(RegData[playerid][pPassword], 64, inputtext);
SendClientMessage(playerid, -1, "Пароль успешно указан");

ShowRegisterDialog(playerid);
return 1;
}
 

Если вы используете оператор условия if, то это легко исправить заменив case REG_DIALOG... на if(dialogid == REG_DIALOG...)

С кодом справились, переходим к аспектам.

 

 

']- Вы можете включать/отключать шифрование пароля в переключателе меняя значение идендификатора ENCRYPT_PASS на 1 и 0 соответственно
- В список можно легко добавить новый пункт. Для этого в энуменатор regdata нужно добавить новую переменную, а в диалог регистрации дописать название пункта по изложенному примеру
- Вы можете добавлять сколько угодно страниц правил просто меняя значение последней в условиях в диалоге REG_DIALOG+1

 

 

 

На этом всё :)
И по традиции, если у вас возникли вопросы или предложения, пишите в эту тему..
Автор - неизвестно. или же Atu или SNAPE
На сторонних pawn-порталах эта тема может быть продублирована мной под ником Atu или SNAPE.
В этой системе нет md5 шифрования, нет проверок на кириллицу и т.п., но это всё можно легко добавить, используя мануалы из интернета.

Всем приятной работы! :)

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×

Важная информация

Мы разместили cookie-файлы на ваше устройство, чтобы помочь сделать этот сайт лучше. Вы можете изменить свои настройки cookie-файлов, или продолжить без изменения настроек.