@@ -12,10 +12,13 @@ use crate::{
12
12
world:: { NoiseData , CHUNK_SIZE , MAX_TREES_PER_CHUNK , NOISE_CHUNK_PER_ROW , NOISE_SIZE } ,
13
13
} ;
14
14
use glam:: Vec3 ;
15
+ use rand:: rngs:: StdRng ;
16
+ use rand:: { Rng , SeedableRng } ;
15
17
use std:: any:: Any ;
16
18
use std:: cell:: RefCell ;
17
19
use std:: collections:: HashMap ;
18
20
use std:: error:: Error ;
21
+ use std:: io:: { self , BufReader , Read } ;
19
22
use std:: rc:: Rc ;
20
23
use std:: sync:: { Arc , RwLock } ;
21
24
use wgpu:: util:: DeviceExt ;
@@ -40,10 +43,11 @@ pub struct Chunk {
40
43
pub chunk_water_index_buffer : Option < wgpu:: Buffer > ,
41
44
pub outside_blocks : Vec < Arc < RwLock < Block > > > ,
42
45
pub visible : bool ,
46
+ pub modified : bool , // if it should be saved
43
47
}
44
48
45
49
impl Chunk {
46
- pub fn add_block ( & mut self , block : Arc < RwLock < Block > > ) {
50
+ pub fn add_block ( & mut self , block : Arc < RwLock < Block > > , modify_status : bool ) {
47
51
let block_borrow = block. read ( ) . unwrap ( ) ;
48
52
let block_position = block_borrow. position ;
49
53
std:: mem:: drop ( block_borrow) ;
@@ -63,14 +67,17 @@ impl Chunk {
63
67
}
64
68
65
69
y_blocks[ block_position. y as usize ] = Some ( block) ;
70
+ if modify_status {
71
+ self . modified = true ;
72
+ }
66
73
}
67
74
pub fn remove_block ( & mut self , block_r_position : & Vec3 ) {
68
- let mut a = 0 ;
69
75
let mut blocks_borrow = self . blocks . write ( ) . unwrap ( ) ;
70
76
let y_blocks = blocks_borrow
71
77
. get_mut ( ( ( block_r_position. x * CHUNK_SIZE as f32 ) + block_r_position. z ) as usize )
72
78
. expect ( "Cannot delete oob block" ) ;
73
79
y_blocks[ block_r_position. y as usize ] = None ;
80
+ self . modified = true ;
74
81
}
75
82
pub fn block_type_at ( & self , position : & glam:: Vec3 ) -> Option < BlockType > {
76
83
let block = self . get_block_at_relative ( position) ?;
@@ -163,6 +170,10 @@ impl Chunk {
163
170
let faces = FaceDirections :: all ( ) ;
164
171
165
172
for face in faces. iter ( ) {
173
+ // For water block types, we only care about the top face
174
+ if block. block_type == BlockType :: Water && * face != FaceDirections :: Top {
175
+ continue ;
176
+ }
166
177
let mut is_visible = true ;
167
178
let face_position = face. get_normal_vector ( ) + position;
168
179
@@ -218,7 +229,6 @@ impl Chunk {
218
229
}
219
230
} else if self . exists_block_at ( & face_position) {
220
231
is_visible = false ;
221
-
222
232
// This can be a oneline if, but it gets very hard to read
223
233
if self . block_type_at ( & face_position) == Some ( BlockType :: Water )
224
234
&& block. block_type != BlockType :: Water
@@ -336,7 +346,12 @@ impl Chunk {
336
346
337
347
pub fn create_blocks_data ( chunk_x : i32 , chunk_y : i32 , noise_data : Arc < NoiseData > ) -> BlockVec {
338
348
let size = ( CHUNK_SIZE * CHUNK_SIZE ) as usize ;
339
- let mut blocks: BlockVec = Arc :: new ( RwLock :: new ( vec ! [ vec![ ] ; size] ) ) ;
349
+ let blocks: BlockVec = Arc :: new ( RwLock :: new ( vec ! [
350
+ Vec :: with_capacity(
351
+ WATER_HEIGHT_LEVEL as usize
352
+ ) ;
353
+ size
354
+ ] ) ) ;
340
355
341
356
for x in 0 ..CHUNK_SIZE {
342
357
for z in 0 ..CHUNK_SIZE {
@@ -358,24 +373,15 @@ impl Chunk {
358
373
359
374
curr. push ( Some ( block. clone ( ) ) ) ;
360
375
}
361
- // Make sure the length is at least water level
376
+ // Fill with water empty blocks
362
377
for y in curr. len ( ) ..=( WATER_HEIGHT_LEVEL as usize ) {
363
378
if let None = curr. get ( y) {
364
- curr. push ( None ) ;
365
- }
366
- }
367
-
368
- for y in 0 ..=WATER_HEIGHT_LEVEL as usize {
369
- if let Some ( entry) = curr. get ( y) {
370
- // If there's not a block on this level, place water
371
- if let None = entry {
372
- let block = Arc :: new ( RwLock :: new ( Block :: new (
373
- glam:: vec3 ( x as f32 , y as f32 , z as f32 ) ,
374
- ( chunk_x, chunk_y) ,
375
- BlockType :: Water ,
376
- ) ) ) ;
377
- curr[ y as usize ] = Some ( block) ;
378
- }
379
+ let block = Arc :: new ( RwLock :: new ( Block :: new (
380
+ glam:: vec3 ( x as f32 , y as f32 , z as f32 ) ,
381
+ ( chunk_x, chunk_y) ,
382
+ BlockType :: Water ,
383
+ ) ) ) ;
384
+ curr. push ( Some ( block) ) ;
379
385
}
380
386
}
381
387
}
@@ -385,34 +391,48 @@ impl Chunk {
385
391
}
386
392
// TODO: Use white noise + check that the tree is not being placed on water.
387
393
pub fn place_trees ( & mut self ) {
388
- let number_of_trees = rand:: random :: < f32 > ( ) ;
389
- let number_of_trees = f32:: floor ( number_of_trees * MAX_TREES_PER_CHUNK as f32 ) as u32 ;
390
-
391
- for _ in 0 ..number_of_trees {
392
- let x = f32:: floor ( rand:: random :: < f32 > ( ) * CHUNK_SIZE as f32 ) as usize ;
393
- let z = f32:: floor ( rand:: random :: < f32 > ( ) * CHUNK_SIZE as f32 ) as usize ;
394
-
395
- let blocks_read = self . blocks . read ( ) . unwrap ( ) ;
396
- let block_column = blocks_read
397
- . get ( ( x * CHUNK_SIZE as usize ) + z)
398
- . expect ( "TODO: fix this case" ) ;
399
- let highest_block = block_column
400
- . last ( )
401
- . expect ( "TODO: Fix this case -h" )
402
- . as_ref ( )
403
- . unwrap ( )
404
- . read ( )
405
- . unwrap ( )
406
- . absolute_position ;
407
- std:: mem:: drop ( blocks_read) ;
408
-
409
- let tree_blocks = crate :: structures:: Tree :: get_blocks ( highest_block) ;
394
+ let mut rng = StdRng :: seed_from_u64 ( ( self . x * 10 * self . y ) as u64 ) ;
395
+ let number_of_trees = rng. gen :: < f32 > ( ) ;
396
+ let mut number_of_trees = f32:: floor ( number_of_trees * MAX_TREES_PER_CHUNK as f32 ) as u32 ;
397
+
398
+ // Do a max 100 retries
399
+ for _ in 0 ..100 {
400
+ if number_of_trees == 0 {
401
+ break ;
402
+ }
403
+ let mut tree_blocks = vec ! [ ] ;
404
+ {
405
+ let x = f32:: floor ( rng. gen :: < f32 > ( ) * CHUNK_SIZE as f32 ) as usize ;
406
+ let z = f32:: floor ( rng. gen :: < f32 > ( ) * CHUNK_SIZE as f32 ) as usize ;
407
+
408
+ let blocks_read = self . blocks . read ( ) . unwrap ( ) ;
409
+ let block_column = blocks_read
410
+ . get ( ( x * CHUNK_SIZE as usize ) + z)
411
+ . expect ( "TODO: fix this case" ) ;
412
+ let highest_block = block_column
413
+ . last ( )
414
+ . expect ( "TODO: Fix this case -h" )
415
+ . as_ref ( )
416
+ . unwrap ( )
417
+ . read ( )
418
+ . unwrap ( ) ;
419
+ if highest_block. block_type == BlockType :: Water
420
+ || highest_block. block_type == BlockType :: Leaf
421
+ {
422
+ continue ;
423
+ }
424
+ let highest_block_position = highest_block. absolute_position . clone ( ) ;
410
425
426
+ tree_blocks. append ( & mut crate :: structures:: Tree :: get_blocks (
427
+ highest_block_position,
428
+ ) ) ;
429
+ number_of_trees -= 1 ;
430
+ }
411
431
for block in tree_blocks. iter ( ) {
412
432
let block_brw = block. read ( ) . unwrap ( ) ;
413
433
let block_chunk = block_brw. get_chunk_coords ( ) ;
414
434
if block_chunk == ( self . x , self . y ) {
415
- self . add_block ( block. clone ( ) ) ;
435
+ self . add_block ( block. clone ( ) , false ) ;
416
436
} else {
417
437
self . outside_blocks . push ( block. clone ( ) )
418
438
}
@@ -488,6 +508,7 @@ impl Chunk {
488
508
chunk_data_layout : Arc < wgpu:: BindGroupLayout > ,
489
509
) -> Chunk {
490
510
let mut was_loaded = false ;
511
+
491
512
let blocks = if let Ok ( blocks) = Self :: load ( Box :: new ( ( x, y) ) ) {
492
513
was_loaded = true ;
493
514
blocks
@@ -511,6 +532,7 @@ impl Chunk {
511
532
} ) ;
512
533
513
534
let mut chunk = Chunk {
535
+ modified : false ,
514
536
chunk_water_index_buffer : None ,
515
537
chunk_water_vertex_buffer : None ,
516
538
blocks,
@@ -582,7 +604,7 @@ impl Loadable<BlockVec> for Chunk {
582
604
let y = coords. next ( ) . unwrap ( ) . parse :: < i32 > ( ) ?;
583
605
584
606
let size = ( CHUNK_SIZE * CHUNK_SIZE ) as usize ;
585
- let mut blocks: BlockVec = Arc :: new ( RwLock :: new ( vec ! [ vec![ ] ; size] ) ) ;
607
+ let blocks: BlockVec = Arc :: new ( RwLock :: new ( vec ! [ vec![ ] ; size] ) ) ;
586
608
if * chunk_position == ( x, y) {
587
609
let file_contents = std:: fs:: read_to_string ( format ! ( "data/chunk{}_{}" , x, y) ) ?;
588
610
for line in file_contents. lines ( ) {
0 commit comments