[закрыто] не выходит окно регистрации.
Я заменил строчку, но сейчас у меня не отвечает сервер. И в mysql_log выдает данную ошибку:
[ERROR] mysql_connect – empty connection data specified
[ERROR] mysql_errno – invalid connection handle (id: 1)
Отредактировано26 февраля, 2020пользователемefeffefe
Мануал – урок – faq регистрация и авторизация на cef mysql
Cегодня мы с Вами напишем с нуля полноценный скрипт регистрации и авторизации для сервера rage mp. В качестве интерфейса мы не будем использовать команды, а сразу сделаем “красиво” на
CEF
. В качестве базы данных будем использовать
MySQL
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
Видео версия как обычно на youtube канале:
Для начала я нашел в Интернете простенький HTML шаблон страницы авторизации:
https://codepen.io/colorlib/pen/rxddKy
Помещаем его в папку cef нашего клиентского скрипта accounts. Туда же ложим стили (style.css) и браузерные скрипты (script.js), которые мы напишем дальше.
Я немного модифицировал шаблон:
1. Добавил фоновую картинку
2. Расставил id для полей ввода, чтобы было удобнее работать с ними.
3. Убрал неиспользуемые стили
4. Добавил блок для вывода ошибок
5. Перевел на русский язык.
В итоге html файл выглядит так:
Теперь при входе игрока на сервер ему будет показываться на форма входа.
Вернемся теперь к index.html и браузерной части. У нас есть две формы (register и login). Форма login отображается по-умолчанию, а register скрыта в стилях. Внизу каждой формы есть ссылка на другую и при помощи функций showLogin() и showRegister() мы будем переключаться между ними. Также для кнопок входа и регистрации добавлен вызов функций registerAttempt() и loginAttempt(), которые будут вызываться по событию onclick
В script.js добавим реализацию этих функций. С переключением между формами все просто:
При отправке запроса на вход или регистрацию нам нужно считать содержимое полей формы, выполнить их базовые проверки и передать в клиент rage mp
Они максимально простые и просто передают данные с браузера дальше на сервер при помощи callRemote. Напоминаю что в качестве data у нас JSON строка с логином и паролем. В таком виде мы передаем ее дальше, поскольку callRemote также позволяет нам передавать только простые строки и числа.
На серверной стороне прежде чем обработать события onLoginAttempt и onRegisterAttempt нужно кое-что подготовить:
- Добавить пакет mysql и настроить подключение к серверу MySQL. Структура базы данных и само подключение будет таким же, как и в уроке по подключению MySQL. У нас будет 1 таблица accounts с тремя столбцами: id, login и password
- Добавить пакет bcrypt для генерации хэша паролей и его проверки.
JavaScript:
mp.events.add('onLoginAttempt', (player, data) => {
data = JSON.parse(data); // преобразовуем данные из json в объект
DB.query('SELECT * FROM accounts WHERE login = ? LIMIT 1', [data.login], function (error, results) { // ищем аккаунт по логину
if(results.length == 0) return player.call('showAuthError', ['Неверный Логин и/или Пароль']); // если аккаунт с таким логином не найден, то возвращаем на клиент текст ошибки
const passwordHash = results[0].password; // если же аккаунт есть, то берем его хеш пароля
bcrypt.compare(data.password, passwordHash, function(err, isMatched) { // сравниваем хэши паролей из базы данных и того что указал пользователь
if( isMatched ) return player.call('hideLoginDialog'); // если пароли не совпадают, значит пользователь авторизовался успешно
player.call('showAuthError', ['Неверный Логин и/или Пароль']); // если же пароли не совпали, то опять таки возвращаем на клиент текст ошибки при помощи события showAuthError
});
});
});
а клиенте событие showAuthError просто показывает текст ошибки в форме.
А при успешном входе мы скрываем окно авторизации и считаем что игрок авторизовался
Для регистрации на серверной стороне обработчик onRegisterAttempt будет немного сложнее. Прежде чем добавить аккаунт нам нужно проверить его на уникальность и его такой логин уже есть в базе данных, то выдавать ошибку.
JavaScript:
mp.events.add('onRegisterAttempt', (player, data) => {
data = JSON.parse(data);
DB.query('SELECT id FROM accounts WHERE login = ?', [data.login], function (error, results) { // Проверяем уникальность логина
if(results.length > 0) return player.call('showAuthError', ['Аккаунт с таким Логином уже существует']); // Если такой логин уже есть, то возвращаем ошибку
bcrypt.hash(data.password, saltRounds, function(err, passwordHash) { // Создаем хэш пароля
DB.query('INSERT INTO accounts SET login = ?, password = ?', [data.login, passwordHash], function (error, results) { // Добавляем аккаунт в базу данных
player.call('hideLoginDialog'); // Скрываем окно авторизации
});
});
});
});
Для тех кто захочет дальше ковырять эту форму, напишу парочку идей того, что можно улучшить и доработать:
1. Добавить защиту от перебора паролей. Кикать после 3 неправильных вводов.
2. Написать функцию isPlayerLoggedIn() которая будет возвращать true если игрок авторизовался и false если еще нет.
3. Добавить столбец position в таблицу accounts. Записывать туда позицию игрока при выходе с сервера.
4. Добавить возможность восстановить пароль. Для этого понадобиться добавить поле для email аккаунта и какой-то способ чтобы отправлять электронные письма с сервера.
Архив
тут ( СКАЧАТЬ )
avtor –
LEV ANGEL
Не появляется окно регистрации когда происходит заход на локальный сервер
[17:02:52 04/30/20] [ERROR] CMySQLQuery::Execute[PlayerRegition] – (error #1146) Table ‘sunlightrp.accounts’ doesn’t exist (Query: “SELECT `Level` FROM `accounts` WHERE `Name` = ‘Yan_Shershen'”)
Собственно, что означают это ошибки. 1. Не произошло подключение к базе, видно где-то ошибся, когда данные по подключению вставлял, а вторая говорит, что таблица с аккаунтами не найдена. Скорей всего вторая вытекает из первой, т.е не осуществилось подключение, и поэтому он не смог ее найти. Или же после еррора подключение все таки смогло наладится(такое случается бывает), но таблица все так же найдена. Просмотри, правильно ли базу подключил в моде и есть ли таблица sunlightrp.accounts в базе данных.
Нету окна авторизации/регистрации
———-
Loaded log file: “server_log.txt”.
———-
SA-MP Dedicated Server
———————-
v0.3e, (C)2005-2022 SA-MP Team
[22:58:00]
[22:58:00] Server Plugins
[22:58:00] ————–
[22:58:00] Loading plugin: crashdetect
[22:58:00] CrashDetect v4.15.1 is OK.
[22:58:00] Loaded.
[22:58:00] Loading plugin: mysql
[22:58:00] >> plugin.mysql: R39-3 successfully loaded.
[22:58:00] Loaded.
[22:58:00] Loading plugin: sscanf
[22:58:00]
[22:58:00] ===============================
[22:58:00] sscanf plugin loaded.
[22:58:00] Version: 2.8.1
[22:58:00] (c) 2022 Alex “Y_Less” Cole
[22:58:00] ===============================
[22:58:00] Loaded.
[22:58:00] Loading plugin: streamer
[22:58:00]
*** Streamer Plugin v2.7.8 by Incognito loaded ***
[22:58:00] Loaded.
[22:58:00] Loaded 4 plugins.
[22:58:00]
[22:58:00] Filterscripts
[22:58:00] —————
[22:58:00] Loading filterscript ‘attachments.amx’…
[22:58:01] Loading filterscript ‘ce.amx’…
[22:58:01]
————————————–
[22:58:01] CamEditor by Drebin
[22:58:01] ————————————–
[22:58:01] Loading filterscript ‘easyCamera.amx’…
[22:58:01] Loading filterscript ‘fly.amx’…
[22:58:01] Loading filterscript ‘fsdebug.amx’…
[22:58:01]
*********************
* SA:MP DEBUG 0.2 *
[22:58:01] * By Simon Campbell *
*********************
[22:58:01] * Version: 0.5d *
*********************
[22:58:01] * — LOADED *
*********************
[22:58:01] Loading filterscript ‘npc_record.amx’…
[22:58:01] Loading filterscript ‘TextDrawEditor1.0.amx’…
[22:58:01]
————————————–
[22:58:01] Text Draw Editor 1.0RC2 by Zamaroht for SA-MP 0.3 Loaded.
[22:58:01] ————————————–
[22:58:01] Loaded 7 filterscripts.
[22:58:01] OnGameo
[22:58:01] Server password has been removed.
[22:58:01] MySQL connection: OK
[22:58:01]
——————————
[22:58:01] Start date: 24.06.2022
[22:58:01] ——————————
[22:58:01] Number of vehicle models: 27
[22:58:01] [serv_log] Load warehouse. Time: 0 ms.
[22:58:01] [serv_log] Load job business. Load: 4 b. Time: 1 ms.
[22:58:01] [serv_log] Load auto business. Load: 2 b. Time: 1 ms.
[22:58:02] [serv_log] Load kvartiry. Load: 461 b. Time: 241 ms.
[22:58:02] [serv_log] Load houses. Load: 115 h. Time: 9 ms.
[22:58:02] [serv_log] Load business. Load: 42 b. Time: 5 ms.
Система регистрации на mysql
Здравствуйте, сегодня я научу вас создавать простую систему регистрации/авторизации!
Первым делом качаем отсюда и подключаем инклуд и плагин, включаем denwer (phpmyadmin).
#include <mysql>
В начало мода добавляем:
#define MYSQL_HOST “localhost”
#define MYSQL_USER “root”
#define MYSQL_DATABASE “bd”
#define MYSQL_PASSWORD “”
#define MYSQL_CONNECT_INFO MYSQL_HOST,MYSQL_USER,MYSQL_DATABASE,MYSQL_PASSWORD
new mysql_connect_ID;
Где localhost/root/bd – ваш хост/имя пользователя/название базы соответственно.
В OnGamemodeInit:
mysql_connect_ID = mysql_connect(MYSQL_CONNECT_INFO);
Тем самым мы подключаем мод к нашей базе.
Далее создаём enum (данные, которые мы будет загружать и выгружать из бд. )
Теперь нам нужно сделать поиск аккаунта при коннекте. В OnPlayerRequestClass:
GetPlayerName(playerid, pInfo[playerid][pName], MAX_PLAYER_NAME);
new query_string[52 MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), “SELECT * FROM `accounts` WHERE `player_name` = ‘%s'”, pInfo[playerid][pName]);
mysql_function_query(mysql_connect_ID, query_string, true, “FindPlayerInTable”,”i”, playerid);
И создаём паблик в конце мода:
forward FindPlayerInTable(playerid);
public FindPlayerInTable(playerid)
{
new rows, fields;
cache_get_data(rows, fields);
if(!rows)
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, “Регистрация нового пользователя”, “Введите пароль для регистрации нового аккаунта:”, “Регистрация”, “Выход”);
}
else
{
ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, “Авторизация”, “Введите пароль от аккаунта для того, чтоб продолжить игру:”, “Вход”, “Выход”);
cache_get_field_content(0, “password”, pInfo[playerid][pPassword], mysql_connect_ID, 30);
}
return 1;
}
Теперь создаём макросы на диалоги. Делается это для того, чтобы вы не запутались при создании новых диалогов (не обязательно).
В начало мода:
Далее создаём сами диалоги. В OnDialogResponse:
switch(dialogid)
{
case dRegister:
{
if(!response)
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_MSGBOX, “Оповещение”, “{FFFFFF}Вы были кикнуты с сервера.n{FF0000}Причина: Отказ от регистрации.n{FFFFFF}Для выхода с сервера введите “/q” в чат”, “Вход”, “Выход”);
return Kick(playerid);
}
if(!strlen(inputtext)) return ErrorDialogMessage(playerid, dRegister, 0);
else if(strlen(inputtext) < 4) return ErrorDialogMessage(playerid, dRegister, 1);
else if(strlen(inputtext) > 30) return ErrorDialogMessage(playerid, dRegister, 2);
for(new i = strlen(inputtext)-1; i != -1; i–)
{
switch(inputtext
)
{
case ‘0’..’9′, ‘а’..’я’, ‘a’..’z’, ‘А’..’Я’, ‘A’..’Z’: continue;
default: return ErrorDialogMessage(playerid, dRegister, 3);
}
}
strins(pInfo[playerid][pPassword], inputtext, 0);
CreateNewAccount(playerid, pInfo[playerid][pPassword]);
return 1;
}
case dLogin:
{
if(!response)
{
ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_MSGBOX, “Оповещение”, “{FFFFFF}Вы были кикнуты с сервера.n{FF0000}Причина: Отказ от авторизации.n{FFFFFF}Для выхода с сервера введите “/q” в чат”, “Вход”, “Выход”);
return Kick(playerid);
}
if(!strlen(inputtext)) return ErrorDialogMessage(playerid, dLogin, 0);
for(new i = strlen(inputtext)-1; i != -1; i–)
{
switch(inputtext)
{
case ‘0’..’9′, ‘а’..’я’, ‘a’..’z’, ‘А’..’Я’, ‘A’..’Z’: continue;
default: return ErrorDialogMessage(playerid, dLogin, 1);
}
}
if(!strcmp(pInfo[playerid][pPassword], inputtext))
{
new query_string[52 MAX_PLAYER_NAME];
format(query_string, sizeof(query_string), “SELECT * FROM `accounts` WHERE `player_name` = ‘%s'”, pInfo[playerid][pName]);
mysql_function_query(mysql_connect_ID, query_string, true, “UploadPlayerAccount”,”i”, playerid);
}
else ErrorDialogMessage(playerid, dLogin, 2);
return 1;
}
}
Создаём функции для этих диалогов. В конец мода:
stock CreateNewAccount(playerid, password[])
{
new query_string[70 MAX_PLAYER_NAME 30];
format(query_string, sizeof(query_string), “INSERT INTO `accounts` (`player_name`, `password`) VALUES (‘%s’, ‘%s’)”, pInfo[playerid][pName], password);
mysql_function_query(mysql_connect_ID, query_string, false, “”, “”);
format(query_string, sizeof(query_string), “Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!”, pInfo[playerid][pName]);
SendClientMessage(playerid, 0xFFFFFF00, query_string);
SpawnPlayer(playerid);
return 1;
}
Загрузка аккаунта. В конец:
forward UploadPlayerAccount(playerid);
public UploadPlayerAccount(playerid)
{
pInfo[playerid][pID] = cache_get_field_content_int(0, “ID”, mysql_connect_ID);
SendClientMessage(playerid, 0xFFFFFF00, “Вы успешно авторизировались!”);
SpawnPlayer(playerid);
return 1;
}
Теперь нужно создать функцию, которая хронит сообщения. Создаём Stock в конце мода.
stock ErrorDialogMessage(playerid, dialogid, error_id)
{
switch(dialogid)
{
case dRegister:
{
switch(error_id)
{
case 0:
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, “Регистрация нового пользователя”, “{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить регистрацию не введя пароль!nВведите пароль для регистрации нового аккаунта:n{C0C0C0}Примечание:n{666666}- Пароль чувствителен к регистру.n- Пароль должен содержать от 4 до 30 символов.n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).”, “Регистрация”, “Выход”);
}
case 1:
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, “Регистрация нового пользователя”, “{FF0000}Ошибка: {FFFFFF}Пароль слишком короткий!nВведите пароль для регистрации нового аккаунта:n{C0C0C0}Примечание:n{666666}- Пароль чувствителен к регистру.n- Пароль должен содержать от 4 до 30 символов.n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).”, “Регистрация”, “Выход”);
}
case 2:
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, “Регистрация нового пользователя”, “{FF0000}Ошибка: {FFFFFF}Пароль слишком длинный!nВведите пароль для регистрации нового аккаунта:n{C0C0C0}Примечание:n{666666}- Пароль чувствителен к регистру.n- Пароль должен содержать от 4 до 30 символов.n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).”, “Регистрация”, “Выход”);
}
case 3:
{
ShowPlayerDialog(playerid, dRegister, DIALOG_STYLE_INPUT, “Регистрация нового пользователя”, “{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!nВведите пароль для регистрации нового аккаунта:n{C0C0C0}Примечание:n{666666}- Пароль чувствителен к регистру.n- Пароль должен содержать от 4 до 30 символов.n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).”, “Регистрация”, “Выход”);
}
}
return 1;
}
case dLogin:
{
switch(error_id)
{
case 0:
{
ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, “Авторизация”, “{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить авторизацию не введя пароль!nВведите пароль от аккаунта для входа на сервер:”, “Вход”, “Выход”);
}
case 1:
{
ShowPlayerDialog(playerid, dLogin, DIALOG_STYLE_INPUT, “Авторизация”, “{FF0000}Ошибка: {FFFFFF}Введённый пароль содержит запрещённые символы!nВведите пароль от аккаунта для входа на сервер:”, “Вход”, “Выход”);
}
case 2:
{
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, dLogin, DIALOG_STYLE_MSGBOX, “Оповещение”, “{FFFFFF}Вы были кикнуты с сервера.n{FF0000}Причина: Превышен лимит попыток на ввод пароля.n{FFFFFF}Для выхода с сервера введите “/q” в чат”, “Вход”, “Выход”);
return Kick(playerid);
}
}
SetPVarInt(playerid, “WrongPassword”, GetPVarInt(playerid, “WrongPassword”) 1);
}
}
return 1;
}
}
return 1;
}
Основа готова. Теперь осталось сделать сохранение.
Код:
stock SaveAccount(playerid)
{
new query_string[(21) (20 MAX_PLAYER_NAME) (19 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 `player_name` = '%s'", query_string, pInfo[playerid][pName]);
mysql_function_query(mysql_connect_ID, query_string, false, "", "");
return 1;
}
И в OnPlayerDisconnect:
Тем самым мы сохраняем аккаунт при выходе с сервера.
Осталось дело за малым. Создать нашу таблицу.
Заходим в phpmyadmin (localhost), затем нажимаем на базы данных, затем в поле, где написано “Создание базы данных” мы вводим название нашей таблицы, которую мы вводили в “MYSQL_DATABASE”. В нашем случае это “BD”
Мы создали базу, теперь нужно создать нужные нам таблицы. В нашем случае она одна – accounts. Название таблицы пишите всегда как указываете в моде т.к одна не та буква/раскладка – вы не подключитесь к этой таблице.
Создаём таблицу, в поле вводим “accounts”, количество столбцов – 3.
Далее настраиваем саму таблицу. Первый столбец называется ID, тип которого INT, а длинна 11. Далее, чтобы иды не мешались – ищем A_I (Auto Increment) и ставим галочку.
Второй столбец – имя: player_name, тип: varchar, длинна: 24, остальное не трогаем.
Ну и последний столбец – это пароль. Имя столбца: password, тип: varchar, длина – 30.
Нажимаем сохранить и слева у нас есть наша таблица.
Кстати, также можно добавить запрет на сообщения в чат при регистрации/авторизации.
Ко всем new:
В public OnPlayerText(playerid, text[]):
if(gPlayerLogged[playerid] == 0)
{
SendClientMessage(playerid, -1, “Авторизуйся на сервере.”);
return 0;
}
В OnPlayerConnect:
gPlayerLogged[playerid] = 1;
Автор системы регистрации: Неизвестно
Автор системы запрета чата: Doberman
Система регистрации на сервере samp – статьи по gta и мультиплеерам grand theft auto
Для начала давайте скачаем необходимые инклюды. Скачать
Перед нами 5 папки: pawno, внутри нее папка include, внутри нее папка YSI; PHP; scriptfiles, внутри нее папка YSI.
Теперь разместим файлы в папках своего сервера. Из архива берем папку YSI (которая лежит в pawno/include) и помещаем ее в свою папку pawno/includes. Дальше из архива в папке scriptfiles берем папку YSI (уже другую!) и помещаем ее в папку scriptfiles вашего сервера. И папку PHP помещаем в главную директорию вашего сервера. Все, с файлами мы закончили.
Теперь открываем ваш мод и наверх ко всем инклюдам добавляем строку
#include <YSIy_ini>
Приступим к основной части. Во-первых добавляем ко всем #define вот эти строки:
#define DIALOG_REGISTER 1
#define DIALOG_LOGIN 2
Вот эту строчку:
#define PATH “/Users/%s.ini”
И цвета, которые нам еще понадобятся:
#define COL_WHITE “{FFFFFF}”
#define COL_RED “{F81414}”
#define COL_GREEN “{00FF22}”
#define COL_LIGHTBLUE “{00CED1}”
Далее нам необходимо создать некий “хранитель” информации:
После всех new (если они у вас есть) добавляем вот это:
enum pInfo
{
pPass,
pCash,
pAdmin,
pKills,
pDeaths
}
new PlayerInfo[MAX_PLAYERS][pInfo];
Теперь нам необходимо создать stock, чтобы наша информация сохранялась (деньги, пароль, уровень админки, кол-во убийств и смертей)
forward LoadUser_data(playerid,name[],value[]);
public LoadUser_data(playerid,name[],value[])
{
INI_Int(“Password”,PlayerInfo[playerid][pPass]);
INI_Int(“Cash”,PlayerInfo[playerid][pCash]);
INI_Int(“Admin”,PlayerInfo[playerid][pAdmin]);
INI_Int(“Kills”,PlayerInfo[playerid][pKills]);
INI_Int(“Deaths”,PlayerInfo[playerid][pDeaths]);
return 1;
}
Дальше создаем вот этот stock
stock UserPath(playerid)
{
new string[128],playername[MAX_PLAYER_NAME];
GetPlayerName(playerid,playername,sizeof(playername));
format(string,sizeof(string),PATH,playername);
return string;
}
И вот этот:
stock udb_hash(buf[]) {
new length=strlen(buf);
new s1 = 1;
new s2 = 0;
new n;
for (n=0; n<length; n )
{
s1 = (s1 buf[n]) % 65521;
s2 = (s2 s1) % 65521;
}
return (s2 << 16) s1;
}
Теперь мы должны сделать так, чтобы при подключении игрока на сервер ему на экран выводилось диалоговое окно.
В паблик
public OnPlayerConnect(playerid)
{
return 1;
}
Перед return 1; добавить вот это
if(fexist(UserPath(playerid)))
{
INI_ParseFile(UserPath(playerid), “LoadUser_%s”, .bExtra = true, .extra = playerid);
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT,””COL_WHITE”Вход на сервер”,””COL_WHITE”Пожалуйста, введите Ваш пароль”,”Ввод”,”Выход”);
}
else
{
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT,””COL_WHITE”Регистрация на сервере”,””COL_WHITE”Пожалуйста, введите Ваш пароль, чтобы зарегистрировать аккаунт”,”Регистрация”,”Выход”);
}
Чтобы наши диалоговые окна работали, мы должны в паблик
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
return 1;
}
Перед return 1; добавить вот это:
switch( dialogid )
{
case DIALOG_REGISTER:
{
if (!response) return Kick(playerid);
if(response)
{
if(!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, “”COL_WHITE”Регистрация”,””COL_RED”Вы ввели некорректный пароль.n”COL_WHITE”Пожалуйста, введите Ваш пароль, чтобы зарегистрироваться.”,”Регистрация”,”Выход”);
new INI:File = INI_Open(UserPath(playerid));
INI_SetTag(File,”data”);
INI_WriteInt(File,”Password”,udb_hash(inputtext));
INI_WriteInt(File,”Cash”,0);
INI_WriteInt(File,”Admin”,0);
INI_WriteInt(File,”Kills”,0);
INI_WriteInt(File,”Deaths”,0);
INI_Close(File);
SetSpawnInfo(playerid, 0, 0, 1958.33, 1343.12, 15.36, 269.15, 0, 0, 0, 0, 0, 0);
SpawnPlayer(playerid);
}
}
case DIALOG_LOGIN:
{
if ( !response ) return Kick ( playerid );
if( response )
{
if(udb_hash(inputtext) == PlayerInfo[playerid][pPass])
{
INI_ParseFile(UserPath(playerid), “LoadUser_%s”, .bExtra = true, .extra = playerid);
GivePlayerMoney(playerid, PlayerInfo[playerid][pCash]);
}
else
{
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT,””COL_WHITE”Вход на сервер”,””COL_RED”Вы ввели некорректный пароль.n”COL_WHITE”Пожалуйста, введите Ваш пароль”,”Вход”,”Выход”);
}
return 1;
}
}
}
Теперь мы должны сделать так, чтобы при выходе наша статистика сохранялась:
в паблик
public OnPlayerDisconnect(playerid, reason)
{
return 1;
}new INI:File = INI_Open(UserPath(playerid));
INI_SetTag(File,”data”);
INI_WriteInt(File,”Cash”,GetPlayerMoney(playerid));
INI_WriteInt(File,”Admin”,PlayerInfo[playerid][pAdmin]);
INI_WriteInt(File,”Kills”,PlayerInfo[playerid][pKills]);
INI_WriteInt(File,”Deaths”,PlayerInfo[playerid][pDeaths]);
INI_Close(File);
Выходим на финишную прямую. Нам нужно добавить в паблик:
public OnPlayerDeath(playerid, killerid, reason)
{
return 1;
}
Перед return 1; вот это
PlayerInfo[killerid][pKills] ;
PlayerInfo[playerid][pDeaths] ;
от и все, теперь при входе на сервер вы сможете зарегистрировать аккаунт, сохранять статистику и заходить на свой аккаунт снова.
Обсуждение туториала