Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Fullscreen NUI
- The most common use case of NUI is a full-screen 'UI page', which is overlaid on top of the game and may or may not have input focus. These are supported on both FiveM and RedM at this time, and are part of basic Citizen framework level support.
- The following natives are related to using full-screen NUI:
- SEND_NUI_MESSAGE
- SET_NUI_FOCUS
- Setting up a fullscreen NUI page
- To assign a full-screen NUI page to a resource, currently you need to specify a single ui_page in the resource manifest for the resource containing an UI page, like shown below:
- -- specify the root page, relative to the resource
- ui_page 'main.html'
- -- every client-side file still needs to be added to the resource packfile!
- files {
- 'main.html',
- 'build/main.js',
- }
- -- a page can also be hosted externally
- ui_page 'https://ui-frontend.cfx.example.com/b20210501/index.html'
- Referencing other assets
- The NUI system registers a https://cfx-nui- protocol scope for resource files. Therefore, you can reference a file in a resource as follows:
- <script type="text/javascript" src="https://cfx-nui-my-resource/production.js" async></script>
- This formerly was known as nui://, but this is no longer a secure context in newer browser versions.
- Developer tools
- CEF remote debugging tools are exposed on http://localhost:13172/ as long as the game is running. You can use any Chromium-based browser to easily access these tools.
- Alternately, it can be opened using the nui_devTools command in the game's F8 console, assuming the developer mode is enabled.
- NUI focus
- There's a limited focus stack for NUI resources, you can set focus to the current resource using the SET_NUI_FOCUS native, which will set keyboard focus and/or mouse cursor focus depending on the provided arguments.
- The most recently focused resource will be ordered on top of the focus stack, and resources are currently implemented as full-screen iframes: that means there's no click-through across resources.
- NUI messages
- You can send a message to the current resource's NUI page using the convenience wrapper SendNUIMessage which encodes a JSON string for you.
- For example:
- -- Lua
- SendNUIMessage({
- type = 'open'
- })
- // browser side
- window.addEventListener('message', (event) => {
- if (event.data.type === 'open') {
- doOpen();
- }
- });
- Direct-rendered UI
- In FiveM, you can also render NUI to a runtime texture, which is called DUI for 'direct NUI'. The following natives help with this:
- CREATE_DUI
- CREATE_RUNTIME_TEXTURE_FROM_DUI_HANDLE
- DESTROY_DUI
- GET_DUI_HANDLE
- IS_DUI_AVAILABLE
- SEND_DUI_MESSAGE
- SEND_DUI_MOUSE_DOWN
- SEND_DUI_MOUSE_MOVE
- SEND_DUI_MOUSE_UP
- SEND_DUI_MOUSE_WHEEL
- SET_DUI_URL
- The native documentation contains information for each of these, but here are some creative use cases for this:
- Rendering in 2D space using DRAW_SPRITE
- Rendering to a game render target object using similar natives.
- Rendering arbitrarily in world space using a specialized Scaleform, like in this forum topic.
- This can be used to make cinema screens, asynchronous in-game hint overlays, etc. fairly trivially.
- NUI callbacks
- NUI can also send calls back to the game using so-called 'NUI callbacks'. These are currently only fully supported in Lua, other languages can be used but need a bit of a tricky workaround as these predate function references in codegen.
- Generally, you'll use the RegisterNUICallback function in Lua, and the REGISTER_NUI_CALLBACK_TYPE native along with an event handler in other languages.
- Both work very similarly, and we'll describe both below:
- Registering a NUI callback in Lua
- RegisterNUICallback('getItemInfo', function(data, cb)
- -- POST data gets parsed as JSON automatically
- local itemId = data.itemId
- if not itemCache[itemId] then
- cb({ error = 'No such item!' })
- return
- end
- -- and so does callback response data
- cb(itemCache[itemId])
- end)
- Registering a NUI callback in C#/JS
- // JS
- RegisterNuiCallbackType('getItemInfo') // register the type
- // register a magic event name
- on('__cfx_nui:getItemInfo', (data, cb) => {
- const itemId = data.itemId;
- if (!itemCache[itemId]) {
- cb({ error: 'No such item!' });
- return;
- }
- cb(itemCache[itemId]);
- });
- // C#
- RegisterNuiCallbackType("getItemInfo"); // register the type
- // register the event handler with manual marshaling
- EventHandlers["__cfx_nui:getItemInfo"] += new Action<IDictionary<string, object>, CallbackDelegate>((data, cb) =>
- {
- // get itemId from the object
- // alternately you could use `dynamic` and rely on the DLR
- if (data.TryGetValue("itemId", out var itemIdObj))
- {
- cb(new
- {
- error = "Item ID not specified!"
- });
- return;
- }
- // cast away
- var itemId = (itemIdObj as string) ?? "";
- // same as above
- if (!ItemCache.TryGetValue(itemId, out Item item))
- {
- cb(new
- {
- error = "No such item!"
- });
- return;
- }
- cb(item);
- });
- Invoking the NUI callback
- // browser-side JS
- fetch(`https://${GetParentResourceName()}/getItemInfo`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json; charset=UTF-8',
- },
- body: JSON.stringify({
- itemId: 'my-item'
- })
- }).then(resp => resp.json()).then(resp => console.log(resp));
- To prevent requests from stalling, you have to return the callback at all times - even if containing just an empty object, or {"ok":true}, or similar.
- Loading screens
- A special NUI frame is the frame called loadingScreen, which is shown during loading of FiveM, instead of the default client-side loading screen or the game loading screen, after joining into a server.
- It is specified similarly to ui_page using loadscreen in the resource manifest:
- loadscreen 'load.html'
- file 'load.html'
- loadscreen 'https://my-server.example.com/loadscreen/'
- Cursor/input
- The loading screen will always be focused for both mouse and keyboard input, however the cursor is not shown by default for legacy reasons.
- The NUI cursor can be enabled by adding a loadscreen_cursor entry to the resource manifest that contains the loading screen:
- loadscreen_cursor 'yes'
- Handover data
- Server scripts can specify data pairs to send to the client loading screen using the handover function in the playerConnecting event. This data will be passed to the loading screen in the window.nuiHandoverData property.
- In addition to data specified by the server, a field named serverAddress is also added with the current IP/port used for the client->server connection.
- Example
- -- Server script
- AddEventHandler('playerConnecting', function(_, _, deferrals)
- local source = source
- deferrals.handover({
- name = GetPlayerName(source)
- })
- end)
- <!-- loading screen page -->
- <h1 id="namePlaceholder">Welcome, <span></span></h1>
- <script type="text/javascript">
- window.addEventListener('DOMContentLoaded', () => {
- console.log(`You are connecting to ${window.nuiHandoverData.serverAddress}`);
- // a thing to note is the use of innerText, not innerHTML: names are user input and could contain bad HTML!
- document.querySelector('#namePlaceholder > span').innerText = window.nuiHandoverData.name;
- });
- </script>
- Lifetime
- By default, the loading screen will show until SHUTDOWN_LOADING_SCREEN is called. However, you can also manually control exit lifetime by setting the loadscreen_manual_shutdown 'yes' directive in your resource manifest.
- When doing so, the following natives become available once scripts start (after game load and connection to network):
- SEND_LOADING_SCREEN_MESSAGE
- SHUTDOWN_LOADING_SCREEN_NUI
- This can be used to, say, add a custom fade-out effect from the loading screen to an in-game view, or integrate NUI events with early-game spawn selection UI.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement