Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 5 из 5
  1. #1
    Аватар для Ray_Grand
    Пользователь

    Статус
    Оффлайн
    Регистрация
    15.11.2015
    Сообщений
    7
    Репутация:
    7 ±

    Простейшая регистрация на MySQL.

    Доброго времени суток, пользователи портала Pro-Pawn. Совсем недавно принялся изучать язык программирования Lua и примерно за неделю, с трудом написал простенькую, но работоспособную регистрацию на плагине MySQL с примером загрузки информации игрока из базы данных. И так, приступим, постараюсь объяснить детально то, что самому известно.
     Скриншот

    Вот что реализовано в системе:
    1. Регистрация и авторизация, в обоих случаях придётся вводить только лишь логин и пароль.
    2. Загрузка данных игрока из базы данных, я решил сделать последнюю позицию игрока, а так - же спавн по ней.
    3. Обновление последней позиции игрока и спавн по ней.
    4. Авторизация/регистрация проходит не по логину, который в клиенте у игрока, а по логину который введен в окне. (Например был ник "Player111", а в базе данных был аккаунт с ником "Player222", и если игрок "Player111" авторизовался под логином "Player222" то его логин сменится и он будет играть под введенным логином.


    Подготовка к написанию самой системы:
    Как установить плагин MySQL (клик) объяснять думаю не нужно, на wiki MTA всё доходчиво объяснено.

    После установки плагина, приступим к созданию таблицы в базе данных. Структура таблицы "players" для аккаунтов на скриншоте ниже:

    У кого не грузит нажмите на этот текст

    Сделали? Отлично, продолжим. Т.к регистрация и авторизация писалась полностью на чистом ресурсе, то идём в папку где находятся все ресурсы (MTA San Andreas 1.5\server\mods\deathmatch\resources) и создаем там новую папку, в которой будут находится наши файлы.

    Приступаем к написанию самой системы.
    В папке с нашим ресурсом создаем первый файл - meta.xml, и добавляем туда следующие строки:
    PHP код:
    <meta>
    <
    script src="server.lua" type="server"/> //Серверная часть ресурса
    <script src="client.lua" type="client"/> //Клиентская часть ресурса
    </meta
    Дальше мы создаем файл client.lua, в котором будет написана клиентская часть ресурса, и в нём же сейчас пишем следующий код:
    PHP код:
    //Первым делом создаем переменные, необходимые для создания GUI окна регистрации и авторизации.
    local Window = {}
    local TabPanel = {}
    local Tab = {}
    local Button = {}
    local Edit = {}
    local Label = {} 
    Сразу после переменных, переходим к созданию первой функции - создания GUI окна. После переменных добавляем:
    PHP код:
    local function createGui()
    //Тут скоро мы продолжим писать код.
    end

    addEventHandler
    ("onClientResourceStart"getResourceRootElement(), function()
        
    createGui() //Создаем окно с авторизацией и регистрацией.
    end
    Теперь внутрь функции createGui, добавляем следующий код:
    PHP код:
    //Создаем переменные, определяющие положение окна с регистрацией/авторизацией.
    local sWidthsHeight guiGetScreenSize()
        
    local Width,Height 370,219 
        local X 
    = (sWidth/2) - (Width/2
        
    local Y = (sHeight/2) - (Height/2
        
    Window[1] = guiCreateWindow(XYWidthHeight"Информационное окно",false//Создаем само окно, где будут расположены все элементы (текста, панели, кнопки и прочее)
        
    TabPanel[1] = guiCreateTabPanel(9,22,352,188,falseWindow[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 text1text2 guiGetText(Edit[1]), guiGetText(Edit[2]) //Записываем в 2 переменные введенный текст в поля логина и пароля.
            
    if(text1 == "") or (text2 == ""then return end //Если поле для ввода логина или пароля пустое - то событие дальше не происходит.
            
    triggerServerEvent("onPlayerLoginEx"getLocalPlayer(), text1text2//Вызываем серверное событие с двумя параметрами - логин, пароль.
        
    endfalse)

        
    addEventHandler("onClientGUIClick"Button[2], function() //Событие, которое будет происходить при нажатии на кнопку регистрации.
            
    local text1text2 guiGetText(Edit[3]), guiGetText(Edit[4])//Записываем в 2 переменные введенный текст в поля логина и пароля.
            
    if(text1 == "") or (text2 == ""then return end //Если поле для ввода логина или пароля пустое - то событие дальше не происходит.
            
    triggerServerEvent("onPlayerRegisterEx"getLocalPlayer(), text1text2//Вызываем серверное событие с двумя параметрами - логин, пароль.
        
    endfalse
    После всего выше написанного, добавляем последнее в клиентскую часть:
    PHP код:
    addEvent("destroyGui"true)
    addEventHandler("destroyGui"getRootElement(), function() //Эта функция пригодится позже, после успешной авторизации или регистрации, для скрытия окна и курсора.
            
    destroyElement(Window[1]) //Удаляем окно с регистрацией и авторизацией.
            
    showCursor(false//Скрываем курсор.
    end
    С клиентской частью закончили. Теперь создаем server.lua и добавляем туда следующий код:
    PHP код:
    database mysql_connect("хостинг""пользователь""пароль""название базы данных"//Переменная с подключением к базе данных, настраивайте сами под себя. 
    После соединения с базой данных, создадим функцию onPlayerLoginEx, которая будет срабатывать когда вы будете нажимать на кнопку авторизации и внутри которой будут проходить все проверки на наличие аккаунта.
    PHP код:
    addEvent('onPlayerLoginEx'true)
    addEventHandler("onPlayerLoginEx"getRootElement(), function(namepassword//Создаем функцию
        
    local result mysql_query(database"SELECT * FROM players WHERE Name = '"..name.."' AND Password = '"..password.."';"//Запрос на проверку наличие аккаунта, по введенным в клиентской части данным (Логин, пароль).
        
    if(result and mysql_num_rows(result) > 0then //Если аккаунт такой существует, то идём дальше.
            
    triggerClientEvent(source"destroyGui"source//Вызываем клиентскую функцию, которая удаляет окно и курсор с экрана.
            
    setPlayerName(sourcename//Устанавливаем игроку имя, введенное в окно логина.
            
    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(sourcegetElementData(source"posX"), getElementData(source"posY"), getElementData(source"posZ")) //Спавним игрока, по загруженным выше координатам.
            
    fadeCamera(sourcetrue//Чтобы не было черного экрана
            
    setCameraTarget(sourcesource//Делаем так, чтобы камера игрока, следила за ним самим же.
            
    outputChatBox("Вы успешно авторизировались на сервере!"source02550//Приветственное сообщение.
        
    else
            
    outputChatBox("Введенный вами пароль неверный, или аккаунт не существует."source25500//Если аккаунт с логином и паролем, введенным в окне авторизации отсутствует, то выводим сообщение, которое ниже.
       
    end
    end

    Осталась последняя функция - onPlayerRegisterEx, которая наверное как Вы и догадались, срабатывает когда игрок жмет на кнопку "Зарегистрироваться"
    PHP код:
    addEvent("onPlayerRegisterEx"true)
    addEventHandler("onPlayerRegisterEx"getRootElement(), function(namepassword//Функция регистрации аккаунта в базе данных.
        
    local result mysql_query(database"SELECT Name FROM players WHERE Name = '"..tostring(name).."';"//Проверяем, если ли аккаунт с именем введенным в окне регистрации.
        
    if(resultthen //Если запрос успешный, идём дальше.
            
    if(mysql_num_rows(result) > 0then //Аккаунт уже есть с таким именем.
                
    outputChatBox("Аккаунт с указанным вами логином уже зарегистрирован, используйте другой!"source)
            else 
    //Аккаунта с таким именем нет, идём дальше.
                
    result mysql_query(database"INSERT INTO players (Name, Password) VALUES ('"..tostring(name).."', '"..tostring(password).."');"//Создаем аккаунт в базе данных с логином и паролем из окна регистрации.
                
    if(resultthen //Если запрос успешный, идём дальше.
                    
    triggerClientEvent(source"destroyGui"source//Вызываем клиентское событие, которое удалит окно и курсор.
                    
    setPlayerName(sourcename//Устанавливаем игроку имя, которое он ввел в окне регистрации.
                    
    spawnPlayer(source1714.96875, -1913.534179687513.566567420959//Спавним игрока на вокзале Лос - Сантоса
                    
    setCameraTarget(sourcesource//Делаем так, чтобы камера игрока, следила за ним самим же.
                    
    fadeCamera(sourcetrue//Чтобы не было черного экрана
                    
    outputChatBox("Вы успешно зарегистрировались на сервере!"source02550//Приветствуем игрока
                
    else
                    
    outputChatBox("При регистрации аккаунта возникла ошибка."source25500//Отправляем это сообщение, если аккаунт почему - то не удалось зарегистрировать.
                
    end
            end
        end
    end

    Осталось лишь сделать обновление позиции игрока при выходе, в серверную часть добавляем:
    PHP код:
    addEventHandler ("onPlayerQuit"getRootElement(), function(quitType//Событие происходящее при выходе игрока.
        
    local xygetElementPosition(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

    Урок был написан специально для Pro-Pawn, копирование на другие ресурсы без разрешения автора - запрещено!

    P.S. Это моя самая первая система реализованная в MTA на Lua, поэтому с радостью выслушаю любую адекватную критику по коду, от более опытных пользователей.
    Последний раз редактировалось Ray_Grand; 09.02.2016 в 20:52.

  2. 7 пользователя(ей) сказали cпасибо:
    #Djuga (07.06.2019) Desulaid (04.02.2016) Disinterpreter (05.02.2016) L0ndl3m (05.02.2016) Reim (13.02.2016) Salvacore (04.02.2016) [ForD] (04.02.2016)
  3. #2
    Аватар для Salvacore
    Инжунер-погромист

    Статус
    Оффлайн
    Регистрация
    10.05.2013
    Адрес
    Аҧсуа бызшәа
    Сообщений
    2,271
    Репутация:
    418 ±
    Хороший урок.
    Всё описано)

  4. #3
    Аватар для Disinterpreter
    Проверенный

    Статус
    Оффлайн
    Регистрация
    02.01.2014
    Сообщений
    88
    Репутация:
    91 ±
    Как я уже говорил ранее в другой теме, не желательно юзать MySQL плагин.
    Так же в целях безопасности необходимо проверять данные о логине и пароле регексом, а не их численность, да и это делать следует на сервере, хоть мта и безопасна, не стоит это делать на клиенте (мой пример, я работал со встроенной ORM на SQLite, но тут важна суть проверок https://github.com/Disinterpreter/MT...n_s.lua#L8-L30).

  5. #4
    Аватар для Reim
    Пользователь

    Статус
    Оффлайн
    Регистрация
    16.06.2015
    Сообщений
    7
    Репутация:
    1 ±
    Цитата Сообщение от Disinterpreter Посмотреть сообщение
    Как я уже говорил ранее в другой теме, не желательно юзать MySQL плагин.

    Между ними есть различия, или любым из них лучше не пользоваться?

    https://wiki.multitheftauto.com/wiki/DbConnect
    https://wiki.multitheftauto.com/wiki/Modules/MTA-MySQL
    https://wiki.multitheftauto.com/wiki/Modules/MySQL

    И кстати все же почему пользоваться mysql в mta лучше не надо?

  6. #5
    Аватар для Disinterpreter
    Проверенный

    Статус
    Оффлайн
    Регистрация
    02.01.2014
    Сообщений
    88
    Репутация:
    91 ±
    Цитата Сообщение от Reim Посмотреть сообщение
    Между ними есть различия, или любым из них лучше не пользоваться?

    https://wiki.multitheftauto.com/wiki/DbConnect
    https://wiki.multitheftauto.com/wiki/Modules/MTA-MySQL
    https://wiki.multitheftauto.com/wiki/Modules/MySQL

    И кстати все же почему пользоваться mysql в mta лучше не надо?
    Я говорил именно про МОДУЛИ т.к им уже много лет и они никем не дорабатываться, а основные разработчики забили... В модуле могут быть дыры и различные баги, а это опасно.

  7. Пользователь сказал cпасибо:
    Reim (12.02.2016)
 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •