bevy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +4279 -0
  3. data/Cargo.toml +36 -0
  4. data/README.md +226 -0
  5. data/crates/bevy/Cargo.toml +52 -0
  6. data/crates/bevy/src/app.rs +43 -0
  7. data/crates/bevy/src/component.rs +111 -0
  8. data/crates/bevy/src/entity.rs +30 -0
  9. data/crates/bevy/src/error.rs +32 -0
  10. data/crates/bevy/src/event.rs +190 -0
  11. data/crates/bevy/src/input_bridge.rs +300 -0
  12. data/crates/bevy/src/lib.rs +42 -0
  13. data/crates/bevy/src/mesh_renderer.rs +328 -0
  14. data/crates/bevy/src/query.rs +53 -0
  15. data/crates/bevy/src/render_app.rs +689 -0
  16. data/crates/bevy/src/resource.rs +28 -0
  17. data/crates/bevy/src/schedule.rs +186 -0
  18. data/crates/bevy/src/sprite_renderer.rs +355 -0
  19. data/crates/bevy/src/system.rs +44 -0
  20. data/crates/bevy/src/text_renderer.rs +258 -0
  21. data/crates/bevy/src/types/color.rs +114 -0
  22. data/crates/bevy/src/types/dynamic.rs +131 -0
  23. data/crates/bevy/src/types/math.rs +260 -0
  24. data/crates/bevy/src/types/mod.rs +9 -0
  25. data/crates/bevy/src/types/transform.rs +166 -0
  26. data/crates/bevy/src/world.rs +163 -0
  27. data/crates/bevy_ruby_render/Cargo.toml +22 -0
  28. data/crates/bevy_ruby_render/src/asset.rs +360 -0
  29. data/crates/bevy_ruby_render/src/audio.rs +511 -0
  30. data/crates/bevy_ruby_render/src/camera.rs +365 -0
  31. data/crates/bevy_ruby_render/src/gamepad.rs +398 -0
  32. data/crates/bevy_ruby_render/src/lib.rs +26 -0
  33. data/crates/bevy_ruby_render/src/material.rs +310 -0
  34. data/crates/bevy_ruby_render/src/mesh.rs +491 -0
  35. data/crates/bevy_ruby_render/src/sprite.rs +289 -0
  36. data/ext/bevy/Cargo.toml +20 -0
  37. data/ext/bevy/extconf.rb +6 -0
  38. data/ext/bevy/src/conversions.rs +137 -0
  39. data/ext/bevy/src/lib.rs +29 -0
  40. data/ext/bevy/src/ruby_app.rs +65 -0
  41. data/ext/bevy/src/ruby_color.rs +149 -0
  42. data/ext/bevy/src/ruby_component.rs +189 -0
  43. data/ext/bevy/src/ruby_entity.rs +33 -0
  44. data/ext/bevy/src/ruby_math.rs +384 -0
  45. data/ext/bevy/src/ruby_query.rs +64 -0
  46. data/ext/bevy/src/ruby_render_app.rs +779 -0
  47. data/ext/bevy/src/ruby_system.rs +122 -0
  48. data/ext/bevy/src/ruby_world.rs +107 -0
  49. data/lib/bevy/animation.rb +597 -0
  50. data/lib/bevy/app.rb +675 -0
  51. data/lib/bevy/asset.rb +613 -0
  52. data/lib/bevy/audio.rb +545 -0
  53. data/lib/bevy/audio_effects.rb +224 -0
  54. data/lib/bevy/camera.rb +412 -0
  55. data/lib/bevy/component.rb +91 -0
  56. data/lib/bevy/diagnostics.rb +227 -0
  57. data/lib/bevy/ecs_advanced.rb +296 -0
  58. data/lib/bevy/event.rb +199 -0
  59. data/lib/bevy/gizmos.rb +158 -0
  60. data/lib/bevy/gltf.rb +227 -0
  61. data/lib/bevy/hierarchy.rb +444 -0
  62. data/lib/bevy/input.rb +514 -0
  63. data/lib/bevy/lighting.rb +369 -0
  64. data/lib/bevy/material.rb +248 -0
  65. data/lib/bevy/mesh.rb +257 -0
  66. data/lib/bevy/navigation.rb +344 -0
  67. data/lib/bevy/networking.rb +335 -0
  68. data/lib/bevy/particle.rb +337 -0
  69. data/lib/bevy/physics.rb +396 -0
  70. data/lib/bevy/plugins/default_plugins.rb +34 -0
  71. data/lib/bevy/plugins/input_plugin.rb +49 -0
  72. data/lib/bevy/reflect.rb +361 -0
  73. data/lib/bevy/render_graph.rb +210 -0
  74. data/lib/bevy/resource.rb +185 -0
  75. data/lib/bevy/scene.rb +254 -0
  76. data/lib/bevy/shader.rb +319 -0
  77. data/lib/bevy/shape.rb +195 -0
  78. data/lib/bevy/skeletal.rb +248 -0
  79. data/lib/bevy/sprite.rb +152 -0
  80. data/lib/bevy/sprite_sheet.rb +444 -0
  81. data/lib/bevy/state.rb +277 -0
  82. data/lib/bevy/system.rb +206 -0
  83. data/lib/bevy/text.rb +99 -0
  84. data/lib/bevy/text_advanced.rb +455 -0
  85. data/lib/bevy/timer.rb +147 -0
  86. data/lib/bevy/transform.rb +158 -0
  87. data/lib/bevy/ui.rb +454 -0
  88. data/lib/bevy/ui_advanced.rb +568 -0
  89. data/lib/bevy/version.rb +5 -0
  90. data/lib/bevy/visibility.rb +250 -0
  91. data/lib/bevy/window.rb +302 -0
  92. data/lib/bevy.rb +390 -0
  93. metadata +150 -0
data/Cargo.toml ADDED
@@ -0,0 +1,36 @@
1
+ [workspace]
2
+ members = ["crates/*", "ext/bevy"]
3
+ resolver = "2"
4
+
5
+ [workspace.package]
6
+ version = "0.1.0"
7
+ edition = "2024"
8
+ license = "MIT OR Apache-2.0"
9
+ repository = "https://github.com/ydah/bevy-ruby"
10
+
11
+ [workspace.dependencies]
12
+ bevy_ecs = "0.15"
13
+ bevy_app = "0.15"
14
+ bevy_math = "0.15"
15
+ bevy_transform = "0.15"
16
+ bevy_color = "0.15"
17
+ bevy_render = { version = "0.15", default-features = false }
18
+ bevy_sprite = { version = "0.15", default-features = false }
19
+ bevy_window = "0.15"
20
+ bevy_winit = "0.15"
21
+ bevy_asset = "0.15"
22
+ bevy_time = "0.15"
23
+ bevy_input = "0.15"
24
+ bevy_core_pipeline = { version = "0.15", default-features = false }
25
+ bevy_hierarchy = "0.15"
26
+ bevy_log = "0.15"
27
+ bevy_core = "0.15"
28
+ bevy_a11y = "0.15"
29
+ bevy_image = "0.15"
30
+ bevy_text = { version = "0.15", features = ["default_font"] }
31
+ bevy_picking = "0.15"
32
+ bevy_prototype_lyon = "0.13"
33
+ magnus = "0.8"
34
+ rb-sys = "0.9"
35
+ parking_lot = "0.12"
36
+ thiserror = "2"
data/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # Bevy Ruby
2
+
3
+ Bevy bindings for Ruby, providing ECS-driven game/app architecture, 2D rendering sync, input bridging, and runtime interaction events.
4
+
5
+ <img width="400" alt="Image" src="https://github.com/user-attachments/assets/440971a6-bf10-4cc2-abe6-e5cf28949b95" />
6
+
7
+ ## Status
8
+
9
+ This project provides a practical, Bevy-compatible API surface in Ruby, with a mix of:
10
+
11
+ - native-backed features through Rust + Bevy integration
12
+ - Ruby convenience/DSL layers for ergonomic usage
13
+
14
+ ### Native-backed (current)
15
+
16
+ - App/game loop integration (`App`, schedules, startup/update flow)
17
+ - ECS bridge (`World`, `Entity`, dynamic component/resource/event plumbing)
18
+ - Render bridge (window + camera + sync to Bevy scene)
19
+ - `Sprite`
20
+ - `Text2d`
21
+ - `Mesh` 2D primitives (rectangle/circle/regular polygon/line/ellipse)
22
+ - Input bridge
23
+ - keyboard and mouse state
24
+ - gamepad state
25
+ - gamepad rumble forwarding (`RumbleRequest`)
26
+ - Picking event bridge (`bevy_picking`)
27
+ - `over`, `out`, `down`, `up`, `click`
28
+
29
+ ### Ruby layer (current)
30
+
31
+ - DSL and registries
32
+ - `ComponentDSL`
33
+ - `ResourceDSL`
34
+ - `EventDSL`
35
+ - `EventRegistry`, readers/writers
36
+ - Runtime helpers
37
+ - `SystemContext` query/spawn/resource/event APIs
38
+ - input helper methods for keyboard/mouse/gamepad
39
+ - picking helper methods (`picking_events`, `picked?`)
40
+ - Value and utility types
41
+ - `Vec2`, `Vec3`, `Quat`, `Transform`, `Color`
42
+ - `KeyboardInput`, `MouseInput`, `GamepadInput`, `Gamepads`, `DeadZone`
43
+
44
+ ### Native build note
45
+
46
+ - The Rust backend currently targets Bevy `0.15`.
47
+ - A number of high-level Ruby modules exist in `lib/bevy/*`, but not all are fully wired end-to-end in native Bevy systems yet (for example, parts of audio/scene/gltf/ui/shader/material-related areas).
48
+
49
+ ## Requirements
50
+
51
+ - Ruby 3.2+
52
+ - Rust toolchain (`rustc`, `cargo`) for native extension build
53
+
54
+ ## Installation
55
+
56
+ Add this line to your application's Gemfile:
57
+
58
+ ```ruby
59
+ gem 'bevy'
60
+ ```
61
+
62
+ Then run:
63
+
64
+ ```bash
65
+ bundle install
66
+ ```
67
+
68
+ ## Installing Native Library
69
+
70
+ This gem does not require installing a separate external runtime shared library.
71
+
72
+ The native extension is built from this repository's Rust crates.
73
+
74
+ ### macOS
75
+
76
+ ```bash
77
+ xcode-select --install
78
+ bundle install
79
+ bundle exec rake compile
80
+ ```
81
+
82
+ ### Linux
83
+
84
+ ```bash
85
+ bundle install
86
+ bundle exec rake compile
87
+ ```
88
+
89
+ ### Windows
90
+
91
+ ```powershell
92
+ bundle install
93
+ bundle exec rake compile
94
+ ```
95
+
96
+ ## Quick Start
97
+
98
+ ```ruby
99
+ require 'bevy'
100
+
101
+ class Velocity < Bevy::ComponentDSL
102
+ attribute :x, Float, default: 120.0
103
+ end
104
+
105
+ app = Bevy::App.new(
106
+ render: true,
107
+ window: { title: 'Bevy Ruby', width: 800.0, height: 600.0 }
108
+ )
109
+
110
+ app.add_startup_system do |ctx|
111
+ ctx.spawn(
112
+ Velocity.new,
113
+ Bevy::Transform.from_xyz(0.0, 0.0, 0.0),
114
+ Bevy::Sprite.new(
115
+ color: Bevy::Color.from_hex('#4ECDC4'),
116
+ custom_size: Bevy::Vec2.new(80.0, 80.0)
117
+ )
118
+ )
119
+ end
120
+
121
+ app.add_update_system do |ctx|
122
+ ctx.query(Velocity, Bevy::Transform) do |entity, vel, transform|
123
+ next_x = transform.translation.x + vel.x * ctx.delta
124
+ vel.x *= -1.0 if next_x > 360.0 || next_x < -360.0
125
+
126
+ ctx.world.insert_component(
127
+ entity,
128
+ transform.with_translation(Bevy::Vec3.new(transform.translation.x + vel.x * ctx.delta, 0.0, 0.0))
129
+ )
130
+ end
131
+
132
+ ctx.app.stop if ctx.key_pressed?('ESCAPE')
133
+ end
134
+
135
+ app.run
136
+ ```
137
+
138
+ ## Gamepad Rumble Example
139
+
140
+ ```ruby
141
+ require 'bevy'
142
+
143
+ app = Bevy::App.new(render: true)
144
+
145
+ app.add_update_system do |ctx|
146
+ next unless ctx.any_gamepad_connected?
147
+
148
+ if ctx.gamepad_just_pressed?(Bevy::GamepadButton::SOUTH)
149
+ ctx.gamepad&.rumble(
150
+ Bevy::RumbleRequest.new(strong: 0.8, weak: 0.3, duration: 0.4)
151
+ )
152
+ end
153
+ end
154
+
155
+ app.run
156
+ ```
157
+
158
+ ## Picking Event Example
159
+
160
+ ```ruby
161
+ require 'bevy'
162
+
163
+ app = Bevy::App.new(render: true)
164
+
165
+ app.add_update_system do |ctx|
166
+ ctx.picking_events(:click).each do |event|
167
+ puts "clicked target=#{event.target_id} button=#{event.button}"
168
+ end
169
+ end
170
+
171
+ app.run
172
+ ```
173
+
174
+ ## API Coverage (Bevy docs parity)
175
+
176
+ | Area | Status | Notes |
177
+ | --- | --- | --- |
178
+ | ECS basics (`App`/`World`/entities/components/resources/events) | Implemented | Core loop and dynamic ECS bindings are available |
179
+ | 2D render sync (`Sprite`/`Text2d`/`Mesh` shapes) | Implemented | Ruby-side component data is synchronized to Bevy |
180
+ | Keyboard and mouse input | Implemented | Render loop input state is exposed through `SystemContext` |
181
+ | Gamepad input + rumble | Implemented | State bridge plus `RumbleRequest` forwarding |
182
+ | Picking events (`over`/`out`/`down`/`up`/`click`) | Implemented | Exposed as `Bevy::PickingEvent` |
183
+ | Camera transform controls (2D) | Implemented | Position/scale helpers are available |
184
+ | 3D/PBR-native workflows | Partial | Current bridge is primarily focused on 2D sync |
185
+ | Asset/scene/gltf/audio/ui/full parity with upstream Bevy | Partial | Some APIs exist in Ruby, but native end-to-end wiring is incomplete in several domains |
186
+ | Upstream Bevy version parity (`0.18+`/`main`) | Not implemented | Current backend target is Bevy `0.15` |
187
+
188
+ ## Development
189
+
190
+ After checking out the repo, install dependencies:
191
+
192
+ ```bash
193
+ bundle install
194
+ ```
195
+
196
+ Build native extension:
197
+
198
+ ```bash
199
+ bundle exec rake compile
200
+ ```
201
+
202
+ Run tests:
203
+
204
+ ```bash
205
+ bundle exec rake spec
206
+ ```
207
+
208
+ Run examples:
209
+
210
+ ```bash
211
+ bundle exec ruby examples/hello_world.rb
212
+ bundle exec ruby examples/input_handling.rb
213
+ bundle exec ruby examples/gamepad.rb
214
+ bundle exec ruby examples/shapes_2d.rb
215
+ bundle exec ruby examples/space_shooter.rb
216
+ ```
217
+
218
+ ## License
219
+
220
+ This project is available under the [MIT License](LICENSE).
221
+
222
+ ## Contributing
223
+
224
+ Bug reports and pull requests are welcome at:
225
+
226
+ - https://github.com/ydah/bevy-ruby
@@ -0,0 +1,52 @@
1
+ [package]
2
+ name = "bevy-ruby"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+ repository.workspace = true
7
+
8
+ [features]
9
+ default = ["rendering"]
10
+ rendering = [
11
+ "bevy_window",
12
+ "bevy_winit",
13
+ "bevy_render",
14
+ "bevy_sprite",
15
+ "bevy_core_pipeline",
16
+ "bevy_asset",
17
+ "bevy_hierarchy",
18
+ "bevy_log",
19
+ "bevy_core",
20
+ "bevy_a11y",
21
+ "bevy_image",
22
+ "bevy_text",
23
+ "bevy_picking",
24
+ "bevy_prototype_lyon",
25
+ ]
26
+
27
+ [dependencies]
28
+ bevy_ecs.workspace = true
29
+ bevy_app.workspace = true
30
+ bevy_math.workspace = true
31
+ bevy_transform.workspace = true
32
+ bevy_color.workspace = true
33
+ bevy_time.workspace = true
34
+ bevy_input.workspace = true
35
+ parking_lot.workspace = true
36
+ thiserror.workspace = true
37
+
38
+ # Optional rendering dependencies
39
+ bevy_window = { workspace = true, optional = true }
40
+ bevy_winit = { workspace = true, optional = true, features = ["x11", "wayland"] }
41
+ bevy_render = { workspace = true, optional = true }
42
+ bevy_sprite = { workspace = true, optional = true }
43
+ bevy_core_pipeline = { workspace = true, optional = true }
44
+ bevy_asset = { workspace = true, optional = true }
45
+ bevy_hierarchy = { workspace = true, optional = true }
46
+ bevy_log = { workspace = true, optional = true }
47
+ bevy_core = { workspace = true, optional = true }
48
+ bevy_a11y = { workspace = true, optional = true }
49
+ bevy_image = { workspace = true, optional = true }
50
+ bevy_text = { workspace = true, optional = true, features = ["default_font"] }
51
+ bevy_picking = { workspace = true, optional = true }
52
+ bevy_prototype_lyon = { workspace = true, optional = true }
@@ -0,0 +1,43 @@
1
+ use crate::component::ComponentRegistry;
2
+ use crate::system::{ScheduleLabel, SystemDescriptor};
3
+ use crate::world::WorldWrapper;
4
+ use std::sync::Arc;
5
+
6
+ pub struct AppBuilder {
7
+ registry: Arc<ComponentRegistry>,
8
+ systems: Vec<SystemDescriptor>,
9
+ }
10
+
11
+ impl AppBuilder {
12
+ pub fn new() -> Self {
13
+ Self {
14
+ registry: ComponentRegistry::new(),
15
+ systems: Vec::new(),
16
+ }
17
+ }
18
+
19
+ pub fn registry(&self) -> &Arc<ComponentRegistry> {
20
+ &self.registry
21
+ }
22
+
23
+ pub fn add_system(&mut self, descriptor: SystemDescriptor) {
24
+ self.systems.push(descriptor);
25
+ }
26
+
27
+ pub fn systems_for_schedule(&self, schedule: ScheduleLabel) -> Vec<&SystemDescriptor> {
28
+ self.systems
29
+ .iter()
30
+ .filter(|s| s.schedule == schedule)
31
+ .collect()
32
+ }
33
+
34
+ pub fn create_world(&self) -> WorldWrapper {
35
+ WorldWrapper::with_registry(Arc::clone(&self.registry))
36
+ }
37
+ }
38
+
39
+ impl Default for AppBuilder {
40
+ fn default() -> Self {
41
+ Self::new()
42
+ }
43
+ }
@@ -0,0 +1,111 @@
1
+ use bevy_ecs::component::ComponentId;
2
+ use parking_lot::RwLock;
3
+ use std::any::TypeId;
4
+ use std::collections::HashMap;
5
+ use std::sync::Arc;
6
+
7
+ #[derive(Debug, Clone)]
8
+ pub struct AttributeDescriptor {
9
+ pub name: String,
10
+ pub attr_type: AttributeType,
11
+ pub default_value: Option<Vec<u8>>,
12
+ }
13
+
14
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
15
+ pub enum AttributeType {
16
+ Integer,
17
+ Float,
18
+ Boolean,
19
+ String,
20
+ Vec2,
21
+ Vec3,
22
+ Quat,
23
+ Entity,
24
+ }
25
+
26
+ #[derive(Debug, Clone)]
27
+ pub struct ComponentMetadata {
28
+ pub name: String,
29
+ pub attributes: Vec<AttributeDescriptor>,
30
+ }
31
+
32
+ #[derive(Debug, Clone)]
33
+ pub struct ComponentData {
34
+ pub metadata: ComponentMetadata,
35
+ pub data: HashMap<String, Vec<u8>>,
36
+ }
37
+
38
+ impl ComponentData {
39
+ pub fn new(name: &str) -> Self {
40
+ Self {
41
+ metadata: ComponentMetadata {
42
+ name: name.to_string(),
43
+ attributes: Vec::new(),
44
+ },
45
+ data: HashMap::new(),
46
+ }
47
+ }
48
+
49
+ pub fn with_attribute(mut self, name: &str, attr_type: AttributeType) -> Self {
50
+ self.metadata.attributes.push(AttributeDescriptor {
51
+ name: name.to_string(),
52
+ attr_type,
53
+ default_value: None,
54
+ });
55
+ self
56
+ }
57
+
58
+ pub fn set_data(&mut self, name: &str, data: Vec<u8>) {
59
+ self.data.insert(name.to_string(), data);
60
+ }
61
+
62
+ pub fn get_data(&self, name: &str) -> Option<&Vec<u8>> {
63
+ self.data.get(name)
64
+ }
65
+ }
66
+
67
+ pub struct ComponentRegistry {
68
+ name_to_id: RwLock<HashMap<String, ComponentId>>,
69
+ id_to_metadata: RwLock<HashMap<ComponentId, ComponentMetadata>>,
70
+ #[allow(dead_code)]
71
+ type_to_id: RwLock<HashMap<TypeId, ComponentId>>,
72
+ }
73
+
74
+ impl ComponentRegistry {
75
+ pub fn new() -> Arc<Self> {
76
+ Arc::new(Self {
77
+ name_to_id: RwLock::new(HashMap::new()),
78
+ id_to_metadata: RwLock::new(HashMap::new()),
79
+ type_to_id: RwLock::new(HashMap::new()),
80
+ })
81
+ }
82
+
83
+ pub fn register(&self, name: &str, component_id: ComponentId, metadata: ComponentMetadata) {
84
+ self.name_to_id
85
+ .write()
86
+ .insert(name.to_string(), component_id);
87
+ self.id_to_metadata.write().insert(component_id, metadata);
88
+ }
89
+
90
+ pub fn get_id(&self, name: &str) -> Option<ComponentId> {
91
+ self.name_to_id.read().get(name).copied()
92
+ }
93
+
94
+ pub fn get_metadata(&self, id: ComponentId) -> Option<ComponentMetadata> {
95
+ self.id_to_metadata.read().get(&id).cloned()
96
+ }
97
+
98
+ pub fn is_registered(&self, name: &str) -> bool {
99
+ self.name_to_id.read().contains_key(name)
100
+ }
101
+ }
102
+
103
+ impl Default for ComponentRegistry {
104
+ fn default() -> Self {
105
+ Self {
106
+ name_to_id: RwLock::new(HashMap::new()),
107
+ id_to_metadata: RwLock::new(HashMap::new()),
108
+ type_to_id: RwLock::new(HashMap::new()),
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,30 @@
1
+ use bevy_ecs::entity::Entity;
2
+
3
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4
+ pub struct EntityWrapper(pub Entity);
5
+
6
+ impl EntityWrapper {
7
+ pub fn new(entity: Entity) -> Self {
8
+ Self(entity)
9
+ }
10
+
11
+ pub fn id(&self) -> u64 {
12
+ self.0.to_bits()
13
+ }
14
+
15
+ pub fn inner(&self) -> Entity {
16
+ self.0
17
+ }
18
+ }
19
+
20
+ impl From<Entity> for EntityWrapper {
21
+ fn from(entity: Entity) -> Self {
22
+ Self(entity)
23
+ }
24
+ }
25
+
26
+ impl From<EntityWrapper> for Entity {
27
+ fn from(wrapper: EntityWrapper) -> Self {
28
+ wrapper.0
29
+ }
30
+ }
@@ -0,0 +1,32 @@
1
+ use bevy_ecs::entity::Entity;
2
+ use thiserror::Error;
3
+
4
+ #[derive(Error, Debug)]
5
+ pub enum BevyRubyError {
6
+ #[error("Entity {0:?} not found")]
7
+ EntityNotFound(Entity),
8
+
9
+ #[error("Component '{component}' not found on entity {entity:?}")]
10
+ ComponentNotFound { entity: Entity, component: String },
11
+
12
+ #[error("Component '{0}' already exists")]
13
+ ComponentAlreadyExists(String),
14
+
15
+ #[error("Resource '{0}' not found")]
16
+ ResourceNotFound(String),
17
+
18
+ #[error("Resource '{0}' already exists")]
19
+ ResourceAlreadyExists(String),
20
+
21
+ #[error("Component '{0}' is not registered")]
22
+ ComponentNotRegistered(String),
23
+
24
+ #[error("Invalid type conversion: expected {expected}, got {actual}")]
25
+ InvalidType { expected: String, actual: String },
26
+
27
+ #[error("System error: {0}")]
28
+ SystemError(String),
29
+
30
+ #[error("World is not available")]
31
+ WorldNotAvailable,
32
+ }