Skip to content

Exports & events

Register screens and Cuxial OS apps from your own resources with Bridge.Screens, the exports of Cuxial Screens and the kit for app pages.

Other resources can add screens to the world, open them from their own interactions and add their own apps to Cuxial OS. The recommended way is Bridge.Screens from Cuxial Bridge: it waits for Cuxial Screens to start and registers everything again if it restarts. Anything not listed on this page is internal.

Bridge.Screens on the server ​

Include the bridge in your resource and declare the dependency:

fxmanifest.lua
lua
shared_scripts {
    '@ox_lib/init.lua',
    '@cuxial_bridge/init.lua',
}

dependencies { 'cuxial_bridge', 'cuxial_screens' }
FunctionReturnsWhat it does
registerScreen(def)ok, errAdds a screen. Same fields as data/screens.lua (see Configuration). Returns true, 'pending' until Cuxial Screens starts. Registering the same id again replaces it.
removeScreen(id)booleanRemoves a screen registered by your resource.
registerApp(def)ok, errAdds an app to Cuxial OS. Returns true, 'pending' if Cuxial Screens has not started yet: it is registered when it does.
unregisterApp(id)booleanRemoves your app.
onCall(appId, method, fn)—Handles a call from your app page.
push(src, appId, event, data)booleanSends data to your app, if that player has it open.
notify(src, appId, title, body?)booleanShows a notification of the system with the icon of your app. Title up to 64 characters, body up to 240.
getSession(src)table | nil{ screen, cid, unlocked, apps } of the player's screen session.
closeFor(src)—Closes the screen the player is using.

Screens and apps registered by a resource are removed when that resource stops.

Add a screen ​

server.lua
lua
Bridge.Screens.registerScreen({
    id = 'office_pc',
    label = 'Office computer',
    model = 'cuxial_screens_test',
    coords = vec3(-75.2, -818.4, 243.4),
    heading = 90.0,
    prop = true,
    access = { jobs = { realestate = 2 }, boss = true },
    tags = { 'office' },
})

Add an app ​

FieldTypeWhat it does
idstringUnique id: letters, numbers, _ and -, up to 64 characters.
labelstringName of the app, already translated.
iconstringPath to an svg, png or webp of your resource, or the id of a system icon (files, notes…).
pagestringPage of your resource opened in the window, such as 'web/dist/index.html'.
size / minSizetable{ w, h } of the window at scale 1, from 320 × 200 to 1920 × 1080.
accesstable{ jobs = { [job] = minGrade }, gangs = { [gang] = minGrade }, boss = true }. Without it, everyone. A job or a gang is enough. With boss = true the player must also be boss of it.
screensstring[]Screen ids where it appears.
tagsstring[]Screen tags where it appears. Without screens or tags, on every screen.
pinnedbooleanAlso pinned to the taskbar.
desktopbooleanAlso gets a desktop icon.
mirrorbooleanfalse shows a Private content card to mirror viewers instead of the app. Default true.
server.lua
lua
Bridge.Screens.registerApp({
    id = 'office_sales',
    label = locale('app_label'),
    icon = 'web/dist/img/icon.svg',
    page = 'web/dist/index.html',
    size = { w = 900, h = 580 },
    minSize = { w = 360, h = 320 },
    access = { jobs = { realestate = 0 } },
    tags = { 'office' },
    desktop = true,
})

Bridge.Screens.onCall('office_sales', 'summary', function(src, payload, session)
    -- session = { screen = screen id, cid = character id, app = 'office_sales' }
    local job = Bridge.GetJob(src)
    if not job or job.name ~= 'realestate' then return nil, 'error_access' end
    return { total = 12 }
end)

The handler returns the data for the page, or nil, 'error_key', 'optional message'. If it throws, the page receives error_app_failed; a method without a handler returns error_method. The handler can wait on database queries.

Cuxial Screens only calls your handler for a valid session: right character, in range, app allowed on that screen, rate limit and sizes. Your own rules (job, grade, money) must still be checked in the handler. Never trust payload.

The list of apps of a session is updated when the player changes job or gang, and windows that no longer apply are closed.

Bridge.Screens on the client ​

FunctionReturnsWhat it does
open(screenId)booleanOpens a screen without the interaction option, for example when the player sits down at a desk. Works with screens that have interact = false.
close()—Closes the screen in use.
isUsing()booleanWhether the player is using a screen.
current()string | nilId of the screen in use.
lua
if Bridge.Screens.open('office_pc') then
    -- the player is on the screen
end

Exports of Cuxial Screens ​

The same functions are available as exports, for resources that do not use the bridge.

SideExportReturnsWhat it does
ServerRegisterScreen(def)ok, errAdds a screen.
ServerRemoveScreen(id)booleanRemoves a screen registered by the calling resource. Screens from data/screens.lua and /screensadmin cannot be removed from outside.
ServerGetSession(src)string | nilId of the screen the player is using.
ServerCloseFor(src)—Closes the player's screen.
ClientUse(id)booleanOpens a screen.
ClientClose()—Closes the screen in use.
ClientIsUsing()booleanWhether the player is using a screen.
ClientCurrent()string | nilId of the screen in use.
lua
local id = exports.cuxial_screens:GetSession(source)

App pages: the kit ​

An app is a web page of your own resource that Cuxial OS opens in a window. It talks to its server only through the screen session, with the kit included in kit/ of Cuxial Screens.

Copy the kit ​

Copy kit/src of Cuxial Screens into your web project as src/lib/screens-app/, and add @rrweb/record 2.1.7 to the dependencies of its package.json. The mirror uses it to show your app to viewers.

Use it in the page ​

ts
import './lib/screens-app/app.css'
import { screens } from './lib/screens-app'

const info = await screens.ready()   // { app, theme, user { name, initials, job }, screen { id, hostname } }

const res = await screens.call<{ total: number }>('summary', { day: 0 })
if (res.ok) total = res.data.total
else error = res.message ?? res.error

screens.on<{ total: number }>('total', d => (total = d.total))
screens.onTheme(t => (theme = t))

List the files ​

Add the built page to the files of your fxmanifest.lua, for example web/dist/index.html, web/dist/js/*.js, web/dist/css/*.css and web/dist/img/*.*.

KitWhat it does
screens.ready()Waits for the connection with the system and returns the app, theme, user and screen.
screens.call(method, payload)Calls onCall on your server. Returns { ok: true, data } or { ok: false, error, message? }.
screens.on(event, fn)Receives the push of your server. Returns a function to stop listening.
screens.onTheme(fn)Called at once and on every change of theme, accent or scale.
screens.notify(title, body?)Notification of the system.
screens.setTitle(title)Changes the window title. null goes back to the app name.
screens.wantEscape(on)With true, Esc goes to your app (to close a modal) instead of leaving the screen.
screens.close()Closes the window.
isDoubleUp(key, event)Double click detection. Use it in onpointerup: screens do not fire dblclick.
rem(theme, n)Converts rem to pixels, for canvas drawing.
app.cssTheme tokens, base layout and the system classes (os-card, os-btn, os-btn-accent, os-input, os-scroll…).

Size everything in rem and adapt with @container app (…) queries: windows can be resized and screens have different resolutions.

Inside the mirror, data-private hides an element, data-mask replaces its text with asterisks, and password fields are always masked. The window title is always visible to viewers.

Do not use NUI callbacks of your own resource from the app page: they would bypass the screen session. Every request goes through screens.call.

Using your own models ​

A model can be used as a screen when its screen is a mesh with its own embedded texture, with a full 0 to 1 UV and an emissive shader, and the model has its ytyp loaded. List it in data/models.lua (see Configuration) with its texture dictionary, the texture name and the four corners of the screen in local space.

Events ​

Cuxial Screens has no public events. Use the functions above.

© Cuxial