aboutsummaryrefslogtreecommitdiff
path: root/stockton-types/src
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
commitc8c5e880781343d72671c231be8e132af5e2f344 (patch)
treed4736c557f0dba0dd667d10c4ad22f22fb2495ad /stockton-types/src
Initial Commit.
Diffstat (limited to 'stockton-types/src')
-rw-r--r--stockton-types/src/entity_store.rs97
-rw-r--r--stockton-types/src/lib.rs27
2 files changed, 124 insertions, 0 deletions
diff --git a/stockton-types/src/entity_store.rs b/stockton-types/src/entity_store.rs
new file mode 100644
index 0000000..99a9525
--- /dev/null
+++ b/stockton-types/src/entity_store.rs
@@ -0,0 +1,97 @@
+//! Stores entities in a world.
+
+use std::collections::HashMap;
+use std::boxed::Box;
+use std::ops::Index;
+use crate::Vector3;
+
+/// An entity, capable of recieving events.
+pub trait Entity {
+
+ /// Should return the position of this entity in 3d space.
+ ///
+ /// This will likely just be `self.pos`
+ fn get_position(&self) -> Vector3;
+
+}
+
+/// Stores all the entities in a live world. The BSPFile only specifies the starting entities,
+/// whereas this is mutable and thus is used to represent the current state of the world's entities.
+///
+/// Internally, this uses a vector to store the entities, and a hashmap to map names to indicies in that vector.
+///
+/// An entity's index may change, so if you want to target an entity throughout frames you should store its name.
+pub struct EntityStore {
+ entities: Vec<Box<dyn Entity>>,
+ name_to_index: HashMap<String, usize>
+}
+
+/// Returned when an entity's name conflicts with an existing entity.
+pub struct NameConflict;
+
+impl EntityStore {
+ /// Try to add the given entity with the given name.
+ ///
+ /// # Returns
+ /// The name & index of the added entity if successful.
+ /// If an entity already exists with the given name, NameConflict is returned.
+ pub fn add(&mut self, entity: Box<Entity>, name: String) -> Result<usize, NameConflict> {
+ if self.name_to_index.contains_key(&name) {
+ return Err(NameConflict)
+ }
+ self.name_to_index.insert(name, self.entities.len());
+ self.entities.push(entity);
+
+ Ok(self.entities.len() - 1)
+ }
+
+ /// Remove the entity with the given index, returning it.
+ ///
+ /// Takes O(2n - i) time.
+ pub fn remove_by_index(&mut self, index: usize) -> Option<Box<Entity>> {
+ if index >= self.entities.len() {
+ return None;
+ }
+ self.name_to_index.retain(|_,v| *v != index);
+ Some(self.entities.remove(index))
+ }
+
+ /// Removes the entity with the given name, returning it.
+ ///
+ /// Takes O(2n - i) time.
+ pub fn remove_by_name(&mut self, name: &str) -> Option<Box<Entity>> {
+ let mut index: usize = self.entities.len();
+
+ self.name_to_index.retain(|k,v| {
+ if k == name {
+ index = *v;
+ return false;
+ }
+ true
+ });
+
+ if index >= self.entities.len() {
+ return None;
+ }
+
+ Some(self.entities.remove(index))
+ }
+}
+
+/// Indexes the EntityStore for a specific index.
+/// If you want to target an entity for longer than one tick, store its name, not an index.
+impl Index<usize> for EntityStore {
+ type Output = Entity;
+ fn index(&self, index: usize) -> &Self::Output {
+ self.entities[index].as_ref()
+ }
+}
+
+/// Indexes the EntityStore for a specific name.
+/// This is what you should use if you plan to target an entity for more than one tick.
+impl Index<&str> for EntityStore {
+ type Output = Entity;
+ fn index(&self, index: &str) -> &Self::Output {
+ self.entities[self.name_to_index[index]].as_ref()
+ }
+} \ No newline at end of file
diff --git a/stockton-types/src/lib.rs b/stockton-types/src/lib.rs
new file mode 100644
index 0000000..259c40c
--- /dev/null
+++ b/stockton-types/src/lib.rs
@@ -0,0 +1,27 @@
+//! Common types for all stockton crates.
+
+extern crate stockton_bsp;
+extern crate nalgebra as na;
+
+use stockton_bsp::BSPFile;
+
+pub mod entity_store;
+use entity_store::EntityStore;
+
+/// Alias for convenience
+pub type Vector2 = na::base::Vector2<f32>;
+/// Alias for convenience
+pub type Vector3 = na::base::Vector3<f32>;
+
+/// Alias for convenience
+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