PT-BR/Introducão ao GUI scripting: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
(Criada a pagina: PT/BR 'Introdução ao GUI scripting'. Created the page: PT/BR 'Introdução ao GUI scripting'.)
 
 
(12 intermediate revisions by 3 users not shown)
Line 1: Line 1:
<!-- place holder -->
Um importante recurso do MTA:SA é capacidade de criar uma GUI (Graphical User Interface) personalizada. Uma GUI consiste em janelas, botões, caixas de edição, caixas de verificação e etc. Em outras palavras, todos os componentes presentes em janelas do Windows, por exemplo. Eles podem ser exibidos enquanto o usuário está no jogo, em vez de eles precisarem usar comandos tradicionais.
Um importante recurso no MTA:SA é a capacidade de roteiro personalizado GUI (Graphic User Interface/Interface Gráfica do Usuário). A GUI consiste de janelas, botões, caixas de edição, caixas de verificação... Quase todos os componentes padrão do formulário em ambientes gráficos. Eles podem ser exibidos enquanto o usuário está em jogo, e usado para entradas e saídas no lugar dos comandos tradicionais.
 
''Obs: É de extrema importância dar uma olhada na [[PT-BR/Introducao_ao_Scripting|Introdução a scripting]] porque muitas perguntas que poderão surgir neste tutorial provavelmente estão relacionados a falta de conceitos básicos de scripting.''


[[Image:AdminGUI.png|thumb|Admin Console GUI]]
[[Image:AdminGUI.png|thumb|Admin Console GUI]]


==Um tutorial para fazer uma janela de login==
==Tutorial: Janela de Login==
Neste tutorial, vamos fazer uma janela de login simples, com duas caixas de entrada e um botão. A janela aparece quando o jogador entra no jogo, e quando o botão é clicado, o jogador é gerado no jogo. O tutorial vai continuar o modo de jogo que fizemos no [[Scripting Introdução|Introdução ao Scripting]] ''(Se você já usou o [[Scripting Introdução|Introdução ao Scripting]], você precisará remover ou comentar a linha [[spawnPlayer]] da função "joinHandler" em seu código, como iremos substituí-lo por uma GUI alternativa neste tutorial)''. Nós também vamos dar uma olhada no scripting client-side.
Neste tutorial, vamos fazer uma janela de login bem simples, com duas caixas de entrada (input boxes) e um botão (button). A janela aparecerá quando o jogador entrar no jogo, e quando o botão de login for clicado, o jogador nasce no mapa. Usaremos o modo de jogo que foi criado no artigo [[PT-BR/Introducao_ao_Scripting|Introdução a scripting]]. Caso tenha seguido os procedimentos desse tutorial e tem o script (script.lua), precisará remover ou comentar a linha [[spawnPlayer]] da função ''joinHandler'', pois o jogador só será gerado no jogo quando feito o login.


===Criando a janela===
===Criando a janela===
Toda a GUI deve ser feita do lado client. Também é uma boa prática manter todos os scripts do lado client em uma pasta separada.  
Todo o script em GUI deve ser feito no lado do cliente. Também é recomendado colocar esses arquivos em uma pasta separada, em prol de manter uma melhor organização.


Vá até o diretório /SeuServerMTA/mods/deathmatch/resources/meuServer/, e crie uma pasta chamada "client". Sob o diretório /client/, crie um arquivo de texto com o nome "gui.lua".
Vá até o diretório ../server/mods/deathmatch/resources/, e crie uma pasta chamada "client". Sob o diretório /client/, crie um arquivo de texto com o nome "gui.lua".


Neste arquivo vamos escrever uma função que cria a janela. Para criar uma janela, iremos utilizar [[guiCreateWindow]]:
Neste arquivo vamos escrever uma função que cria a janela. Para fazer isto, iremos utilizar [[guiCreateWindow]]:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function criarJanelaDeLogin()
function criarJanelaDeLogin()
-- definir a posição X e Y da janela
-- definir a posição X e Y
local X = 0.375
local x = 0.375
local Y = 0.375
local y = 0.375
-- definir a largura e altura da janela
-- definir a largura e altura
local Largura = 0.25
local largura = 0.25
local Altura = 0.25
local altura = 0.25
-- criar a janela e salvar o valor de seu elemento na variável 'wdwLogin'
-- criar a janela e defini-la na variável 'janelaLogin'
-- clique no nome da função para ler a sua documentação
-- clique no nome da função para ler a sua documentação
wdwLogin = guiCreateWindow(X, Y, Largura, Altura, "Por favor efetue o Login", true)
janelaLogin = guiCreateWindow(x, y, largura, altura, "Efetue o Login", true)
end
end
</syntaxhighlight>
</syntaxhighlight>


===Relativo e Absoluto===
===Relativo e Absoluto===
Nota-se que o argumento final passado para guiCreateWindow no exemplo acima é ''true''. Isto indica que as coordenadas e dimensões da janela são '''relativa''', o que significa que é uma ''porcentagem'' do tamanho total da tela. Isto significa que se o lado esquerdo da tela é 0, e a extrema-direita é 1, uma posição X de 0.5 representaria o ponto central da tela. Similarmente, se a parte superior da tela é 0 e no fundo é 1, uma posição Y de 0.2 seria 20% do caminho para baixo da tela. Os mesmos princípios se aplicam para largura e altura, bem como (com um valor de largura de 0.5 significa que a janela será a metade da largura da tela).
Veja que o último argumento colocado em guiCreateWindow é ''true''. Isto indica que as coordenadas e dimensões da janela são '''relativas''', o que significa que é uma ''porcentagem'' do tamanho total da tela. Em outras palavras, se o lado esquerdo da tela é 0, e a extrema-direita é 1. Desta maneira, a posição X valendo 0.5 representaria o ponto central da tela. De forma análoga, se a parte superior da tela é 0 e a inferior é 1, uma posição Y de 0.2 seria 20% do caminho para baixo da tela. Os mesmos princípios se aplicam para largura e altura, exemplo: Se a largura for 0.5, a janela será a metade da largura da tela.


A alternativa de utilizar valores relativos é utilizar '''absolutos''' (passando ''false'' ao invés de true para guiCreateWindow). Os valores absolutos são calculados como o número total de pixels do canto superior esquerdo de seu parent (se nenhum elemento parent gui é especificado, o parent é a própria tela). Se assumirmos uma resolução de ecrã de 1920x1200, o lado esquerdo da tela sendo 0 pixel e os extrema-direita, sendo 1920 pixels, uma posição X de 960 representará o ponto central da tela. Similarmente, se a parte superior da tela é de 0 pixel eo fundo é de 1200, uma posição Y de 20 seria de 20 pixels para baixo a partir da parte superior da tela. Os mesmos princípios se aplicam a largura e altura, bem como (com um valor de largura de 50 ou seja, a janela será de 50 pixels de largura). ''Você pode usar [[guiGetScreenSize]] e um pouco de matemática para calcular certas posições absolutas.''
Caso não queira utilizar valores relativos, poderá optar por '''absolutos''' ao colocar ''false'' no argumento. Os valores absolutos são calculados como o número total de pixels do canto superior esquerdo do elemento, o qual o componente GUI está subordinado. Se nenhum elemento pai for especificado, este será a própria tela. Neste caso, se tivermos uma resolução de tela de 1920x1200, o lado esquerdo será 0 pixel e o de extrema-direita, será 1920 pixels. Uma posição X de 960 representará o ponto central da tela. Similarmente, se a parte superior da tela é de 0 pixel e o fundo é de 1200, uma posição Y de 20 seria de 20 pixels para baixo a partir da parte superior da tela. Os mesmos princípios se aplicam a largura e altura. Exemplo: Caso a largura seja 50, a janela terá os exatos 50 pixels de largura. ''Com um pouco de matemática, e usando a função [[guiGetScreenSize]], você poderá calcular as posições absolutas corretamente.''


As diferenças entre o uso de valores relativos e absolutos é muito simples; gui criada usando valores absolutos será sempre exatamente o mesmo tamanho de pixel e posição, enquanto gui criado usando valores relativos será sempre uma porcentagem do tamanho do seu parent.
As diferenças entre o uso de valores relativos e absolutos é muito simples. Se for uma GUI criada usando valores absolutos, cada unidade valerá um pixel. Enquanto os valores relativos usarão a porcentagem para definir essas posições.


Absoluto é geralmente mais fácil de usar quando a edição do código é á mão, no entanto a escolha do tipo depende da situação que você está usando para isso.
Absoluto é geralmente mais fácil de usar quando a edição do código for feita a mão. Entretanto, a escolha do tipo de medida dependerá da finalidade do componente GUI.


Para esta presente introdução iremos utilizar valores relativos.
Uma das principais razões de se utilizar valores relativos é para evitar que as janelas fiquem fora da tela ou em posições indesejáveis. Uma GUI que foi feita, por exemplo, na resolução de 1080p e for posicionada no canto superior direito com valores absolutos, ficará fora da tela caso esse script fosse executado em 720p. Oras, porque posicionarei uma janela nas coordenadas (1080, 0) se a tela do sujeito só vai até 720 pixels no eixo x? Simplesmente não vai funcionar.
 
Neste tutorial, obviamente usaremos valores relativos para a tela de login, e seus componentes, ficarem exatamente onde é preciso.


===Adicionando os componentes===
===Adicionando os componentes===
Em seguida, vamos adicionar os rótulos de texto (labels) (dizendo "username:" e "senha:"), caixas de edição (edit boxes) (para inserir seus dados) e um botão para efetuar login.
Vamos adicionar:
* Textos(labels) para indicar o que é cada campo - usuário, senha  
* Caixas de edição (edit boxes), para que o usuário possa inserir seus dados
* Um botão para efetuar o login


Para criar botões você deve usar [[guiCreateButton]] e para criar caixas de edição você deve usar [[guiCreateEdit]]:
Para criar botões você deve usar [[guiCreateButton]], e para criar caixas de edição você deve usar [[guiCreateEdit]]:


'''Note que agora iremos escrever mais código para a nossa função atual 'criarJanelaDeLogin'. Esta não é uma nova função e se destina a substituir o que você já tem.'''
'''Note que agora iremos adicionar mais instruções para a função ''criarJanelaDeLogin''. Portanto, esta não é uma nova função, e sim uma substituta da qual você já tem.'''
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function criarJanelaDeLogin()
function criarJanelaDeLogin()
local X = 0.375
local x = 0.375
local Y = 0.375
local y = 0.375
local Largura = 0.25
local largura = 0.25
local Altura = 0.25
local altura = 0.25
wdwLogin = guiCreateWindow(X, Y, Largura, Altura, "Por favor efetue o Login", true)
wdwLogin = guiCreateWindow(x, y, largura, altura, "Efetue o Login", true)
-- definir as novas posições X e Y para o primeiro label
-- Definir as novas posições x e y para o primeiro label
X = 0.0391
x = 0.0391
Y = 0.1979
y = 0.1979
-- definir o novo valor de largura e altura para o primeiro label
-- Definir o novo valor de largura e altura para o primeiro label
Largura = 0.3672
largura = 0.3672
Altura = 0.25
altura = 0.25
-- criar o primeiro label, note que o último argumento passado é 'wdwLogin', que significa a janela
-- Criar o primeiro label. Note que o último argumento passado é 'wdwLogin', representando a janela
-- o que criámos acima é o parent deste rótulo de texto (label)(assim toda a posição e os valores de tamanho são agora relativo para a posição dessa janela)
-- Ou seja, ele será o elemento pai (parent) deste texto (label)
guiCreateLabel(X, Y, Largura, Altura, "Nome de Usuario", true, wdwLogin)
-- Assim toda os valores de tamanho serão relativos a esta janela
-- altere o valor de Y, assim o segundo label esteja ligeiramente abaixo do primeiro
guiCreateLabel(x, y, largura, altura, "Usuário:", true, wdwLogin)
Largura = 0.25
 
-- Alterar o valor de y, assim o segundo label ficará ligeiramente abaixo do primeiro
largura = 0.25
y = 0.5
guiCreateLabel(x, y, largura, altura, "Senha:", true, wdwLogin)
 
-- Valores para as entradas
x = 0.415
y = 0.2
largura = 0.5
altura = 0.15
editUsuario = guiCreateEdit(x, y, largura, altura, "", true, wdwLogin)
Y = 0.5
Y = 0.5
guiCreateLabel(X, Y, Largura, Altura, "Senha", true, wdwLogin)
editSenha = guiCreateEdit(x, y, largura, altura, "", true, wdwLogin)


X = 0.415
-- Definir o tamanho máximo de caracteres do nome de usuário e a senha para 50
Y = 0.2
Largura = 0.5
Altura = 0.15
editUsuario = guiCreateEdit(X, Y, Largura, Altura, "", true, wdwLogin)
Y = 0.5
edtSenha = guiCreateEdit(X, Y, Largura, Altura, "", true, wdwLogin)
-- definir o tamanho máximo de caracteres do nome de usuário e Senha para 50
guiEditSetMaxLength(editUsuario, 50)
guiEditSetMaxLength(editUsuario, 50)
guiEditSetMaxLength(edtSenha, 50)
guiEditSetMaxLength(editSenha, 50)
X = 0.415
x = 0.415
Y = 0.7
y = 0.7
Largura = 0.25
largura = 0.25
Altura = 0.2
altura = 0.2
btnLogin = guiCreateButton(X, Y, Largura, Altura, "Login", true, wdwLogin)
btnLogin = guiCreateButton(x, y, largura, altura, "Login", true, wdwLogin)
-- tornar a janela invisível
-- Tornar a janela invisível
guiSetVisible(wdwLogin, false)
guiSetVisible(wdwLogin, false)
end
end
</syntaxhighlight>
</syntaxhighlight>
Note que cada componente GUI criado é um filho da janela, isto é feito através da especificação do elemento pai (wdwLogin, neste caso) ao criar o componente.
Em nosso script, quando usamos a função para criar cada componente da janela, definimos a variável ''wdwLogin'' no último argumento. Isso significa que esses componentes estão contidos na janela. Em inglês dizemos que ele é um ''child element'' e a janela é um ''parent element''..


Note that every GUI component created is a child of the window, this is done by specifying the parent element (wdwLogin, in this case) when creating the component.
Isto é muito útil porque não só significa que todos os componentes estão anexados à janela e irão mover-se com ela. Além disso, todas as alterações realizadas na janela serão aplicadas a todos os elementos subordinados, ou elementos filhos. Para ocultar a janela, simplesmente usaremos a função:
 
Isto é muito útil porque não só significa que todos os componentes estão anexados à janela e irá mover-se com ela, mas também que todas as alterações feitas para a janela pai será aplicada para todos os elementos filho. Por exemplo, agora podemos ocultar toda a GUI que acabamos de criar, basta ocultar a janela:
 
This is very useful because not only does it mean that all the components are attached to the window and will move with it, but also that any changes done to the parent window will be applied down the tree to these child components. For example, we can now hide all of the GUI we just created by simply hiding the window:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
guiSetVisible(wdwLogin, false) -- oculta toda a GUI que fizemos para que possamos mostrá-los para o jogador, quando for preciso.
guiSetVisible(wdwLogin, false) -- Isso fará com que todos os elementos subordinado fiquem invisíveis também. O conjunto só será mostrado quando for preciso.
</syntaxhighlight>
</syntaxhighlight>


===Usando a função criada anteriormente===
 
A função criarJanelaDeLogin agora está completa, mas nada vai acontecer até que nós a chamamos. È Recomendado criar toda a GUI quando o recurso client for iniciado, então será ocultada, e mostrará para o jogador quando necessário. Portanto, vamos escrever um manipulador de eventos para "[[onClientResourceStart]]" para criar a janela:
===Usando a função que acabamos de fazer===
A nossa função agora está completa, mas nada irá acontecer até que nós a chamamos. É Recomendado criar toda a GUI quando o recurso do cliente for iniciado, em seguida, ocultá-la e mostrar para o jogador quando necessário. Portanto, vamos adicionar um manipulador de eventos com o evento ''onClientResourceStart'' para criar a janela:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- anexar o manipulador de eventos para o elemento raiz (root element) do recurso
-- anexa o manipulador de eventos para o elemento raiz (root element) do recurso:
-- isso significa que ele só irá desencadear (trigger) quando seu próprio recurso é iniciado
-- isto significa que ele só irá ser executado quando o próprio recurso for iniciado.
addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()),  
addEventHandler( "onClientResourceStart", getResourceRootElement(getThisResource()),  
function ()
function ()
criarJanelaDeLogin()
criarJanelaDeLogin()
end
end
)
)
</syntaxhighlight>
</syntaxhighlight>
Como este é uma janela de login, agora precisamos mostrar a janela quando o jogador entra no jogo.
Como se trata de uma janela de login, precisamos mostrar a janela quando o jogador entrar no servidor.
Isto pode ser feito usando o mesmo evento, "[[onClientResourceStart]]", para que possamos modificar o código acima e incluir para mostrar a janela:
Isto pode ser feito usando o mesmo evento, ou seja, ''onClientResourceStart''. Agora, precisamos complementar o código anterior para que mostre a janela.
 
As this is a log in window, we now need to show the window when the player joins the game.
This can be done using the same event, "[[onClientResourceStart]]", so we can modify the above code to include showing the window:
 
'''Observe que agora estamos escrevendo mais código para o nosso manipulador 'onClientResourceStart' existente. Este não é um novo manipulador de eventos e se destina a substituir o que você já tem.'''


'''Note that we are now writing more code for our existing 'onClientResourceStart' handler. This is not a new event handler and is meant to replace what you already have.'''  
'''No código a seguir, vamos dar mais funcionalidade para o evento 'onClientResourceStart'. Note que não será criado um novo manipulador de eventos, este código só substituirá o que você já tem.'''
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
addEventHandler("onClientResourceStart", getResourceRootElement(getThisResource()),  
addEventHandler( "onClientResourceStart", getResourceRootElement(getThisResource()),  
function ()
function ()
-- criar a janela de login e seus componentes
-- Chamando a função para criar a janela de login e seus componentes.
criarJanelaDeLogin()
criarJanelaDeLogin()


-- saída de uma mensagem de boas-vindas ao jogador
-- Mostrar uma mensagem de boas-vindas ao jogador.
                outputChatBox("Bem-vindo ao meu servidor MTA:SA, por favor efetue o login.")
outputChatBox("Bem-vindo ao meu servidor do MTA:SA, por favor efetue o login.")


-- se a GUI foi criada com êxito, então, mostrar a GUI para o jogador
-- Se a GUI foi criada com êxito, então ela será mostrada ao jogador.
        if (wdwLogin ~= nil) then
if (wdwLogin ~= nil) then
guiSetVisible(wdwLogin, true)
guiSetVisible(wdwLogin, true)
else
else
-- se a GUI não foi criada corretamente, notificar o jogador
-- Se a GUI não foi criada corretamente, notificaremos o jogador.
outputChatBox("Um erro inesperado ocorreu e a janela de login não foi criada.")
outputChatBox("Um erro inesperado ocorreu e a janela de login não foi criada.")
        end
end


-- habilitar o cursor para os jogadores (para que eles possam selecionar e clique sobre os componentes)
-- Habilitar o cursor para o jogador, para que ele possa clicar sobre os componentes.
        showCursor(true)
showCursor(true)
-- definir o foco de entrada para a GUI, permitindo que os jogadores (por exemplo) para pressione 'T', sem que o chatbox abra
-- Definir o foco de entrada para a GUI, permitindo, por exemplo, que os jogadores pressionem 't', sem que o chatbox abra.
        guiSetInputEnabled(true)
guiSetInputEnabled(true)
end
end
)
)
</syntaxhighlight>
</syntaxhighlight>


Note que temos uma simples verificação de segurança antes de tornar a janela visível, no caso improvável de que a janela não foi criada, significa que wdwLogin não é um elemento válido, nós não temos um erro. e apenas informamos o jogador o que aconteceu.
Note que uma verificação preventiva antes de tornar a janela visível. Caso a janela não seja criada com êxito, isto é, se wdwLogin não for um valor válido, notificaremos ao jogador que um erro ocorreu.
Na próxima etapa, vamos criar a funcionalidade para o botão de login.
 
Na próxima etapa, vamos dar funcionalidade ao botão de login.


==Programando o botão==
==Programando o botão==
Agora que nós criamos nossa GUI e mostrou-a para o jogador, é preciso programa-la para que possa funcionar.  
Agora que criamos nossa interface e a mostramos ao jogador, é preciso programá-la para que tudo funcione.  


===Detectando o clique===
===Detectando o clique===
Quando o jogador clica em qualquer parte da GUI, o evento "[[onClientGUIClick]]" será acionado para o componente GUI que você clicou. Isso nos permite facilmente detectar quaisquer cliques sobre o elemento GUI que deseja usar.
Quando o jogador clicar em qualquer parte da GUI, o evento ''onClientGUIClick'' é chamado para o componente que você clicou. Isto nos permite detectar facilmente quaisquer cliques sobre o elemento GUI que desejar.
Por exemplo, podemos anexar o evento para o botão btnLogin para obter todos os cliques sobre ele:
Por exemplo, podemos anexar o evento ao botão 'btnLogin' para sabermos quando ele for clicado:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- anexar o evento onClientGUIClick para btnLogin e definir-lo para chamar a função 'submeterLoginClient'
-- Anexar o evento 'onClientGUIClick' para o botão btnLogin.
addEventHandler("onClientGUIClick", btnLogin, submeterLoginClient, false)
-- E chamar a função 'requisitarLogin' quando clicar nele.
addEventHandler("onClientGUIClick", btnLogin, requisitarLogin, false)
</syntaxhighlight>
</syntaxhighlight>
'''Observe o argumento final passado é "false". Isto indica que o evento só irá acionar diretamente sobre btnLogin, não se o evento tem propagado para cima ou para baixo da árvore. Se configurado para "true", enquanto anexado ao elemento gui significa que se clicar em qualquer elemento no mesmo ramo vai disparar esse evento.'''


Esta linha de código agora pode ser adicionada dentro da função criarJanelaDeLogin. É um erro comum, tentar anexar eventos a elementos GUI inexistentes,  então certifique-se sempre de anexar os seus eventos '''depois''' o elemento gui (neste caso, o botão) foi criado:
'''Observe que o último argumento é ''false''. Isto quer dizer que o evento só será chamado para btnLogin, e não para o seu elemento pai, que é a janela. Por outro lado, se for colocado "true", o evento será chamado para o elemento pai.'''


'''Note que vamos agora escrever mais código para a nossa função 'criarJanelaDeLogin'.'''  
Esse código agora pode ser colocado dentro da função criarJanelaDeLogin. Um erro comum, é anexar eventos para elementos GUI inexistentes, então certifique-se de sempre anexar os seus eventos '''depois''' que o elemento gui (neste caso, o botão) for criado:
 
'''No código a seguir, vamos adicionar o evento para detectar o clique, dentro da função 'criarJanelaDeLogin'.'''  
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function criarJanelaDeLogin()
function criarJanelaDeLogin()
Line 166: Line 171:
...
...


-- agora adicionar o evento onClientGUIClick para o botão que acabamos de criar
-- agora, adicionar o evento onClientGUIClick para o botão que acabamos de criar
addEventHandler("onClientGUIClick", btnLogin, submeterLoginClient, false)
addEventHandler("onClientGUIClick", btnLogin, requisitarLogin, false)
</syntaxhighlight>
</syntaxhighlight>


===Gerenciando o clique===
===Quando clicar no botão===
Agora que podemos detectar quando o jogador clica no botão, é preciso escrever o código para gerenciar o que acontece quando ele é clicado.
Agora que podemos detectar quando o jogador clica no botão, vamos escrever o código para fazer a próxima etapa depois que o botão for clicado.
Em nosso manipulador de eventos [[onClientClick]], a função submeterLoginClient sempre será chamada quando o botão btnLogin for clicado.
No manipulador de eventos [[onClientClick]], a função requisitarLogin sempre será chamada quando o botão btnLogin for clicado.
Portanto, agora podemos usar a função submeterLoginClient para controlar o que acontece quando o botão é clicado:
Então, no próximo código, vamos começar a dar funcionalidade para a função requisitarLogin:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- criar a função e definir os parâmetros para 'botão' (button) e 'estado' (state)
-- criar a função e definir os dois parâmetros do evento: 'button' - botão e state - estado do clique
-- (eles são passados automaticamente pelo onClientGUIClick)
function requisitarLogin(button,state)
function submeterLoginClient(button,state)
-- se o botão foi clicado com o botão esquerdo do mouse, e o estado do clique for 'up' (solto)
-- se o nosso botão de login foi clicado com o botão esquerdo do mouse, eo estado do botão do mouse é up
if button == "left" and state == "up" then
if button == "left" and state == "up" then
-- mover o foco de entrada de volta para o jogo (permitindo aos jogadores para se movimentar, abrir o chat, etc)
-- mudar o foco de entrada de volta para o jogo (permitindo ao jogador se movimentar e abrir o chat)
guiSetInputEnabled(false)
guiSetInputEnabled(false)
-- ocultar a janela e todos os componentes
-- ocultar a janela e todos os componentes
Line 189: Line 193:
end
end
</syntaxhighlight>
</syntaxhighlight>
Agora, quando o botão é clicado, a janela será ocultada e todos os controles serão permitidos para o jogador. Em seguida, vamos ligar com o lado server para permitir que o jogador execute spawn.
Agora, quando o botão de login for clicado, a janela será ocultada, o cursor do mouse desabilitado e o foco de entrada será desativado.
Na próxima etapa, vamos chamar o lado do servidor para permitir que o jogador seja gerado no jogo.


===Chamando o lado server===
===Chamando o servidor===
Chamando o lado server pode ser feito usando [[triggerServerEvent]]. Isto lhe permite chamar um evento especificado no server através do client. Se quiser chamar o client através do server pode ser feito usando [[triggerClientEvent]].
Para chamar um evento do lado do servidor, usamos [[triggerServerEvent]]. Essa função lhe permite chamar um evento definido no lado do servidor por meio do cliente. O contrário pode ser feito usando a função [[triggerClientEvent]].
Aqui, usamos a função [[triggerServerEvent]] para chamar o nosso evento personalizado no lado server, chamado "submeterLogin", que irá controlar a função de spawn que é do lado server.
Agora vamos usar a função [[triggerServerEvent]] para chamar o evento que será feito no lado do servidor, esse evento irá controlar a função de 'spawn'.


'''Note que iremos agora escrever mais código para a nossa função 'submeterLoginClient'. Esta não é uma nova função e se destina a substituir o que você já tem.'''  
'''No código a seguir, vamos complementar a função 'requisitarLogin'. Para o seu entendimento, observe os comentários pelo código.'''  
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function submeterLoginClient(button,state)
function requisitarLogin(button,state)
if button == "left" and state == "up" then
if button == "left" and state == "up" then
-- obter o texto inserido no campo 'nomeDeUsuario'
-- obter o texto inserido no campo 'nomeDeUsuario'
local nomeDeUsuario = guiGetText(editUsuario)
local nomeDeUsuario = guiGetText(editUsuario)
-- obter o texto inserido no campo 'senha'
-- obter o texto inserido no campo 'senha'
local senha = guiGetText(edtSenha)
local senha = guiGetText(editSenha)
 
-- note que 'editUsuario' e 'editSenha' são variáveis definidas na criação do campo de edição
-- se o nome de usuário e senha existem
-- se o nome de usuário e senha existem
if nomeDeUsuario and senha then
if nomeDeUsuario and senha then
-- acionar o evento server 'submeterLogin' e passar o nome de usuário e senha para ele
-- chamar o evento do servidor 'submeterLogin' e passar o nome de usuário e senha nos argumentos
triggerServerEvent("submeterLogin", getRootElement(), nomeDeUsuario, senha)
triggerServerEvent("submeterLogin", getRootElement(), nomeDeUsuario, senha)


-- ocultar a gui, desabilitar o cursor e retornar o controle para o jogador
-- ocultar a janela, desabilitar o cursor e desativar foco de entrada
guiSetInputEnabled(false)
guiSetInputEnabled(false)
guiSetVisible(wdwLogin, false)
guiSetVisible(wdwLogin, false)
showCursor(false)
showCursor(false)
else
else
-- caso contrário, irá sair uma mensagem para o jogador, se o nome de usuário e/ou senha não existem
-- se o nome de usuário ou senha não existir, sairá uma mensagem para o jogador,
-- e não ocultar a gui
outputChatBox("Por favor, digite o nome de usuário e senha.", 230, 0, 0)
outputChatBox("Por favor, digite o nome de usuário e senha.")
end
end
end
end
Line 222: Line 227:
</syntaxhighlight>
</syntaxhighlight>


===Criando o evento do lado server===
===Criando o evento no servidor===
Neste ponto nós temos agora todos os códigos necessários no lado do client, então abrra seu arquivo do lado server 'script.lua' (do [[Scripting Introduction|Introdução ao Scripting]]) ou outro arquivo do lado server adequado para trabalhar.
Agora que finalizamos a parte do lado do cliente, abra seu arquivo do lado do servidor 'script.lua' (do [[PT-BR/Introducao_ao_Scripting|Introdução a scripting]]) ou apenas crie um novo arquivo.


No lado do servidor, lembre-se que o jogador executará o spawn assim que entrar.
Lembre-se que o jogador só será gerado no jogo assim que ele logar. Então, em primeiro lugar, vamos criar o evento personalizado 'submeterLogin'.
Então, em primeiro lugar, teremos que definir o evento personalizado que iremos usar antes no client. Isto pode ser feito usando [[addEvent]] e [[AddEventHandler]].
Para isso, você terá de usar as funções [[addEvent]] e [[addEventHandler]].
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- criar nossa função loginHandler, com parâmetros 'username' e 'senha' (passado pelo client gui)
-- criar função loginHandler, com os parâmetros: 'username' e 'senha' (enviado pelo lado do cliente)
function loginHandler(username,senha)
function loginHandler(username,senha)


end
end


-- definir o nosso evento personalizado e permitir que ele seja acionado a partir do cliente ('true')
-- definir o evento personalizado e permitir que ele seja chamado a partir do cliente usando 'true'
addEvent("submeterLogin",true)
addEvent("submeterLogin",true)
-- adicionar um manipulador de eventos para quando 'submeterLogin' for acionado, a função 'loginHandler' é chamada
-- adicionar um manipulador de eventos para quando 'submeterLogin' for chamado,
-- chamar também a função 'loginHandler' que está ligada a ele
addEventHandler("submeterLogin",root,loginHandler)
addEventHandler("submeterLogin",root,loginHandler)
</syntaxhighlight>
</syntaxhighlight>
 
<!-- Aqui.... -->
===Efetuando login===
===Efetuando login===
Agora, temos uma função que é chamada através do evento personalizado 'submeterLogin', podemos começar a trabalhar com o login e spawn do jogador, usando a nossa função 'loginHandler':
Agora, temos uma função que é chamada através do evento personalizado 'submeterLogin'.
Para finalizar, iremos complementar a função 'loginHandler':
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function loginHandler(username,senha)
function loginHandler(username,senha)
Line 249: Line 256:
spawnPlayer(client, 1959.55, -1714.46, 10)
spawnPlayer(client, 1959.55, -1714.46, 10)
fadeCamera(client, true)
fadeCamera(client, true)
                        setCameraTarget(client, client)
setCameraTarget(client, client)
outputChatBox("Bem-vindo ao servidor.", client)
outputChatBox("Bem-vindo ao servidor.", client)
end
end
Line 255: Line 262:
-- se o nome de usuário ou senha não estão corretos, informar para o jogador
-- se o nome de usuário ou senha não estão corretos, informar para o jogador
outputChatBox("Nome de usuário e senha inválidos. Por favor, tente novamente.",client)
outputChatBox("Nome de usuário e senha inválidos. Por favor, tente novamente.",client)
        end
end
end
end


Line 261: Line 268:
addEventHandler("submeterLogin",root,loginHandler)
addEventHandler("submeterLogin",root,loginHandler)
</syntaxhighlight>
</syntaxhighlight>
'''Para os fins deste tutorial, um sistema de username e senha muito básico é mostrado. Para uma alternativa mais compreensiva, você pode usar o Sistema de Conta ou um banco de dados MySQL.'''


Observe também o uso da variável "client", é uma variável interna usada pelo MTA para identificar o jogador que disparou o evento.
Agora você pode colocar em prática o que aprendeu neste tutorial e começar a trabalhar com login e spawn do jogador, usando a função 'loginHandler'.
'''Note que um sistema de registro não está integrado ao tutorial. Para isso, você pode optar pelo uso do Sistema de conta nativo do MTA ou um banco de dados MySQL.'''
 
Observe também o uso da variável "client": é uma variável interna usada pelo MTA para identificar o jogador que fez o evento ser chamado.




Finalmente, não se esqueça de incluir o arquivo gui.lua novo no meta.xml do recurso principal, e nomeá-lo como um script client:
Por fim, não se esqueça de incluir o arquivo gui.lua novo no meta.xml do recurso, e definir na tag 'type' como um script do lado do cliente:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<script src="client/gui.lua" type="client" />
<script src="client/gui.lua" type="client" />
Line 272: Line 281:




Neste ponto, temos agora uma janela de login básico que verifica nome de usuário do jogador e senha quando o botão de login é clicado. Se eles estiverem corretos, o jogador é automaticamente gerado no jogo.
Neste tutorial, criamos uma simples janela que verifica o nome de usuário e a senha quando o botão de login é pressionado. Se os dados estiverem corretos, o jogador entrará no jogo.


Para mais ajuda com GUI, consulte [[:Category:GUI_Tutorials|tutoriais GUI]].
Para mais ajuda com GUI, consulte [[:Category:GUI_Tutorials|Tutoriais GUI]] (página em inglês).


[[categoria:GUI_Tutorials]]
[[Category:GUI_Tutorials]]
[[en:Introduction to Scripting the GUI]]
[[es:Introducción a la Programación de GUI]]
[[it:Introduzione_allo_scripting_della_GUI]]
[[it:Introduzione_allo_scripting_della_GUI]]
[[ru:Introduction to Scripting the GUI]]
[[ru:Introduction to Scripting the GUI]]
[[es:Introducción a la Programación de GUI]]

Latest revision as of 06:17, 21 October 2015

Um importante recurso do MTA:SA é capacidade de criar uma GUI (Graphical User Interface) personalizada. Uma GUI consiste em janelas, botões, caixas de edição, caixas de verificação e etc. Em outras palavras, todos os componentes presentes em janelas do Windows, por exemplo. Eles podem ser exibidos enquanto o usuário está no jogo, em vez de eles precisarem usar comandos tradicionais.

Obs: É de extrema importância dar uma olhada na Introdução a scripting porque muitas perguntas que poderão surgir neste tutorial provavelmente estão relacionados a falta de conceitos básicos de scripting.

Admin Console GUI

Tutorial: Janela de Login

Neste tutorial, vamos fazer uma janela de login bem simples, com duas caixas de entrada (input boxes) e um botão (button). A janela aparecerá quando o jogador entrar no jogo, e quando o botão de login for clicado, o jogador nasce no mapa. Usaremos o modo de jogo que foi criado no artigo Introdução a scripting. Caso tenha seguido os procedimentos desse tutorial e tem o script (script.lua), precisará remover ou comentar a linha spawnPlayer da função joinHandler, pois o jogador só será gerado no jogo quando feito o login.

Criando a janela

Todo o script em GUI deve ser feito no lado do cliente. Também é recomendado colocar esses arquivos em uma pasta separada, em prol de manter uma melhor organização.

Vá até o diretório ../server/mods/deathmatch/resources/, e crie uma pasta chamada "client". Sob o diretório /client/, crie um arquivo de texto com o nome "gui.lua".

Neste arquivo vamos escrever uma função que cria a janela. Para fazer isto, iremos utilizar guiCreateWindow:

function criarJanelaDeLogin()
	-- definir a posição X e Y
	local x = 0.375
	local y = 0.375
	-- definir a largura e altura
	local largura = 0.25
	local altura = 0.25
	-- criar a janela e defini-la na variável 'janelaLogin'
	-- clique no nome da função para ler a sua documentação
	janelaLogin = guiCreateWindow(x, y, largura, altura, "Efetue o Login", true)
end

Relativo e Absoluto

Veja que o último argumento colocado em guiCreateWindow é true. Isto indica que as coordenadas e dimensões da janela são relativas, o que significa que é uma porcentagem do tamanho total da tela. Em outras palavras, se o lado esquerdo da tela é 0, e a extrema-direita é 1. Desta maneira, a posição X valendo 0.5 representaria o ponto central da tela. De forma análoga, se a parte superior da tela é 0 e a inferior é 1, uma posição Y de 0.2 seria 20% do caminho para baixo da tela. Os mesmos princípios se aplicam para largura e altura, exemplo: Se a largura for 0.5, a janela será a metade da largura da tela.

Caso não queira utilizar valores relativos, poderá optar por absolutos ao colocar false no argumento. Os valores absolutos são calculados como o número total de pixels do canto superior esquerdo do elemento, o qual o componente GUI está subordinado. Se nenhum elemento pai for especificado, este será a própria tela. Neste caso, se tivermos uma resolução de tela de 1920x1200, o lado esquerdo será 0 pixel e o de extrema-direita, será 1920 pixels. Uma posição X de 960 representará o ponto central da tela. Similarmente, se a parte superior da tela é de 0 pixel e o fundo é de 1200, uma posição Y de 20 seria de 20 pixels para baixo a partir da parte superior da tela. Os mesmos princípios se aplicam a largura e altura. Exemplo: Caso a largura seja 50, a janela terá os exatos 50 pixels de largura. Com um pouco de matemática, e usando a função guiGetScreenSize, você poderá calcular as posições absolutas corretamente.

As diferenças entre o uso de valores relativos e absolutos é muito simples. Se for uma GUI criada usando valores absolutos, cada unidade valerá um pixel. Enquanto os valores relativos usarão a porcentagem para definir essas posições.

Absoluto é geralmente mais fácil de usar quando a edição do código for feita a mão. Entretanto, a escolha do tipo de medida dependerá da finalidade do componente GUI.

Uma das principais razões de se utilizar valores relativos é para evitar que as janelas fiquem fora da tela ou em posições indesejáveis. Uma GUI que foi feita, por exemplo, na resolução de 1080p e for posicionada no canto superior direito com valores absolutos, ficará fora da tela caso esse script fosse executado em 720p. Oras, porque posicionarei uma janela nas coordenadas (1080, 0) se a tela do sujeito só vai até 720 pixels no eixo x? Simplesmente não vai funcionar.

Neste tutorial, obviamente usaremos valores relativos para a tela de login, e seus componentes, ficarem exatamente onde é preciso.

Adicionando os componentes

Vamos adicionar:

  • Textos(labels) para indicar o que é cada campo - usuário, senha
  • Caixas de edição (edit boxes), para que o usuário possa inserir seus dados
  • Um botão para efetuar o login

Para criar botões você deve usar guiCreateButton, e para criar caixas de edição você deve usar guiCreateEdit:

Note que agora iremos adicionar mais instruções para a função criarJanelaDeLogin. Portanto, esta não é uma nova função, e sim uma substituta da qual você já tem.

function criarJanelaDeLogin()
	local x = 0.375
	local y = 0.375
	local largura = 0.25
	local altura = 0.25
	wdwLogin = guiCreateWindow(x, y, largura, altura, "Efetue o Login", true)
	
	-- Definir as novas posições x e y para o primeiro label
	x = 0.0391
	y = 0.1979
	-- Definir o novo valor de largura e altura para o primeiro label
	largura = 0.3672
	altura = 0.25
	-- Criar o primeiro label. Note que o último argumento passado é 'wdwLogin', representando a janela
	-- Ou seja, ele será o elemento pai (parent) deste texto (label)
	-- Assim toda os valores de tamanho serão relativos a esta janela
	guiCreateLabel(x, y, largura, altura, "Usuário:", true, wdwLogin)

	-- Alterar o valor de y, assim o segundo label ficará ligeiramente abaixo do primeiro
	largura = 0.25
	y = 0.5
	guiCreateLabel(x, y, largura, altura, "Senha:", true, wdwLogin)

	-- Valores para as entradas
	x = 0.415
	y = 0.2
	largura = 0.5
	altura = 0.15
	editUsuario = guiCreateEdit(x, y, largura, altura, "", true, wdwLogin)
	Y = 0.5
	editSenha = guiCreateEdit(x, y, largura, altura, "", true, wdwLogin)

	-- Definir o tamanho máximo de caracteres do nome de usuário e a senha para 50
	guiEditSetMaxLength(editUsuario, 50)
	guiEditSetMaxLength(editSenha, 50)
	
	x = 0.415
	y = 0.7
	largura = 0.25
	altura = 0.2
	btnLogin = guiCreateButton(x, y, largura, altura, "Login", true, wdwLogin)
	
	-- Tornar a janela invisível
	guiSetVisible(wdwLogin, false)
end

Em nosso script, quando usamos a função para criar cada componente da janela, definimos a variável wdwLogin no último argumento. Isso significa que esses componentes estão contidos na janela. Em inglês dizemos que ele é um child element e a janela é um parent element..

Isto é muito útil porque não só significa que todos os componentes estão anexados à janela e irão mover-se com ela. Além disso, todas as alterações realizadas na janela serão aplicadas a todos os elementos subordinados, ou elementos filhos. Para ocultar a janela, simplesmente usaremos a função:

guiSetVisible(wdwLogin, false) -- Isso fará com que todos os elementos subordinado fiquem invisíveis também. O conjunto só será mostrado quando for preciso.


Usando a função que acabamos de fazer

A nossa função agora está completa, mas nada irá acontecer até que nós a chamamos. É Recomendado criar toda a GUI quando o recurso do cliente for iniciado, em seguida, ocultá-la e mostrar para o jogador quando necessário. Portanto, vamos adicionar um manipulador de eventos com o evento onClientResourceStart para criar a janela:

-- anexa o manipulador de eventos para o elemento raiz (root element) do recurso:
-- isto significa que ele só irá ser executado quando o próprio recurso for iniciado.
addEventHandler( "onClientResourceStart", getResourceRootElement(getThisResource()), 
	function ()
		criarJanelaDeLogin()
	end
)

Como se trata de uma janela de login, precisamos mostrar a janela quando o jogador entrar no servidor. Isto pode ser feito usando o mesmo evento, ou seja, onClientResourceStart. Agora, precisamos complementar o código anterior para que mostre a janela.

No código a seguir, vamos dar mais funcionalidade para o evento 'onClientResourceStart'. Note que não será criado um novo manipulador de eventos, este código só substituirá o que você já tem.

addEventHandler( "onClientResourceStart", getResourceRootElement(getThisResource()), 
	function ()
		-- Chamando a função para criar a janela de login e seus componentes.
		criarJanelaDeLogin()

		-- Mostrar uma mensagem de boas-vindas ao jogador.
		outputChatBox("Bem-vindo ao meu servidor do MTA:SA, por favor efetue o login.")

		-- Se a GUI foi criada com êxito, então ela será mostrada ao jogador.
		if (wdwLogin ~= nil) then
			guiSetVisible(wdwLogin, true)
		else
			-- Se a GUI não foi criada corretamente, notificaremos o jogador.
			outputChatBox("Um erro inesperado ocorreu e a janela de login não foi criada.")
		end

		-- Habilitar o cursor para o jogador, para que ele possa clicar sobre os componentes.
		showCursor(true)
		-- Definir o foco de entrada para a GUI, permitindo, por exemplo, que os jogadores pressionem 't', sem que o chatbox abra.
		guiSetInputEnabled(true)
	end
)

Note que há uma verificação preventiva antes de tornar a janela visível. Caso a janela não seja criada com êxito, isto é, se wdwLogin não for um valor válido, notificaremos ao jogador que um erro ocorreu.

Na próxima etapa, vamos dar funcionalidade ao botão de login.

Programando o botão

Agora que criamos nossa interface e a mostramos ao jogador, é preciso programá-la para que tudo funcione.

Detectando o clique

Quando o jogador clicar em qualquer parte da GUI, o evento onClientGUIClick é chamado para o componente que você clicou. Isto nos permite detectar facilmente quaisquer cliques sobre o elemento GUI que desejar. Por exemplo, podemos anexar o evento ao botão 'btnLogin' para sabermos quando ele for clicado:

-- Anexar o evento 'onClientGUIClick' para o botão btnLogin.
-- E chamar a função 'requisitarLogin' quando clicar nele.
addEventHandler("onClientGUIClick", btnLogin, requisitarLogin, false)

Observe que o último argumento é false. Isto quer dizer que o evento só será chamado para btnLogin, e não para o seu elemento pai, que é a janela. Por outro lado, se for colocado "true", o evento será chamado para o elemento pai.

Esse código agora pode ser colocado dentro da função criarJanelaDeLogin. Um erro comum, é anexar eventos para elementos GUI inexistentes, então certifique-se de sempre anexar os seus eventos depois que o elemento gui (neste caso, o botão) for criado:

No código a seguir, vamos adicionar o evento para detectar o clique, dentro da função 'criarJanelaDeLogin'.

function criarJanelaDeLogin()
	-- criar todos os nossos elementos da GUI
	...

	-- agora, adicionar o evento onClientGUIClick para o botão que acabamos de criar
	addEventHandler("onClientGUIClick", btnLogin, requisitarLogin, false)

Quando clicar no botão

Agora que podemos detectar quando o jogador clica no botão, vamos escrever o código para fazer a próxima etapa depois que o botão for clicado. No manipulador de eventos onClientClick, a função requisitarLogin sempre será chamada quando o botão btnLogin for clicado. Então, no próximo código, vamos começar a dar funcionalidade para a função requisitarLogin:

-- criar a função e definir os dois parâmetros do evento: 'button' - botão e state - estado do clique
function requisitarLogin(button,state)
	-- se o botão foi clicado com o botão esquerdo do mouse, e o estado do clique for 'up' (solto)
	if button == "left" and state == "up" then
		-- mudar o foco de entrada de volta para o jogo (permitindo ao jogador se movimentar e abrir o chat)
		guiSetInputEnabled(false)
		-- ocultar a janela e todos os componentes
		guiSetVisible(wdwLogin, false)
		-- desabilitar o cursor do mouse
		showCursor(false)
	end
end

Agora, quando o botão de login for clicado, a janela será ocultada, o cursor do mouse desabilitado e o foco de entrada será desativado. Na próxima etapa, vamos chamar o lado do servidor para permitir que o jogador seja gerado no jogo.

Chamando o servidor

Para chamar um evento do lado do servidor, usamos triggerServerEvent. Essa função lhe permite chamar um evento definido no lado do servidor por meio do cliente. O contrário pode ser feito usando a função triggerClientEvent. Agora vamos usar a função triggerServerEvent para chamar o evento que será feito no lado do servidor, esse evento irá controlar a função de 'spawn'.

No código a seguir, vamos complementar a função 'requisitarLogin'. Para o seu entendimento, observe os comentários pelo código.

function requisitarLogin(button,state)
	if button == "left" and state == "up" then
		-- obter o texto inserido no campo 'nomeDeUsuario'
		local nomeDeUsuario = guiGetText(editUsuario)
		-- obter o texto inserido no campo 'senha'
		local senha = guiGetText(editSenha)
		-- note que 'editUsuario' e 'editSenha' são variáveis definidas na criação do campo de edição
		
		-- se o nome de usuário e senha existem
		if nomeDeUsuario and senha then
			-- chamar o evento do servidor 'submeterLogin' e passar o nome de usuário e senha nos argumentos
			triggerServerEvent("submeterLogin", getRootElement(), nomeDeUsuario, senha)

			-- ocultar a janela, desabilitar o cursor e desativar foco de entrada
			guiSetInputEnabled(false)
			guiSetVisible(wdwLogin, false)
			showCursor(false)
		else
			-- se o nome de usuário ou senha não existir, sairá uma mensagem para o jogador,
			outputChatBox("Por favor, digite o nome de usuário e senha.", 230, 0, 0)
		end
	end
end

Criando o evento no servidor

Agora que finalizamos a parte do lado do cliente, abra seu arquivo do lado do servidor 'script.lua' (do Introdução a scripting) ou apenas crie um novo arquivo.

Lembre-se que o jogador só será gerado no jogo assim que ele logar. Então, em primeiro lugar, vamos criar o evento personalizado 'submeterLogin'. Para isso, você terá de usar as funções addEvent e addEventHandler.

-- criar função loginHandler, com os parâmetros: 'username' e 'senha' (enviado pelo lado do cliente)
function loginHandler(username,senha)

end

-- definir o evento personalizado e permitir que ele seja chamado a partir do cliente usando 'true'
addEvent("submeterLogin",true)
-- adicionar um manipulador de eventos para quando 'submeterLogin' for chamado,
-- chamar também a função 'loginHandler' que está ligada a ele
addEventHandler("submeterLogin",root,loginHandler)

Efetuando login

Agora, temos uma função que é chamada através do evento personalizado 'submeterLogin'. Para finalizar, iremos complementar a função 'loginHandler':

function loginHandler(username,senha)
	-- verificar se o nome de usuário e senha estão corretos
	if username == "user" and senha == "apple" then
		-- se o jogador foi logado com sucesso, então gerar ele no jogo
		if (client) then
			spawnPlayer(client, 1959.55, -1714.46, 10)
			fadeCamera(client, true)
			setCameraTarget(client, client)
			outputChatBox("Bem-vindo ao servidor.", client)
		end
	else
		-- se o nome de usuário ou senha não estão corretos, informar para o jogador
		outputChatBox("Nome de usuário e senha inválidos. Por favor, tente novamente.",client)
	end			
end

addEvent("submeterLogin",true)
addEventHandler("submeterLogin",root,loginHandler)

Agora você pode colocar em prática o que aprendeu neste tutorial e começar a trabalhar com login e spawn do jogador, usando a função 'loginHandler'. Note que um sistema de registro não está integrado ao tutorial. Para isso, você pode optar pelo uso do Sistema de conta nativo do MTA ou um banco de dados MySQL.

Observe também o uso da variável "client": é uma variável interna usada pelo MTA para identificar o jogador que fez o evento ser chamado.


Por fim, não se esqueça de incluir o arquivo gui.lua novo no meta.xml do recurso, e definir na tag 'type' como um script do lado do cliente:

<script src="client/gui.lua" type="client" />


Neste tutorial, criamos uma simples janela que verifica o nome de usuário e a senha quando o botão de login é pressionado. Se os dados estiverem corretos, o jogador entrará no jogo.

Para mais ajuda com GUI, consulte Tutoriais GUI (página em inglês).