BLOXAR Lua API
Block scripts in BLOXAR are written in Lua and run in an isolated virtual machine (fengari) — each script has its own separate state, and scripts cannot see each other's variables directly. Blocks can communicate with each other only through the explicit engine functions described in this document, or through events (emit/on).
🔑 Core principle
A script has no direct access to the engine's 3D objects. Instead of parent.position.x = 5 use functions like
setBlockPosition(id, x, y, z), where id is the unique UUID of a block.
🚀 First script
- Open the project in Studio Mode.
- In the Explorer panel, select a block, click
➕and add📜 Script. - Click the script — the code editor will open.
- Write Lua code and click
Save & Close. - Click Publish to publish the world to the server.
Important: scripts are saved only via Publish (an actual publication of the world), not via local saving of the .blxr file. After publishing, re-enter the place so that the script takes effect.
Minimal example
function onTick(dt)
if isKeyDown('e') then
say('Hello from the script!')
end
end
onTick(dt) is the only function the engine calls automatically, every frame, with dt being the time in seconds since the previous frame. All other code inside the script is written around it.
🧬 Block variables
These functions are available only inside a script attached to a block — they return data of precisely this block, without requiring a UUID.
Current coordinates of the block the script is attached to.
The block's name, set in the editor.
The unique ID of this block — use it in functions like setBlockPosition(id, ...) to move itself.
⚡ Events
Called once when a player enters a radius of ~1.5 from the block. who is the player's nickname.
Called once when a player touches the block up close (radius ~1.0).
Sends an event to all blocks subscribed to eventName via on().
Subscribe/unsubscribe. When triggered, the script's global function onEvent_<eventName>(data).
-- Button block
on('door_toggle')
function onEvent_door_toggle(data)
say('The door received a signal from ' .. data.from)
end
function onTick(dt)
if isKeyDown('e') then
emit('door_toggle', 'state', 'open')
end
end
❤️ Player health and position
Current and maximum player health.
Whether the player is alive right now.
Deals damage / restores health. Does not go beyond 0..max.
Instantly kills or respawns the player at the spawn point.
Check/enable temporary invulnerability after spawning.
Player position. Returns three numbers: local x, y, z = getPlayerPosition().
Teleports the player or shifts them by an offset.
Teleports the player to the specified block (slightly above its position).
Player rotation around the vertical axis, in radians.
Nickname and skin of the local player.
Walk-through-walls mode.
Distance from the player to a point — the basis for traps and triggers.
⌨️ Input
Whether a key is held down right now. A lowercase string: 'w', 'e', ' ' (space), 'shift'.
At least one / all of the listed keys are held down simultaneously.
A comma-separated list of all held keys — for debugging.
🎥 Camera
Current camera position.
Camera distance from the player in third-person mode (1..40).
Whether the script is running in Studio mode (touch events do not fire there).
🌍 Time of day and gravity
Current time of day in radians (0..2π — a full cycle).
Quickly set the time of day by name.
Reads/changes the strength of gravity in the world; resetGravity() restores the default value.
Service data about the environment and the world.
Turns clouds on/off, or starts terrain generation.
Scans placed blocks (water/lava nearby, average height) — useful for AI scripts. Format: "hasWater:0,hasLava:0,blockCount:12,avgY:3.5,dominantColor:...".
🧱 Blocks
Each function takes or returns a uuid — the unique ID of a block (you can get it via getBlockUUID() for your own block, findBlockByName() for someone else's, or as the result of spawnBlock()).
Search
UUID of the first block with the specified name.
All matching UUIDs, comma-separated. See also the data tables below.
General information about all blocks in the world.
Reading properties
Block position and scale.
Block name, color (hex) and physical collision.
Modification
Moves a block in the world.
Recolors, scales, rotates a block (radians).
Shows/hides a block.
Creation / removal
Creates a new block. shape: 'box', 'sphere', 'cone', 'cylinder'.
Removes a block (or all blocks with the specified name).
📡 Raycast
A ray from the camera forward. Returns the UUID of the first block hit.
A ray from an arbitrary point in an arbitrary direction.
🎒 Inventory and score
The currently selected slot and switching to another.
What is in the slot.
Puts an item into a slot or clears it.
Variables shared by all scripts for the duration of the session — handy for keeping score or a simple currency.
setGlobalVar('score', (getGlobalVar('score') or 0) + 10)
say('Score: ' .. getGlobalVar('score'))
👥 Multiplayer
Read-only — other players are controlled by the server directly.
Format: "id:nick:x:y:z;id:nick:x:y:z". For a proper table, see getOtherPlayersTable() below.
Number of players nearby and the position of a specific one by its id.
🔊 Sound and chat
Plays an engine sound effect.
Background music from a link.
A message on behalf of the script in chat + a speech bubble above the player.
A system message in a different color — for warnings.
⏱ Timers
Runs a Lua function after the specified number of seconds.
wait(2, function()
say('2 seconds have passed')
end)
🖥️ UI and dialogs
A pop-up notification at the top of the screen (toast).
A modal window with an OK button in the center of the screen.
📊 Data tables
Most API functions return a string (easier to marshal into Lua), but for lists of objects there are versions that return a real Lua table.
An array of tables {id, nickname, x, y, z}.
An array of UUID strings instead of a comma-separated string.
for i, p in ipairs(getOtherPlayersTable()) do
print(p.nickname, p.x, p.y, p.z)
end
🎬 Animations
Enables/disables a block's built-in animation (for example, constant rotation).
🧮 Math and utilities
Distance between two points in 3D.
Standard helpers that plain Lua lacks.
Time in seconds since the page was loaded.
Output to the browser console — the main tool for debugging scripts.
💡 Ready-made examples (Copy & Paste)
Light car (get in with E)
local carId = nil
local seated = false
local eWasDown = false
local speed = 6.0
local turnSpeed = 2.2
local enterRadius = 2.5
local rotY = 0
function onTick(dt)
if carId == nil then carId = getBlockUUID() end
local cx, cy, cz = getBlockX(), getBlockY(), getBlockZ()
local eDown = isKeyDown('e')
local ePressed = eDown and not eWasDown
eWasDown = eDown
if not seated then
if ePressed and distanceToPlayer(cx, cy, cz) < enterRadius then
seated = true
say('Got behind the wheel')
end
return
end
if ePressed then
seated = false
say('Got out of the car')
setPlayerPosition(cx + 2, cy + 1, cz)
return
end
if isKeyDown('a') then rotY = rotY + turnSpeed * dt end
if isKeyDown('d') then rotY = rotY - turnSpeed * dt end
local moveDir = 0
if isKeyDown('w') then moveDir = 1 end
if isKeyDown('s') then moveDir = -1 end
local nx, nz = cx, cz
if moveDir ~= 0 then
nx = cx + math.sin(rotY) * speed * dt * moveDir
nz = cz + math.cos(rotY) * speed * dt * moveDir
end
setBlockPosition(carId, nx, cy, nz)
setBlockRotation(carId, 0, rotY, 0)
setPlayerPosition(nx, cy + 1.0, nz)
setPlayerRotationY(rotY)
end
Spike trap (damage on touch)
local cooldown = 0
function onTick(dt)
cooldown = math.max(0, cooldown - dt)
local x, y, z = getBlockX(), getBlockY(), getBlockZ()
if distanceToPlayer(x, y, z) < 1.2 and cooldown <= 0 then
cooldown = 1.5
damagePlayer(20)
playSound('land', 1)
end
end
Interactive button
local activated = false
function onTick(dt)
local x, y, z = getBlockX(), getBlockY(), getBlockZ()
if distanceToPlayer(x, y, z) < 3 and not activated then
if isKeyDown('e') then
activated = true
playSound('jump', 1)
setBlockColor(getBlockUUID(), 0x2EE6A6)
announce('Button activated!')
end
end
end
Portal with a delay
local used = false
function onPlayerEnter(who)
if used then return end
used = true
say(who .. ' activated the portal')
wait(1, function()
setPlayerPosition(0, 5, 0)
used = false
end)
end