Cube Scripts

Configuration

Every option in config.lua and server/config.lua explained.

Cube Monitoring has two config files, and the split matters.

FileLoaded onHolds
config.luaClient and serverEverything players may safely see
server/config.luaServer onlyWebhooks, API keys, TURN credentials
Danger

Never put a webhook or an API token in config.lua. It is a shared script, so every connected player receives a copy of it and anyone can read it from their game cache.

General#

config.lua
Config.Debug = true
Config.Framework = "auto" -- auto / esx / qbcore / standalone
Config.Locale = "en"      -- en / fr
Config.ColorNUI = "7C5CFFFF"

Config.Debug prints [DEBUG] lines for stream lifecycle and TURN caching. Turn it off in production.

Config.Framework is detected automatically when left on "auto". Set it explicitly to skip detection or to force standalone on a framework server.

Config.ColorNUI is the accent colour of the interface, as RRGGBBAA.

Notifications#

config.lua
Config.Notification = "framework" -- standalone / framework / ox_lib / custom

Only used when Config.NotifyTarget is on. For anything custom, edit Notify in client/function.lua:

client/function.lua
Notify = function(message)
    if Config.Notification == "custom" then
        exports['my-notify']:Alert(message)
        return
    end
    -- ...
end

Permissions#

config.lua
Config.Permission = "ace" -- ace / framework / both
Config.Ace = "cube_monitoring.admin"
Config.Groups = {
    esx = { "admin", "superadmin" },
    qbcore = { "admin", "god" },
}
ValueBehaviour
aceAce permission only. Works on any server.
frameworkFramework groups only. Requires ESX or QBCore.
bothEither one grants access.

For anything else - a database lookup, a Discord role check, your own admin resource - edit HasPermission in server/function.lua:

server/function.lua
HasPermission = function(src)
    return exports['my-admin']:isStaff(src)
end

It receives the player's server id and must return a boolean. It gates every command, every NUI callback and the player list.

Commands#

config.lua
Config.Commands = {
    panel = "watchpanel",
    watch = "watchgame",
    screenshot = "screen",
    unwatch = "unwatch",
}

Config.OpenPanelOnWatchCommand = true

Rename any of them. With OpenPanelOnWatchCommand on, running the watch command with no argument opens the player list instead of printing usage.

Stream limits#

config.lua
Config.MaxConcurrentStreams = 6
Config.MaxStreamsPerTarget = 3
Config.AllowSelfWatch = false
Config.NotifyTarget = false
SettingEffect
MaxConcurrentStreamsWindows one admin can open at once. Each stream is a separate peer connection on the target's machine, so this is your main cost control.
MaxStreamsPerTargetAdmins that can watch the same player simultaneously.
AllowSelfWatchWhether an admin can watch themselves. Useful for testing.
NotifyTargetTells the watched player. Off by default; enable it if your rules require disclosure.
config.lua
Config.ScreenshotTimeout = 30000
Config.PlayerListRefresh = 5000

PlayerListRefresh is how often, in milliseconds, the player list is pushed to open panels.

Quality#

config.lua
Config.Quality = {
    fps = 15,
    bitrate = 6000000,
    width = 1600,
    height = 900,
    idleFps = 24,
    screenshotQuality = 0.9,
}

The defaults favour a sharp image over a smooth one, which is what you want when reading chat or spotting a menu.

Tip

If watched players report frame drops, lower bitrate before lowering fps. Bitrate is what costs them upload bandwidth.

Interface#

config.lua
Config.Window = {
    width = 640,
    height = 400,
    minWidth = 320,
    minHeight = 220,
    cascadeOffset = 32,
    startX = 360,
    startY = 80,
    snapThreshold = 18,
}

New windows open at startX / startY, each offset by cascadeOffset so they never land exactly on top of each other. snapThreshold is the distance in pixels at which a dragged window snaps to a screen edge.

config.lua
Config.Panel = {
    startOpen = true,
    width = 300,
    showPing = true,
    showLiveBadge = true,
    defaultSort = "id", -- id / name / ping
}

Server config#

Everything below lives in server/config.lua and never reaches a client.

server/config.lua
ServerConfig.Webhook = ""

ServerConfig.Logs = {
    enabled = false,
    webhook = "",
}

Webhook is the default target for the screenshot upload exports. Logs posts an embed to Discord every time a watch session starts, recording which admin watched which player.

TURN settings are covered in the WebRTC guide.

Locales#

config.lua
Config.Locale = "en"

Files live in locales/. To add a language, copy locales/en.lua, rename the file and the table key, and translate the values:

locales/es.lua
Locales = Locales or {}

Locales['es'] = {
    ['no_permission'] = 'No tienes permiso para usar este comando.',
    -- ...
}

It is picked up automatically - the manifest loads locales/*.lua. Any key you leave out falls back to English, and missing keys print a [WARN] line so you can spot them.