Доброго времени суток. Совсем недавно я принялся изучать язык программирования Lua и примерно за неделю, с трудом написал простенькую, но работоспособную регистрацию на плагине MySQL с примером загрузки информации игрока из базы данных. И так, приступим, постараюсь объяснить детально то, что самому известно.
Вот что реализовано в системе:
1. Регистрация и авторизация, в обоих случаях придётся вводить только лишь логин и пароль.
2. Загрузка данных игрока из базы данных, я решил сделать последнюю позицию игрока, а так - же спавн по ней.
3. Обновление последней позиции игрока и спавн по ней.
4. Авторизация/регистрация проходит не по логину, который в клиенте у игрока, а по логину который введен в окне. (Например был ник "Player111", а в базе данных был аккаунт с ником "Player222", и если игрок "Player111" авторизовался под логином "Player222" то его логин сменится и он будет играть под введенным логином.
Подготовка к написанию самой системы:
Как установить плагин MySQL объяснять думаю не нужно, на Wiki MTA всё доходчиво объяснено.
После установки плагина, приступим к созданию таблицы в базе данных. Структура таблицы "players" для аккаунтов на скриншоте ниже:
Сделали? Отлично, продолжим. Т.к регистрация и авторизация писалась полностью на чистом ресурсе.
Tо идём в папку где находятся все ресурсы (MTA San Andreas 1.5\server\mods\deathmatch\resources) и создаем там новую папку, в которой будут находится наши файлы.
Приступаем к написанию самой системы.
В папке с нашим ресурсом создаем первый файл - meta.xml, и добавляем туда следующие строки:
<meta> <script src="server.lua" type="server"/> //Серверная часть ресурса <script src="client.lua" type="client"/> //Клиентская часть ресурса </meta>
Дальше мы создаем файл client.lua, в котором будет написана клиентская часть ресурса, и в нём же сейчас пишем следующий код:
//Первым делом создаем переменные, необходимые для создания GUI окна регистрации и авторизации. local Window = {} local TabPanel = {} local Tab = {} local Button = {} local Edit = {} local Label = {}
Сразу после переменных, переходим к созданию первой функции - создания GUI окна. После переменных добавляем:
local function createGui() //Тут скоро мы продолжим писать код. end addEventHandler("onClientResourceStart", getResourceRootElement(), function() createGui() //Создаем окно с авторизацией и регистрацией. end)
Теперь внутрь функции createGui, добавляем следующий код:
//Создаем переменные, определяющие положение окна с регистрацией/авторизацией. local sWidth, sHeight = guiGetScreenSize() local Width,Height = 370,219 local X = (sWidth/2) - (Width/2) local Y = (sHeight/2) - (Height/2) Window[1] = guiCreateWindow(X, Y, Width, Height, "Информационное окно",false) //Создаем само окно, где будут расположены все элементы (текста, панели, кнопки и прочее) TabPanel[1] = guiCreateTabPanel(9,22,352,188,false, Window[1]) //Создаем TabPanel, на которой и будут расположены кнопки, с помощью которых можно будет переключаться между регистрацией и авторизацией. //GUI элементы авторизации. Tab[1] = guiCreateTab("Авторизация", TabPanel[1]) Edit[1] = guiCreateEdit(77,10,160,28,"",false,Tab[1]) //Создаем поле для ввода логина. guiEditSetMaxLength (Edit[1], 22) //Устанавливаем максимальную длину введенного в поле текста - 22 символа. Label[1] = guiCreateLabel(9,15,88,30,"Логин:",false,Tab[1]) //Создаем текст левее поля для ввода логина. guiSetFont(Label[1],"default-bold-small") //Устанавливаем шрифт для текста выше. Edit[2] = guiCreateEdit(77,45,160,28,"",false,Tab[1]) //Создаем поле для ввода пароля. guiEditSetMaxLength (Edit[2], 30) //Устанавливаем максимальную длину введенного в поле текста - 30 символа. Label[2] = guiCreateLabel(9,50,88,30,"Пароль:",false,Tab[1]) //Создаем текст левее поля для ввода пароля. guiSetFont(Label[2],"default-bold-small") //Устанавливаем шрифт для текста выше. Button[1] = guiCreateButton(97,80,112,29,"Авторизоваться",false,Tab[1]) //После всех элементов выше, создаем кнопку. //GUI элементы регистрации. Tab[2] = guiCreateTab("Регистрация",TabPanel[1]) Edit[3] = guiCreateEdit(77,10,160,28,"",false,Tab[2]) //Создаем поле для ввода логина. guiEditSetMaxLength (Edit[3], 22) //Устанавливаем максимальную длину введенного в поле текста - 22 символа. Label[3] = guiCreateLabel(9,15,88,30,"Логин:",false,Tab[2]) //Создаем текст левее поля для ввода логина. guiSetFont(Label[3],"default-bold-small") //Устанавливаем шрифт для текста выше. Edit[4] = guiCreateEdit(77,45,160,28,"",false,Tab[2]) //Создаем поле для ввода пароля. guiEditSetMaxLength (Edit[4], 30) //Устанавливаем максимальную длину введенного в поле текста - 30 символа. Label[4] = guiCreateLabel(9,50,88,30,"Пароль:",false,Tab[2]) //Создаем текст левее поля для ввода пароля. guiSetFont(Label[4],"default-bold-small") //Устанавливаем шрифт для текста выше. Button[2] = guiCreateButton(92,80,130,29,"Зарегистрироваться",false,Tab[2]) //Создаем кнопку. showCursor(true) //Показываем курсор. addEventHandler("onClientGUIClick", Button[1], function() //Событие, которое будет происходить при нажатии на кнопку авторизации. local text1, text2 = guiGetText(Edit[1]), guiGetText(Edit[2]) //Записываем в 2 переменные введенный текст в поля логина и пароля. if(text1 == "") or (text2 == "") then return end //Если поле для ввода логина или пароля пустое - то событие дальше не происходит. triggerServerEvent("onPlayerLoginEx", getLocalPlayer(), text1, text2) //Вызываем серверное событие с двумя параметрами - логин, пароль. end, false) addEventHandler("onClientGUIClick", Button[2], function() //Событие, которое будет происходить при нажатии на кнопку регистрации. local text1, text2 = guiGetText(Edit[3]), guiGetText(Edit[4])//Записываем в 2 переменные введенный текст в поля логина и пароля. if(text1 == "") or (text2 == "") then return end //Если поле для ввода логина или пароля пустое - то событие дальше не происходит. triggerServerEvent("onPlayerRegisterEx", getLocalPlayer(), text1, text2) //Вызываем серверное событие с двумя параметрами - логин, пароль. end, false)
После всего выше написанного, добавляем последнее в клиентскую часть:
addEvent("destroyGui", true) addEventHandler("destroyGui", getRootElement(), function() //Эта функция пригодится позже, после успешной авторизации или регистрации, для скрытия окна и курсора. destroyElement(Window[1]) //Удаляем окно с регистрацией и авторизацией. showCursor(false) //Скрываем курсор. end)
С клиентской частью закончили. Теперь создаем server.lua и добавляем туда следующий код:
database = mysql_connect("хостинг", "пользователь", "пароль", "название базы данных") //Переменная с подключением к базе данных, настраивайте сами под себя.
После соединения с базой данных, создадим функцию onPlayerLoginEx, которая будет срабатывать когда вы будете нажимать на кнопку авторизации.
И внутри которой будут проходить все проверки на наличие аккаунта.
addEvent('onPlayerLoginEx', true) addEventHandler("onPlayerLoginEx", getRootElement(), function(name, password) //Создаем функцию local result = mysql_query(database, "SELECT * FROM players WHERE Name = '"..name.."' AND Password = '"..password.."';") //Запрос на проверку наличие аккаунта, по введенным в клиентской части данным (Логин, пароль). if(result and mysql_num_rows(result) > 0) then //Если аккаунт такой существует, то идём дальше. triggerClientEvent(source, "destroyGui", source) //Вызываем клиентскую функцию, которая удаляет окно и курсор с экрана. setPlayerName(source, name) //Устанавливаем игроку имя, введенное в окно логина. local row = mysql_fetch_assoc(result) setElementData(source, "posX", (row['X'])) //Из поля 'X' в базе данных получаем значение и записываем его в ключ "posX' на сервере. setElementData(source, "posY", (row['Y'])) //Из поля 'Y' в базе данных получаем значение и записываем его в ключ "posY' на сервере. setElementData(source, "posZ", (row['Z'])) //Из поля 'Z' в базе данных получаем значение и записываем его в ключ "posZ' на сервере. spawnPlayer(source, getElementData(source, "posX"), getElementData(source, "posY"), getElementData(source, "posZ")) //Спавним игрока, по загруженным выше координатам. fadeCamera(source, true) //Чтобы не было черного экрана setCameraTarget(source, source) //Делаем так, чтобы камера игрока, следила за ним самим же. outputChatBox("Вы успешно авторизировались на сервере!", source, 0, 255, 0) //Приветственное сообщение. else outputChatBox("Введенный вами пароль неверный, или аккаунт не существует.", source, 255, 0, 0) //Если аккаунт с логином и паролем, введенным в окне авторизации отсутствует, то выводим сообщение, которое ниже. end end)
Осталась последняя функция - onPlayerRegisterEx, которая наверное как Вы и догадались, срабатывает когда игрок жмет на кнопку "Зарегистрироваться"
addEvent("onPlayerRegisterEx", true) addEventHandler("onPlayerRegisterEx", getRootElement(), function(name, password) //Функция регистрации аккаунта в базе данных. local result = mysql_query(database, "SELECT Name FROM players WHERE Name = '"..tostring(name).."';") //Проверяем, если ли аккаунт с именем введенным в окне регистрации. if(result) then //Если запрос успешный, идём дальше. if(mysql_num_rows(result) > 0) then //Аккаунт уже есть с таким именем. outputChatBox("Аккаунт с указанным вами логином уже зарегистрирован, используйте другой!", source) else //Аккаунта с таким именем нет, идём дальше. result = mysql_query(database, "INSERT INTO players (Name, Password) VALUES ('"..tostring(name).."', '"..tostring(password).."');") //Создаем аккаунт в базе данных с логином и паролем из окна регистрации. if(result) then //Если запрос успешный, идём дальше. triggerClientEvent(source, "destroyGui", source) //Вызываем клиентское событие, которое удалит окно и курсор. setPlayerName(source, name) //Устанавливаем игроку имя, которое он ввел в окне регистрации. spawnPlayer(source, 1714.96875, -1913.5341796875, 13.566567420959) //Спавним игрока на вокзале Лос - Сантоса setCameraTarget(source, source) //Делаем так, чтобы камера игрока, следила за ним самим же. fadeCamera(source, true) //Чтобы не было черного экрана outputChatBox("Вы успешно зарегистрировались на сервере!", source, 0, 255, 0) //Приветствуем игрока else outputChatBox("При регистрации аккаунта возникла ошибка.", source, 255, 0, 0) //Отправляем это сообщение, если аккаунт почему - то не удалось зарегистрировать. end end end end)
Осталось лишь сделать обновление позиции игрока при выходе, в серверную часть добавляем:
addEventHandler ("onPlayerQuit", getRootElement(), function(quitType) //Событие происходящее при выходе игрока. local x, y, z = getElementPosition(source) //Получаем координаты игрока. mysql_query(database, "UPDATE players SET X = '"..x.."', Y = '"..y.."', Z = '"..z.."' WHERE Name = '"..getPlayerName(source).."';") //Обновляем их в базе данных. end)
pastebin (client.lua)
pastebin (server.lua)
Автор урока: Ray_Grand
Теги: MySQL