Skip to content

feat(Engine): introduce WorldModelVersion 600, restore sync script support - #2007

Merged
alexwarren merged 6 commits into
mainfrom
feat/worldmodel-v600-sync-undeprecation
Aug 9, 2026
Merged

feat(Engine): introduce WorldModelVersion 600, restore sync script support#2007
alexwarren merged 6 commits into
mainfrom
feat/worldmodel-v600-sync-undeprecation

Conversation

@alexwarren

@alexwarren alexwarren commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Restores v5-parity WorldModel version gating: GetInput()/Ask()/ShowMenu() (the plain expression forms) had their >= v540 guard silently dropped during the async/TCS migration, un-deprecating them for every game regardless of declared version. Restored the guard for v540 <= version < v600.
  • Introduces a new WorldModelVersion.v600 where these synchronous forms — along with request(Wait)/request(Pause) — are deliberately re-enabled, since they're now backed by TaskCompletionSource-based async blocking rather than real thread blocking and are genuinely more usable than their callback replacements for many authors. New/edited games from the Editor now save as v600.
  • Also un-deprecates two more Core.aslx convenience functions in the same spirit: Pause() and WaitForKeyPress() had their bodies swapped for an unconditional error("...is obsolete...") / deleted outright back when the sync-blocking approach was deprecated in favour of callback-based scripts. Since v600 makes the underlying sync-style blocking safe again (TCS-based, not a real thread block), restored both, with their original Script Adder entries, so the Adder shows a proper "Pause for N seconds" / "Wait for key press" control instead of the generic "Raise UI request" panel.
    • Note: this is not a bug fix for already-published games — Core.aslx functions are inlined into a game's .quest file at publish time (see Packager/GameSaver.CanSave), so a game published while Pause()/WaitForKeyPress() were deprecated already carries its own working copy of the old function body and was never broken. The change only affects the authoring experience: games created or edited in the Editor from now on get the restored functions instead of the deprecation stub. See the new "Core Library Semantics" section in CLAUDE.md.
  • Restores the "set"/"foreach" expression-template picker that existed in the pre-WASM Quest 5 editor but was never ported to the WASM/AppShell frontend — only "if" templates had a picker UI. Generalized WasmEditorBridge's if-only plumbing (GetIfExpressionTemplates/GetIfExpressionTemplateData) into type-parameterized GetExpressionTemplates(expressionType)/GetExpressionTemplateData(expr, expressionType), and factored ScriptEditor.svelte's duplicated if/else-if template-picker markup into one shared snippet reused by the generic expression-control renderer. This gives GetInput()/ShowMenu() a real "set variable" picker entry ("player's typed input" / "player's choice from a menu").
  • Along the way, discovered that (function)Ask/(function)ShowMenu (the Script Adder's callback-sugar forms) aren't redundant with the sync expression forms — they render completely differently (inline numbered hyperlinks via CoreFunctions.aslx, vs. a jQuery UI popup dialog for the expression forms). Kept both addable. Filed Modernize the jQuery UI popup used by Ask()/ShowMenu() expression forms #2006 to track modernizing that popup separately.

Test plan

  • dotnet build --configuration Release — clean
  • dotnet test --configuration Release — 343/343 passing, including new V600UndeprecationTests covering version gating for GetInput/Ask/ShowMenu/request(Wait)/request(Pause)/Pause()/WaitForKeyPress() across v530/v540/v550/v580/v600
  • svelte-check / eslint in src/AppShell — clean
  • Manually verified in the running WasmEditor Script Adder: "Wait for key press" and "Pause for a number of milliseconds" show proper controls (not the generic "Raise UI request" panel); "Get input"/"Show a menu" are gone in favor of the "set variable" template picker; "Ask a question"/"Show a menu" callback forms remain addable; inserted scripts produce the expected literal script text in Code view for each case

🤖 Generated with Claude Code

alexwarren and others added 4 commits August 8, 2026 16:24
…on 600

The async TCS migration accidentally dropped the WorldModelVersion >= v540
guard from ExpressionOwner.GetInput()/Ask()/ShowMenu() (the commit message
called this "un-deprecated" in passing), while the sibling
request(Wait)/request(Pause) guards in RequestScript survived untouched -
an inconsistency, not a deliberate decision. This restores parity with the
real Quest 5 engine for v540-v580 games.

Since these sync forms are now backed by TaskCompletionSource-based async
blocking rather than a real blocked thread, they're genuinely more usable
than the callback replacements they were deprecated in favour of. This adds
WorldModelVersion.v600 as the version where all five are deliberately
re-enabled, defaults new/edited games to it, and bumps the 16 per-language
new-game templates and AppShell's catalog version filter to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Pause(seconds) had unconditionally called error("...obsolete as of Quest
5.5") since 2018, independent of any WorldModel version check - even v600
games couldn't use it despite request(Pause,...) itself working again.
Restored the original function body (delegates to request (Pause, ...), so
RequestScript's own version gate applies naturally) and its Script Adder
entry, replacing the ad-hoc raw request(Pause,...) adder entry added
earlier with a proper "Pause for [n] seconds" control.

Generalized the WasmEditorBridge/ScriptEditor "if"-only expression-template
plumbing (GetIfExpressionTemplates/GetIfExpressionTemplateData) into a
type-parameterized GetExpressionTemplates(expressionType)/
GetExpressionTemplateData(expr, expressionType), and threaded the
already-present-but-unread <usetemplates> control attribute through to the
frontend. Factored ScriptEditor.svelte's duplicated if/else-if
template-picker markup into one shared snippet, now also used by the
generic "expression" control renderer - restoring the "set"/"foreach"
template picker that existed in the pre-WASM Quest 5 editor but was never
ported when the frontend was rewritten.

This gives GetInput()/ShowMenu() a real picker (the "set variable" value
field's "player's typed input"/"player's choice from a menu" templates),
so their callback-sugar adder entries ((function)GetInput, get input,
(function)ShowMenu) are hidden again now that there's a discoverable
sync-form alternative - matching how (function)Ask was already hidden in
favour of the "if" picker's "player answers a yes/no question" template.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WaitForKeyPress() was a Core.aslx function (delegating to
request (Wait, "")) from 2011 until it was deleted outright in a 2018
cleanup commit - unlike Pause(), which survived that era but had its body
swapped for an unconditional error. Restored it (same fix shape as the
Pause() restoration in acef8dc) and its Script Adder entry, replacing the
ad-hoc raw request(Wait, "") adder entry with a proper "Wait for key press"
control - no more "Raise UI request" dropdown for this one either.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
These aren't actually superseded by the synchronous Ask()/ShowMenu()
expression forms - they render completely differently. "Ask (...) { }"
and "ShowMenu (...) { }" (the FunctionCallScript-sugar forms) resolve to
CoreFunctions.aslx's own Ask/ShowMenu ASLX functions - the same ones the
parser's disambiguation prompt uses - which print numbered cmdlink
hyperlinks inline in the transcript. The bare expression forms
(ExpressionOwner.Ask/ShowMenu) instead go through PlayerUi.ShowQuestion/
ShowMenu, a jQuery UI popup dialog, in both WebPlayer and WasmPlayer.

I'd incorrectly treated these as sync/async variants of the same feature
and hidden the callback forms once the expression forms got their own
template pickers. They're actually two genuinely different renderings,
so both should stay easily addable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
alexwarren and others added 2 commits August 9, 2026 08:58
…ations

Core library functions are inlined into the game file at publish time,
not referenced live — so a published .quest file always keeps its own
working copy of old library code, unaffected by later deprecations or
changes to the engine's current Core.aslx. Clarifies that "restoring" a
deprecated Core.aslx function is an authoring-experience fix, not a bug
fix for already-published games (per feedback on #2007).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… numbers

Replace "Quest 5.4/5.5 or later" phrasing with explicit WorldModel version
numbers (540, 550, 600) for consistency with the rest of the codebase, and
bound the gated ranges at 580 (the last version below 600) rather than 599.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@alexwarren
alexwarren merged commit 44669ec into main Aug 9, 2026
7 checks passed
@alexwarren
alexwarren deleted the feat/worldmodel-v600-sync-undeprecation branch August 9, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant