use crate::card::Card;
use crate::ecs::entity_store::{ReadReference, StoreHandle, WriteReference};
use crate::ecs::{Component, ComponentAdapter, ComponentManager, Entity, EntityManager};
use crate::snowflake::{Snowflake, SnowflakeGenerator};
use crate::util::Result;
use dashmap::DashMap;
use std::any::TypeId;
use std::collections::HashSet;
use std::sync::Arc;
pub struct CardType {
type_id: Snowflake,
component_manager: Arc<ComponentManager<CardType>>,
components_attached: HashSet<TypeId>,
component_preloads: DashMap<TypeId, Box<dyn Component<Self> + Send + Sync + 'static>>,
dirty: bool,
}
impl CardType {
pub fn new(
type_id: Snowflake,
component_manager: Arc<ComponentManager<CardType>>,
components_attached: HashSet<TypeId>,
) -> CardType {
CardType {
type_id,
component_manager,
components_attached,
component_preloads: DashMap::new(),
dirty: false,
}
}
pub fn generate(
snowflake_gen: &mut SnowflakeGenerator,
component_manager: Arc<ComponentManager<CardType>>,
) -> CardType {
CardType {
type_id: snowflake_gen.generate(),
component_manager,
components_attached: HashSet::new(),
component_preloads: DashMap::new(),
dirty: false,
}
}
pub fn id(&self) -> Snowflake {
self.type_id
}
}
impl Entity for CardType {
fn new(id: Snowflake, cm: Arc<ComponentManager<Self>>, components: HashSet<TypeId>) -> Self {
CardType::new(id, cm, components)
}
fn id(&self) -> Snowflake {
self.type_id
}
fn component_manager(&self) -> &ComponentManager<CardType> {
&self.component_manager
}
fn components_attached(&self) -> &HashSet<TypeId> {
&self.components_attached
}
fn components_attached_mut(&mut self) -> &mut HashSet<TypeId> {
&mut self.components_attached
}
fn preloaded_components(
&self,
) -> &DashMap<TypeId, Box<dyn Component<Self> + Send + Sync + 'static>> {
&self.component_preloads
}
fn dirty(&self) -> bool {
self.dirty
}
fn dirty_mut(&mut self) -> &mut bool {
&mut self.dirty
}
}
impl Clone for CardType {
fn clone(&self) -> Self {
Self {
type_id: self.type_id,
dirty: self.dirty,
component_manager: self.component_manager.clone(),
components_attached: self.components_attached.clone(),
component_preloads: DashMap::new(),
}
}
}
#[derive(Clone)]
pub struct AttachedCardType {
type_id: Snowflake,
}
impl AttachedCardType {
pub fn new(type_id: Snowflake) -> AttachedCardType {
AttachedCardType { type_id }
}
pub fn type_id(&self) -> Snowflake {
self.type_id
}
pub fn load(&self, ecs: &EntityManager) -> Result<ReadReference<StoreHandle<CardType>>> {
ecs.load(self.type_id)
}
pub fn load_mut(&self, ecs: &EntityManager) -> Result<WriteReference<StoreHandle<CardType>>> {
ecs.load_mut(self.type_id)
}
}
impl From<Snowflake> for AttachedCardType {
fn from(id: Snowflake) -> AttachedCardType {
AttachedCardType { type_id: id }
}
}
impl From<AttachedCardType> for Snowflake {
fn from(card_type: AttachedCardType) -> Snowflake {
card_type.type_id
}
}
impl Component<Card> for AttachedCardType {}
pub type CardTypeLayer<W> = ComponentAdapter<Card, Snowflake, AttachedCardType, W>;
#[cfg(test)]
mod tests {
use super::*;
use crate::local_storage::{LocalComponentStorage, LocalEntityStorage};
use crate::snowflake::SnowflakeGenerator;
#[derive(Debug, Clone, PartialEq)]
struct MockTypeData {
title: String,
character: String,
}
struct Fixtures {
ecs_manager: EntityManager,
snowflake_gen: SnowflakeGenerator,
}
impl Fixtures {
fn new() -> Fixtures {
let mut ecs_manager = EntityManager::new();
ecs_manager
.register_entity(LocalEntityStorage::<Card>::new())
.unwrap();
ecs_manager
.register_entity(LocalEntityStorage::<CardType>::new())
.unwrap();
ecs_manager
.register_component(
"MockTypeData",
LocalComponentStorage::<CardType, MockTypeData>::new(),
)
.unwrap();
ecs_manager
.register_component(
"CardType",
CardTypeLayer::new(LocalComponentStorage::<Card, Snowflake>::new()),
)
.unwrap();
Fixtures {
ecs_manager,
snowflake_gen: SnowflakeGenerator::new(0, 0),
}
}
}
impl Component<CardType> for MockTypeData {}
#[test]
fn test_store_type() {
let mut fixtures = Fixtures::new();
let type_id = fixtures.snowflake_gen.generate();
let card_id: Snowflake;
let mut card: Card = fixtures
.ecs_manager
.create(fixtures.snowflake_gen.generate())
.unwrap();
card.set_component(AttachedCardType::new(type_id)).unwrap();
card_id = card.id();
fixtures.ecs_manager.store(card).unwrap();
let handle = fixtures.ecs_manager.load::<Card>(card_id).unwrap();
let card = handle.get().unwrap();
let attached_type: AttachedCardType = card.get_component().unwrap().unwrap();
assert_eq!(attached_type.type_id, type_id);
}
#[test]
fn test_attached_card_type_load() {
let mut fixtures = Fixtures::new();
let mut card_type: CardType = fixtures
.ecs_manager
.create(fixtures.snowflake_gen.generate())
.unwrap();
let type_id = card_type.id();
let type_data = MockTypeData {
title: "Foo".to_owned(),
character: "Alice".to_owned(),
};
card_type.set_component(type_data).unwrap();
fixtures.ecs_manager.store(card_type).unwrap();
let card_id: Snowflake;
let mut card: Card = fixtures
.ecs_manager
.create(fixtures.snowflake_gen.generate())
.unwrap();
card.set_component(AttachedCardType::new(type_id)).unwrap();
card_id = card.id();
fixtures.ecs_manager.store(card).unwrap();
let handle = fixtures.ecs_manager.load::<Card>(card_id).unwrap();
let card = handle.get().unwrap();
let attached_type: AttachedCardType = card.get_component().unwrap().unwrap();
assert_eq!(attached_type.type_id, type_id);
let handle = attached_type.load(&fixtures.ecs_manager).unwrap();
let card_type = handle.get().unwrap();
let type_data: MockTypeData = card_type.get_component().unwrap().unwrap();
assert_eq!(type_data.title, "Foo");
assert_eq!(type_data.character, "Alice");
}
}