Panel de administración

hz_lib incluye un panel de administración centralizado en el que se conecta cada módulo HZ-Script. En lugar de que cada script traiga su propio comando e interfaz de configuración, todo está detrás de un único /hzpanel accesible para los admins. El panel construye automáticamente un editor tipado para cada campo de configuración declarado en el bridge_schema.lua de cada módulo.

Disponible desde hz_lib v1.1.0. Las versiones anteriores solo incluían el bridge de framework / inventario.

Abrir el panel

En el juego (chat, consola F8 o atajo de teclado):

/hzpanel

  • Solo consola (F8 del servidor): /hzpanel desde la consola del servidor no abre la NUI. Escríbelo desde el juego.
  • Requiere el permiso ACE configurado en HZBridge.Panel.AcePermission (por defecto admin). Consulta Configurar los permisos más abajo.
  • Pulsa Escape o el botón de cerrar para salir. Las sesiones están protegidas por token y caducan tras HZBridge.Panel.SessionTokenTtlMs sin actividad (5 min por defecto): vuelve a abrir el panel para renovarla.
También puedes abrir directamente la pestaña de un módulo desde otro script:

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


Configurar los permisos

El panel está protegido por el nodo ACE canónico admin de FXServer. Hacen falta dos líneas en server.cfg:

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

Sustituye YOUR_LICENSE por la licencia del jugador en tu servidor (la ves al escribir /hzpanel una vez: la salida de consola del fallo muestra todos tus identificadores y un bloque listo para copiar con tu licencia ya incluida).

Puedes pegar las dos líneas directamente en la consola del servidor para arreglarlo al instante, sin reiniciar. Si las pones en server.cfg, reinicia FXServer (o vuelve a ejecutar exec server.cfg) para cargarlas.

Trampa del server.cfg de qb-core: un qb-core recién instalado trae add_ace group.admin command allow en server.cfg pero no add_ace group.admin admin allow. El menú admin de qb-core usa su tabla de base de datos qbcore_admins en lugar del nodo ACE canónico admin, por eso falta la línea. Casi todos los tickets de permisos de hz_lib vienen de aquí: añade la segunda línea y listo.

Un jugador que tiene el ACE command (puede ejecutar cualquier comando) también puede abrir el panel. En el primer arranque, los grupos admin del framework (admin, god, superadmin, owner en ESX, QBCore, QBox u Ox Core) se añaden como roles de staff con acceso completo a los módulos, así que los admins gestionados por tu framework pueden abrir el panel sin configurar ACE. Aun así, ACE es el método recomendado porque no depende del framework y se audita en un solo sitio.

Si la comprobación falla, la consola del servidor muestra:

  • El nodo ACE exacto comprobado
  • Todos tus identificadores de jugador
  • Una matriz de prueba ACE (qué nodos están concedidos y cuáles no)
  • Las dos líneas exactas add_principal + add_ace para copiar, con tu licencia ya incluida
Mira el error en rojo en tu consola: la solución está ahí. Disponible desde v1.1.1.
command.hzpanel NO da acceso al panel. Un error habitual es probar add_ace identifier.X command.hzpanel allow. hz_lib no usa ese nodo: la comprobación se hace sobre el AcePermission configurado (por defecto admin), no sobre el nombre del comando.

Nodo ACE personalizado

Si no quieres usar el nodo canónico admin (por ejemplo, quieres que solo una parte del staff abra el panel sin darle todos los demás comandos de admin), configura un nodo propio en config.lua:

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

Y después en server.cfg:

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

El valor de respaldo (cuando AcePermission es nil o '') es 'admin', alineado con el valor por defecto de la configuración desde v1.1.1. Las versiones anteriores usaban 'hz_lib.admin' como respaldo, lo que bloqueaba a los clientes que solo tenían concedido el ACE canónico admin. Actualiza a v1.1.1 o superior si te afecta.

Roles del staff

El acceso no es todo o nada: cada rol de staff recibe, módulo por módulo, uno o varios de estos tres derechos.

DerechoPermite
viewLeer los ajustes del módulo
configCambiar sus ajustes guardados
manageUsar sus acciones en directo (por ejemplo, cambiar el clima ahora)
  • Edita los roles en /hzpanel > Access control. Solo ve esta pestaña un rol con permiso para editar los accesos, y solo un grupo ACE puede tener ese permiso.
  • En el primer arranque, el grupo detrás de AcePermission (group.admin por defecto) recibe acceso completo y el derecho de editar los accesos, así que instalar hz_lib no deja a nadie fuera.
  • Un jugador cuyos grupos no coinciden con ningún rol conserva el acceso completo si tiene AcePermission o command. Un jugador que coincide con un rol conserva los límites de ese rol.
  • Los derechos se comprueban en cada acción: un admin degradado pierde el acceso incluso con el panel ya abierto.
  • ¿Te has quedado fuera? Ejecuta hzaccess_recover <grupo> en la consola del servidor (por ejemplo hzaccess_recover admin).
Los ajustes correspondientes (activación, varios roles, búsqueda de grupos) están en Control de acceso.

Qué puedes modificar

El panel detecta automáticamente cada recurso que incluye un archivo bridge_schema.lua en su raíz. Con hz_lib v1.2.0, estos recursos HZ incluyen un esquema y tienen su propia pestaña:

MóduloQué puedes ajustar
hz_libTema global: acento, superficies, modo degradado, escala de esquinas, fuentes, posición del seguimiento de objetivos
HZ-WeatherZonas (editor + mapa), pronóstico, hora, estaciones, eventos, configuración
HZ-TelevisionCanales, valores por defecto, opciones de rendimiento
HZ-LoadingLoading Creator (editor en directo de la pantalla de carga), telemetría
HZ-PauseMenuAjustes generales, imagen del servidor, integración con el HUD
HZ-TextUiTextUI Designer (aspecto de los avisos)
HZ-BankingFunciones, economía, imagen de marca, acceso, cuentas compartidas, efectivo y atracos, costes y límites, ahorros, préstamos, facturas (1.0.1)
HZ-Fuel (1.0.1)Pago, precios del combustible, de la carga y del bidón, consumo, paga y fianza del repartidor
HZ-BetsCuotas, límites de apuesta, fuentes de eventos
Los scripts de terceros pueden añadir su propia pestaña simplemente incluyendo un bridge_schema.lua: consulta la sección del DSL de esquema más abajo.

Un valor guardado en el panel manda sobre el archivo de config del propio script. Un punto marca cada ajuste cambiado en el panel, y su botón de restablecer borra el valor del panel: el ajuste vuelve a seguir el archivo de config del script (hz_lib 1.2.1 o posterior). Hasta hz_lib 1.2.0, el botón de restablecer guardaba en su lugar el valor por defecto del propio panel.


El DSL de esquema

El bridge_schema.lua de cada módulo es un pequeño DSL en Lua que declara la configuración que muestra el panel. El DSL se ejecuta en un entorno aislado (sin _G, sin io directo, con subconjuntos limitados de string / table / math), así que un esquema con errores o malicioso no puede romper el servidor.

Ejemplo 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)

Eso es todo: abre /hzpanel, aparece la pestaña "Your Script" con dos campos tipados, y los cambios se escriben en disco y se envían a cada cliente suscrito.

Tipos de campo

TipoSe muestra comoNotas
booleanInterruptor
numberCampo numérico con min / max / stepVariante deslizador cuando step ≤ 1 y el rango está acotado
stringCampo de texto, pattern + maxLength opcionales
enumLista desplegable (una opción)Opciones con choices = { 'a', 'b', 'c' }
enum-multiSelección múltiple limitada (chips)Nuevo en v1.1.0, se guarda como list<string>
colorSelector de color hexValidado como #RRGGBB
keybindCaptura de atajo (tecla + modificadores)
list<string>Campo de etiquetas (añadir/quitar libre)
list<object>Editor de tabla en línea con columnas itemSchema
vehicle-listCuadrícula de selección de vehículosSe rellena automáticamente desde GetAllVehicleModels()
weapon-listCuadrícula de selección de armasCatálogo fijo integrado en el panel
actionBotón que lanza un evento de servidorPara acciones tipo "Aplicar preset" / "Reset"
enum-actionLista desplegable de acciones
viewComponente React personalizado a todo el anchoIntegrado en el panel de hz_lib, consulta Vistas personalizadas más abajo

Secciones, grupos, pestañas

  • section(id, { label, tab, dependsOn }, body): agrupación visual dentro de la pestaña de un módulo. tab es el id de la subpestaña (declarada con module(name, { tabs = { ... } })). dependsOn = { field = 'X', equals = true } pliega la sección cuando la condición es falsa.
  • group(id, { label }, body): grupo plegable dentro de una sección.
  • field(id, type, opts): un campo. opts admite default, description, requiresRestart, serverOnly, deprecated, hidden, dependsOn, además de los extras propios de cada tipo. serverOnly = true deja el valor en el servidor (nunca se envía a los jugadores): úsalo para secretos como las URL de webhook.
  • invariant(sectionId, fn): validación entre campos. Se ejecuta en cada intento de guardado. Devuelve nil (ok) o un texto (mensaje de error).
  • migrations({ [N] = function(values) ... end }): sube schemaVersion e incluye una migración para reescribir los valores guardados antiguos.

Vistas personalizadas

Algunos scripts HZ necesitan algo más que un formulario: un editor de mapa, un gráfico de pronóstico, un editor de pantalla de carga. Declaran un campo view, con una lista events de los eventos de servidor que la vista puede lanzar. El componente React en sí está integrado en el panel de hz_lib, cuyo código fuente no se entrega: un esquema de terceros usa los tipos de campo de arriba.

HZ-Weather incluye seis vistas: Map, ZoneEditor, Events, Forecast, SeasonsPanel, TimePanel.


Cascada de tema (Appearance)

La pestaña Appearance de hz_lib centraliza los valores visuales que comparten todas las NUI HZ. Un solo cambio vuelve a colorear HZ-Weather, HZ-AudioMixer y HZ-Television en directo, sin reiniciar. Los nuevos scripts que se conectan heredan la cascada automáticamente siempre que su NUI lea las variables CSS canónicas --hz-*.

Ejes que controlas

EjeClavesEfecto
Acentoaccent / accentHi / goldColor de firma, su variante al pasar el ratón y el color de los valores (dinero, XP). Por defecto: cian #00B4FF / #0095D9 / ámbar #FFB830.
Superficiessurface / subpanel / tintPanel exterior / subpanel interior / tono al pasar el ratón. Solo RGB: cada consumidor decide la opacidad.
Modo degradadogradientMode = 'gradient' \| 'solid'solid (por defecto) convierte cada degradado de acento en un color plano, con un aspecto más sobrio.
EsquinasradiusNone / Xs / Sm / Md / Lg / XlEscala de esquinas de seis niveles. Por defecto 0/4/8/12/16/20.
FuentesfontDisplay / fontBody / fontNumberFuentes de Google para títulos y etiquetas, texto y cifras. Por defecto Barlow Condensed / Barlow / Barlow Condensed.
Siete presets integrados ajustan todo esto con un clic: Cyan (el predeterminado), Vice, Ember, Toxic, Amethyst, Crimson y Mono. Cada valor sigue siendo editable después. También puedes guardar tus propios presets: se guardan en tu propio cliente de juego, no se comparten con los demás admins.

Posición del seguimiento de objetivos

La misma pestaña coloca el seguimiento de objetivos que muestran los trabajos y misiones HZ (consulta Seguimiento de objetivos):

AjusteValoresEfecto
Screen sideleft (por defecto), rightLado de la pantalla donde se listan los pasos
Height (% from the top)0 a 90 (por defecto 26)Súbelo si la lista tapa otro elemento del HUD

Cómo lo usan los módulos

El contenido completo se envía cada vez que el admin guarda:

-- 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 contiene pilas de fuentes CSS listas para usar y la URL de una hoja de Google Fonts (href). En tu NUI, escribe cada clave como variable CSS en :root (por ejemplo --hz-accent-rgb, --hz-surface-rgb, --hz-radius-md). Los componentes usan las variables con rgb(var(--hz-accent-rgb) / 0.45) / var(--hz-radius-md), así que la cascada es automática.

Obtén el tema actual de forma síncrona al arrancar (servidor):

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

O pídelo con TriggerServerEvent('HZ-Bridge:theme:request'): el servidor responde con TriggerClientEvent('HZ-Bridge:theme:updated', src, theme).

Atajo: añade '@hz_lib/ui/relay.lua' a tus client_scripts y carga https://cfx-nui-hz_lib/ui/hz-ui.css y https://cfx-nui-hz_lib/ui/hz-ui.js en tu página. El relé envía el tema a tu NUI y el kit lo aplica, al cargar y en cada cambio.

Seguridad + auditoría

  • Esquemas aislados: el DSL se ejecuta sin io, os ni debug directos, y con una biblioteca estándar limitada. Un bridge_schema.lua con errores puede fallar al cargar (queda en el log), pero no puede tumbar el servidor.
  • Escrituras limitadas: por defecto 10 escrituras cada 5 s por origen. Configurable con HZBridge.Panel.RateLimitWrites / RateLimitWindowMs.
  • Tokens de sesión: cada apertura del panel emite un token que caduca tras 5 minutos sin actividad; los tokens caducados reciben un nuevo arranque en la siguiente petición.
  • Validación: cada guardado pasa por la validación del tipo de campo, las comprobaciones opcionales pattern / min / max y luego las funciones invariant de la sección antes de llegar al disco.
  • Log de auditoría: cada guardado aceptado escribe una línea en data/_audit.log. Al pasar de 10 MB, el archivo se renombra data/_audit.<fecha>.<hora>.log y empieza uno nuevo. hz_lib nunca borra estos archivos (HZBridge.Panel.AuditRetentionDays no se aplica en la v1.2.0): borra tú los antiguos si necesitas un límite de conservación.
  • Escrituras atómicas: la configuración guardada de cada módulo se escribe en data/<module>.json pasando antes por un archivo temporal. Los campos marcados requiresRestart quedan además pendientes en data/<module>.pending.json y se aplican al reiniciar el recurso.
  • Derechos comprobados en cada acción, no solo al abrir el panel. Un admin al que se le retiran los derechos no puede seguir editando con el panel ya abierto.

Referencia

  • Código del DSL de esquema: modules/panel/schema_dsl.lua en tu carpeta de hz_lib (abierto, sin cifrar)
  • Configuración guardada por módulo: data/<module>.json, más data/<module>.pending.json para los cambios que esperan un reinicio
  • Roles del staff: data/_access.json
  • Auditoría: data/_audit.log