GUI работает на стороне клиента. Хорошим решением будет поместить все клиентские скрипты в отдельный каталог. Перейдите в каталог /Ваш сервер MTA/mods/deathmatch/resources/myserver/ и создайте подкаталог "client". В нём создайте текстовый файл и назовите его "gui.lua". В этом файле мы напишем функцию, отображающую окно:
Code
function CreateLoginWindow()  local X = 0.375  local Y = 0.375  local Width = 0.25  local Height = 0.25  wdwLogin = guiCreateWindow(X, Y, Width, Height, "Please Log In", true) end
Вы можете кликнуть по имени функции, чтобы прочитать её описание. Заметьте, что координаты окна задаются в процентах от размеров экрана. Это значит, что левая граница экрана по ширине принимается за 0, а правая за 1, соответственно, "X" равное 0.5 обозначает середину экрана. Аналогично и для позиции по высоте, ширины и высоты окна (если "width" равно 0.5, окно будет в половину ширины экрана). Теперь мы добавим текстовые метки (с надписями "username:" и "password:"), поля ввода и кнопку. Замените функцию её полной версией:
Code
function CreateLoginWindow()  local X = 0.375  local Y = 0.375  local Width = 0.25  local Height = 0.25  wdwLogin = guiCreateWindow(X, Y, Width, Height, "Please Log In", true)    X = 0.0825  Y = 0.2  Width = 0.25  Height = 0.25  guiCreateLabel(X, Y, Width, Height, "Username", true, wdwLogin)  Y = 0.5  guiCreateLabel(X, Y, Width, Height, "Password", true, wdwLogin)    X = 0.415  Y = 0.2  Width = 0.5  Height = 0.15  edtUser = guiCreateEdit(X, Y, Width, Height, "", true, wdwLogin)  Y = 0.5  edtPass = guiCreateEdit(X, Y, Width, Height, "", true, wdwLogin)  guiEditSetMaxLength(edtUser, 50)  guiEditSetMaxLength(edtPass, 50)    X = 0.415  Y = 0.7  Width = 0.25  Height = 0.2  btnLogin = guiCreateButton(X, Y, Width, Height, "Log In", true, wdwLogin)    guiSetVisible(wdwLogin, false) end
Обратите внимание на то, что каждый компонент интерфейса является дочерним по отношению к окну, это достигается указанием родительского элемента (wdwLogin, в данном случае) при создании элемента:
Code
guiCreateLabel(X, Y, Width, Height, "Password", true, wdwLogin)
Это очень удобно, т.к. в дальнейшем, при отображении окна, можно обращаться только к родительскому элементу. К примеру:
Code
guiSetVisible(wdwLogin, false) --прячет всё окно целиком так, что мы можем показать его игроку в любой момент.
Функция CreateLoginWindow написана, но она не будет работать, пока мы её не вызовем. Рекомендуется создавать все окна при запуске ресурса на клиенте, прятать их, и показывать игроку позднее, когда они понадобятся. Для этого напишем обработчик события "onClientResourceStart", в котором будем создавать окно:
Code
addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()),   function ()   CreateLoginWindow()  end )
Заметьте, что мы выполняем проверку перед показом окна, так, в случае, если окно не создано, не возникнет ошибки. Функция showCursor включает управление мышью, а guiSetInputEnabled позволяет быть уверенным, что использование при вводе некоторых клавиш, таких как "A", "S", "D", "W", "T", не приведёт к движению персонажа, или вводу текста в чате. На следующем шаге мы заставим кнопку работать так, как задумывалось. Когда пользователь кликает по любому элементу интерфейса, генерируется событие "onClientGUIClick" для этого элемента. К примеру, если вы кликните по кнопке, можно добавить обработчик для этого события:
Code
addEventHandler("onClientGUIClick", theButtonElement, theHandlerFunction, false)
В нашем скрипте требуется только обработчик привязанный к кнопке. При клике по ней, клиент должен сообщить серверу, что нужно респаунить игрока. Найдите обработчик события "onClientResourceStart" из предыдущей части и добавьте следующую строку сразу ПОСЛЕ вызова CreateLoginWindow() :
Code
addEventHandler("onClientGUIClick", btnLogin, clientSubmitLogin, false)
Обработчик должен быть добавлен здесь, чтобы быть уверенным, что переменная btnLogin содержит существующую кнопку. Нельзя привязать событие к несуществующему элементу. Вы, должно быть, заметили, что нам потребуется функция "clientSubmitLogin", вызываемая в предыдущей строке.
Code
function clientSubmitLogin(button, state)  if (button == "left" and state == "up") then     triggerServerEvent("SubmitLogin", getRootElement(), guiGetText(edtUser), guiGetText(edtPass))   guiSetInputEnabled(false)   guiSetVisible(wdwLogin, false)   showCursor(false)  end end
Переменная "button" передается обработчиком события и содержит строку с именем этой кнопки (к примеру "left" или "right"). Здесь мы познакомились с новой концепцией пользовательских событий. Пользовательские события могут генерироваться как на одной стороне, так и на разных (с сервера на клиент и наоборот). Мы используем функцию triggerServerEvent, чтобы сгенерировать событие "SubmitLogin" на сервере. Теперь у нас есть весь необходимый клиентский код. На сервере, как вы помните, мы спавним игрока как только он подключается к серверу:
Code
function joinHandler()  local x,y,z  x = 1959.55  y = -1714.46  z = 10  spawnPlayer(source, x, y, z)  fadeCamera(source, true)  outputChatBox("Welcome to My Server", source) end addEventHandler("onPlayerJoin", getRootElement(), joinHandler)
Так как теперь мы должны спавнить игрока после нажатия на кнопку, нам нужно заменить событие "onPlayerJoin" пользовательским событием, генерируемым клиентом. Замените приведенный выше код следующим образом:
Code
function joinHandler(username, password)  local x,y,z  x = 1959.55  y = -1714.46  z = 10         if (client) then        spawnPlayer(client, x, y, z)        fadeCamera(client, true)        outputChatBox("Welcome to My Server", client)         end end   addEvent("SubmitLogin", true) addEventHandler("SubmitLogin", getRootElement(), joinHandler)
Обратите внимание на второй параметр функции addEvent (имеющий значение "true"), он указывает, что событие может быть сгенерировано другой стороной. так же заметьте, что "client" - внутренняя переменная, используемая MTA для идентификации игрока, сгенерировавшего событие. И, наконец, не забудьте добавить файл gui.lua в meta.xml основного ресурса и пометть его как клиентский:
Code
<script src="client/gui.lua" type="client" />

Теперь у нас есть минимальное окно авторизации, спавнящее игрока при нажатии кнопки "login". Вы также можете использовать логин и пароль, передаваемые функцией triggerServerEvent для идентификации пользователя.
Message edited by Fanor - Понеділок, 25.04.2011, 21:24