Engine iterations

Every Virtual Matter world runs on one engine iteration, such as iteration076. An iteration is a release branch of the engine: within one iteration a world picks up newer builds as they ship, and those keep the Lua API the same. Moving to a new iteration can change the Lua API, the shaders and the network protocol, so a world only moves when its maker, or the platform with notice, moves it.

See which iteration a world runs

  • The project page shows the editor's iteration next to Engine, and each play server's iteration on its own row. A warning appears when they differ, or when the running engine is still on an older build than the one the world is set to.
  • npx virtualmatter status prints the same, and so does the play_server_status MCP tool.
  • In Lua, AE:GetVersion() returns the running engine's version: 76.x is iteration076.
  • The boot log names it on its first lines: Version (Major.Minor.Revision.Build): 76.0... and Git branch: release/iteration076.

Move a world

  1. On the project page, press Update next to Engine and pick the build. Leave "Also update base prefabs" on unless you changed the SDK's own scripts: it refreshes the stock SDK files to the new iteration and saves your files to GitHub first.
  2. The editor restarts on the new iteration. Check npx virtualmatter errors and the boot log, and play it.
  3. Publish (Update play servers, or npx virtualmatter publish). This moves the play servers to the editor's iteration too: until then they keep running the old one.

To try an iteration without risking the live world, remix the project (Remix on its page), move the copy, and test there. The original and its play servers stay where they are.

When the platform moves worlds to a new iteration, the maker is told before it happens: on the project page, in npx virtualmatter status, and by email.

The desktop app plays worlds of its own iteration only. npx virtualmatter open downloads the client that matches the world, and keeps one client per iteration.

iteration076

Changes since iteration073 (iteration075 lived for a few days in between; the only API difference from 075 is the sky). A world moving from 073 hits the first group straight away, usually inside pcall, where the failure is silent.

Moved or now takes an Asset instead of a path:

  • VoxelData.receiveTransform moved to Object.receiveTransform (on the object, not its voxel component). Writing an unknown field on an engine object throws.
  • Audio:PlaySound and Audio:PlaySoundRelative take a sound Asset, not a path string.
  • Object:AddScript takes a LuaFile Asset, not a file name.
  • Server:PreloadVDRsForPrefab takes a prefab Asset, not a name.
  • UI:AddWindow takes a name or a Lua Asset, not the old save flag.
  • VoxelEdit.imageColor and VoxelEdit.imageNormal accept an Asset or AssetLink; VoxelEdit:GetImageResource is gone.

Removed:

  • The Sky component and Object:AddSkybox. The sky is now set on the client: Client:SetSky, Client:SetSkyLook, Client:SetSunDirection, Client:SetSkyEnabled, Client:ClearSky and the matching getters.
  • Script.file, Object.voxelRenderer, Object.preserveOnLuaReset.
  • Scene:CreateMaterial, Scene.voxelDataResourceTemplateSizeThreshold.
  • Init mode: Server:EnterInitMode, Server:EnterLiveMode, Server:IsInitMode, Client:IsInitMode, and Client:ConnectToServer.
  • Client.platform and Client.sysInfo.
  • UI:SaveUI, UI.showUI, Widget.save, Window.noHide and the Window asset list (Window:AddAsset, Window:GetAsset, Window:GetAssets and the rest).
  • The Mat3x4 type.
  • The debug triggers TriggerCrash, TriggerCriticalError, TriggerException.

Changed behaviour:

  • Scene:CloneObject(obj, name, setSaveToFalse): the third argument used to be keepPrefabLink.
  • Server:SaveToPlayScene(enterSession) takes an argument.
  • Scene:GetObjectByName, Scene:GetObjectById, Scene:GetActiveCamera and UI:CloneWidget can return nil; Scene:MoveObject and its siblings return whether the move happened.
  • Brush and voxel-edit callbacks receive more: OnFinished gets the result info, VoxelEdit.onError gets the reason and the op count, VoxelEdit.onFinished gets a status.
  • UI:LoadUI() takes no path; UI:AddWidget lost its save argument.

New: shader errors (Client:GetShaderErrors, Client:RequestReloadShaders, Client:SetVPuzzleShaderDefines), Lua GC mode (AE:SetLuaGCMode), video and vsync modes, Vox:flushEdits and Vox:pendingEdits, OpBase:Batch, script metadata (AE:GetScriptMetadata), Client:IsInitialAssetSyncDone, and the util.whenAssetsReady and util.whenAssetsSynced helpers for assets a client is still downloading.

Shaders: a world's own copies under Shaders/ override the engine's by asset id. At boot the engine refreshes copies you never edited and keeps edited ones, logging one line: Montage shader overrides ... maker-edited kept. An edited copy keeps working only if it still matches the engine's inputs, so diff your edited shaders against the new iteration's stock ones after a move.

Network: a 076 client speaks a newer scene and voxel stream protocol than 073, so a desktop app of one iteration cannot join a world of the other.