Writing GessaScript source to rewrite or remove behavior a patch cannot express (whole-body script text)
replaceScriptFromGessaScript operation replaces the entire script body; the compiler owns IR, node ids, and layout, and returns structured GS_* diagnostics (stable codes + source paths) when the source does not parse or validate.Use this for
Not for
Pairs with: Collectibles pickups scoring and win condition, Event wiring one trigger emits another responder reacts, UI HUD panels widgets and world nameplates
When to use
You want to author or REWRITE a whole script as text - including removing a handler or changing an existing value, which the add-only semantic ops cannot express. One replaceScriptFromGessaScript operation replaces the entire script body; the compiler owns IR, node ids, and layout, and returns structured GS_* diagnostics (stable codes + source paths) when the source does not parse or validate. For small additive tweaks, prefer the typed ops instead.
The call
{
"id_or_key": "coin_pickup",
"request": {
"ifVersion": <current version>,
"intent": "Rewrite coin pickup as whole-body source.",
"operations": [
{ "op": "replaceScriptFromGessaScript", "source": "<the whole script text>" }
]
}
}
via project_apply_script_semantic_patch. The op is in the ai_safe pack.
The grammar (complete for v1)
Top-level, inside script <scriptKey> { ... }:
var <name>: <type> = <literal>;custom event <key>(<params>);event <eventName>(<params>) { <statements> }function <name>(<params>) -> <type> { <statements> }(prefixexportto expose)
Statements:
let <name> = <expression>;set <path> = <expression>;host <Namespace>.<name>(<args>);component <ComponentType>.patch({ ... });if <expression> { ... } else { ... }for <name> from <expr> to <expr> max <number> { ... }while <expression> max <number> { ... }return <expression>;
Expressions:
- JSON literals, arrays, records,
vector3(x, y, z) get(path.to.value)- read a variable/state pathevent.key(),event.payload(path, type, default?)record.get(record, path, type, default?)array.length(v),array.get(v, index, type, default?),array.first(v, type, default?)call <functionName>(...)(or bare<functionName>(...)as a statement)- math/comparison/boolean HELPER CALLS, not operators:
add,sub,mul,div,mod,eq,ne,lt,lte,gt,gte,and,or,not. Writeif gt(deltaSeconds, 0) { ... }, neverif (deltaSeconds > 0).
It is NOT TypeScript: no imports, no arbitrary code, no infix arithmetic or comparison operators, no const, no template strings. Unsupported syntax returns GS_* diagnostics naming the construct and its span.
Compile-verified example
script script.launch {
var score: number = 0;
custom event combat.hit(entityId: string);
event onStart() {
let greeting = "ready";
host Debug.log(greeting);
component TransformComponent.patch({ position: vector3(0, 1, 0) });
}
event onTick(deltaSeconds: number) {
if gt(deltaSeconds, 0) {
host Debug.log("tick");
}
}
export function addScore(by: number) -> number {
return add(by, 1);
}
}
Handler events available: onStart, onTick(deltaSeconds), onTriggerEnter, onTimerFired, onActionResolved, onCustomEvent (custom events also arrive via their declared key; read fields with event.payload(...)).
Gotchas
- The source replaces the WHOLE script: include every handler you want to keep.
- Host namespaces are the Script SDK surface (
Debug,World,Warehouse,Match,Events,UI, ...) - discover exact signatures viaengine_get_sdk_function_signature/engine-reference/script-sdk. set score = add(score, 1);mutates a declaredvar;letbindings are local to the handler.- Component patches go through
component <Type>.patch({...})with canonical component fields (seeengine-reference/component-types).