Denver Studio - Docs

Hooks no vRP

Pontos de integração obrigatórios e opcionais no vRP base e em recursos auxiliares

Hooks no vRP

Alguns dados (novo jogador, banimento, ticket atendido) não vêm de eventos automáticos do vRP — eles acontecem dentro de funções específicas. Para o FiveTrack capturar, é preciso adicionar pequenas chamadas nos pontos certos.

Todos os hooks são envoltos em pcall + GetResourceState('fivetrack') == 'started'. Se o FiveTrack estiver parado/removido, o vRP continua funcionando normalmente.


1. Novo jogador

Onde: vrp/modules/core.lua — logo após o INSERT na tabela accounts/NewAccount.

local Account = vRP.Account(License)
if not Account then
    vRP.Query("accounts/NewAccount",{ License = License, Token = vRP.GenerateToken() })
    Account = vRP.Account(License)
    if GetResourceState('fivetrack') == 'started' then
        pcall(function() exports.fivetrack:registerNewPlayer() end)
    end
end

Alimenta: contador newPlayers do push_metrics → gráfico de aquisição de jogadores no painel.


2. Banimento

Onde: vrp/modules/core.lua — após cada vRP.Query("accounts/InsertBanned", ...).

Geralmente há 2 ocorrências (uma para ban via comando admin, outra para ban automático/anticheat).

SendToDiscord(Passport, Mode, Amount, Reason, Account.discord, Staff)
vRP.Query("hwid/All", { Account = Account.id, Banned = 1 })
vRP.Query("accounts/InsertBanned", { License = Account.License, Timer = Timer, Reason = Reason })
if GetResourceState('fivetrack') == 'started' then
    pcall(function() exports.fivetrack:registerBan() end)
end
SendToDiscord(Source, Mode, Amount, Reason, Account[1].discord, Staff)
vRP.Query("hwid/All", { Account = Account[1].id, Banned = 1 })
vRP.Query("accounts/InsertBanned", { License = License, Timer = Timer, Reason = Reason })
if GetResourceState('fivetrack') == 'started' then
    pcall(function() exports.fivetrack:registerBan() end)
end

Alimenta: contador bans do push_metrics → página Banimentos do painel (histórico diário).


3. Ticket atendido pelo Staff

Onde: no recurso alerts/ (ou equivalente que processa chamados de jogadores) — quando um staff com permissão Admin aceita um chamado.

AddEventHandler("alerts:tryAcceptRequest", function(id)
    -- ... lógica existente que valida e aceita o ticket ...

    exports["discord"]:Embed("chamados", "...")

    if GetResourceState('fivetrack') == 'started' and temp_permission == 'Admin' then
        pcall(function()
            exports.fivetrack:registerTicket({
                staffId       = tostring(user_id),
                staffName     = user_identity.Name or 'Staff',
                staffLastName = user_identity.Lastname,
                staffRole     = temp_permission,
            })
        end)
    end
end)

Alimenta: página Staff do painel — ranking de atendentes, SLA, detector de burnout.

Filtramos por temp_permission == 'Admin' porque um chamado pode ser atendido por Polícia/Médico (in-game) ou por Admin (suporte). Apenas o atendimento de Admin conta como ticket de staff.


4. Mudança de job

Onde: vrp/modules/core.lua — dentro de vRP.SetPermission, logo após vRP.SetSrvData("Permissions:"..Permission,Consult,true).

Algumas variantes do vRP (notadamente creative-enchanted) não emitem vRP:playerJoinGroup automaticamente — elas só chamam funções (vRP.SetPermission / vRP.RemovePermission). Sem esse evento, a página Retenção fica zerada (todos os jogadores aparecem como "Ainda sem cargo").

Adicione esta chamada para que o FiveTrack receba a mudança:

vRP.ServiceEnter(source,Passport,Permission,true)
vRP.SetSrvData("Permissions:"..Permission,Consult,true)

if GetResourceState('fivetrack') == 'started' then
    pcall(function() TriggerEvent('vRP:playerJoinGroup', Passport, Permission, Consult[Passport], Mode) end)
end

O players.lua do FiveTrack escuta vRP:playerJoinGroup e classifica o cargo via Config.LegalOrganizations / Config.IllegalOrganizations antes de enviar para o backend.

Em vRP-EX, nexus-base e vRP "padrão", o evento vRP:playerJoinGroup já é emitido nativamente — este hook só é necessário em bases creative-enchanted.

Alimenta: página Retenção — primeiro cargo, tempo até o primeiro job legal/ilegal, cohorts por cargo.

Se sua base usa um evento totalmente custom, você pode disparar manualmente sem passar pelo vRP:playerJoinGroup:

exports.fivetrack:registerJobChange(source, fromJob, toJob, jobType)
-- jobType: 'legal' | 'ilegal' | 'neutro'

5. Hooks que NÃO precisam ser adicionados

Estes eventos são padrão do FiveM ou do vRP e o FiveTrack escuta sozinho:

EventoO que dispara
playerConnecting(não usado diretamente)
playerDropped(reason)Heatmap: classifica reason → crash/drop_s2c/drop_c2s/quit
Connect(passport, source, isFirstSpawn)creative-enchanted: registra entry de sessão
Disconnect(passport, source, license)creative-enchanted: registra exit de sessão
vRP:playerSpawn(user_id, source, first_spawn)vrpex/nexus: registra entry
vRP:playerLeave(user_id, source)vrpex/nexus: registra exit
vRP:playerJoinGroup(passport, permission, level, mode)players.lua: classifica + envia job change

Checklist de hooks aplicados

Antes de subir o servidor, confira no vrp/modules/core.lua:

  • 1 chamada exports.fivetrack:registerNewPlayer() após accounts/NewAccount
  • 2 chamadas exports.fivetrack:registerBan() após accounts/InsertBanned
  • creative-enchanted apenas: 1 TriggerEvent('vRP:playerJoinGroup', ...) dentro de vRP.SetPermission
  • (opcional) 1 chamada exports.fivetrack:registerTicket(...) em alerts/server.lua

Sem o hook de novo jogador, o contador newPlayers fica em 0 — mas sessões continuam sendo registradas via Connect/Disconnect, então a métrica de retenção ainda funciona (apenas o gráfico de "novos jogadores por dia" fica vazio).

Sem o hook de ban, o gráfico da página Banimentos fica vazio.