@@ -367,6 +367,140 @@ impl ChunkSection {
367367 } ,
368368 }
369369 }
370+
371+ pub fn slime_to_sec (
372+ crawlstate : CrawlState ,
373+ value : & slimeball_lib:: Section ,
374+ block_states : & Blocks ,
375+ ) -> Self {
376+ let mut blocks = Vec :: new ( ) ;
377+ let bit_length = ( 64 - ( value. block_states . palette . len ( ) as u64 ) . leading_zeros ( ) ) . max ( 4 ) ;
378+
379+ let blocks_per_long = 64 / bit_length;
380+
381+ #[ cfg( not( feature = "modern_art" ) ) ]
382+ let bit_mask = ( 1 << bit_length) - 1 ;
383+
384+ match value. block_states . data {
385+ None => blocks. fill ( 0 ) ,
386+ Some ( ref data) => {
387+ trace ! ( "data.len(): {}" , data. len( ) ) ;
388+ trace ! ( "blocks_per_long: {blocks_per_long}" ) ;
389+ blocks. resize ( data. len ( ) * blocks_per_long as usize , 0 ) ;
390+ let mut i = 0 ;
391+ for long in data. iter ( ) {
392+ #[ cfg( not( feature = "modern_art" ) ) ]
393+ {
394+ let long = * long as u64 ;
395+ for b in 0 ..blocks_per_long {
396+ blocks[ i] = ( ( long >> ( bit_length * b) ) & bit_mask) as i16 ;
397+ i += 1 ;
398+ }
399+ }
400+
401+ #[ cfg( feature = "modern_art" ) ]
402+ {
403+ let mut long = * long as u64 ;
404+ while long != 0 {
405+ blocks[ i] = ( long & ( ( 1 << bit_length) - 1 ) ) as i16 ;
406+ long >>= bit_length;
407+ i += 1 ;
408+ }
409+ }
410+ }
411+ }
412+ }
413+
414+ let palette = value
415+ . block_states
416+ . palette
417+ . iter ( )
418+ . map ( |b| BlockState :: parse_state_slime ( b, block_states) . unwrap_or ( BlockState :: AIR ) )
419+ . collect :: < Vec < _ > > ( ) ;
420+
421+ let blocks: Vec < u16 > = blocks
422+ . iter ( )
423+ // todo: come up with a better way to do this(?)
424+ . map ( |b| palette. get ( * b as usize ) . unwrap_or ( & BlockState :: AIR ) . 0 )
425+ . collect ( ) ;
426+
427+ let block_count = blocks. iter ( ) . filter ( |b| * * b != 0 ) . collect :: < Vec < _ > > ( ) . len ( ) ;
428+
429+ let bit_length = match palette. len ( ) {
430+ 1 => 0 ,
431+ l => ( 64 - l. leading_zeros ( ) ) . max ( 4 ) as u8 ,
432+ } ;
433+
434+ trace ! ( "bit_length: {bit_length}" ) ;
435+
436+ let palette = {
437+ if bit_length == 15 {
438+ Palette :: Direct
439+ } else if bit_length >= 4 {
440+ Palette :: Indirect ( VarInt ( palette. len ( ) as i32 ) , palette)
441+ } else {
442+ Palette :: SingleValued ( * palette. first ( ) . unwrap ( ) )
443+ }
444+ } ;
445+
446+ let blocks = match palette {
447+ Palette :: Indirect ( _, ref p) => blocks
448+ . iter ( )
449+ . map ( |requested| p. iter ( ) . position ( |pb| pb. 0 == * requested) . unwrap ( ) as u16 )
450+ . collect :: < Vec < _ > > ( ) ,
451+ _ => blocks,
452+ } ;
453+
454+ trace ! ( "palette: {:?}" , palette) ;
455+ trace ! ( "blocks: {:?}" , blocks) ;
456+
457+ let data = {
458+ let data = match palette {
459+ Palette :: Direct | Palette :: Indirect ( ..) => {
460+ let blocks_per_long = 64 / bit_length;
461+ let mut data = vec ! [ 0i64 ; blocks. len( ) / blocks_per_long as usize ] ;
462+ let mut blocks_so_far = 0 ;
463+ let mut long_index = 0 ;
464+
465+ for block in blocks {
466+ if blocks_so_far == blocks_per_long {
467+ blocks_so_far = 0 ;
468+ long_index += 1 ;
469+ }
470+
471+ let block = block as i64 ;
472+
473+ data[ long_index] |= block << ( blocks_so_far * bit_length) ;
474+ blocks_so_far += 1 ;
475+ trace ! ( "block: {} ({:b}), long (after appending): {:b}, blocks so far: {blocks_so_far}" , block, block, data[ long_index] )
476+ }
477+
478+ data
479+ }
480+ Palette :: SingleValued ( _) => Vec :: with_capacity ( 0 ) ,
481+ } ;
482+
483+ let data = fastnbt:: LongArray :: new ( data. to_vec ( ) ) ;
484+ trace ! ( "data: {:?}" , data) ;
485+ data
486+ } ;
487+
488+ Self {
489+ block_count : block_count as i16 ,
490+ block_states : PalettedContainer {
491+ bits_per_entry : bit_length,
492+ palette,
493+ data_array : data,
494+ } ,
495+ biomes : PalettedContainer {
496+ bits_per_entry : 0 ,
497+ palette : Palette :: SingleValued ( BlockState (
498+ crawlstate. registry_cache . the_end_biome_id ,
499+ ) ) ,
500+ data_array : fastnbt:: LongArray :: new ( vec ! [ ] ) ,
501+ } ,
502+ }
503+ }
370504}
371505
372506impl ChunkDataUpdateLightC < ' _ > {
@@ -414,6 +548,55 @@ impl ChunkDataUpdateLightC<'_> {
414548 block_light_arrays : vec ! [ ] ,
415549 }
416550 }
551+
552+ pub fn from_slime (
553+ crawlstate : CrawlState ,
554+ value : & slimeball_lib:: Chunk ,
555+ block_states : & Blocks ,
556+ ) -> Self {
557+ let data = value
558+ . sections
559+ . iter ( )
560+ . map ( |sec| ChunkSection :: slime_to_sec ( crawlstate. clone ( ) , sec, block_states) )
561+ . collect :: < Vec < _ > > ( ) ;
562+
563+ let block_entities = value
564+ . tile_entities
565+ . clone ( )
566+ . into_iter ( )
567+ . filter_map ( |e| {
568+ world:: BlockEntity :: try_parse ( e) . map_or_else (
569+ |why| {
570+ warn ! (
571+ "Failed to parse block entity: {why}, ignoring in final chunk packet for ({}, {})" ,
572+ value. x,
573+ value. z,
574+ ) ;
575+ None
576+ } ,
577+ |e| match e. keep_packed {
578+ true => None ,
579+ false => Some ( e) ,
580+ } ,
581+ )
582+ } )
583+ . map ( Into :: into)
584+ . collect :: < Vec < self :: BlockEntity > > ( ) ;
585+
586+ Self {
587+ x : value. x ,
588+ z : value. z ,
589+ heightmaps : HeightMaps ( HashMap :: new ( ) ) ,
590+ data,
591+ entities : block_entities,
592+ sky_light_mask : BitVec :: from_elem ( 18 , false ) ,
593+ block_light_mask : BitVec :: from_elem ( 18 , false ) ,
594+ empty_sky_light_mask : BitVec :: from_elem ( 18 , true ) ,
595+ empty_block_light_mask : BitVec :: from_elem ( 18 , true ) ,
596+ sky_light_arrays : vec ! [ ] ,
597+ block_light_arrays : vec ! [ ] ,
598+ }
599+ }
417600}
418601
419602#[ derive( Debug , Packet , Encode ) ]
0 commit comments