1+ use std:: sync:: Mutex ;
2+ use specs:: prelude:: * ;
3+ use crate :: { Map , tile_walkable } ;
4+
5+ struct SpatialMap {
6+ blocked : Vec < ( bool , bool ) > ,
7+ tile_content : Vec < Vec < ( Entity , bool ) > >
8+ }
9+
10+ impl SpatialMap {
11+ fn new ( ) -> Self {
12+ Self {
13+ blocked : Vec :: new ( ) ,
14+ tile_content : Vec :: new ( )
15+ }
16+ }
17+ }
18+
19+ lazy_static ! {
20+ static ref SPATIAL_MAP : Mutex <SpatialMap > = Mutex :: new( SpatialMap :: new( ) ) ;
21+ }
22+
23+ pub fn set_size ( map_tile_count : usize ) {
24+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
25+ lock. blocked = vec ! [ ( false , false ) ; map_tile_count] ;
26+ lock. tile_content = vec ! [ Vec :: new( ) ; map_tile_count] ;
27+ }
28+
29+ pub fn clear ( ) {
30+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
31+ lock. blocked . iter_mut ( ) . for_each ( |b| { b. 0 = false ; b. 1 = false ; } ) ;
32+ for content in lock. tile_content . iter_mut ( ) {
33+ content. clear ( ) ;
34+ }
35+ }
36+
37+ pub fn populate_blocked_from_map ( map : & Map ) {
38+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
39+ for ( i, tile) in map. tiles . iter ( ) . enumerate ( ) {
40+ lock. blocked [ i] . 0 = !tile_walkable ( * tile) ;
41+ }
42+ }
43+
44+ pub fn index_entity ( entity : Entity , idx : usize , blocks_tile : bool ) {
45+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
46+ lock. tile_content [ idx] . push ( ( entity, blocks_tile) ) ;
47+ if blocks_tile {
48+ lock. blocked [ idx] . 1 = true ;
49+ }
50+ }
51+
52+ pub fn is_blocked ( idx : usize ) -> bool {
53+ let lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
54+ lock. blocked [ idx] . 0 || lock. blocked [ idx] . 1
55+ }
56+
57+ pub fn set_blocked ( idx : usize , blocked : bool ) {
58+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
59+ lock. blocked [ idx] = ( lock. blocked [ idx] . 0 , blocked) ;
60+ }
61+
62+ pub fn for_each_tile_content < F > ( idx : usize , mut f : F )
63+ where F : FnMut ( Entity )
64+ {
65+ let lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
66+ for entity in lock. tile_content [ idx] . iter ( ) {
67+ f ( entity. 0 ) ;
68+ }
69+ }
70+
71+ pub fn get_tile_content_clone ( idx : usize ) -> Vec < Entity > {
72+ let lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
73+ lock. tile_content [ idx] . iter ( ) . map ( |( e, _) | * e) . collect ( )
74+ }
75+
76+ pub fn move_entity ( entity : Entity , moving_from : usize , moving_to : usize ) {
77+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
78+ let mut entity_blocks = false ;
79+ lock. tile_content [ moving_from] . retain ( |( e, blocks) | {
80+ if * e == entity {
81+ entity_blocks = * blocks;
82+ false
83+ } else {
84+ true
85+ }
86+ } ) ;
87+ lock. tile_content [ moving_to] . push ( ( entity, entity_blocks) ) ;
88+
89+ // Recalculate blocks for both tiles
90+ let mut from_blocked = false ;
91+ let mut to_blocked = false ;
92+ lock. tile_content [ moving_from] . iter ( ) . for_each ( |( _, blocks) | if * blocks { from_blocked = true ; } ) ;
93+ lock. tile_content [ moving_to] . iter ( ) . for_each ( |( _, blocks) | if * blocks { to_blocked = true ; } ) ;
94+ lock. blocked [ moving_from] . 1 = from_blocked;
95+ lock. blocked [ moving_to] . 1 = to_blocked;
96+ }
97+
98+ pub fn remove_entity ( entity : Entity , idx : usize ) {
99+ let mut lock = SPATIAL_MAP . lock ( ) . unwrap ( ) ;
100+ lock. tile_content [ idx] . retain ( |( e, _) | * e != entity ) ;
101+ let mut from_blocked = false ;
102+ lock. tile_content [ idx] . iter ( ) . for_each ( |( _, blocks) | if * blocks { from_blocked = true ; } ) ;
103+ lock. blocked [ idx] . 1 = from_blocked;
104+ }
0 commit comments