Skip to main content
Glama

scene_set_client_script

Destructive

Adds or replaces a client-side Lua script in a save copy, enabling interactive UI, menus, and 2D games on the player's screen with variables and lifecycle callbacks.

Instructions

Put a client script (客户端脚本) into a copy of a save, or replace the one of that name: Lua 5.3 that runs on the player's own machine and drives client controls (scene_add_client_ui puts those on the screen and says which script their root carries). This is the way to an interface that moves and answers the mouse and any key, to a menu, to a whole 2D game on the screen; a node graph cannot do these. The game calls the functions OnInit(), OnStart(), OnEnable(), OnDisable(), OnDestroy() when the script defines them, and OnUpdate(dt) every frame once the script has called script:EnableUpdate(true) (not before: seen in play). variables gives the script values it reads with script:GetParam(name): any of the twenty types the editor offers (integer, float, boolean, string, vector3, the ids guid, configId, prefabId and controlId, entity, and a list of each); one marked public can be given another value by each control that carries the script (scene_add_client_ui, script: {name, values}), which is how one script serves several controls. script.object is the control the script is on; control:GetChild(name) finds a control under it. From the level a script reads custom variables (game.GetGlobalCustomVariableValue(Enum.CustomVariableEntityType.PlayerSelf | Level | AvatarSelf, name), and script:RegisterCustomVariableChangedHandler to hear a change), so a graph tells the screen something that lasts by setting a variable; a graph sends the scripts of one player a message of the moment with f.sendSignal('client:NAME', player) (a signal of scene_add_signal; the script hears it with script:RegisterServerSignalHandler("NAME", function(name, params) ... end)); to the level a script sends a signal (game.ServerSignal(name):SendSignal()). Not available in this Lua: coroutine, io, load, loadfile, dofile, package, most of os and debug (refused here). require is there: require("NAME") runs the script whose file is NAME.lua (another script of the save, put there with this tool and carried by no control) once and gives what it returns, so a level can be several files; the name is the file name without .lua, letter for letter. Color(r, g, b, a) takes 0 to 255 (fractions give black), and the fill of an image (a bar that grows, a cooldown ring: SetFillHorizontal, SetFillRadial360, fillAmount) shows only on an image whose mask is on (mask: true in scene_add_client_ui, or control.enableMask = true): the result says so when the script looks like either mistake, as it does for an OnUpdate that was never enabled and a tween that was never played. A script that does not compile is refused here at once, with line and column; names it gets wrong (a function game does not have, an Enum value, a signal or a variable the save lacks) come back as problems, each with the nearest name there is; a fault while it runs comes back in the prints of the playtest with a traceback. read_knowledge {id:"client-lua.zh-CN"} is the page on writing one, with a worked script; the whole API is the official page (search_knowledge "客户端控件API文档"). Replacing a script keeps its id: the controls that carry it need no change, so a round of work on the Lua is this call and a playtest, and that playtest takes about a minute: when the save the last playtest opened is still open and nothing but the text of the scripts differs, playtest_start writes the Lua into the files the editor keeps beside the save (the game runs those) and plays, without importing anything. Writes a new .gil in the workspace; the official save is not touched.

Input Schema

NameRequiredDescriptionDefault
fileNo
nameYes
sourceNo
mapPathNo
variablesNo
outputNameNo
sourceFileNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say destructive=true, readOnly=false; the description adds what actually happens: a new .gil is written, the official save is not touched, replacing keeps the script id so controls need no change, and non-compiling scripts are refused immediately with line/column. It further discloses runtime error reporting via playtest prints and precisely which Lua features are unavailable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded, but the body is a dense, digressive run-on with heavy parentheticals (Color fractions, mask/fill gotchas, require naming rules, enumeration of the twenty types) that belong in the referenced read_knowledge page. Valuable content, but far beyond what earns a place in a tool definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no output schema, the description covers behavior, lifecycle callbacks, validation, error surfacing and the playtest round-trip thoroughly. Only the file/path/output-naming parameters are left unexplained, which is a minor residual gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the parameter burden. It thoroughly explains variables (the twenty types, script:GetParam, the public per-control flag), the name/replacement semantics and the source text, but file, mapPath, outputName and sourceFile are never explained — over half the parameters remain undocumented anywhere.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource: writes a client Lua 5.3 script into a copy of a save or replaces the one with that name. It explicitly distinguishes itself from siblings: client UI is scene_add_client_ui's job, the script is what drives it, and 'a node graph cannot do these' separates it from scene_add_graph.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use rules: use scripts when the interface must move, respond to input, or host menus/2D games — something a graph cannot do. It also names the alternatives for cross-domain communication (graph sets a custom variable, graph sends f.sendSignal) and states the replace-vs-new behavior and the required follow-up playtest.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools