Bevy ECS Integration
Relevant source files
The following files were used as context for generating this wiki page:
Cyrus uses the Bevy Entity Component System (ECS) to rebuild The Elder Scrolls Adventures: Redguard. The project pins Bevy to version 0.20 to maintain API stability across the workspace. The ECS architecture manages game logic, world loading, input handling, and rendering through a modular plugin system.
Sources: README.md:9, AGENTS.md:204-205, Cargo.toml:23
Plugin Architecture
The application organizes functionality into distinct Bevy plugins. These plugins encapsulate specific responsibilities like player movement, scripting, and asset loading. The cyrus-game crate provides the primary GamePlugin, which coordinates the core simulation.
Core Plugins and Responsibilities
| Plugin | Responsibility | File Reference |
|---|---|---|
GamePlugin | Installs app state, fidelity policies, and sub-plugins. | crates/cyrus-game/README.md:10 |
PlayerPlugin | Manages player scenes, input sampling, and movement rules. | crates/cyrus-game/README.md:10,19 |
ScriptPlugin | Hosts SOUP actors and handles logical game updates. | crates/cyrus-game/README.md:10,20 |
EguiPlugin | Sets up the UI renderer and applies WebGL compatibility fixes. | crates/cyrus-app/src/lib.rs:82 |
LoadingOverlayPlugin | Displays progress during asset preparation. | crates/cyrus-app/README.md:23 |
Plugin Dependency Flow
This diagram shows how the GamePlugin acts as a central hub for gameplay-related sub-systems.
The GamePlugin requires the host to supply infrastructure for assets, input, and state management.
Sources: crates/cyrus-game/README.md:10-12, crates/cyrus-app/src/lib.rs:82-96
Application Setup and Configuration
The cyrus-app crate centralizes the boilerplate required to launch a Bevy application in both native and browser environments.
Window and Asset Initialization
You configure the primary window through the window function. This function creates a WindowPlugin and allows size overrides via the CYRUS_WINDOW_SIZE environment variable.
For asset management, the register_cache function must run before AssetPlugin. It registers a cache:// asset source pointing to a platform-specific directory (e.g., ~/.cache/cyrus on Linux).
Sources: crates/cyrus-app/src/lib.rs:11-23,43-62, README.md:46-49, crates/cyrus-app/README.md:21-22
Feature Sets
Cyrus utilizes a specific subset of Bevy features to maintain portability and performance.
State and Simulation Control
The ECS manages the simulation clock and input suppression to handle UI transitions and menus.
- Simulation Clock: The
cyrus-gamecrate includes aclockmodule that manages shared simulation timing and timing snapshots. - Input Suppression: Systems set
InputSuppressedbeforeInputSamplewhen the player interacts with the console, logbook, or inventory. - Suspension: Opening the logbook or inventory screen suspends the simulation clock and stops automatic gameplay input.
Sources: crates/cyrus-game/README.md:14-16,21
Render Compatibility Hooks
Cyrus includes specific overrides for Bevy's rendering to support various platforms. For example, the EguiPlugin modifies the EGUI_SHADER_HANDLE when targeting WebGL to remove incompatible WGPU binding arrays.
// crates/cyrus-app/src/lib.rs:89-95
#[cfg(target_arch = "wasm32")]
if let bevy::shader::Source::Wesl(source) = &mut app
.world_mut()
.resource_mut::<Assets<bevy::shader::Shader>>()
.get_mut(&bevy_egui::render::EGUI_SHADER_HANDLE)
.expect("egui installs its shader")
.source
{
*source = source.replace("enable wgpu_binding_array;", "").into();
}
Sources: crates/cyrus-app/src/lib.rs:89-95
Conclusion
The Bevy ECS integration in Cyrus provides a structured, plugin-based framework that separates core gameplay rules from platform-specific rendering and asset loading. By pinning Bevy 0.20 and isolating crates like cyrus-game and cyrus-app, the project ensures that faithful reproduction of Redguard logic remains independent of the host environment.