#[macro_use]
extern crate derivative;
extern crate hibitset;
extern crate shred;
extern crate specs;
extern crate shrev;
use std::hash::Hash;
use std::marker::PhantomData;
use hibitset::BitSet;
use specs::storage::{UnprotectedStorage, ComponentEvent};
use specs::{Component, Join, World, Tracked};
use shrev::EventChannel;
type Index = u32;
pub trait Id: Copy + Eq + Hash + Ord + Send + Sync + Sized + 'static {
fn from_u32(value: u32) -> Self;
fn id(&self) -> u32;
}
#[derive(Derivative)]
#[derivative(Default(bound = "D: Default"))]
pub struct Storage<C, D: UnprotectedStorage<C>, I> {
data: D,
bitset: BitSet,
phantom: PhantomData<(C, I)>,
}
impl<C, D, I> Storage<C, D, I>
where
C: Component,
D: UnprotectedStorage<C>,
I: Id,
{
pub fn get(&self, id: I) -> Option<&C> {
match self.bitset.contains(id.id()) {
true => unsafe { Some(self.data.get(id.id())) },
false => None,
}
}
pub fn get_mut(&mut self, id: I) -> Option<&mut C> {
match self.bitset.contains(id.id()) {
true => unsafe { Some(self.data.get_mut(id.id())) },
false => None,
}
}
pub fn insert(&mut self, id: I, comp: C) -> Option<C> {
let old = match self.bitset.add(id.id()) {
true => unsafe { Some(self.data.remove(id.id())) },
false => None,
};
unsafe {
self.data.insert(id.id(), comp);
}
old
}
pub fn remove(&mut self, id: I) -> Option<C> {
match self.bitset.remove(id.id()) {
true => unsafe { Some(self.data.remove(id.id())) },
false => None,
}
}
}
impl<C, D, I> Tracked for Storage<C, D, I>
where D: Tracked + UnprotectedStorage<C>,
C: Component
{
fn channel(&self) -> &EventChannel<ComponentEvent> { self.data.channel() }
fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent> { self.data.channel_mut() }
}
impl<C, D, I> Drop for Storage<C, D, I>
where
D: UnprotectedStorage<C>,
{
fn drop(&mut self) {
unsafe {
self.data.clean(&self.bitset);
}
}
}
impl<'a, C, D, I> Join for &'a Storage<C, D, I>
where
D: UnprotectedStorage<C>,
{
type Type = &'a C;
type Value = &'a D;
type Mask = &'a BitSet;
unsafe fn open(self) -> (Self::Mask, Self::Value) {
(&self.bitset, &self.data)
}
unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
(*value).get(id)
}
}
impl<'a, C, D, I> Join for &'a mut Storage<C, D, I>
where
D: UnprotectedStorage<C>,
{
type Type = &'a mut C;
type Value = &'a mut D;
type Mask = &'a BitSet;
unsafe fn open(self) -> (Self::Mask, Self::Value) {
(&self.bitset, &mut self.data)
}
unsafe fn get(value: &mut Self::Value, id: Index) -> Self::Type {
let value: *mut Self::Value = value as *mut Self::Value;
(*value).get_mut(id)
}
}
pub trait WorldExt {
fn register_tile_comp<C, I>(&mut self)
where
C: Component + Send + Sync,
C::Storage: Default,
I: Id;
}
impl WorldExt for World {
fn register_tile_comp<C, I>(&mut self)
where
C: Component + Send + Sync,
C::Storage: Default,
I: Id,
{
self.add_resource(Storage::<C, C::Storage, I>::default());
}
}