Форум Pawn-Wiki.Ru - Воплоти мечту в реальность!: [WINDOWS] [MYSQL] Мод с нуля | часть 2 - Форум Pawn-Wiki.Ru - Воплоти мечту в реальность!

Перейти к содержимому

  • (2 Страниц) +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

[ Урок ]
[WINDOWS] [MYSQL] Мод с нуля | часть 2
Оценка: -----

#1
Пользователь офлайн   unknownscripter 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию
ПЕРВАЯ ЧАСТЬ УРОКА

Снова всех приветствую, сегодня продолжаем писать мод с нуля. Уже в этом уроке будет создаваться регистрация и авторизация и после нее конечно же отправление игрока на спавн. Не буду тянуть драгоценные секунды вашей жизни. Приступаем:

Качаем архив, который находится в конце урока и распаковываем его в папку с сервером. Открываем его конфиг и вставляем в самый низ строку подключения плагинов.
plugins mysql

Закончили с подключением плагина, переходим в мод.

Открываем наш мод, который мы создавали в прошлом уроке и на первых строчках мы видим код:
// This is a comment
// uncomment the line below if you want to write a filterscript
//#define FILTERSCRIPT

#include <a_samp>

#if defined FILTERSCRIPT

public OnFilterScriptInit()
{
	print("\n--------------------------------------");
	print(" Blank Filterscript by your name here");
	print("--------------------------------------\n");
	return 1;
}

public OnFilterScriptExit()
{
	return 1;
}

#else

main()
{
	print("\n----------------------------------");
	print(" Blank Gamemode by your name here");
	print("----------------------------------\n");
}

#endif


Его нужно почистить от лишнего мусора, который нам не понадобится. Весь код можно удалить, кроме main() {...} и подключения инклуда SA-MP'a.
Результат [Показать]


Теперь нам нужно подключить сам инклуд MySQL, взаимодействовать который будет напрямую с плагином для работы с БД. После строки с подключением последнего инклуда вставляем новую строку:
#include <a_mysql>
и получаем
#include <a_samp>
#include <a_mysql>


Нам нужно создать переменную, которая будет являться подключением к БД. Кроме этого, я решил сделать еще и макросы для подключения и массив, который будем использовать для форматирования запросов на 256 ячеек. Думаю, на первое время хватит.
#define MYSQL_HOST "127.0.0.1"
#define MYSQL_USER "root"
#define MYSQL_PASS ""
#define MYSQL_BASE "pawnwiki"

new
	MySQL: mysqlHandle,
	query[256]
;


Подключаем БД: ищем коллбэк (public) OnGameModeInit и прописываем функции подключения
mysqlHandle = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_BASE); // создаем подключение к БД
if (mysql_errno() != 0) // если подключению помешала какая-то ошибка
{
	print("[mysql] could not connect to database!"); // выводим в консоль сообщение о том, что БД не подключена
	return SendRconCommand("exit"); // прерываем работу мода
}


Для избежания предупреждений о дубликате подключения в логах MySQL нужно закрыть подключение после выключения мода:
public OnGameModeExit()
{
	mysql_close(mysqlHandle);
	return 1;
}

Настроим немного мод и можно приступать к основному.
SendRconCommand("hostname Pawn-Wiki.Ru (МОД С НУЛЯ)"); // отображаемое название в списке серверов
SetGameModeText("[GM] Pawn-Wiki.Ru"); // Mode, которое так же видно в клиенте

AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0); // подробнее узнаете на wiki.sa-mp.com


В начало мода прописываем перечисление (enum) с автоподсчетом ID диалогов и информации о игроке:
enum
{
	DIALOG_ID_NONE, // 0
	DIALOG_ID_REGISTER_PASSWORD, // 1
	DIALOG_ID_REGISTER_GENDER,
	DIALOG_ID_LOGIN
};

enum PLAYER_INFO
{
	pID, // ID аккаунта
	pName[MAX_PLAYER_NAME + 1], // имя игрока (Почему + 1? Строка всегда заканчивается \0, поэтому 0 - считается как символ)
	pPassword[22 + 1], // пароль
	pGender, // пол персонажа
	pSkin, // скин
	pCash // наличные
};


После них создаем переменные для использования последнего перечисления (ну и еще переменную с проверкой на авторизацию игрока).
new
	PlayerInfo[MAX_PLAYERS][PLAYER_INFO],
	bool: playerLoggedStatus[MAX_PLAYERS]
;


Закончено. Можно двигаться дальше. Ищем коллбэк OnPlayerConnect и нам нужно записать имя игрока и запустить таймер для выполнения запроса:
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME); // получаем имя игрока и записываем полученное в pName
SetTimerEx("@__timerPlayerGetAccount", 1000, 0, "i", playerid);
// запускаем таймер который будет выполнять запрос поиска игрока в БД
// делается это чтобы установить вид (камеру) игроку при авторизации/регистрации


Создаем так же коллбэк, в "теле" которого будет выполняться код:
@__timerPlayerGetAccount(playerid);
@__timerPlayerGetAccount(playerid)
{
	SetPlayerCameraPos(playerid, 1027.7542, -1075.3053, 109.6629);
	SetPlayerCameraLookAt(playerid, 1028.7198, -1075.5803, 109.6678);
	// в моем варианте камера будет на вид небоскребов Лос Сантоса
	
	format(query, sizeof query, "SELECT * FROM `accounts` WHERE `name` = '%s'", PlayerInfo[playerid][pName]); // форматируем запрос с перебором таблицы accounts и поиском совпадения в поле name
	mysql_tquery(mysqlHandle, query, "@__mysqlGetPlayerAccount", "i", playerid);
}


Коллбэк таймера мы создали, но теперь нужно еще и запроса. Делаем:
@__mysqlGetPlayerAccount(playerid);
@__mysqlGetPlayerAccount(playerid)
{
	SetPlayerColor(playerid, 0xFF); // устанавливаем игроку черный цвет
	
	if (cache_num_rows() == 0) // если найдено 0 совпадений, то игрок должен зарегистрироваться
	    ShowPlayerDialog(
			playerid, DIALOG_ID_REGISTER_PASSWORD, DIALOG_STYLE_INPUT, "Регистрация",
			"{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n"\
			"Для начала игры на сервере, необходимо пройти регистрацию\n"\
			"\n"\
			"Придумайте и введите пароль в строку ниже:", "Далее", "Отмена");

	else // ну, а если найдено - авторизация
	    ShowPlayerDialog(
			playerid, DIALOG_ID_LOGIN, DIALOG_STYLE_PASSWORD, "Авторизация",
			"{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n"\
			"Аккаунт с таким ником уже зарегистрирован\n"\
			"\n"\
			"Введите пароль, указанный при регистрации:", "Далее", "Отмена");
}


Создаем реакцию диалогов на действия игрока. Ищем OnDialogResponse и начинаем писать (ну не Ctrl + C же):
switch (dialogid)
{
    case DIALOG_ID_NONE: // тут ничего изменять не надо будет
        return 0;
        
	case DIALOG_ID_REGISTER_PASSWORD: // регистрация (ввод пароля)
	{
	    if (response == 0) // если игрок нажал 2 кнопку, кикаем его
	        return Kick(playerid);
	        
		if (!(6 <= strlen(inputtext) <= 22)) // введено от 6 до 22 символов
		{
		    SendClientMessage(playerid, -1, "Длина пароля должна состовлять от 6 до 22 символов!"); // выводим игроку ошибку
		    
		    return ShowPlayerDialog(
				playerid, DIALOG_ID_REGISTER_PASSWORD, DIALOG_STYLE_INPUT, "Регистрация",
				"{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n"\
				"Для начала игры на сервере, необходимо пройти регистрацию\n"\
				"\n"\
				"Придумайте и введите пароль в строку ниже:", "Далее", "Отмена"); // и снова открываем диалог
		}
		
		for (new i = 0; i < strlen(inputtext); i ++) // цикл, который будет повторяться 'strlen(inputtext)' раз
		{
		    switch (inputtext[i]) // перебор символов. поможет от ввода русских символов в пароле
		    {
		        case 'a'..'z', 'A'..'Z', '0'..'9': // если i ячейка забита буквой от a до Z или цифрой от 0 до 9
		            continue; // пропускаем дальше
		            
				default: // соотвественно иначе
				{
				    SendClientMessage(playerid, -1, "В пароле не должно быть других букв кроме английских!"); // выводим игроку ошибку
				    
				    return ShowPlayerDialog(
						playerid, DIALOG_ID_REGISTER_PASSWORD, DIALOG_STYLE_INPUT, "Регистрация",
						"{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n"\
						"Для начала игры на сервере, необходимо пройти регистрацию\n"\
						"\n"\
						"Придумайте и введите пароль в строку ниже:", "Далее", "Отмена"); // и еще раз открываем диалог
				}
		    }
		}
		
		PlayerInfo[playerid][pPassword][0] = EOS; // очищаем pPassword для playerid
		strins(PlayerInfo[playerid][pPassword], inputtext, 0); // и вставляем inputtext в pPassword начиная с 0 ячейки
		
		ShowPlayerDialog(
		    playerid, DIALOG_ID_REGISTER_GENDER, DIALOG_STYLE_MSGBOX, "Регистрация",
		        "{FFFFFF}Выберите пол Вашего персонажа:", "Мужской", "Женский"); // диалог выбора пола
	}
	
	case DIALOG_ID_REGISTER_GENDER: // регистрация (выбор пола)
	{
	    PlayerInfo[playerid][pGender] = response; // пол устанавливается по ID нажатой кнопки. 1 кнопка - 1 (мужской), 2 кнопка - 0 (женский)
	    PlayerInfo[playerid][pSkin] = (response ? 26 : 172); // скин игрока устанавливается так же, тут применяем тернарный оператор (ссылка на урок ниже)
	    
	    format(query, sizeof query,
			"INSERT INTO `accounts` (`name`, `password`, `gender`, `cash`) VALUES ('%s', MD5('%s'), '%d', '%d')",
			PlayerInfo[playerid][pName], PlayerInfo[playerid][pPassword], PlayerInfo[playerid][pGender], PlayerInfo[playerid][pSkin]);
		// форматируем запрос INSERT INTO - добавление новой строки в таблицу accounts
		// MD5('%s') хеширует строку в шифровку MD5
		mysql_tquery(mysqlHandle, query);
		
		format(query, sizeof query, "SELECT * FROM `accounts` WHERE `name` = '%s'", PlayerInfo[playerid][pName]); // форматируем запрос с перебором таблицы accounts и поиском совпадения в поле name
		mysql_tquery(mysqlHandle, query, "@__mysqlGetPlayerAccount", "i", playerid); // снова отправим запрос поиска аккаунта. если все пройдет без ошибок - игрок авторизуется
	}
	
	case DIALOG_ID_LOGIN: // авторизация
	{
	    if (response == 0) // если игрок нажал 2 кнопку, кикаем его
	        return Kick(playerid);
	        
		format(query, sizeof query, "SELECT * FROM `accounts` WHERE `name` = '%s' AND `password` = MD5('%s')",
			PlayerInfo[playerid][pName], inputtext); // форматируем запрос с перебором таблицы accounts и поиском совпадений между name и pName, password (уже хешированный) и pPassword
		mysql_tquery(mysqlHandle, query, "@__mysqlUploadPlayerAccount", "i", playerid);
	}
}

Готово.

При авторизации мы отправляли БД запрос на поиск совпадений с name и pName и password с inputtext (хешированным). Для него тоже нужно создать коллбэк, который мы указывали при выполнении (@__mysqlUploadPlayerAccount)
@__mysqlUploadPlayerAccount(playerid);
@__mysqlUploadPlayerAccount(playerid)
{
	if (cache_num_rows() == 0) // найденых строк == 0, т.е. игрок ввел не верный пароль
	{
	    // выводим сообщение с ошибкой открываем диалог и обрываем выполнение кода коллбэка дальше
	    SendClientMessage(playerid, 0xFF0000FF, "Введен не правильный пароль этого аккаунта!");
	    
	    return ShowPlayerDialog(
			playerid, DIALOG_ID_LOGIN, DIALOG_STYLE_PASSWORD, "Авторизация",
			"{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n"\
			"Аккаунт с таким ником уже зарегистрирован\n"\
			"\n"\
			"Введите пароль, указанный при регистрации:", "Далее", "Отмена");
	}
	
	playerLoggedStatus[playerid] = true; // переменная авторизации игрока (true - авторизован, false наоборот)
	SetPlayerColor(playerid, 0xFFFFFF33); // устанавливаем немного прозрачный белый цвет игроку
	
	cache_get_value_name_int(0, "id", PlayerInfo[playerid][pID]); // вытаскиваем содержимое поля id и записываем результат в pID
	cache_get_value_name_int(0, "gender", PlayerInfo[playerid][pGender]); // аналогично тому что выше, но уже с gender и pGender
	cache_get_value_name_int(0, "skin", PlayerInfo[playerid][pSkin]);
	cache_get_value_name_int(0, "cash", PlayerInfo[playerid][pCash]);
	
	SetCameraBehindPlayer(playerid); // устанавливаем камеру за игрока
	SpawnPlayer(playerid); // и спавним его
	
	return 1;
}


Все, мы закончили. Осталось написать спавн игрока и создать базу данных. В OnPlayerSpawn:
if (playerLoggedStatus[playerid] == false) // если игрок нажал кнопку Spawn или заспавнился
    return Kick(playerid); // кикаем его, чтобы не сломал систему
    
SetCameraBehindPlayer(playerid); // устанавливаем камеру за игрока
    
SetPlayerPos(playerid, 1154.2678, -1768.5897, 16.5938); // устанавливаем координаты спавна
SetPlayerSkin(playerid, PlayerInfo[playerid][pSkin]); // устанавливаем скин из pSkin

ResetPlayerMoney(playerid); // очищаем деньги игрока (игровые)
GivePlayerMoney(playerid, PlayerInfo[playerid][pCash]); // и выдаем их в размере pCash

СДЕЛАНО!

Я буду использовать phpMyAdmin (который будет создавать для меня Denwer).
Переходим по локальному адресу localhost/Tools/phpMyAdmin

При переходе же видно Создать базу данных. В строке вписываем указанное Вами название таблицы (MYSQL_BASE в моде) и кодировку выбираем cp_1251_general_ci. Она защищает мод русские символы от ??????????? после импорта из БД. Создали, направляемся в нашу базу данных.
Скрытый текст [Показать]


При входе в БД у нас еще нет созданных таблиц, поэтому и отображается уведомление с этой "проблемой".
Ниже видно "Создать таблицу". В поле Имя вписываем accounts (или ваш вариант), Количество столбцов оставляем пустым.
Скрытый текст [Показать]


Добавляем 2 строки и приступаем творить таблицу.
Синтаксис: Имя - Тип - Длина - По умолчанию
id - INT - 11 - (ставим галочку на A_I. Это AUTO_INCREMENT, то есть автоматический инкремент. При создании новой строки в этой таблице к ее номеру будет прибавляться +1, тем самым создавая новый ID аккаунта.
name - VARCHAR - 24 - (пусто)
password - VARHCAR - 24 - (пусто)
gender - INT - 11 - 0
skin - INT - 11 - 1
cash - INT - 11 - (тут вы можете поставить свое значение денег, выдаваемое при регистрации. У меня $100).
Скрытый текст [Показать]

Сохраняем все и можно запускать сервер. Открываем samp-server.exe и если все правильно заходим на сервер (127.0.0.1:порт (указан в server.cfg))
Скрытый текст [Показать]

Мы все сделали, закончили, теперь можно отдыхать. Ниже можете писать свои вопросы или замечания (мне), я все прочитаю и отвечу. Следующий урок будет завтра ну или через 2-3 дня. До встречи.


Plugin MySQL R41-4

Сообщение отредактировал unknownscripter: 18 Апрель 2018 - 08:17

3

#2
Пользователь офлайн   Nestyreff 

  • Stone tm
  • Вставить ник
  • Раскрыть информацию
"Подключаем БД: ищем коллбэк (public) OnGameModeInit и прописываем функции подключения" - Чуть ранее ты говорил о том, чтобы оставить только main и инклуды.
0

#3
Пользователь офлайн   unknownscripter 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияNestyreff (18 Апрель 2018 - 08:21) писал:

"Подключаем БД: ищем коллбэк (public) OnGameModeInit и прописываем функции подключения" - Чуть ранее ты говорил о том, чтобы оставить только main и инклуды.


Не совсем понял.
0

#4
Пользователь офлайн   Nestyreff 

  • Stone tm
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияunknownscripter (18 Апрель 2018 - 08:24) писал:

Не совсем понял.

"Его нужно почистить от лишнего мусора, который нам не понадобится. Весь код можно удалить, кроме main() {...} и подключения инклуда SA-MP'a."
, а потом:
"ищем OnPlayerConnect", который, следуя уроку, мы уже удалили.
0

#5
Пользователь офлайн   unknownscripter 

  • Прохожий
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияNestyreff (18 Апрель 2018 - 08:32) писал:

Нажмите сюда, чтобы прочитать это сообщение. [Показать]

Имеется ввиду не весь код
Изображение
0

#6
Пользователь офлайн   Nestyreff 

  • Stone tm
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияunknownscripter (18 Апрель 2018 - 08:38) писал:

Имеется ввиду не весь код
Изображение

Как это имеется ввиду? Ты прямо сказал оставить только main и инклуды. Даже потом код вставил, что нужно оставить.

Сообщение отредактировал Nestyreff: 18 Апрель 2018 - 08:47

0

#7
Пользователь офлайн   Sonic X 

  • Х_X
  • Вставить ник
  • Раскрыть информацию
Я не понимаю, зачем нужно это? Ну вот зачем???? :wacko: Я таких уроков сотню найду. Если там будет описано другими словами - ничего страшного. Мод с 0 ты не напишешь., а если и будешь писать, то тут тем не хватит. Я прям вижу, как кто-то научится по ТАКИМ урокам скриптингу. :facepalm: У тебя всё одинаковое, очень сильно похоже на другие уроки, тогда спрашивается, зачем нам этот урок? Любой может установить MySQL. Это делается так, пишешь в поисковике "как подключить MySQL samp". Всё. Приэтом врятле твоя тему будет в топе.. Зря время тратишь своё :wink:

Сообщение отредактировал Sonic X: 18 Апрель 2018 - 09:32

0

#8
Пользователь офлайн   Nestyreff 

  • Stone tm
  • Вставить ник
  • Раскрыть информацию

Просмотр сообщенияSonic X (18 Апрель 2018 - 09:31) писал:

Нажмите сюда, чтобы прочитать это сообщение. [Показать]

Я про тоже. Однако, автор уверен в том, что все уроки не были нормально закончены. А закончить их и нельзя, в скриптах появляются всё новые и новые штуки, которые только дополняют это ремесло.
0

#9
Пользователь офлайн   Sonic X 

  • Х_X
  • Вставить ник
  • Раскрыть информацию
Как бы "писать" мод и выкладывать части об этом на форум или тот же ютуб - глупо. Нужно рассказывать как и что необходимо делать, а также, что возможно сделать, помимо того, что сделал автор в том "скрипте", который вы будете разбирать.
0

#10
Пользователь офлайн   Mars_Flex 

  • Местный
  • Вставить ник
  • Раскрыть информацию
Зачем делать такое??
ShowPlayerDialog(
                        playerid, DIALOG_ID_LOGIN, DIALOG_STYLE_PASSWORD, "Авторизация",
                        "{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n"\
                        "Аккаунт с таким ником уже зарегистрирован\n"\
                        "\n"\
                        "Введите пароль, указанный при регистрации:", "Далее", "Отмена");

Не что бы проще?
ShowPlayerDialog(playerid, DIALOG_ID_LOGIN, DIALOG_STYLE_PASSWORD, "Авторизация",
   "{FFFFFF}Приветствуем Вас на сервере {FFFF00}Pawn-Wiki.Ru{FFFFFF}!\n\
   Аккаунт с таким ником уже зарегистрирован\n\
   "Введите пароль, указанный при регистрации:", 
"Далее", "Отмена");

Сообщение отредактировал Mars_Flex: 18 Апрель 2018 - 13:57

0

Поделиться темой:


  • (2 Страниц) +
  • 1
  • 2
  • Вы не можете создать новую тему
  • Вы не можете ответить в тему

1 человек читают эту тему
0 пользователей, 1 гостей, 0 скрытых пользователей


Яндекс.Метрика