Engine v5.1.9
July 3, 2026
A patch to Connection.
- ⚠️ If your world suddenly looks different after this update: your custom look script is running again. It was silently crashing on the last few engine versions (since around 5.1.5), so your world was rendering with no look applied at all. The crash is fixed and your authored look applies again — that new appearance is your own look script working. If it feels off (too dark, too bright, too saturated), ask Savi to retune the exposure — don't delete the look.
- If a model ref in your world is malformed (a name the asset server can't parse), the logs now tell you once, clearly, which ref is broken and why — instead of retrying it silently in the background forever.
- Behind-the-scenes: game-server logs now identify which world and engine version they came from, so problems in live games get traced and fixed faster. Nothing changes in your worlds.
- Savi now judges a custom material's cost by the measured GPU number in every preview, calibrated against real games' materials — expensive shaders (especially layered fur and transparency) get priced honestly before they ship instead of being mistaken for free.
- Wrong-shaped primitive keys no longer fail silently: writing
topRadiuswhere the engine wantsradiusTopnow warns with the correct spelling instead of quietly rendering your shape with default dimensions — and Savi's other dead-end errors (misplaced primitive dims, event handlers in one-shot scripts, mis-called primitive helpers) now say what to do instead of just what went wrong, so she fixes them in one step. - Behind-the-scenes: the engine now reports exactly where script runs spend their time, so slow
run_scriptmoments get found and fixed faster. Nothing changes in your worlds. - Worlds with lots of effects now render far more of them on the GPU: idle effects lend their GPU budget to the ones actually firing (and take it back when they fire again), instead of the first few effects permanently hogging it while everything else dropped to the low-quality fallback renderer.
- Fixed rain and similar effects falling through flat terrain on the GPU path — drops now land and die exactly at the ground (splashes, rings, and hearts appear on the surface instead of underground).
- Behind-the-scenes: effect re-fires stay correct and warm around edited effect art and slow texture loads. Nothing changes in your worlds.
- Fixed a ~1s whole-game hitch (sometimes "all meshes reloading") when a trigger effect fired again after sitting idle for minutes — level-ups, kill ceremonies, and other occasional effects now keep their GPU resources warm and re-fire instantly.
- Effects can now burst into multiple children on death:
when(heart.dies, { count: 8 })shatters every dying heart into 8 shards (up to 32 per death). Combine withprobabilityto make only some deaths shatter — a shattering death always bursts the full count. The shards' spread, speed, and look stay yours: author them ininit:/inherit:like any population. - Objects no longer silently vanish after joining: if a generated mesh gets lost on the way to your screen, the engine now notices within seconds and re-sends it automatically — and it leaves an honest log entry instead of nothing, so "the spec says it exists but I can't see it" stops happening (and stops looking like Savi lying about your world).
- Savi now builds isometric and 2.5D sprite buildings from modular floor, wall, and roof pieces on the grid — with doors and windows as wall variants and roofs that hide when you walk inside — instead of painting each building as one flat image.
- Fixed images and models with transparent edges (cutouts, sprites, foliage) showing solid black around them — transparency renders correctly again.
- Material previews now show the real GPU cost of your material — the number that actually decides whether a shader is cheap — instead of only the CPU cost, which stayed misleadingly flat even for very expensive materials. Savi reads it with every preview, labeled as one point on the cost curve (your device, preview resolution), so expensive materials get caught before they ship.
- Worlds with extremely dense decoration carpets no longer risk freezing on the first frame of weaker devices — the engine caps how many instances it builds at once (generously), tells Savi in the logs when it did, and the quality system keeps tuning from there.
- Scattered decorations (grass, flowers, rocks) now stay out of buildings stamped as terrain structures — no more flowers poking through walls or grass carpeting a roof. Want plants inside a ruin on purpose? Set
filter: { avoidStructures: false }on that scatter. - Savi's script edits now reach you while you're in the game: previously in singleplayer, once you'd built anything in-session, every fix Savi saved was silently ignored by your running game — it looked broken until you refreshed the page, while friends joining fresh got the working version. Edits and version restores now apply live, and if an edit ever is withheld, the game says so in the logs instead of staying silent.
- Heavy building no longer stutters the world for players — when Savi and her wisps save in rapid bursts, the room now applies the newest state once instead of hitching on every save.
- Fixed: one malformed field in your game's spec can no longer break ALL building — before, a single badly-shaped list (for example after asking for a full game wipe) silently blocked every change from reaching the game for minutes. Now the engine repairs what it can, keeps applying everything else, and tells Savi exactly which field was wrong so she can fix it in seconds.
- Savi can now truthfully wait for the world to finish loading:
api.getWorldResidency()reports when everything has actually streamed in on a player's machine (and how much is still pending), so start buttons, intros, and loading screens can gate on the real thing instead of timers or framerate guesses. - Behind-the-scenes: game tabs left open for hours no longer keep hammering the server with expired credentials — nothing changes in your worlds.
- Behind-the-scenes: connection-health reporting got more accurate — nothing changes in your worlds.
- One long stall no longer snowballs into a permanent slideshow: when your tab hiccups for over a second (backgrounding it, a big world update landing), the engine catches the renderer up with one full refresh — it used to mistake its own refresh for another stall and refresh forever (climbing memory, a hot GPU, an eventual crash on a world you were just standing in). Now one stall means one refresh, then the game goes back to normal streaming.
- Repeated "nothing changed" updates stopped chewing the frame budget: per-tick scripts that re-apply the same particle or light settings every tick, and re-delivered identical terrain configs, now recognize "same content" and stay quiet — real changes flow exactly as before.
- Fires that never burned out now burn out:
seconds()with no argument now reads the current game clock in seconds instead of silently returning 0, so scripts measuring elapsed time with it (campfire fuel, cooldowns) work the way they always meant to. - Big terrain worlds stopped slowing down while nothing moves — the biggest cause of "server running behind" slowdowns in large worlds is gone, and heavy terrain editing stays smooth.
- Game menus no longer trigger the browser's right-click/copy-paste menus, text-drag selection, or image drag-to-save — automatic now, no script guards needed. Want copyable text somewhere? Add
select-textto that element; a deliberately draggable image just needsdraggable="true". - Real WebAudio for your games: write playlists, crossfades, ducking, and custom mixes as plain WebAudio in your UI script's
onMount— the engine hands you its live audio graph (audio.context,audio.bus("Music"),audio.buffer(ref)), your sounds respect every player's volume settings, and the engine cleans your graph up on every edit automatically. - Music can finally end: track-end transitions, playlists, and menu→gameplay music are now ~15 lines of vanilla WebAudio instead of workarounds around
musicShift.