Room, hotspot, and cyborg scripts may use Lua 5.4 running in the browser via WebAssembly
(Wasmoon). Scripts never receive window, the DOM, or PSNet — only the sandboxed
global palace, which mirrors classic and extended IPTSCRAE host effects.
Register handlers with palace.on:
palace.on("ENTER", function(ctx)
palace.chat.say("hello from lua")
end)
palace.on("OUTCHAT", function(ctx)
-- mutate ctx.chatstr to rewrite outgoing chat (best-effort)
if ctx.chatstr == "ping" then
ctx.chatstr = "pong"
end
end)
Supported event names match IPTSCRAE: SIGNON, ROOMLOAD, ENTER,
LEAVE, SIGNOFF, SELECT, OUTCHAT, INCHAT,
ALARM, PROPCHANGE, LOCK, UNLOCK, MACRO0–MACRO12.
When a target has both IPTSCRAE and Lua sources, they run in authored scripts[] order.
Cyborg scripts still run before room-level scripts, which run before hotspot scripts.
palace surface| API | Tier | Notes |
|---|---|---|
palace.chat.say(text) | classic | Send as local user |
palace.chat.local(text) | classic | Local balloon |
palace.chat.room(text) | classic | Room message |
palace.chat.global(text) | classic | Server-wide (wizard) |
palace.chat.log(text) | classic | Chat log line |
palace.room.goto(id) | classic | Navigate |
palace.room.id() / name() / serverName() | classic | Read-only |
palace.user.name() / id() / rank() | classic | Local user |
palace.spot.state(id[, n]) | classic | Get/set pict state |
palace.spot.lock(id) / unlock(id) | classic | Door lock sim |
palace.sound.play(name) | classic | Room sound |
palace.globals.get/set/delete/keys | classic | Shared with IPTSCRAE GLOBAL |
palace.net.goto(url) | extended | Gated by extended iptscrae pref |
palace.spot.setScript(id, src) | extended | Gated by extended iptscrae pref |
localStorage (palaceIptGlobals).GET/PATCH /api/v1/chat/me/script-globals (revisioned, per-account, cross-server).io, os, package, debug, require, load*, and print are removed.palace capabilities.; IPTSCRAE (scripts[0])
ON SELECT {
"ipt clicked" SAY
}
-- Lua (scripts[1])
palace.on("SELECT", function(ctx)
palace.chat.say("lua clicked")
local n = palace.globals.get("CLICKS") or 0
palace.globals.set("CLICKS", n + 1)
end)