summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecs/examples/extension.rs77
-rw-r--r--ecs/src/extension.rs56
-rw-r--r--ecs/src/lib.rs13
3 files changed, 146 insertions, 0 deletions
diff --git a/ecs/examples/extension.rs b/ecs/examples/extension.rs
new file mode 100644
index 0000000..2022b05
--- /dev/null
+++ b/ecs/examples/extension.rs
@@ -0,0 +1,77 @@
+use ecs::actions::Actions;
+use ecs::event::Event;
+use ecs::extension::{Collector as ExtensionCollector, Extension};
+use ecs::{Component, Query, World};
+
+#[derive(Debug, Component)]
+struct Position
+{
+ x: u32,
+ y: u32,
+}
+
+#[derive(Debug, Component)]
+struct EnemySpawnSource;
+
+#[derive(Debug, Component)]
+enum EvilnessLevel
+{
+ Medium,
+}
+
+#[derive(Debug)]
+struct Update;
+
+impl Event for Update {}
+
+fn spawn_enemies(
+ spawner_query: Query<(EnemySpawnSource, Position)>,
+ enemies_query: Query<(EvilnessLevel,)>,
+ mut actions: Actions,
+)
+{
+ let Some((_, enemy_spawner_position)) = spawner_query.iter().next() else {
+ return;
+ };
+
+ let enemy_cnt = enemies_query.iter().count();
+
+ if enemy_cnt > 3 {
+ return;
+ }
+
+ actions.spawn((
+ EvilnessLevel::Medium,
+ Position {
+ x: enemy_spawner_position.x * enemy_cnt as u32,
+ y: enemy_spawner_position.y,
+ },
+ ));
+
+ println!("Spawned enemy with medium evilness and 45 strength");
+}
+
+struct EnemySpawningExtension;
+
+impl Extension for EnemySpawningExtension
+{
+ fn collect(self, mut collector: ExtensionCollector<'_>)
+ {
+ collector.add_system(Update, spawn_enemies);
+
+ collector.add_entity((Position { x: 187, y: 30 }, EnemySpawnSource));
+ }
+}
+
+fn main()
+{
+ let mut world = World::new();
+
+ world.add_extension(EnemySpawningExtension);
+
+ for _ in 0..7 {
+ world.emit(Update);
+
+ world.perform_queued_actions();
+ }
+}
diff --git a/ecs/src/extension.rs b/ecs/src/extension.rs
new file mode 100644
index 0000000..fc5a345
--- /dev/null
+++ b/ecs/src/extension.rs
@@ -0,0 +1,56 @@
+use crate::component::Sequence as ComponentSequence;
+use crate::event::Event;
+use crate::sole::Sole;
+use crate::system::System;
+use crate::{SoleAlreadyExistsError, World};
+
+/// A collection of systems, entities & soles that can be added to a [`World`].
+pub trait Extension
+{
+ fn collect(self, collector: Collector<'_>);
+}
+
+/// Passed to a [`Extension`] to collects it's systems, entities & soles.
+pub struct Collector<'world>
+{
+ world: &'world mut World,
+}
+
+impl<'world> Collector<'world>
+{
+ /// Returns a new `Collector` for the given [`World`].
+ pub fn new(world: &'world mut World) -> Self
+ {
+ Self { world }
+ }
+
+ /// Adds a system to the [`World`].
+ pub fn add_system<'this, EventT, SystemImpl>(
+ &'this mut self,
+ event: EventT,
+ system: impl System<'this, SystemImpl>,
+ ) where
+ EventT: Event,
+ {
+ self.world.register_system(event, system);
+ }
+
+ /// Adds a entity to the [`World`].
+ pub fn add_entity<Comps>(&mut self, components: Comps)
+ where
+ Comps: ComponentSequence,
+ {
+ self.world.create_entity(components);
+ }
+
+ /// Adds a globally shared singleton value to the [`World`].
+ ///
+ /// # Errors
+ /// Returns `Err` if this [`Sole`] has already been added.
+ pub fn add_sole<SoleT>(&mut self, sole: SoleT) -> Result<(), SoleAlreadyExistsError>
+ where
+ SoleT: Sole,
+ {
+ self.world.add_sole(sole)
+ }
+}
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 285f3b3..009ff21 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -12,6 +12,7 @@ use std::vec::Drain;
use crate::actions::Action;
use crate::component::{Component, Sequence as ComponentSequence};
use crate::event::{Event, Id as EventId, Ids, Sequence as EventSequence};
+use crate::extension::{Collector as ExtensionCollector, Extension};
use crate::lock::Lock;
use crate::sole::Sole;
use crate::system::{System, TypeErased as TypeErasedSystem};
@@ -20,6 +21,7 @@ use crate::type_name::TypeName;
pub mod actions;
pub mod component;
pub mod event;
+pub mod extension;
pub mod lock;
pub mod query;
pub mod sole;
@@ -120,6 +122,17 @@ impl World
drop(event);
}
+ /// Adds a extensions.
+ ///
+ /// # Panics
+ /// Will panic if mutable internal lock cannot be acquired.
+ pub fn add_extension(&mut self, extension: impl Extension)
+ {
+ let extension_collector = ExtensionCollector::new(self);
+
+ extension.collect(extension_collector);
+ }
+
/// Emits a event, running all systems listening to the event for each compatible
/// entity.
///