Painel de administração

O hz_lib traz um painel de administração centralizado ao qual cada módulo HZ-Script se conecta. Em vez de cada script trazer o seu próprio comando e interface de configuração, tudo fica atrás de um único /hzpanel acessível aos admins. O painel constrói automaticamente um editor tipado para cada campo de configuração declarado no bridge_schema.lua de cada módulo.

Disponível desde o hz_lib v1.1.0. As versões anteriores só traziam o bridge de framework / inventário.

Abrir o painel

No jogo (chat, console F8 ou atalho de teclado):

/hzpanel

  • Só no console (F8 do servidor): /hzpanel no console do servidor não abre a NUI. Digite-o dentro do jogo.
  • Exige a permissão ACE configurada em HZBridge.Panel.AcePermission (padrão admin). Veja Dar acesso ao painel mais abaixo.
  • Pressione Escape ou o botão de fechar para sair. As sessões são protegidas por token e expiram após HZBridge.Panel.SessionTokenTtlMs sem atividade (5 min por padrão): abra o painel de novo para renovar.
Você também pode abrir diretamente a aba de um módulo a partir de outro script:

-- server export — opens the panel for `src` and preselects the named module
exports['hz_lib']:OpenPanel(src, 'hz_weather')


Dar acesso ao painel

O painel é protegido pelo nó ACE canônico admin do FXServer. São necessárias duas linhas no server.cfg:

add_principal identifier.license:YOUR_LICENSE group.admin
add_ace group.admin admin allow

Troque YOUR_LICENSE pela licença do jogador no seu servidor (você a vê digitando /hzpanel uma vez: a saída do console da falha mostra todos os seus identificadores e um bloco pronto para copiar com a sua licença já preenchida).

Você pode colar as duas linhas direto no console do servidor para resolver na hora, sem reiniciar. Se colocá-las no server.cfg, reinicie o FXServer (ou execute exec server.cfg de novo) para carregá-las.

Armadilha do server.cfg do qb-core: um qb-core recém-instalado traz add_ace group.admin command allow no server.cfg, mas não add_ace group.admin admin allow. O menu admin do qb-core usa a tabela de banco de dados qbcore_admins em vez do nó ACE canônico admin, por isso a linha falta. Quase todo ticket de permissão do hz_lib vem daqui: adicione a segunda linha e pronto.

Um jogador com o ACE command (pode executar qualquer comando) também pode abrir o painel. Na primeira inicialização, os grupos admin do framework (admin, god, superadmin, owner no ESX, QBCore, QBox ou Ox Core) são adicionados como cargos da staff com acesso total aos módulos, então os admins gerenciados pelo seu framework conseguem abrir o painel sem configurar o ACE. Mesmo assim, o ACE é o caminho recomendado, porque não depende do framework e pode ser auditado em um só lugar.

Se a verificação falhar, o console do servidor mostra:

  • O nó ACE exato verificado
  • Todos os seus identificadores de jogador
  • Uma matriz de teste ACE (quais nós estão liberados e quais não)
  • As duas linhas exatas add_principal + add_ace para copiar, com a sua licença já preenchida
Veja o erro em vermelho no seu console: a solução está ali. Disponível desde a v1.1.1.
command.hzpanel NÃO dá acesso ao painel. Um erro comum é tentar add_ace identifier.X command.hzpanel allow. O hz_lib não usa esse nó: a verificação é feita no AcePermission configurado (padrão admin), não no nome do comando.

Nó ACE personalizado

Se você não quiser usar o nó canônico admin (por exemplo, quer que só parte da staff abra o painel sem receber todos os outros comandos de admin), configure um nó próprio no config.lua:

HZBridge.Panel.AcePermission = 'hzbridge.panel.admin'

Depois, no server.cfg:

add_principal identifier.license:YOUR_LICENSE group.hzbridge.staff
add_ace group.hzbridge.staff hzbridge.panel.admin allow

O valor de reserva (quando AcePermission é nil ou '') é 'admin', alinhado com o padrão da configuração desde a v1.1.1. As versões anteriores usavam 'hz_lib.admin' como reserva, o que trancava do lado de fora os clientes que só tinham o ACE canônico admin. Atualize para a v1.1.1 ou superior se isso afetar você.

Cargos da staff

O acesso não é tudo ou nada: cada cargo da staff recebe, módulo por módulo, um ou mais destes três direitos.

DireitoPermite
viewLer as configurações do módulo
configAlterar as configurações salvas dele
manageUsar as ações ao vivo dele (por exemplo, mudar o clima agora)
  • Edite os cargos em /hzpanel > Access control. Só vê essa aba um cargo com permissão para editar os acessos, e só um grupo ACE pode receber essa permissão.
  • Na primeira inicialização, o grupo por trás de AcePermission (group.admin por padrão) recebe acesso total e o direito de editar os acessos, então instalar o hz_lib não tranca ninguém do lado de fora.
  • Um jogador cujos grupos não correspondem a nenhum cargo mantém o acesso total se tiver AcePermission ou command. Um jogador que corresponde a um cargo mantém os limites desse cargo.
  • Os direitos são verificados a cada ação: um admin rebaixado perde o acesso mesmo com o painel já aberto.
  • Ficou sem acesso? Execute hzaccess_recover <grupo> no console do servidor (por exemplo hzaccess_recover admin).
As configurações correspondentes (ativação, vários cargos, busca de grupos) estão em Controle de acesso.

O que você pode alterar

O painel detecta automaticamente cada recurso que traz um arquivo bridge_schema.lua na raiz. Com o hz_lib v1.2.0, estes recursos HZ trazem um schema e têm a sua própria aba:

MóduloO que você pode ajustar
hz_libTema global: destaque, superfícies, modo degradê, escala de cantos, fontes, posição do rastreador de objetivos
HZ-WeatherZonas (editor + mapa), previsão, hora, estações, eventos, configuração
HZ-TelevisionCanais, valores padrão, opções de desempenho
HZ-LoadingLoading Creator (editor ao vivo da tela de carregamento), telemetria
HZ-PauseMenuConfigurações gerais, identidade do servidor, integração com o HUD
HZ-TextUiTextUI Designer (aparência dos avisos)
HZ-BankingFunções, economia, identidade visual, acesso, contas compartilhadas, dinheiro e assaltos, custos e limites, poupança, empréstimos, faturas (1.0.1)
HZ-Fuel (1.0.1)Pagamento, preços do combustível, da recarga e do galão, consumo, pagamento e depósito do entregador
HZ-BetsOdds, limites de aposta, fontes de eventos
Scripts de terceiros podem adicionar a sua própria aba simplesmente trazendo um bridge_schema.lua: veja a seção sobre a DSL de schema mais abaixo.

Um valor salvo no painel tem prioridade sobre o arquivo de config do próprio script. Um ponto marca cada ajuste alterado no painel, e o botão de redefinir dele apaga o valor do painel: o ajuste volta a seguir o arquivo de config do script (hz_lib 1.2.1 ou mais recente). Até o hz_lib 1.2.0, o botão de redefinir salvava no lugar o padrão do próprio painel.


A DSL de schema

O bridge_schema.lua de cada módulo é uma pequena DSL em Lua que declara a configuração exibida pelo painel. A DSL roda em um ambiente isolado (sem _G, sem io direto, com subconjuntos restritos de string / table / math), então um schema com erros ou malicioso não consegue quebrar o servidor.

Exemplo mínimo

-- resources/your-script/bridge_schema.lua
module('your-script', {
    schemaVersion = 1,
    label = { en = 'Your Script', fr = 'Ton script' },
}, function()
    section('general', {
        label = { en = 'General', fr = 'Général' },
    }, function()
        field('Enabled', 'boolean', {
            default = true,
            label = { en = 'Enabled', fr = 'Activé' },
            description = {
                en = 'Master on/off switch for the script.',
                fr = 'Interrupteur global du script.',
            },
        })

        field('PlayerLimit', 'number', {
            default = 32, min = 1, max = 256, step = 1,
            label = { en = 'Max concurrent players', fr = 'Joueurs simultanés max' },
        })
    end)
end)

É só isso: abra o /hzpanel, a aba "Your Script" aparece com dois campos tipados, e as alterações são gravadas no disco e enviadas a cada cliente inscrito.

Tipos de campo

TipoAparece comoObservações
booleanInterruptor
numberCampo numérico com min / max / stepVira controle deslizante quando step ≤ 1 e o intervalo é limitado
stringCampo de texto, pattern + maxLength opcionais
enumLista suspensa (uma escolha)Opções via choices = { 'a', 'b', 'c' }
enum-multiSeleção múltipla limitada (chips)Novo na v1.1.0, salvo como list<string>
colorSeletor de cor hexValidado como #RRGGBB
keybindCaptura de atalho (tecla + modificadores)
list<string>Campo de tags (adicionar/remover livremente)
list<object>Editor de tabela em linha com colunas itemSchema
vehicle-listGrade de seleção de veículosPreenchida automaticamente a partir de GetAllVehicleModels()
weapon-listGrade de seleção de armasCatálogo fixo embutido no painel
actionBotão que dispara um evento de servidorPara ações do tipo "Aplicar preset" / "Reset"
enum-actionLista suspensa de ações
viewComponente React personalizado em largura totalEmbutido no painel do hz_lib, veja Visualizações personalizadas abaixo

Seções, grupos, abas

  • section(id, { label, tab, dependsOn }, body): agrupamento visual dentro da aba de um módulo. tab é o id da subaba (declarada via module(name, { tabs = { ... } })). dependsOn = { field = 'X', equals = true } recolhe a seção quando a condição é falsa.
  • group(id, { label }, body): grupo recolhível dentro de uma seção.
  • field(id, type, opts): um campo. opts aceita default, description, requiresRestart, serverOnly, deprecated, hidden, dependsOn, além dos extras de cada tipo. serverOnly = true mantém o valor no servidor (nunca enviado aos jogadores): use para segredos como URLs de webhook.
  • invariant(sectionId, fn): validação entre campos. Roda a cada tentativa de salvar. Retorna nil (ok) ou um texto (mensagem de erro).
  • migrations({ [N] = function(values) ... end }): aumente schemaVersion e inclua uma migração para reescrever os valores salvos antigos.

Visualizações personalizadas

Alguns scripts HZ precisam de mais do que um formulário: um editor de mapa, um gráfico de previsão, um editor de tela de carregamento. Eles declaram um campo view, com uma lista events dos eventos de servidor que a visualização pode disparar. O componente React em si fica embutido no painel do hz_lib, cujo código-fonte não é entregue: um schema de terceiros usa os tipos de campo acima.

O HZ-Weather traz seis visualizações: Map, ZoneEditor, Events, Forecast, SeasonsPanel, TimePanel.


Cascata de tema (Appearance)

A aba Appearance do hz_lib centraliza os valores visuais compartilhados por todas as NUIs HZ. Uma única alteração recolore HZ-Weather, HZ-AudioMixer e HZ-Television ao vivo, sem reiniciar. Novos scripts que se conectam herdam a cascata automaticamente, desde que a NUI deles leia as variáveis CSS canônicas --hz-*.

O que você controla

EixoChavesEfeito
Destaqueaccent / accentHi / goldCor de assinatura, a variante ao passar o mouse e a cor dos valores (dinheiro, XP). Padrão: ciano #00B4FF / #0095D9 / âmbar #FFB830.
Superfíciessurface / subpanel / tintPainel externo / subpainel interno / tom ao passar o mouse. Só RGB: cada consumidor decide a opacidade.
Modo degradêgradientMode = 'gradient' \| 'solid'solid (padrão) transforma cada degradê de destaque em cor chapada, com um visual mais sóbrio.
CantosradiusNone / Xs / Sm / Md / Lg / XlEscala de cantos em seis níveis. Padrão 0/4/8/12/16/20.
FontesfontDisplay / fontBody / fontNumberFontes do Google para títulos e rótulos, texto e números. Padrão Barlow Condensed / Barlow / Barlow Condensed.
Sete presets embutidos ajustam tudo isso com um clique: Cyan (o padrão), Vice, Ember, Toxic, Amethyst, Crimson e Mono. Cada valor continua editável depois. Você também pode salvar os seus próprios presets: eles ficam no seu próprio cliente de jogo, sem ser compartilhados com os outros admins.

Posição do rastreador de objetivos

A mesma aba posiciona o rastreador de objetivos exibido pelos trabalhos e missões HZ (veja Rastreador de objetivos):

AjusteValoresEfeito
Screen sideleft (padrão), rightLado da tela onde as etapas aparecem
Height (% from the top)0 a 90 (padrão 26)Aumente se a lista cobrir outro elemento do HUD

Como os módulos usam o tema

O conteúdo completo é enviado sempre que o admin salva:

-- server (any resource)
AddEventHandler('HZ-Bridge:theme:updated', function(theme)
    -- theme: { preset, accent, accentHi, gold, surface, subpanel, tint,
    --         gradientMode, radiusNone, radiusXs, radiusSm, ..., radiusXl,
    --         fontDisplay, fontBody, fontNumber,
    --         fonts = { display, body, number, href } }
end)

-- client
RegisterNetEvent('HZ-Bridge:theme:updated', function(theme)
    SendNUIMessage({ action = 'theme', data = theme })
end)

fonts traz pilhas de fontes CSS prontas para uso e a URL de uma folha do Google Fonts (href). Na sua NUI, escreva cada chave como variável CSS em :root (por exemplo --hz-accent-rgb, --hz-surface-rgb, --hz-radius-md). Os componentes usam as variáveis via rgb(var(--hz-accent-rgb) / 0.45) / var(--hz-radius-md), então a cascata é automática.

Obtenha o tema atual de forma síncrona ao iniciar (servidor):

local theme = exports['hz_lib']:GetTheme()

Ou peça com TriggerServerEvent('HZ-Bridge:theme:request'): o servidor responde com TriggerClientEvent('HZ-Bridge:theme:updated', src, theme).

Atalho: adicione '@hz_lib/ui/relay.lua' aos seus client_scripts e carregue https://cfx-nui-hz_lib/ui/hz-ui.css e https://cfx-nui-hz_lib/ui/hz-ui.js na sua página. O relé envia o tema para a sua NUI e o kit o aplica, ao carregar e a cada alteração.

Segurança + auditoria

  • Schemas isolados: a DSL roda sem io, os ou debug diretos, com uma biblioteca padrão restrita. Um bridge_schema.lua com erros pode falhar ao carregar (fica no log), mas não derruba o servidor.
  • Gravações limitadas: por padrão 10 gravações a cada 5 s por origem. Configurável via HZBridge.Panel.RateLimitWrites / RateLimitWindowMs.
  • Tokens de sessão: cada abertura do painel gera um token que expira após 5 minutos sem atividade; tokens expirados recebem uma nova inicialização na próxima requisição.
  • Validação: cada salvamento passa pela validação do tipo de campo, pelas verificações opcionais pattern / min / max e depois pelas funções invariant da seção antes de ir para o disco.
  • Log de auditoria: cada salvamento aceito grava uma linha em data/_audit.log. Acima de 10 MB, o arquivo é renomeado para data/_audit.<data>.<hora>.log e um novo começa. O hz_lib nunca apaga esses arquivos (HZBridge.Panel.AuditRetentionDays não é aplicado na v1.2.0): apague você mesmo os antigos se precisar de um limite de retenção.
  • Gravações atômicas: a configuração salva de cada módulo é gravada em data/<module>.json passando antes por um arquivo temporário. Campos marcados com requiresRestart também ficam pendentes em data/<module>.pending.json e são aplicados quando o recurso reinicia.
  • Direitos verificados a cada ação, não só ao abrir o painel. Um admin que perde os direitos não consegue continuar editando com o painel já aberto.

Referência

  • Código da DSL de schema: modules/panel/schema_dsl.lua na sua pasta do hz_lib (aberto, não criptografado)
  • Configuração salva por módulo: data/<module>.json, mais data/<module>.pending.json para as alterações que esperam um reinício
  • Cargos da staff: data/_access.json
  • Auditoria: data/_audit.log