Pular para o conteúdo

Eventos do servidor

Servidor

Eventos são a forma de reagir ao que acontece no servidor: um jogador entra, um veículo explode, alguém pega um pickup. Você registra uma função e o servidor a chama quando aquilo acontece.

addEventHandler("onPlayerJoin", root, function()
outputDebugString(getPlayerName(source) .. " entrou no servidor")
end)

Todos os manipuladores registrados por um resource são removidos quando ele para.

Registra uma função para ser chamada quando o evento disparar.

bool addEventHandler ( string nomeDoEvento, element elemento, function manipulador [, bool propagar = true, string prioridade = "normal" ] )

Parâmetros

NomeTipoDescrição
nomeDoEventostringNome do evento.
elementoelementElemento ao qual o manipulador fica preso. Veja Propagação.
manipuladorfunctionFunção a chamar. Recebe os parâmetros do evento como argumentos.
propagarboolfalse faz o manipulador rodar só quando elemento é o próprio source. O padrão é true.
prioridadestring"low", "normal" (o padrão) ou "high", opcionalmente com um modificador como "high+5". Decide a ordem entre manipuladores no mesmo ponto da árvore.

Retorno — true se o manipulador foi registrado, false caso contrário.

Um erro dentro do manipulador não derruba o servidor nem impede os outros manipuladores de rodar: ele é registrado no console com o nome do resource e do evento.

Desfaz um addEventHandler.

bool removeEventHandler ( string nomeDoEvento, element elemento, function manipulador )

O nome, o elemento e a função precisam ser exatamente os mesmos usados no registro — por isso guarde a função em uma variável se pretende removê-la depois.

local function aoEntrar()
outputDebugString(getPlayerName(source) .. " entrou")
end
addEventHandler("onPlayerJoin", root, aoEntrar)
removeEventHandler("onPlayerJoin", root, aoEntrar)

Retorno — true se o manipulador existia e foi removido, false caso contrário.

Lista os manipuladores presos diretamente a um elemento.

table getEventHandlers ( string nomeDoEvento, element elemento )

Só aparecem os manipuladores registrados pelo seu próprio resource — os de outros resources ficam invisíveis. Um elemento sem manipuladores devolve uma tabela vazia; um argumento inválido devolve false.

for _, fn in ipairs(getEventHandlers("onPlayerJoin", root)) do
removeEventHandler("onPlayerJoin", root, fn)
end

Enquanto um manipulador está executando, cinco globais ficam disponíveis:

GlobalConteúdo
sourceO elemento que originou o evento — o mesmo descrito na linha Source de cada evento abaixo.
clientO jogador que enviou o evento, quando ele veio do cliente. É nil em eventos disparados pelo próprio servidor.
eventNameO nome do evento em execução, como texto.
sourceResourceO resource cujo script chamou triggerEvent. É nil quando quem disparou foi a engine ou a rede.
sourceResourceRootO elemento raiz desse resource, nil nos mesmos casos.

Cada manipulador recebe o próprio conjunto de valores e tem eles restaurados ao retornar, então um manipulador que dispara um evento aninhado continua vendo o seu próprio source na linha seguinte à chamada aninhada.

addEventHandler("onVehicleExplode", root, function(comExplosao)
local veiculo = source -- cópia local: sobrevive ao timer
outputDebugString(eventName .. " em " .. getVehicleName(veiculo))
setTimer(function()
if isElement(veiculo) then respawnVehicle(veiculo) end
end, 5000, 1)
end)

Os parâmetros do evento não são globais: eles chegam como argumentos normais da função, na ordem descrita na referência abaixo.

O elemento passado ao addEventHandler não precisa ser exatamente o source do evento. O manipulador roda quando qualquer uma destas condições é verdadeira:

  • o elemento é o próprio source;
  • o source é descendente do elemento, em qualquer profundidade;
  • o elemento é a raiz (root);
  • o elemento é descendente do source — os eventos descem pela árvore, além de subir.

Ou seja: prender à raiz pega tudo, prender à raiz do seu resource pega tudo o que o seu resource criou, e prender a um elemento específico pega ele e os filhos dele — além de qualquer evento disparado num ancestral dele, como um triggerEvent no root.

Os manipuladores rodam nessa ordem: os do source, depois os dos ancestrais, do mais próximo para cima, depois os dos descendentes. No mesmo ponto da árvore, quem decide é a prioridade. Um manipulador registrado com propagar igual a false só roda quando está preso ao próprio source.

local garagem = createElement("garagem")
local carro = createVehicle(411, 0, 0, 5)
setElementParent(carro, garagem)
-- roda para qualquer veículo do servidor
addEventHandler("onVehicleExplode", root, function() end)
-- roda só para os veículos dentro da "garagem"
addEventHandler("onVehicleExplode", garagem, function() end)
-- roda só para este carro
addEventHandler("onVehicleExplode", carro, function() end)

Quando um evento é disparado sem elemento de origem, apenas os manipuladores presos à raiz são executados.

Além dos eventos do servidor, você pode criar os seus.

Registra um nome de evento.

bool addEvent ( string nomeDoEvento [, bool permitirRemoto = false ] )
NomeTipoPadrãoDescrição
nomeDoEventostring—Nome do evento.
permitirRemotoboolfalseSe true, scripts do cliente podem disparar este evento no servidor.

Dispara um evento no servidor, agora, no mesmo tick.

bool triggerEvent ( string nomeDoEvento, element origem [, ... ] )

Os valores extras viram os argumentos do manipulador.

Retorno — false se algum manipulador cancelou o evento, true caso contrário (inclusive quando ninguém está escutando).

addEvent("onCompraDeArma")
addEventHandler("onCompraDeArma", root, function(arma, preco)
if getElementData(source, "dinheiro") < preco then
cancelEvent(true, "saldo insuficiente")
end
end)
addEventHandler("onCompraDeArma", root, function()
if wasEventCancelled() then
outputDebugString("compra recusada: " .. getCancelReason())
end
end, true, "low") -- roda depois do manipulador acima
if triggerEvent("onCompraDeArma", jogador, 31, 5000) then
giveWeapon(jogador, 31, 200)
end

Dispara um evento nos clientes.

bool triggerClientEvent ( element/table destinos, string nomeDoEvento, element origem [, ... ] )
NomeTipoDescrição
destinoselement ou tablePara quem enviar. Um jogador atinge só ele; qualquer outro elemento atinge todos os jogadores abaixo dele na árvore — passar root atinge o servidor inteiro. Uma tabela de elementos também é aceita.
nomeDoEventostringNome do evento no cliente.
origemelementElemento que vira o source do lado do cliente.
...anyArgumentos repassados ao manipulador do cliente.

Do lado do cliente, o evento só é entregue se tiver sido registrado com addEvent(nome, true). Sem isso, a mensagem é descartada silenciosamente.

triggerClientEvent(root, "onPlacarAtualizado", root, "Gabriel", 12)

Para uma carga grande, triggerLatentClientEvent manda o mesmo evento por uma fila com banda limitada, em vez de tudo de uma vez.

Marca o evento em execução como cancelado.

bool cancelEvent ( [ bool cancelar = true, string motivo = "" ] )

Sempre devolve true. Chamar cancelEvent(false) não faz nada — em particular, não desfaz um cancelamento feito por outro manipulador.

bool wasEventCancelled ( )

Devolve true se o evento em execução já foi cancelado por algum manipulador.

string getCancelReason ( )

Devolve o motivo passado ao cancelEvent para o evento em execução, ou uma string vazia se não houve motivo. Depois que triggerEvent retorna, o motivo some — leia-o num manipulador posterior, como no exemplo acima.

O servidor dispara 86 eventos, agrupados por área:

Os eventos de combate nascem do relato do cliente. O servidor valida cada número antes de disparar o evento — dano fora da faixa de 0 a 200, atacante em outra dimensão ou interior, morte relatada duas vezes e faca a mais de 5 unidades de distância são descartados sem disparar nada.

Cada entrada e cada saída disparam um par de eventos: um com a forma como source e outro com o elemento como source. A verificação roda para jogadores, peds, veículos e objetos.

Marcadores funcionam como as formas de colisão, com duas diferenças: o interior precisa bater (um elemento em outro interior conta como fora do marcador) e existe um par extra de eventos só para jogadores.

O formato depende do tipo do marcador: checkpoint e cylinder ignoram a altura, e todos os demais são esferas. O raio é o tamanho do marcador.

Cada coleta dispara um par de eventos: um com o pickup como source e outro com o jogador como source. Os dois sempre disparam; cancelar qualquer um dos dois já é suficiente para bloquear o efeito.

Um pickup só é testado contra jogadores vivos, no mesmo interior e na mesma dimensão, dentro de um raio de 1 unidade.

Estes eventos só existem quando o chat de voz está ligado na configuração do servidor.