use ron::{
de::from_reader,
from_str,
ser::{to_string_pretty, PrettyConfig},
};
use serde::{Deserialize, Serialize};
use std::{
cell::{RefCell, RefMut},
fs::File,
io::Write,
};
use crate::{support::nameof, Component};
#[derive(Serialize, Deserialize)]
pub struct Entity {
pub(crate) id: usize,
pub is_active: bool,
stored_components: Vec<String>,
components: Vec<RefCell<Box<dyn Component>>>,
}
impl Entity {
pub fn import_ron(path: &str) -> std::io::Result<Self> {
let file = File::open(path)?;
let e: Entity = match from_reader(file) {
Ok(x) => x,
Err(e) => panic!("Failed to deserialize entity: {}", e),
};
return Ok(e);
}
pub fn from_ron(ron: &str) -> Self {
let e: Entity = match from_str(ron) {
Ok(x) => x,
Err(e) => panic!("Failed to deserialize entity: {}", e),
};
return e;
}
pub fn export_ron(&self, path: &str) -> std::io::Result<()> {
let mut file = File::create(path)?;
let ron = self.to_ron();
file.write_all(ron.as_bytes())?;
return Ok(());
}
pub fn to_ron(&self) -> String {
return match to_string_pretty(self, PrettyConfig::default()) {
Ok(s) => s,
Err(e) => panic!("Failed to serialize entity: {}", e),
};
}
pub fn id(&self) -> usize {
return self.id;
}
pub fn has_component<T: 'static + Component>(&self) -> bool {
let name = &String::from(std::any::type_name::<T>());
return self.stored_components.contains(name);
}
pub fn get_component<T: 'static + Component>(&self) -> Option<RefMut<T>> {
for component in self.components.iter() {
if let Ok(borrowed) = component.try_borrow() {
if !borrowed.as_any().is::<T>() {
continue;
}
} else {
continue;
}
return Some(RefMut::map(component.borrow_mut(), |component| {
component.as_any_mut().downcast_mut::<T>().unwrap()
}));
}
println!(
"Component \'{}\' either doesn't exist in entity {} or is already borrowed",
std::any::type_name::<T>(),
self.id
);
return None;
}
}
pub struct EntityBuilder {
components: Vec<RefCell<Box<dyn Component>>>,
stored_components: Vec<String>,
}
impl EntityBuilder {
pub fn new() -> Self {
return EntityBuilder {
components: vec![],
stored_components: vec![],
};
}
pub fn with<T: 'static + Component>(mut self, component: T) -> Self {
self.stored_components
.push(String::from(nameof(&component)));
self.components.push(RefCell::new(Box::new(component)));
return self;
}
pub fn build(self) -> Entity {
return Entity {
id: 0,
is_active: true,
components: self.components,
stored_components: self.stored_components,
};
}
}