NX CreativeNX CreativeDocs
Scriptsnx_write

Exports

Public exports registered by nx_write.

nx_write exposes a client API for opening, placing, and closing writing sessions, plus two server-side helpers. The client exports let a custom inventory open, place, and close sessions, and let custom positioning tooling create placements directly. The server exports forward an open request to a player and create trusted placements. See Configuration for Config.Inventory, which decides whether nx_write touches ox_inventory itself or leaves item handling to you.

Client

exports.nx_write:placeFromSlotclient

Start the in-world placement preview for the note held in the given inventory slot. The slot's item must carry a saved document (a docId in its metadata); if it does not, the player is notified to save it first.

Parameters

  • slotnumberox_inventory slot number of the notepad or post-it to place.

Returns

nil
-- Wired on the notepad item in ox_inventory/data/items.lua,
-- so the inventory's right-click "Place" button enters placement.
buttons = {
    {
        label = 'Place',
        action = function(slot)
            exports.nx_write:placeFromSlot(slot)
        end,
    },
},

During the preview the player aims at a surface, then commits with the Config.Placement.controls.commit key or cancels with the cancel key. On commit the note is placed for every nearby player and the item is consumed from the slot.

exports.nx_write:Openclient

Open or continue a writing session. Returns false if a session or placement preview is already active, or if the kind is unknown. Pass docId to continue a saved document; omit it for a new one. slot and itemName are opaque values echoed back in nx_write:documentSaved on save.

Parameters

  • optstable{ kind?: string (default "notepad"), docId?: number, title?: string, slot?: any, itemName?: string, page?: number, readOnly?: boolean }.

Returns

boolean
-- Continue a document your custom inventory stored on the item.
exports.nx_write:Open({
    kind     = 'notepad',
    docId    = item.metadata.docId,
    slot     = item.slot,
    itemName = item.name,
})
exports.nx_write:Placeclient

Start the in-world placement preview for a saved document. docId is required, since the placement renders the document's saved preview image. slot and itemName ride along to the server and are echoed on nx_write:placementCreated.

Parameters

  • optstable{ kind?: string (default "notepad"), docId: number, slot?: any, itemName?: string }.

Returns

boolean
exports.nx_write:Place({ kind = 'notepad', docId = item.metadata.docId, slot = item.slot, itemName = item.name })
exports.nx_write:CreatePlacementclient

Create a committed placement at explicit coords and rotation, skipping the in-world aim preview. This is the hook for custom positioning tooling (transform gizmos, snapping, free-rotate): your UX owns where the note goes, nx_write owns persistence, render, and multiplayer sync. It runs the same server callback as a preview commit, so it persists, bakes and renders on every client, and fires nx_write:placementCreated. Returns the placement id on success, or false. A client-driven create is still validated against the player's position (Config.Placement.maxPlaceDistance plus 2 m slack); use the server export for an unbounded, trusted placement.

Parameters

  • optstablePose, in priority order. { kind?: string (default "notepad"), docId: number (the saved document to render), entity?: number (read coords and quat off a live entity, the precise path: point it at your gizmo preview prop), coords?: vector3, quat?: { x, y, z, w } (lossless, preferred over rotation), rotation?: vector3 (pitch, roll, yaw in GTA euler degrees), surfaceKind?: "wall" | "table" (inferred from the pose when omitted), slot?: any, itemName?: string }.

Returns

number | false
-- From a transform gizmo: the tool owns positioning, nx_write owns the rest.
-- Passing a live entity is the precise path: the placement is
-- byte-identical to the preview prop the player was dragging.
local id = exports.nx_write:CreatePlacement({
    kind     = 'notepad',
    docId    = item.metadata.docId,
    entity   = gizmoPreviewProp,
    slot     = item.slot,
    itemName = item.name,
})

-- Or place at explicit coords with a lossless quat.
exports.nx_write:CreatePlacement({
    kind   = 'notepad',
    docId  = item.metadata.docId,
    coords = vec3(215.7, -810.2, 30.7),
    quat   = { x = 0.0, y = 0.0, z = 0.0, w = 1.0 },
})

[!note] Prefer entity or quat for the pose. Both are exact. rotation (GTA euler) is a convenience that round-trips cleanly for flat or upright poses only. When surfaceKind is omitted, nx_write infers it from the prop's world face normal and validates it against the kind's allowed surfaces.

exports.nx_write:RefreshPlacementsclient

Re-pull placements from the server and render any not held locally. Live creates already arrive over the spawn broadcast, so this is a manual resync for tooling that writes to nx_write_placements out of band. Idempotent. Returns true if the refresh ran.

Returns

boolean
exports.nx_write:RefreshPlacements()
exports.nx_write:Closeclient

Save (or discard) the active writing session and close it. Pass true to discard without saving. Returns false if no session was active.

Parameters

  • discardbooleantrue discards the session without saving. Defaults to false (save and close).

Returns

boolean
exports.nx_write:Close()      -- save and close
exports.nx_write:Close(true)  -- discard and close
exports.nx_write:IsBusyclient

True while a writing session or a placement preview is active. Gate your own item-use with it so a second use does not double-open.

Returns

boolean
if not exports.nx_write:IsBusy() then
    exports.nx_write:Open({ kind = 'notepad', docId = item.metadata.docId })
end

Server

exports.nx_write:Openserver

Forward an open request to a player's client. Mirrors the client Open export and accepts the same opts. Use this when your inventory routes item-use through a server hook.

Parameters

  • sourcenumberServer id of the player to open the session for.
  • optstableSame shape as the client Open export.

Returns

boolean
-- From your inventory's server-side item-use handler.
exports.nx_write:Open(source, {
    kind     = 'notepad',
    docId    = item.metadata.docId,
    slot     = item.slot,
    itemName = item.name,
})
exports.nx_write:CreatePlacementserver

Create a placement at explicit coords from the server, bypassing the aim preview. The trusted mirror of the client CreatePlacement export. Because the server supplies the coords, the per-player rate-limit and distance gate are skipped (those guard the untrusted client callback). Everything else is identical to a preview commit: it persists, broadcasts so every client bakes and renders it, and fires nx_write:placementCreated. Pass coords with quat or rotation; there is no entity option, since the server cannot read a client entity. Returns the placement id on success, or false.

Parameters

  • sourcenumberServer id of the player credited with the placement.
  • optstable{ kind?: string (default "notepad"), docId: number, coords: vector3, quat?: { x, y, z, w } (lossless, preferred), rotation?: vector3 (pitch, roll, yaw in GTA euler degrees), surfaceKind?: "wall" | "table" (defaults to a surface the kind allows), slot?: any, itemName?: string }.

Returns

number | false
-- Seed a placement programmatically from a server hook.
local id = exports.nx_write:CreatePlacement(source, {
    kind   = 'notepad',
    docId  = docId,
    coords = vec3(215.7, -810.2, 30.7),
    quat   = { x = 0.0, y = 0.0, z = 0.0, w = 1.0 },
})

[!note] These exports work in any inventory mode. They pair with the server events (nx_write:documentSaved, nx_write:placementCreated, nx_write:placementPickedUp), which is how a custom inventory persists the docId and bridges items on place and pickup.

On this page