1use std::sync::{RwLock, Arc, RwLockReadGuard, RwLockWriteGuard};
2use std::collections::{HashMap, HashSet};
3use std::collections::hash_map::Entry;
4use std::fmt::{Debug, Formatter};
5
6use hecs::{World as EcsWorld, EntityBuilder, Entity, EntityRef};
7use uuid::Uuid;
8
9use crate::entity::{GlobalEntities, EntityType};
10use crate::block::{GlobalBlocks, BlockState};
11use crate::biome::GlobalBiomes;
12use crate::heightmap::GlobalHeightmaps;
13use crate::pos::{EntityPos, BlockPos};
14use crate::debug;
15
16use super::source::{LevelSource, ChunkLoadRequest, ChunkSaveRequest, LevelSourceError, ProtoChunk};
17use super::chunk::{Chunk, ChunkHeight, ChunkResult, ChunkError};
18
19
20pub struct LevelEnv {
23 pub blocks: GlobalBlocks,
25 pub biomes: GlobalBiomes,
27 pub entities: GlobalEntities,
29 pub heightmaps: GlobalHeightmaps
31}
32
33impl LevelEnv {
34
35 pub fn new(
36 blocks: GlobalBlocks,
37 biomes: GlobalBiomes,
38 entities: GlobalEntities,
39 heightmaps: GlobalHeightmaps
40 ) -> Self {
41 LevelEnv {
42 blocks,
43 biomes,
44 entities,
45 heightmaps
46 }
47 }
48
49}
50
51impl Debug for LevelEnv {
52 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53 f.debug_struct("LevelEnv")
54 .field("states_count", &self.blocks.states_count())
55 .field("blocks_count", &self.blocks.blocks_count())
56 .field("entity_types_count", &self.entities.entity_types_count())
57 .field("heightmaps_count", &self.heightmaps.heightmaps_count())
58 .finish()
59 }
60}
61
62
63pub struct Level {
67 id: String,
69 env: Arc<LevelEnv>,
72 source: Box<dyn LevelSource>,
75 loading_chunks: HashSet<(i32, i32)>,
77 height: ChunkHeight,
79 pub chunks: ChunkStorage,
81 pub entities: EntityStorage
83}
84
85impl Level {
86
87 pub fn new<S>(id: String, env: Arc<LevelEnv>, height: ChunkHeight, source: S) -> Self
88 where
89 S: LevelSource + 'static,
90 {
91
92 assert_ne!(env.blocks.states_count(), 0, "The given environment has no state, a level requires at least one block state.");
93 assert_ne!(env.biomes.biomes_count(), 0, "The given environment has no biome, a level requires at least one biome.");
94
95 Level {
96 id,
97 height,
98 source: Box::new(source),
99 loading_chunks: HashSet::new(),
100 chunks: ChunkStorage {
101 chunks: HashMap::new()
102 },
103 entities: EntityStorage {
104 ecs: EcsWorld::new(),
105 builder: EntityBuilder::new()
106 },
107 env,
108 }
109
110 }
111
112 pub fn get_id(&self) -> &String {
114 &self.id
115 }
116
117 pub fn get_env(&self) -> &Arc<LevelEnv> {
119 &self.env
120 }
121
122 pub fn get_height(&self) -> ChunkHeight {
125 self.height
126 }
127
128 pub fn request_chunk_load(&mut self, cx: i32, cz: i32) -> bool {
132 if !self.loading_chunks.contains(&(cx, cz)) {
133 match self.source.request_chunk_load(ChunkLoadRequest {
135 env: Arc::clone(&self.env),
136 height: self.height,
137 cx,
138 cz
139 }) {
140 Ok(_) => {
141 self.loading_chunks.insert((cx, cz));
142 true
143 }
144 Err(_) => false
145 }
146 } else {
147 false
148 }
149 }
150
151 pub fn load_chunks_with_callback<F>(&mut self, mut callback: F)
155 where
156 F: FnMut(i32, i32, Result<&Arc<RwLock<Chunk>>, LevelSourceError>),
157 {
158 while let Some(res) = self.source.poll_chunk() {
159 match res {
160 Ok(ProtoChunk {
161 inner: chunk,
162 mut proto_entities,
163 dirty
164 }) => {
165
166 let mut chunk = *chunk;
167 let (cx, cz) = chunk.get_position();
168 self.loading_chunks.remove(&(cx, cz));
171
172 let mut entities_handles = Vec::with_capacity(proto_entities.len());
175
176 for (entity_builder, _) in &mut proto_entities {
178 unsafe {
179 let entity = self.entities.add_entity_unchecked(entity_builder);
180 chunk.add_entity_unchecked(entity);
181 entities_handles.push(entity);
182 }
183 }
184
185 for (i, (_, passengers)) in proto_entities.into_iter().enumerate() {
187 if !passengers.is_empty() {
188
189 let mut base_entity = self.entities.ecs.get_mut::<BaseEntity>(entities_handles[i]).unwrap();
194 let mut passengers_handles = Vec::with_capacity(passengers.len());
195
196 for passenger_proto_index in passengers {
197 passengers_handles.push(entities_handles[passenger_proto_index]);
198 }
199
200 base_entity.passengers = Some(passengers_handles);
201
202 }
203 }
204
205 let chunk_arc = self.chunks.insert_chunk(chunk);
206 callback(cx, cz, Ok(chunk_arc));
207
208 if dirty {
209 self.request_chunk_save(cx, cz);
210 }
211
212 },
213 Err((err, chunk_info)) => {
214 debug!("Failed to load chunk at {}/{}: {}", chunk_info.cx, chunk_info.cz, err);
217 self.loading_chunks.remove(&(chunk_info.cx, chunk_info.cz));
218 callback(chunk_info.cx, chunk_info.cz, Err(err));
219 }
220 }
221 }
222 }
223
224 #[inline]
227 pub fn load_chunks(&mut self) {
228 self.load_chunks_with_callback(|_, _, _| {});
229 }
230
231 #[inline]
234 pub fn get_loading_chunks_count(&self) -> usize {
235 self.loading_chunks.len()
236 }
237
238 pub fn request_chunk_save(&mut self, cx: i32, cz: i32) -> bool {
241 if let Some(chunk) = self.chunks.get_chunk_arc(cx, cz) {
242 self.source.request_chunk_save(ChunkSaveRequest {
243 cx,
244 cz,
245 chunk
246 }).is_ok()
247 } else {
248 false
249 }
250 }
251
252 pub fn spawn_entity(&mut self, entity_type: &'static EntityType, pos: EntityPos) -> Option<Entity> {
255
256 if !self.env.entities.has_entity_type(entity_type) {
257 return None;
258 }
259
260 let chunk = self.chunks.get_chunk_at_block_mut(BlockPos::from(&pos));
261 let entity = unsafe { self.entities.spawn_entity_unchecked(entity_type, pos) };
262
263 if let Some(mut chunk) = chunk {
264 unsafe {
265 chunk.add_entity_unchecked(entity);
266 }
267 }
268
269 Some(entity)
270
271 }
272
273}
274
275
276pub struct ChunkStorage {
277 chunks: HashMap<(i32, i32), Arc<RwLock<Chunk>>>,
279}
280
281impl ChunkStorage {
282
283 pub fn get_chunks_count(&self) -> usize {
286 self.chunks.len()
287 }
288
289 pub fn insert_chunk(&mut self, chunk: Chunk) -> &Arc<RwLock<Chunk>> {
291 let pos = chunk.get_position();
292 let arc = Arc::new(RwLock::new(chunk));
293 match self.chunks.entry(pos) {
294 Entry::Occupied(mut o) => {
295 o.insert(arc);
296 o.into_mut()
297 },
298 Entry::Vacant(v) => {
299 v.insert(arc)
300 }
301 }
302 }
303
304 pub fn get_chunk_arc(&self, cx: i32, cz: i32) -> Option<Arc<RwLock<Chunk>>> {
305 self.chunks.get(&(cx, cz)).map(Arc::clone)
306 }
307
308 pub fn is_chunk_loaded(&self, cx: i32, cz: i32) -> bool {
310 self.chunks.contains_key(&(cx, cz))
311 }
312
313 pub fn get_chunk(&self, cx: i32, cz: i32) -> Option<RwLockReadGuard<Chunk>> {
315 self.chunks.get(&(cx, cz)).map(|arc| arc.read().unwrap())
316 }
317
318 pub fn get_chunk_mut(&self, cx: i32, cz: i32) -> Option<RwLockWriteGuard<Chunk>> {
320 self.chunks.get(&(cx, cz)).map(|arc| arc.write().unwrap())
321 }
322
323 #[inline]
325 pub fn get_chunk_at(&self, x: i32, z: i32) -> Option<RwLockReadGuard<Chunk>> {
326 self.get_chunk(x >> 4, z >> 4)
327 }
328
329 #[inline]
331 pub fn get_chunk_at_mut(&self, x: i32, z: i32) -> Option<RwLockWriteGuard<Chunk>> {
332 self.get_chunk_mut(x >> 4, z >> 4)
333 }
334
335 #[inline]
336 pub fn get_chunk_at_block(&self, block_pos: BlockPos) -> Option<RwLockReadGuard<Chunk>> {
337 self.get_chunk_at(block_pos.x, block_pos.z)
338 }
339
340 #[inline]
341 pub fn get_chunk_at_block_mut(&self, block_pos: BlockPos) -> Option<RwLockWriteGuard<Chunk>> {
342 self.get_chunk_at_mut(block_pos.x, block_pos.z)
343 }
344
345 pub fn set_block_at(&self, x: i32, y: i32, z: i32, block: &'static BlockState) -> ChunkResult<()> {
348 if let Some(mut chunk) = self.get_chunk_at_mut(x, z) {
349 chunk.set_block_at(x, y, z, block)
350 } else {
351 Err(ChunkError::ChunkUnloaded)
352 }
353 }
354
355 pub fn get_block_at(&self, x: i32, y: i32, z: i32) -> ChunkResult<&'static BlockState> {
356 if let Some(chunk) = self.get_chunk_at(x, z) {
357 chunk.get_block_at(x, y, z)
358 } else {
359 Err(ChunkError::ChunkUnloaded)
360 }
361 }
362
363}
364
365
366pub struct EntityStorage {
367 pub ecs: EcsWorld,
369 builder: EntityBuilder,
371}
372
373impl EntityStorage {
374
375 pub unsafe fn spawn_entity_unchecked(&mut self, entity_type: &'static EntityType, pos: EntityPos) -> Entity {
387
388 self.builder.add(BaseEntity::new(entity_type, Uuid::new_v4(), pos));
389
390 for &component in entity_type.codecs {
391 component.default(&mut self.builder);
392 }
393
394 self.ecs.spawn(self.builder.build())
395
396 }
397
398 pub unsafe fn add_entity_unchecked(&mut self, entity_builder: &mut EntityBuilder) -> Entity {
401 self.ecs.spawn(entity_builder.build())
402 }
403
404 pub fn remove_entity(&mut self, entity: Entity) -> bool {
405 self.ecs.despawn(entity).is_ok()
406 }
407
408 pub fn get_entity_ref(&self, entity: Entity) -> Option<EntityRef> {
409 self.ecs.entity(entity).ok()
410 }
411
412}
413
414pub struct BaseEntity {
416 pub entity_type: &'static EntityType,
417 pub uuid: Uuid,
418 pub pos: EntityPos,
419 passengers: Option<Vec<Entity>>
421}
422
423impl BaseEntity {
424
425 pub fn new(entity_type: &'static EntityType, uuid: Uuid, pos: EntityPos) -> Self {
426 Self {
427 entity_type,
428 uuid,
429 pos,
430 passengers: None
431 }
432 }
433
434}