Commands#
City Builder registers two in-game commands. Anyone can type them, but the server checks the permission first — a framework admin or a job in Config.CreatorJobs — and refuses everyone else.
Command | Where | Description |
|---|---|---|
| In game | Opens decoration mode: the free camera, the furniture catalogue and the placed-object manager. |
| In game | Opens the Furniture Creator, to add, edit and remove custom props. Renamed with |
Neither command has a default key. Bind one in your keybinds or a radial menu, as shown below.
Client Exports#
For other scripts that need to know when somebody is building — to pause their own keybinds, HUD or interactions while the free camera is in use.
inDecorate
Returns true while the local player has decoration mode open.
local building = exports['qs-citybuilder']:inDecorate() --[[@as boolean]]
-- e.g. in your own keybind
if exports['qs-citybuilder']:inDecorate() then
return -- do not open my menu over the builder
endClient Events#
Opening the builder from your own script
Trigger citybuilder:decorate:open on the client — from a radial menu, a laptop prop, a target option. The permission is still checked.
-- client: ox_lib radial menu
lib.addRadialItem({
id = 'citybuilder',
icon = 'hammer',
label = 'City Builder',
onSelect = function()
TriggerEvent('citybuilder:decorate:open')
end
})-- server: open it for a player
TriggerClientEvent('citybuilder:decorate:open', source)The Furniture Creator has no event; run its command instead: ExecuteCommand('citybuilderfurniture').
Custom Prop Events#
Any prop can run your own code when a player presses E next to it — an arcade machine that starts a mini-game, a jukebox that opens a music menu, a terminal that opens a job panel. Every placed copy of that model gets the [E] - Interact prompt.
Register the model
In
config/furniture.lua, add the model name toConfig.DynamicFurnitureswith the client event to fire and where the prompt sits relative to the prop:lua Config.DynamicFurnitures = { ['prop_arcade_01'] = { event = 'my-arcade:client:open', offset = { x = 0.0, y = -0.5, z = 1.0 }, }, ['bkr_prop_clubhouse_jukebox_01a'] = { event = 'my-jukebox:client:open', offset = { x = 0.0, y = 0.0, z = 1.2 }, }, }Listen for it
The event is triggered on the client of the player who pressed E, with the placed object's unique id —
citybuilder_<id>— so each copy of the prop can keep its own state:lua -- in your own resource (client) AddEventHandler('my-arcade:client:open', function(uniq) print('Arcade used:', uniq) -- e.g. 'citybuilder_42' -- open your mini-game here end)
Unique IDs and the Database#
Every placed object is a row of qs_citybuilder_decorations, and its unique id is citybuilder_ followed by the row's id. The same id names its stash in your inventory and is passed to custom prop events, so a script can tie its own data to one specific object.
Column | Holds |
|---|---|
| The prop's model. |
| JSON |
|
|
| The identifier of the builder who placed it, and when. |
Rows edited directly in the database are only picked up when the resource restarts. Use decoration mode for changes on a live server.



