Changelog
New updates and improvements
Protocol 46 - August 3rd, 2026 (Currently Nightly)
Protocol 46 adds runtime tilemap authoring, engine-managed live events, device emulation, substantially richer UIDoc styling, and new CSL and C# APIs. It also improves keybinds, inventory security, cloud builds, automation, asset loading, voice, and developer-facing diagnostics.
Compatibility and Migration
Player Spine tracks
The engine-owned player skin animation moved from track 10000 to track 10
Tracks 0, 1, 2, and 10 are reserved; custom player animation layers should use tracks 3 through 9
C# inventory handles
Item_Definition.IdandItem_Instance.Definitionare now read-only and cachedRemove code that assigns either property
C# player-list rendering
Player.GetSpineInstanceForPlayerList()was removedThe built-in player list now renders profile avatars
UIDoc binding expressions
Treat
classanddata-keyvalues as static;{{...}}interpolation is supported only in text and imagesrcdata-for-key,data-scroll-zoom, anddata-style-*take direct binding expressions without mustachesUse
data-style-color,data-style-opacity, image effects, or explicit list contents for dynamic presentationdata-ifis limited to top-level bool bindings, with optional!inversion
Runtime Tilemap API
Added full runtime tilemap access in both CSL and C#
Query and resize tilemap dimensions
Add, remove, configure, and clear ground or wall layers
Configure automatic or manual layer sorting, tile size, tint, masks, outlines, wall tops, collision, inset, and offset
Add, replace, weight, and remove a layer's textures
Query, set, and clear individual tiles
Convert between tile, local, and world coordinates
CSL additions include
Tile_Layer_Kind,Tile_Layer_Mode, and the newTilemap_ComponentmethodsCSL tilemap mutations are predicted scene state and participate in rollback and reconciliation
C# additions include
TilemapLayerKind,TilemapLayerMode, and matchingTilemap_Componentproperties and methodsC# tilemap mutations affect the current simulation only; multiplayer games must invoke equivalent changes on every peer through their existing RPC flow
Layer indices shift when a layer is removed, invalid indices fail loudly, wall height must be at least 2, and each layer supports at most 256 textures
Tilemap layer tinting now affects rendered tiles
Overlapping expanded wall rows now produce continuous wall masks instead of visible internal seams
UIDoc UI and Styling
Added project fonts through CSS
@font-faceTTF and OTF
Fontassets can provide multiple weights and styles for one familyUIDoc selects the nearest face and can synthesize a missing bold or slanted face
Fonts load asynchronously and automatically invalidate text layout when ready
Expanded text styling with
font-family, realfont-weight,font-style,letter-spacing, improved line-height behavior, and up to eight text shadowsAdded
data-text-reservefor stable intrinsic layout when frequently changing text has a known widest sampleExpanded backgrounds and effects
Linear, radial, and conic gradients with up to eight stops and Oklab or sRGB interpolation
Up to eight box shadows, including inset shadows
filter: blur(...), alpha-awaredrop-shadow(...), andbackdrop-filter: blur(...)image-tint,image-grayscale, directional and radial image fills, bound fill amounts, and improvedobject-fitAdded paint-only
data-style-coloranddata-style-image-fill-amountbindings that avoid structural layout invalidation
Expanded layout support
calc(...)addition and subtraction for supported lengthsposition: fixed, richer inset/size units, relative translation percentages, flex alignment and wrapping improvements, and stricter property-specific value validation
Tailwind-style lowering now covers more layout, text, color, shadow, transform, and image-effect utilities
Responsive and interaction variants, bracket values, and
@applyare supported when they lower to the UIDoc subset
Added the hand-drawn Game UI kit
Add
@import "game-ui-kit";to use the built-in modal, button, tab, progress-bar, banner, porthole, item-slot, checkbox, and toggle styles and art
Added more reliable keyed-list identities and documented exact runtime test selectors for repeated controls
Scroll layout, zooming, nested state restoration, font layout, clipping, and transformed hit testing are more reliable
UIDoc draws faster, and paint-only binding changes avoid unnecessary relayout
Unsupported declarations, values, selectors, malformed HTML, and unsupported media queries now produce clearer asset diagnostics
New CSL APIs and Behavior
Live events
Added
Live_Events.is_active,Live_Events.is_local_player_presenting,Live_Events.presenter_count, andLive_Events.get_presenterLive_Event_Presenterexposes the presenter's slot, display name, speaking state, and client-local ghost entityPresenter ghosts are intentionally excluded from normal entity and component iteration
Haptics
Added
Haptics.play_impactwith.LIGHT,.MEDIUM, and.HEAVYimpact types
Ads
Added
Ads.request_interstitial() -> boolRewarded and interstitial ads can now be hosted by the web client as well as native clients
World_Progress_Bar.drawnow safely does nothing on the server instead of entering client UI codeAbility buttons respect
draw_but_dont_use_keybind, honor remapped bindings, and no longer render the wordUnboundCSL chat-command arguments typed as
Playernow receive the player named in the argument instead of the command sender
C# API Changes
Added
Camera.IsVisibleoverloads for a world point, world rect,Sprite_Renderer, andSpine_AnimatorClients test the local camera; servers return true when any player camera sees the target
The optional
apronexpands the tested bounds
Added
UI.TextSettings.LetterSpacingInventory and items
Added
Inventory.GetItemQuantityById,Inventory.HasItemById, andInventory.GetFirstItemByIdAdded allocation-conscious
Item_Instance.GetMetadatas(string[] keys, ref string[] values)Added
Inventory.RequireOwnership,OwnerUserIds,AddOwnerUserId,RemoveOwnerUserId, andClearOwnerUserIdsBuilt-in player inventories automatically require their player's user ID
Custom inventories remain shared by default; adding an owner automatically enables ownership enforcement
Unauthorized client merge, swap, and use commands are rejected by the server
Save callbacks
Save.GetOfflinePlayernow invokes its callback exactly once for every completed requestUnknown players and failed requests supply empty data, and failures are logged
Ordered save-data reads follow the same callback-on-failure contract with an empty result
Live events
Added
LiveEvents.IsActive,IsLocalPlayerPresenting,PresenterCount,GetPresenter, andTryGetPresenterBySlotLiveEventPresenterexposes slot, display name, speaking state, and a client-local ghost entityLive-event ghosts remain directly usable but are hidden from normal scene and component enumeration
CSL Compiler, JSON, and Project Validation
Constant fixed-size arrays now report the correct
.countCSL compilation is faster and uses less temporary memory, and inclusive and reverse loops execute with lower VM overhead
The compiler now reports
No CSL script files foundfor an empty scripts tree instead of accepting an unusable projectJSON handling is safer and more standards-compliant
Strings and object keys are escaped correctly when serializing
Escaped object keys are decoded when parsing
Mixed-type arrays no longer enter the numeric-array serializer and crash
Reading a JSON array into a fixed-size array stops at the shorter length instead of reading or writing out of bounds
Added compiler semantic-analysis output for editor and language-server integrations on Windows and macOS
The output includes compiler diagnostics, declarations, types, scopes, and identifier occurrences
Live Events, Voice, and Player UI
Added engine-managed live events with streamed presenter voice, transforms, skins, and Spine animation state
Audience clients receive synchronized, client-local presenter ghosts without adding those ghosts to replicated gameplay state
Live-event playback includes buffering, recovery, presenter status, and failure reporting for unstable connections
Voice capture and playback quality and voice isolation were improved
The in-game player list now uses current profile avatars and an unknown-avatar fallback
Chat filtering recognizes word boundaries for short blocked terms, reducing false positives while expanding coverage
Editor and Developer Workflow
Added phone and tablet emulation to the editor play toolbar
Profiles cover small and large phones, a foldable, and tablets
Emulation uses native landscape resolution, safe areas, cutouts, rounded-screen clipping, phone/tablet device classification, and remapped mouse input
Fitfills the client window;Physicalestimates real-world display size from monitor density
UIDoc authoring improvements
The visual editor now uses the production runtime more consistently for selection, layout, style editing, generated wrappers, saving, and diagnostics
Added
uidoc_create_assetand liveuidoc_runtime_inspectautomation toolsRenamed the generated interface inspection tool from
uidoc_contracttouidoc_interface
Local asset search now has relevance ranking, aliases, type intent, project/engine/all scopes, pagination, file-change-aware hashes, and world-size metadata
Project agent setup now writes
opencode.jsonin addition to Claude, Cursor, Codex, and generic MCP discovery filesCloud builds now package scene source and perform authoritative scene packing from that source
Scene-export failures and timeouts surface the relevant server log instead of hanging or silently producing stale output
Cloud-build draft projects can still be packaged when the local scripts currently do not compile, so server-side diagnostics remain available
Editor filesystem failures now produce clearer errors on Windows and macOS
Editor numeric fields preserve float precision, Windows clipboard paste handles UTF-8 safely, and linked prefab descendants are hidden from the editable hierarchy
New-project creation rejects the entire games directory and folders that already contain another All Out project
Exceptionally long entity filenames no longer crash project loading
Automation, Testing, and Diagnostics
Game startup now launches a consistent compiled snapshot
Source changes during startup, compile failures, launch failures, automation bind failures, process exits, and readiness timeouts return distinct structured errors
test_actionaccepts common argument aliases, normalizes component paths, and returns clearer invalid-argument, timeout, unavailable-client, ambiguous-target, and not-found errorsNon-idempotent test actions such as interactions and inventory operations no longer fail intermittently when transient input is dropped
Test clients and dummy peers are cleaned up when a run ends, including partial or failed launches
Client and server crashes now retain structured process attribution, exit status, CSL and native top frames, artifact paths, and log paths
Fatal runtime errors shown in the editor and to players include more useful error categories and context
Automation screenshots, UI inspection, input, test result discovery, and macOS child-process handling are more reliable
Runtime, Platform, and Performance
Keybind remapping is now kept per player, validated, saved atomically, restored by action name, and fully reconciled with the server
Duplicate assignments are removed consistently and corrupt keybind files are ignored safely
Engine-owned UI and fullscreen controls now honor the local player's remapped bindings
Desktop clients can use the static on-screen joystick with a mouse
Asset loading and game transitions
Bundled preview textures no longer stall unrelated asset loading during startup
Android joins do less upfront audio work and avoid asset-loading stalls
Failed web downloads and decodes, draw contexts, and game-leave resources release more memory reliably
Web clients have more accurate memory and frame-time reporting, including clean handling of standby and resume gaps
Web hosts can set an engine-owned UI scale multiplier without changing game-authored UI scale
Idle scenes skip unnecessary lighting and tonemapping passes
Android window, input queue, WebView, fatal-signal reporting, and game-transition lifecycle handling are more robust
Linux asset processing accepts projects up to 2 GiB and server-side Redis reconnect handling is more resilient
UIDoc rendering, CSL analysis, runtime tilemap updates, and network prediction recovery are faster and more stable
Protocol 45 - July 15th, 2026
Protocol 45 adds UIDoc and scene-owned paint canvases, expands CSL gameplay and rendering APIs, improves live development tooling, and delivers substantial multiplayer, pathfinding, collision, scripting, and runtime improvements.
Compatibility and Migration
Client version
The client version is now 1.45.1
Android version code is now 492
Protocol and game data
Protocol 45 clients and servers cannot communicate with protocol 44 builds
Deploy matching client and server builds together
The game-state memory version increased from 58 to 75
Rebuild and republish games and packed scene data after upgrading
Replicated C# components
Replicated component IDs now support values above 255
The limit remains 255 serialized components per entity
Entity payloads over 65,535 bytes now fail explicitly instead of being truncated
CSL template strings
Backtick strings now support
{expression}interpolationLiteral braces in existing raw backtick strings must be written as
{{and}}A lone closing brace is now a compile error
Interpolated templates require
import "core:basic"and are not compile-time constantsBacktick strings without interpolation remain raw constants
Numeric literals
Literals larger than 64 bits now fail compilation
Values outside an explicit integer suffix or enum range now fail instead of silently wrapping or truncating
Fractional literals can no longer use an integer suffix
Source builds
Native Windows, Linux, and iOS builds now require Rust/Cargo for UIDoc layout support
iOS builds also require the
aarch64-apple-iosRust target
UIDoc Screen-Space UI
Added
.uidocdirectory assets for authoring responsive screen-space UIEach asset contains an
index.htmland can include anindex.cssSupported content includes text, images, buttons, text inputs, conditions, and repeated lists
CSL can bind text, bools, floats, image paths, lists, inputs, and events
Layout and styling
Supports responsive flex and block layouts, safe areas, interaction states, and client-specific viewport sizing
Supports vertical and horizontal scrolling, nested scroll-state restoration, and bound
data-scroll-zoomTailwind-style utilities, responsive and pseudo-state variants, arbitrary values, and
@applycan be lowered during asset baking when enabled by the stylesheetLayout accounts for each client's viewport, locale, safe area, and replicated UI scale
New CSL surface
Added
UIDoc_Asset,UIDoc_Event,UI.uidoc, binding and list helpers, event polling, and text-input value access
UIDoc uses a deliberately constrained HTML/CSS subset
It is deterministic engine UI, not an embedded browser
JavaScript, browser APIs, forms, external URLs, CSS grid, variables, transitions, and keyframes are not supported
Unsupported output fails asset validation instead of silently degrading
Existing immediate-mode UI and UIK projects remain supported
Guidance for new screen-space UI now favors UIDoc
Visual UIDoc Editor
Selecting a UIDoc replaces the entity-centric scene, hierarchy, and inspector with UIDoc authoring tools
The scene view uses the production UIDoc parser, layout, and renderer for an exact runtime-backed preview
Elements can be selected, moved, resized, inserted, duplicated, deleted, reordered, and reparented
Design and Styles inspectors edit common HTML and CSS properties, including colors
The Interface inspector infers fields, inputs, lists, and actions directly from UIDoc markup
Saving generates a typed CSL wrapper under
scripts/generated/uidocUIDoc edits have document-aware save, undo/redo, external-change detection, and compiler diagnostics
New CSL Gameplay and Rendering APIs
Scene-owned dynamic canvases
Dynamic_Canvascan create, destroy, fill, stamp, set, and sample pixel canvasesSprite_Renderercan display a canvasSpine attachments can override their texture with a canvas and optionally use skeleton-space UVs
Animated Spine hit positions can be converted back to stable canvas coordinates
Canvas state participates in sync, prediction, rollback, and reconciliation
Current limits are 512×512 pixels, 16 canvases per scene, and 4 MiB of canvas pixels per scene
Scene color sampling
Player.request_scene_color_sampleandPlayer.try_get_scene_color_samplesupport eyedropper-style mechanicsSample results are client-authored visual input and must not be trusted as authoritative game state
Dynamic canvas methods are currently available from CSL
C# receives the generated
Dynamic_Canvashandle but not the full canvas API
Interactables
Added subtitle getters, setters, and editable subtitle color
Emotes and effects
Added equipped-emote checks, counted block reasons, trigger and cancellation APIs
Added
Effect_Base.get_duration_remaining
Inventory
Added
Inventory.has_item_idAdded
Inventory_Draw_Options.on_before_drawandon_after_draw
Rendering and interpolation
Added
get_fixed_delta_time,Camera.size_last_frame,world_to_screen_interpolation_offset, andUI.quad_interpolatedAdded
UI.player_avatarfor drawing a static player avatarAdded interpolated aiming helpers and an Entity overload for tutorial arrows
Spine and player materials
Added helpers for using a player's material and destroying an entity after its current animation
Added canvas painting options and skeleton-space attachment overrides
Added
color_replace_get_colorfor reading avatar palette colors
Sound documentation now covers
SFX.fade_out_and_stopand controlling returned sound IDs from server-side CSL
Player and Runtime Changes
CSL games now support the standard emote wheel
Equipped thumbnails, synchronized effects and sounds, looping, gameplay block reasons, and movement cancellation are supported
Fixed several emote state and headless-server crashes
Interaction prompts can display a localized, independently colored subtitle
Instant interactables with no hold duration now trigger correctly from a mobile tap
Aiming indicators, target reticles, tutorial arrows, and dropped-item UI now interpolate more smoothly
Multiplayer
Ongoing state and drop-in traffic is substantially smaller
Recovery from missing updates and long hitches is more reliable
Prediction now continues catching up instead of accumulating a permanent resimulation backlog
Web clients use the correct simulation budget on high-refresh-rate displays
Rollback no longer repeats UI side effects such as click sounds
Scroll views
New views remain at the start until deliberately scrolled
Horizontal-only views accept horizontal wheel input
Transient zero-sized layouts no longer corrupt scroll offsets
Recreated UIDoc elements retain their scroll position
UI scale now participates correctly in prediction and replay, reducing layout and hit-target mismatches after changing scale
Android hardware volume buttons continue controlling system volume while in-game
Global leaderboard names containing formatting characters such as
%now display literallyOffscreen leaderboards are also culled
Dropped items can be culled visually without freezing their gameplay movement
Reparenting an entity beneath a disabled entity immediately applies the correct disabled state
Rewarded-ad and CSL purchase grants more reliably wait for client replication before processing
Restored the built-in CSL green-button asset reference
All Collider-derived components on an entity now participate in CSL physics
Projects using multiple colliders may observe newly correct contacts
CSL Compiler and Project Workflow
Compiler diagnostics
Capturing procedure literals remain unsupported and now produce an explicit error
returnoutside a procedure now reports an error instead of crashingVery long boolean chains and large switches no longer overflow the compiler's native stack
Script-heavy workloads benefit from optimizer, bytecode-inlining, and value-formatting improvements
Core library vendoring
Opening a CSL project copies the engine core library into
scripts/.ao_coreimport "core:*"resolves against that project copyThe copy is included when publishing and is not rewritten when unchanged
Treat
.ao_coreas generated content and do not edit it manually
C# API Changes
Vector2,Vector3, andVector4now explicitly implement component-wiseEqualsandGetHashCodeTheir behavior in dictionaries and sets is now consistent
Added
Camera.WorldToScreenInterpolationOffsetBuilt-in aiming indicators and target reticles now use frame interpolation
Aiming helpers gained optional interpolation-offset parameters
Normal calls remain source-compatible
Reflection, delegates, or method groups relying on the previous exact arity may need updating
Editor, Automation, and Testing
Editor
compilecan hot-reload CSL into a running editor-launched game and reconnect clients to the updated stateScene edits still require a stop and restart
Restored and hardened live game tools for starting and stopping games, screenshots, UI-tree inspection, clicking and holding, keyboard input, and text input
Added
test_actionfor running individual Test.Runner actions in a live gameSupported actions include waiting, movement, navmesh pathfinding, interaction, abilities, assertions, inventory and save operations, and variable or component inspection
Added
assets_validate,uidoc_interface, anduidoc_diagnosticsDirect
client_waitandclient_healthintegrations should migrate totest_action(wait)and the newer automation health classificationTest.pathfind_tonow follows the navmeshAdded
Test.assert_balance_rangefor timing-tolerant economy assertionsInjected test movement is no longer discarded by mobile joystick recomputation
Screenshot requests time out cleanly instead of occasionally hanging
Test execution fails fast when a game launch is already in progress
Automation and compile failures now provide clearer diagnostics and stack traces
Performance, Hosting, and Stability
Navmesh pathfinding and rebuilds are substantially faster, especially for repeated paths and unreachable targets
Collision-heavy CSL games now avoid testing every collider against every other collider
Web builds use a smaller initial memory reservation and clean up failed asset decode and download paths more reliably
Linux-hosted servers account for container memory limits while loading assets, reducing startup and prewarming out-of-memory failures
Asset prewarming and UIDoc replication have lower peak memory use
Protocol 44 - June 13th, 2026
This protocol update focuses on CSL compiler performance and memory use, better callback resolution, smoother sync/interpolation behavior, and several runtime fixes for strings, assets, and world-space UI.
Sync and Interpolation
Network sync now uses the protocol 44 32hz variable sim/sync cadence
Game simulation now advances at a lower fixed cadence than rendering
Rendering can still look smooth by drawing with an interpolation offset from the previous rendered position to the current simulated position
Entity-attached rendering
World-space rendering calls inside supported component callbacks are automatically attached to that component's entity and interpolated
In those callbacks,
UI.push_world_draw_context()is enough for labels, prompts, health bars, and similar entity-following visuals to move smoothly between sim ticksOutside component callbacks, use
UI.begin_world_space_ui(entity)anddefer UI.end_world_space_ui()when drawing world-space UI or other immediate-mode visuals that should follow an entityUI.begin_world_space_ui(entity)pushes the world draw context and uses the entity's built-in interpolation dataUse
entity.mark_teleported()when an entity moves discontinuously and you explicitly do not want the next render to interpolate across that jumpLarge teleports are also detected automatically: if an entity moves more than 3 world units since the previous frame, interpolation is skipped for that frame
Manual interpolation offsets
Use
UI.push_interpolation_offset(offset)before any custom rendering that needs interpolationAlways pair it with
UI.pop_interpolation_offset(), usually throughdefer UI.pop_interpolation_offset()The offset should represent the movement from the last rendered position to the current position
Component entity anchoring uses the same interpolation-offset stack, so nested manual offsets follow normal push/pop order
Custom non-entity positions
Use
Position_Interpolation_Helperin your own class or struct when you own a position that is not covered by an entity's built-in interpolationStore one helper per moving thing, call
.update(current_position), and pass the returned offset toUI.push_interpolation_offset
Animated fill amounts
Use
Float_Interpolation_HelperwithUI.quad(..., params={fill=UI.quad_fill(helper.update(progress), .RIGHT)})for smoothly animated fills such as progress barsUse
UI.quad_fill(progress, .RIGHT)when the fill amount does not need interpolation.RIGHTfills left to right as the amount moves from0to1;.NONEleaves the quad unfilled and is the zero-initialized valueQuad_Paramsalso acceptsnine_slicedata for the same draw call
Particle :: class {
position: v2;
velocity: v2;
interp: Position_Interpolation_Helper;
update :: method(dt: float) {
position += velocity * dt;
UI.push_interpolation_offset(interp.update(position));
defer UI.pop_interpolation_offset();
// Draw the particle here.
}
}Interpolation anchor context
Supported component lifecycle callbacks now automatically push that component entity's interpolation offset while the callback runs
This applies to
ao_start,ao_update,ao_late_update,ao_end,ao_on_interactable_used, andao_on_holding_interactableao_can_use_ability,ao_can_use_interactable, andao_on_state_syncare intentionally not anchored; keep them small, fast, and pureThis applies to sim-owned world-space draw contexts only; present/combine rendering does not read component interpolation anchor state
C# component update loops also scope this with push/pop per component, so exceptions cannot leak a stale interpolation anchor
CSL Language and Compiler Changes
New procedure-resolution directives
#optional_procedure_of_call(call)was addedIt works like
#procedure_of_call(call), but unresolved optional calls return an empty procedure value instead of producing a hard error#procedure_types_are_leniently_compatible(src_type, dst_type)was added as a compile-time bool check for callback/interface compatibility
Interface and callback matching
Interface procedure requirements now allow compatible derived-class parameter types where the call is safe
Overloaded interface method implementations now resolve to the concrete implementation on the actual receiver type
Procedure type-vs-overload mistakes now produce clearer compile errors
Polymorphic assignability constraints
Polymorphic type parameters can now constrain assignability with syntax like
$T/BaseThis supports APIs that accept a base type while preserving the caller's concrete type
Range loop bounds
Integer widening is now allowed for range bounds when the widening conversion is safe
Invalid non-widening range bounds now report a compile error instead of crashing
New GC helper
#unrootify_object(value)was addedIt removes a root from an existing object without freeing the object immediately
Diagnostics and performance
Misplaced
givestatements now produce a targeted errorSource locations were compacted internally, preserving file/line reporting while reducing compiler memory
The compiler received major memory and throughput optimizations for large scripts
Core API and Runtime Changes
Interactable.set_listenerNow accepts a concrete component listener type instead of collapsing the listener to
ComponentCallback lookup now uses CSL call resolution through
#optional_procedure_of_callInherited and overload-nested
can_use,on_interact, andon_holdingcallbacks now resolve to the right concrete listener procedureInteractablenow also declares thecan_useinterface callback
World-space UI
UI.begin_world_space_ui(entity)now pushes world draw context in addition to interpolation offsetPassing
nullis supported and uses a zero interpolation offsetUI.end_world_space_ui()now pops both interpolation and draw context
Global leaderboard package
core:global_leaderboardadds a reusableGlobal_Leaderboard : Componentfor world-space ranked scoreboards backed by ordered savesImport it with
import "core:global_leaderboard"and addGlobal_Leaderboardto a scene entitySet
leaderboard_idon the component, optionally setoptional_titleOn the server, call
Global_Leaderboard.increment_score(player, leaderboard_id, amount)to add to a player's score
String getters
Player.get_username(),Player.get_user_id(),Player.get_name_override(), andEntity.get_name()now cache rooted CSL stringsRepeated calls avoid unnecessary string allocation while still updating when the native value changes
Asset handles
Spine skeleton, attachment texture, and cosmetic APIs now resolve CSL asset handles through the scene asset lookup table
This fixes cases where CSL-visible assets are represented by script stubs instead of direct native VM objects
Formatting
tprint/formatted string output now recognizesFormat_IntandFormat_Floatby link idPadded integer and float formatting now works in cases where the format helper type is not pointer-identical to the cached runtime type
Protocol 43 - May 27th, 2026
This protocol update tightens CSL validation, removes several legacy APIs, changes UIK interaction handling, and updates a few core library behaviors.
Breaking CSL Changes
Struct and class parameters
Explicit
$on struct or class parameters is now illegalstruct($T: typeid)→struct(T: typeid)This affects patterns like
List,Hashtable, andComponent_IteratorPolymorphic procedures like
proc($T: typeid, ...)still work
Stray
$identifierusageStandalone
$identifieris now rejected instead of being treated likeidentifier
Reserved keywords
bit_fieldis now a reserved keywordAny identifier named
bit_fieldwill now fail
String and char escapes
Unknown escape sequences now produce a compile error
They no longer slip through or panic at runtime
Invalid code now fails earlier
Calling non-procedure or non-polymorphic types now errors
Comparing incompatible types now errors
Core API Breaks
core:ao/generatedsrc/csl/core/ao/generated.cslwas removedIts contents were folded into
core:aoDirect imports of
core:ao/generatednow break
game_support.cslsrc/csl/game_support.cslwas deletedCode relying on its empty
Player :: class : Player_Basemust now definePlayerdirectly
Generated
selffieldsGenerated
selffields were removed from wrappers likeEntity,Component,State_Machine*,Item_Definition_Base,Item_Instance_Base, andInventory_Base
Item definition getters
Item_Definition_Base.get_name()andItem_Definition_Base.get_id()were removed from the base APIItem_Definitionstill keeps soft-deprecated gettersCode typed as
Item_Definition_Basemust use.nameand.id
Spine instance hierarchy
Spine_Instance_Basewas removedSpine_Instancenow inheritsSpine_Instance_FieldsdirectlyExplicit references or casts to
Spine_Instance_Basenow break
Skeleton APIs
Spine_Animator.set_skeleton()andSpine_Instance.set_skeleton()now returnu64get_skeleton()now takes an optionalid: u64 = 0
Collider hierarchy
Circle_Collider,Box_Collider,Polygon_Collider, andEdge_Collidernow inherit fromColliderThey no longer inherit directly from
ComponentNormal component usage should still work
Reflection and direct parent checks can break
UIK Breaks
Interact handles were removed
UIK.Interact_Handlewas removedInteractive APIs now return
Interact_ResultdirectlyThis affects
panel_begin_interactive,toggle,card_end, bothtaboverloads,button,icon_button,icon_button_label, andtitle_area
Resolve flow changed
UIK.resolve(handle)was removedUIK.clicked,UIK.hovering,UIK.pressed, and related helpers now takeInteract_ResultYou can also read
.clicked,.hovering, and related fields directly
Deferred handle patterns
Old patterns that store handles and resolve them after
UIK.end()should be rewritten to the new simpler pattern
Yellow enum names
..._YELLOW1was renamed to..._YELLOW..._YELLOW2was renamed to..._ORANGE
Library and behavior changes
Math helpers
Generic
lerp,clamp,min, andmaxwere replaced with concrete overloadslerpnow supportsv2,v3,v4, andfloatclamp,min, andmaxnow supportintandfloatCalls on other types can now break
UIK layout helpers
rect_sidebar_left,rect_sidebar_right,rect_topbar,rect_hotbar, andrect_dialogchanged layout behaviorTheir signatures stay the same
Existing layouts may shift
Protocol 42 - April 16th, 2026
This protocol update brings major CSL breaking changes, stricter runtime enforcement, an overhauled SFX system, and several new engine APIs.
Breaking Changes
Type system
b8,b16,b32, andb64were removed. Onlyboolremains.Scripts using those type names will fail to compile.
Entity hierarchy fields were replaced with methods
entity.parent→entity.get_parent()entity.first_child/entity.last_child→entity.get_first_child()/entity.get_last_child()entity.next_sibling/entity.prev_sibling→entity.get_next_sibling()/entity.get_prev_sibling()entity.first_component/entity.last_component→entity.get_first_component()/entity.get_last_component()
Component navigation fields were replaced with methods
component.prev_component_on_entity→component.get_prev_component_on_entity()component.next_component_on_entity→component.get_next_component_on_entity()
Component state fields were replaced with accessors
component.enabled→component.get_enabled()/component.set_enabled()
Component iterator updates
next(ref Component_Iterator)was removed. Use.next()instead.
Effects system was restructured
entity.active_effect→entity.get_active_effect()and now safely returnsnullwhen no effects existentity.first_effect→entity.get_first_effect()entity.last_effect→entity.get_last_effect()
List construction changed
List.appendis now hard-deprecated for list construction. Use[..]Tinstead.
Math functions
atan2changed parameter order fromatan2(x, y)toatan2(y, x)to match standard C behaviorGeneric
min(a, b)andmax(a, b)procedures were removed frombasic.cslnormalize(v)no longer includes a zero-length safety check and may now produceNaNorinfsin,cos,atan2,pow, andsqrtchanged from foreign calls to intrinsic VM opcodesSerialized bytecode is incompatible with previous builds
New
f64overloads were added forsin,cos,atan2,pow, andsqrt
Removed APIs
The
Gifasset class was removed entirely, including theGiftype,UI.Gif()widget,UIGifcomponent, and related internal calls in C# and CSLSprite_Renderer.WaitForLoadwas removed and now only exists as an obsolete no-op in C#
Runtime enforcement
UI functions now panic outside player update context on the client
This affects
ui_button,ui_begin_button,ui_end_button,ui_push_scroll_view,ui_pop_scroll_view,ui_compute_scroll_bar_rect,ui_drag_drop_source,ui_drag_drop_target,ui_blocker,ui_begin_modal, andui_end_modalThese must be called from
core_player_updateorcore_player_late_update
SFX system overhaul
SFX playback is now authoritative on the server
The server tracks active sounds persistently, including ID, duration, elapsed time, and fade-out state
Clients now mirror the server's active sound list
sfx_stopnow works correctly across the network
CSL Language Changes
Method call syntax now uses
.instead of->b->set_x(20);→b.set_x(20);
Fixed-size array literals now support values directly
[4]int{1, 2, 3, 4}is now valid
Casting now supports prefix syntax in addition to suffix casting
Half-closed ranges now support
^Hashtables are now supported
Class members now support default values, including reassignment in derived classes
Implicit integer widening is now allowed for safe widening conversions
Example:
s32→s64
switchcases now support multiple values and inclusive ranges
switch level {
case 1, 2, 3: tier = .BEGINNER;
case 4..10: tier = .INTERMEDIATE;
case 11..20, 25, 30..50: tier = .ADVANCED;
default: tier = .UNKNOWN;
}Migration tooling note: do not blindly replace every -> with .. Return type definitions still use ->, so a global search-and-replace will corrupt valid code.
Deprecations
case:with no expression in aswitchis deprecated. Usedefault:instead.Duplicate
defaultcases now produce a compile error.get_real_time()is now soft-deprecated. Userng_root_seed()for RNG seeding.rng_seed_time()is now soft-deprecated and returnsrng_root_seed()internally.
New APIs
DatetimeIncludes
year,month,day,hour,minute, andsecondass64
get_nanoseconds_since_epoch() -> s64Returns UTC nanoseconds
get_utc_datetime() -> Datetimerng_root_seed() -> u64Returns the deterministic game-instance RNG seed
SFX.fade_out_and_stop(id, fade_time)Player_Base.get_name_override() -> stringPlayer_Base.set_name_override(name)core_globals.server_on_chat_message_receivedCallback signature:
proc(player: Player, message: string)
Texture_Asset.get_uvs() -> v2, v2Returns low and high UV coordinates
Time.nanoseconds_since_epoch() -> u64SFX_Desc.local_only: boolHard-deprecated. Use
SFX_Desc.specific_to_player.
SFX_Desc.specific_to_player: PlayerTracks the sound on the server but only triggers playback on the target player's client
Sprite_Renderer.mask_in_shadow: boolSpine_Animator.mask_in_shadow: boolSpine animation APIs
Spine_Animator.set_on_event()Spine_Animator.set_on_animation_start()Spine_Animator.set_on_animation_end()Spine_Event_Data
Spine animator access
All Spine methods are now available directly on
Spine_Animator.instanceis no longer required
Entity.set_name()Entity.compare_name(name: string) -> boolScene inventory and save APIs
Added inventory capacity APIs
Added auto-save APIs
Voice and VOIP APIs
voice_set_range(float)voice_get_range()Scene::voip_range
UIK
New API for building UIs
Docs are coming soon
Protocol 41 - March 3rd, 2026
This protocol update improved CSL netcode performance dramatically and introduced new Terrain and Tilemap editor tools and a built in agent to help with scripting and world building!
New Features
Terrain tool
Paint grasslands, oceans, shores, caves and more with broad high performance brush strokes
Tilemap editor tool
Bring a tile set (or use one of ours) and create tiled maps using the new tilemap component
Agent pane
Hooks into Claude Code or Codex-Cli and can build maps, write scripts, and design UI
New MCP features
Tools for world building
Tools for reading game logs
Tools for adding full SFX from our catalog to your games!
Protocol 40 - Feb 9th, 2026
This protocol update introduces CSL and makes major improvements to the editor workflow for new projects. Protocol 40 is expected to launch around Feb 3rd
New Features
Adds support for our new game programming language. You'll see new experiences built with this soon!
Voice chat quality and moderation accuracy improved
Added chat spam prevention
Core app features are now translated into 34 languages!
Improved text rendering on low-end devices
Android now supports deeplinks from web/push notifications into the app.
Editor Changes
The editor now has you select a "game projects" directory at startup and will make any game there available to you When creating a new game from Campfire, we now automatically fill in the ao.project with your game ID.
Added saving progress bar to the top of the editor when saving
Added in-editor asset search
Assets in your project can now be rearranged in folders directly in the editor
Improved project upload (zip) speed
Launching the game for testing will use the latest version of the scene even if you haven't saved yet
You can now change the scale of Sprite_Renderers directly in editor
You can now create and save custom layouts for editor panel positions
The MCP server is now installed automatically
CSL is now default for new projects. If you need C# you must remove csl: true from ao.project
Last updated