Web Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The Web Architecture of cyrus enables the game and its asset viewer to run directly in modern web browsers using WebAssembly (WASM) and WebGL2. It facilitates the execution of the Bevy-based Rust engine by bridging browser-specific APIs, such as the File System Access API and Service Workers, with the core gameplay logic.
The architecture centers on a thin JavaScript loader that initializes the WASM environment, manages asset streaming from a local GOG install, and handles browser-specific lifecycle events like audio context resumption and graphics context loss. Sources: README.md, crates/cyrus-web/Cargo.toml
Application Bootstrapping
The browser entry point is index.html, which provides the cyrus-web data-engine target and anchors the loading UI. The loader.js module orchestrates the transition from HTML to a running Rust application.
Initialization Sequence
- Environment Setup:
loader.jswraps theAudioContextto handle browser autoplay restrictions by resuming audio on the first user interaction (pointer, key, or touch). - Asset Connection: The loader calls
chooseInstall()to acquire access to the game files. If running in a full web environment, it initializesgame-assets.jsto index the installation. - Service Worker: It registers
sw.jsto manage asset caching and offline capabilities. - WASM Fetching: The loader fetches the
cyrus-web_bg.wasmbinary, providing progress updates to the UI's loading bar. - Instantiation: It invokes the
initfunction exported by the WASM glue code to start the Bevy engine.
Sources: crates/cyrus-web/web/index.html:1-13, dev/web/loader.js:4-28, dev/web/loader.js:77-111
The diagram shows the sequential steps taken by the JavaScript loader to prepare the browser environment for the WebAssembly game engine. Sources: dev/web/loader.js
Asset Management and Installation Access
Because cyrus requires a user-provided GOG install, the web architecture uses two primary methods to access game data without shipping copyrighted assets.
Access Methods
- Local File System: Users select their local Redguard folder via a browser picker. The files remain on the local machine and are read through the
File System Access API. - Game-File Server: A local Python-based server (
web-server.py) can serve the assets over HTTP. The browser connects to this server to stream game data.
Progress Tracking
The cyrus-assets-worker manages the background decoding of original game formats into browser-compatible buffers. The loader monitors this progress to update the "Loading application" status and the specific asset being processed (e.g., textures, models).
Sources: README.md, dev/scripts/web-server.py, dev/web/loader.js:82-89, dev/scripts/build-web.sh:34-40
World Navigation and Lifecycle
The debug.rs module in cyrus-web manages how the browser transitions between different game worlds. It utilizes URL parameters to define the starting scene and tracks the loading state of "sidecar" assets.
Staged Loading
To prevent the application from hanging or showing incomplete scenes, the web architecture implements a staging system.
- SceneRequest: Triggered by a URL change or internal script call.
- StagedWorld: A resource created to hold handles for animations, scripts, player data, and GLTF scenes while they load.
- Commitment: The world only swaps once all handles in the
StagedWorldreport aLoadedstate.
Sources: crates/cyrus-web/src/debug.rs:25-56, crates/cyrus-web/src/debug.rs:77-105
URL Configuration Parameters
| Parameter | Values | Description |
|---|---|---|
scene | String (e.g., START) | The ID of the world to load immediately. |
skip-startup | true, false | Bypasses splash screens and menus. |
water | faithful, modern | Sets the fidelity mode for water rendering. |
fog | faithful, modern | Sets the fidelity mode for atmospheric fog. |
Sources: dev/web/loader.js:63-74, crates/cyrus-web/src/debug.rs:125-132
This sequence diagram illustrates the asynchronous world loading process, ensuring the game remains responsive while assets are prepared in the background. Sources: crates/cyrus-web/src/debug.rs:40-115
Build and Deployment Pipeline
The web application is compiled using a specialized pipeline that targets wasm32-unknown-unknown.
- Cargo Build: The project is built with specific profiles (e.g.,
wasm-devorwasm-release). - wasm-bindgen: This tool generates the JavaScript bindings required for the browser to communicate with the Rust binary.
- Artifact Packaging: The
build-web.shscript aggregates the WASM binary, JS snippets, and static web assets (HTML, CSS, loader) into a unifiedtarget/webdirectory. - Provenance: A build provenance JSON is generated to track the artifacts and their sources.
Sources: dev/scripts/build-web.sh:13-33, crates/cyrus-web/Cargo.toml:23-35
Summary of Components
| Component | Responsibility | File Path |
|---|---|---|
| Loader | Orchestrates startup, WASM fetch, and UI. | dev/web/loader.js |
| Debug Handler | Manages web-specific world switching/URL history. | crates/cyrus-web/src/debug.rs |
| Asset Worker | Background thread for asset decoding. | dev/web/asset-worker.js |
| Build Script | Compiles Rust to WASM and packages web root. | dev/scripts/build-web.sh |
| Entry Point | Main Bevy application initialization. | crates/cyrus-web/src/main.rs |
Sources: crates/cyrus-web/Cargo.toml, dev/web/loader.js, crates/cyrus-web/src/debug.rs