This commit is contained in:
LunarAkai 2025-08-04 01:47:13 +02:00
commit ca57bce787
7 changed files with 177 additions and 484 deletions

View file

@ -0,0 +1,131 @@
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct GenerationalIndex {
index: usize,
generation: u64,
}
impl GenerationalIndex {
pub fn index(&self) -> usize {
self.index
}
pub fn generation(&self) -> u64 {
self.generation
}
}
struct AllocatorEntry {
is_live: bool,
generation: u64,
}
pub struct GenerationalIndexAllocator {
entries: Vec<AllocatorEntry>,
free: Vec<usize>,
}
impl GenerationalIndexAllocator {
pub fn allocate(&mut self) -> GenerationalIndex {
match self.free.pop() {
Some(index) =>{
self.entries[index].generation += 1;
self.entries[index].is_live = true;
GenerationalIndex {
index,
generation: self.entries[index].generation,
}
},
None => {
self.entries.push(AllocatorEntry {
is_live: true,
generation: 0,
});
GenerationalIndex {
index: self.entries.len() -1,
generation: 0,
}
}
}
}
// Returns true if the index was allocated before and is now deallocated
pub fn deallocate(&mut self, index: GenerationalIndex) -> bool {
if self.is_live(index) {
self.entries[index.index()].is_live = false;
self.free.push(index.index());
true
} else {
false
}
}
pub fn is_live(&self, index: GenerationalIndex) -> bool {
index.index() < self.entries.len() && self.entries[index.index()].generation == index.generation && self.entries[index.index()].is_live
}
}
struct ArrayEntry<T> {
value: T,
generation: u64,
}
pub struct GenerationalIndexArray<T>(Vec<Option<ArrayEntry<T>>>);
impl <T> GenerationalIndexArray<T> {
pub fn set(&mut self, index: GenerationalIndex, value: T) {
while self.0.len() <= index.index() {
self.0.push(None);
}
let previous_generation = match &self.0[index.index()] {
Some(entry) => entry.generation,
None => 0,
};
if previous_generation > index.generation() {
panic!("write an index from previous gen");
}
self.0[index.index()] = Some(ArrayEntry {
value,
generation: index.generation(),
});
}
pub fn remove(&mut self, index: GenerationalIndex) {
if index.index() < self.0.len() {
self.0[index.index()] = None;
}
}
pub fn get(&self, index: GenerationalIndex) -> Option<&T> {
if index.index() >= self.0.len() {
return None;
}
match &self.0[index.index()] {
Some(entry) => if entry.generation == index.generation() {
Some(&entry.value)
} else {
None
},
None => None
}
}
pub fn get_mut(&mut self, index: GenerationalIndex) -> Option<&mut T> {
if index.index() >= self.0.len() {
return None;
}
match &mut self.0[index.index()] {
Some(entry) => if entry.generation == index.generation() {
Some(&mut entry.value)
} else {
None
},
None => None
}
}
}

View file

@ -0,0 +1,15 @@
use anymap::AnyMap;
use crate::generational_index::{GenerationalIndex, GenerationalIndexAllocator, GenerationalIndexArray};
pub mod generational_index;
pub type Entity = GenerationalIndex;
pub type EntityMap<T> = GenerationalIndexArray<T>;
// based on: https://kyren.github.io/2018/09/14/rustconf-talk.html
pub struct ECS {
pub entity_allocator: GenerationalIndexAllocator,
pub entity_components: AnyMap,
pub resources: AnyMap
}