Interfaces: menus, inputs and NUI · Lesson 3/3 · 10 min
Your own NUI: when menus aren't enough
For HUDs, phones or shops with a custom design you need NUI: a web page (HTML/CSS/JS) on top of the game.
When you want an interface with your own design (a HUD, a phone, a nice-looking shop) you build a NUI: a web page that FiveM draws over the game. It works the same with QBCore as without it.
Declare it and open/close with focus
-- fxmanifest.lua
ui_page 'html/index.html'
files { 'html/index.html', 'html/style.css', 'html/app.js' }fxmanifest.lua
-- client.lua
RegisterCommand('tienda', function()
SetNuiFocus(true, true) -- give focus and mouse to the web page
SendNUIMessage({ action = 'open' })
end)
RegisterNUICallback('close', function(_, cb)
SetNuiFocus(false, false) -- return control to the game!
cb('ok')
end)
-- buy: the client only ASKS; the server decides
RegisterNUICallback('comprar', function(data, cb)
QBCore.Functions.TriggerCallback('tienda:comprar', function(ok)
cb({ ok = ok })
end, data.item)
end)client.lua
The #1 NUI bug: forgetting SetNuiFocus(false, false) on close leaves the player with the mouse out and unable to move. Always wire the close with ESC and via callback. And remember: the real purchase is validated on the SERVER (callback), never in the JS.
Practice what you learned
0/3Para abrir tu NUI y darle el ratón al jugador, ¿qué llamada necesitas?
Completa la función nativa que manda datos desde Lua hacia la web (JS).
({ action = 'open', data = { dinero = 500 } })Pista
Lua → JS: la web escucha estos mensajes con un addEventListener('message').
Este callback cierra la NUI pero deja al jugador atrapado sin poder moverse. Falta devolverle el control quitando el foco.
Este código tiene un fallo:
RegisterNUICallback('close', function(_, cb) cb('ok')end)Reescríbelo corregido:
Pista
El bug nº1 de NUI: olvidar SetNuiFocus(false, false) al cerrar deja el ratón fuera y bloquea el movimiento.
Challenge: code it yourself
Create the skeleton of a NUI: fxmanifest with ui_page/files, open with /tienda giving focus, and a 'close' callback that removes it.
Write it yourself in your editor (VS Code) and test it on your server. You learn here by doing it, not by copying.
See hint
ui_page → /tienda opens with focus → JS listens for 'open' and shows; ESC does a fetch to 'close' that removes the focus.
Escribe aquí tu solución:
