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:placeFromSlotclientStart 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
slotnumber— ox_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:OpenclientOpen 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:PlaceclientStart 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
booleanexports.nx_write:Place({ kind = 'notepad', docId = item.metadata.docId, slot = item.slot, itemName = item.name })exports.nx_write:CreatePlacementclientCreate 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
optstable— Pose, 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
entityorquatfor the pose. Both are exact.rotation(GTA euler) is a convenience that round-trips cleanly for flat or upright poses only. WhensurfaceKindis omitted, nx_write infers it from the prop's world face normal and validates it against the kind's allowed surfaces.
exports.nx_write:RefreshPlacementsclientRe-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
booleanexports.nx_write:RefreshPlacements()exports.nx_write:CloseclientSave (or discard) the active writing session and close it. Pass true to discard without saving. Returns false if no session was active.
Parameters
discardboolean— true discards the session without saving. Defaults to false (save and close).
Returns
booleanexports.nx_write:Close() -- save and close
exports.nx_write:Close(true) -- discard and closeexports.nx_write:IsBusyclientTrue 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
booleanif not exports.nx_write:IsBusy() then
exports.nx_write:Open({ kind = 'notepad', docId = item.metadata.docId })
endServer
exports.nx_write:OpenserverForward 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
sourcenumber— Server id of the player to open the session for.optstable— Same 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:CreatePlacementserverCreate 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
sourcenumber— Server 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 thedocIdand bridges items on place and pickup.