aboutsummaryrefslogtreecommitdiff
path: root/stockton-types
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:18 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:18 +0100
commit6ee3384750bb065e4397b02e2cc7f567f96da73a (patch)
tree2011ee3c2f654c0d00350d6385d1875b421bc3bb /stockton-types
parent70fb71ba581e33ef574eadf4dfa4a8eb84740df3 (diff)
feat(world): world creation
Diffstat (limited to 'stockton-types')
-rw-r--r--stockton-types/src/entity_store.rs18
-rw-r--r--stockton-types/src/lib.rs16
-rw-r--r--stockton-types/src/world.rs40
3 files changed, 63 insertions, 11 deletions
diff --git a/stockton-types/src/entity_store.rs b/stockton-types/src/entity_store.rs
index 99a9525..9984c0a 100644
--- a/stockton-types/src/entity_store.rs
+++ b/stockton-types/src/entity_store.rs
@@ -76,6 +76,24 @@ impl EntityStore {
Some(self.entities.remove(index))
}
+
+ /// Make a new EntityStore from a list of entities & names.
+ ///
+ /// Returns None in case of name conflicts in list.
+ pub fn from_entities(entities: Vec<(Box<Entity>, String)>) -> Option<EntityStore> {
+ let mut store = EntityStore {
+ entities: Vec::with_capacity(entities.len()),
+ name_to_index: HashMap::with_capacity(entities.len())
+ };
+
+ for (entity, name) in entities {
+ if store.add(entity, name).is_err() {
+ return None;
+ }
+ }
+
+ Some(store)
+ }
}
/// Indexes the EntityStore for a specific index.
diff --git a/stockton-types/src/lib.rs b/stockton-types/src/lib.rs
index 259c40c..0612e86 100644
--- a/stockton-types/src/lib.rs
+++ b/stockton-types/src/lib.rs
@@ -3,10 +3,11 @@
extern crate stockton_bsp;
extern crate nalgebra as na;
-use stockton_bsp::BSPFile;
-
pub mod entity_store;
-use entity_store::EntityStore;
+pub use entity_store::{EntityStore, Entity};
+
+pub mod world;
+pub use world::World;
/// Alias for convenience
pub type Vector2 = na::base::Vector2<f32>;
@@ -17,11 +18,4 @@ pub type Vector3 = na::base::Vector3<f32>;
pub type Vector2i = na::base::Vector2<i32>;
/// Alias for convenience
-pub type Vector3i = na::base::Vector3<i32>;
-
-/// A live and playable world. There are two parts: The map, which has walls and other static objects,
-/// and entities, which can move around and do things and are physics simulated.
-pub struct World<'a> {
- pub map: BSPFile<'a>,
- pub live_entities: EntityStore,
-} \ No newline at end of file
+pub type Vector3i = na::base::Vector3<i32>; \ No newline at end of file
diff --git a/stockton-types/src/world.rs b/stockton-types/src/world.rs
new file mode 100644
index 0000000..f687f5e
--- /dev/null
+++ b/stockton-types/src/world.rs
@@ -0,0 +1,40 @@
+//! The thing you play on and all the associated state.
+
+use crate::{EntityStore, Entity};
+use stockton_bsp::lumps::entities::Entity as BSPEntity;
+use stockton_bsp::BSPFile;
+
+use std::pin::Pin;
+
+/// A live and playable world. There are two parts: The map, which has walls and other static objects,
+/// and entities, which can move around and do things and are physics simulated.
+pub struct World<'a> {
+ pub map: Pin<Box<BSPFile<'a>>>,
+ pub live_entities: EntityStore,
+}
+
+impl<'a> World<'a> {
+ /// Create a new world from a BSPFile.
+ ///
+ /// Returns None if any entities in the map have name conflicts.
+ ///
+ /// `mapper` is called for each BSPEntity to map it to a concrete rust type.
+ pub fn new<F>(bsp: Pin<Box<BSPFile<'a>>>, mapper: F) -> Option<World<'a>>
+ where F: Fn(&BSPEntity) -> (Box<Entity>, String) {
+
+ let mut entities: Vec<(Box<Entity>, String)> = Vec::with_capacity(bsp.entities.entities.len());
+ for bsp_ent in bsp.entities.entities.iter() {
+ entities.push(mapper(&bsp_ent));
+ }
+
+ let store = EntityStore::from_entities(entities);
+ if store.is_none() {
+ return None;
+ }
+
+ Some(World {
+ map: bsp,
+ live_entities: store.unwrap()
+ })
+ }
+} \ No newline at end of file