@@ -6,7 +6,7 @@ use crate::{
66 Chunk , ChunkPosition , ChunkSection ,
77} ;
88
9- use super :: { block_entity:: BlockEntityData , entity:: EntityData , serialization_helper :: packed_u9 } ;
9+ use super :: { block_entity:: BlockEntityData , entity:: EntityData } ;
1010use bitvec:: { bitvec, vec:: BitVec } ;
1111use blocks:: BlockId ;
1212use byteorder:: { BigEndian , ReadBytesExt , WriteBytesExt } ;
@@ -26,8 +26,8 @@ use std::{fs, io, iter};
2626const REGION_SIZE : usize = 32 ;
2727
2828/// The data version supported by this code, currently corresponding
29- /// to 1.13.2 .
30- const DATA_VERSION : i32 = 1631 ;
29+ /// to 1.16.5 .
30+ const DATA_VERSION : i32 = 2586 ;
3131
3232/// Length, in bytes, of a sector.
3333const SECTOR_BYTES : usize = 4096 ;
@@ -51,69 +51,49 @@ pub struct ChunkLevel {
5151 z_pos : i32 ,
5252 last_update : i64 ,
5353 inhabited_time : i64 ,
54+ #[ serde( default ) ]
5455 sections : Vec < LevelSection > ,
5556 #[ serde( serialize_with = "nbt::i32_array" ) ]
5657 biomes : Vec < i32 > ,
58+ #[ serde( default ) ]
5759 entities : Vec < EntityData > ,
5860 #[ serde( rename = "TileEntities" ) ]
61+ #[ serde( default ) ]
5962 block_entities : Vec < BlockEntityData > ,
60- heightmaps : Heightmaps ,
6163 #[ serde( rename = "ToBeTicked" ) ]
64+ #[ serde( default ) ]
6265 awaiting_block_updates : Vec < Vec < i16 > > ,
6366 #[ serde( rename = "LiquidsToBeTicked" ) ]
67+ #[ serde( default ) ]
6468 awaiting_liquid_updates : Vec < Vec < i16 > > ,
69+ #[ serde( default ) ]
6570 post_processing : Vec < Vec < i16 > > ,
6671 #[ serde( rename = "TileTicks" ) ]
72+ #[ serde( default ) ]
6773 scheduled_block_updates : Vec < ScheduledBlockUpdate > ,
6874 #[ serde( rename = "LiquidTicks" ) ]
75+ #[ serde( default ) ]
6976 scheduled_liquid_updates : Vec < ScheduledBlockUpdate > ,
7077 #[ serde( rename = "Status" ) ]
78+ #[ serde( default ) ]
7179 worldgen_status : Cow < ' static , str > ,
7280}
7381
74- /// Represents the heightmap data of a chunk.
75- #[ derive( Serialize , Deserialize , Debug ) ]
76- #[ serde( rename_all = "SCREAMING_SNAKE_CASE" ) ]
77- pub struct Heightmaps {
78- // sometimes a few of those are missing, but we regenerate them anyways
79- /// Deserialization: length of 0 means field was missing,
80- /// length is guaranteed to be a multiple of 64,
81- /// length should be 256 to represent valid data
82- #[ serde( with = "packed_u9" , default ) ]
83- light_blocking : Vec < u16 > ,
84- /// Deserialization: length of 0 means field was missing,
85- /// length is guaranteed to be a multiple of 64,
86- /// length should be 256 to represent valid data
87- #[ serde( with = "packed_u9" , default ) ]
88- motion_blocking : Vec < u16 > ,
89- /// Deserialization: length of 0 means field was missing,
90- /// length is guaranteed to be a multiple of 64,
91- /// length should be 256 to represent valid data
92- #[ serde( with = "packed_u9" , default ) ]
93- motion_blocking_no_leaves : Vec < u16 > ,
94- /// Deserialization: length of 0 means field was missing,
95- /// length is guaranteed to be a multiple of 64,
96- /// length should be 256 to represent valid data
97- #[ serde( with = "packed_u9" , default ) ]
98- ocean_floor : Vec < u16 > ,
99- /// Deserialization: length of 0 means field was missing,
100- /// length is guaranteed to be a multiple of 64,
101- /// length should be 256 to represent valid data
102- #[ serde( with = "packed_u9" , default ) ]
103- world_surface : Vec < u16 > ,
104- }
105-
10682/// Represents a chunk section in a region file.
10783#[ derive( Serialize , Deserialize , Debug ) ]
10884#[ serde( rename_all = "PascalCase" ) ]
10985pub struct LevelSection {
11086 y : i8 ,
11187 #[ serde( serialize_with = "nbt::i64_array" , rename = "BlockStates" ) ]
88+ #[ serde( default ) ]
11289 states : Vec < i64 > ,
90+ #[ serde( default ) ]
11391 palette : Vec < LevelPaletteEntry > ,
11492 #[ serde( serialize_with = "nbt::i8_array" ) ]
93+ #[ serde( default ) ]
11594 block_light : Vec < i8 > ,
11695 #[ serde( serialize_with = "nbt::i8_array" ) ]
96+ #[ serde( default ) ]
11797 sky_light : Vec < i8 > ,
11898}
11999
@@ -234,7 +214,7 @@ impl RegionHandle {
234214
235215 // Parse NBT data
236216 let cursor = Cursor :: new ( & buf[ 1 ..] ) ;
237- let root: ChunkRoot = match compression_type {
217+ let mut root: ChunkRoot = match compression_type {
238218 1 => nbt:: from_gzip_reader ( cursor) . map_err ( Error :: Nbt ) ?,
239219 2 => nbt:: from_zlib_reader ( cursor) . map_err ( Error :: Nbt ) ?,
240220 _ => return Err ( Error :: InvalidCompression ( compression_type) ) ,
@@ -245,17 +225,17 @@ impl RegionHandle {
245225 return Err ( Error :: UnsupportedDataVersion ( root. data_version ) ) ;
246226 }
247227
248- let level = & root. level ;
228+ let level = & mut root. level ;
249229
250230 let mut chunk = Chunk :: new ( original_pos) ;
251231
252232 // Read sections
253- for section in & level. sections {
233+ for section in & mut level. sections {
254234 read_section_into_chunk ( section, & mut chunk) ?;
255235 }
256236
257237 // Read biomes
258- if level. biomes . len ( ) != 256 {
238+ if level. biomes . len ( ) != 1024 {
259239 return Err ( Error :: IndexOutOfBounds ) ;
260240 }
261241 for index in 0 ..1024 {
@@ -339,7 +319,12 @@ impl RegionHandle {
339319 }
340320}
341321
342- fn read_section_into_chunk ( section : & LevelSection , chunk : & mut Chunk ) -> Result < ( ) , Error > {
322+ fn read_section_into_chunk ( section : & mut LevelSection , chunk : & mut Chunk ) -> Result < ( ) , Error > {
323+ if section. y < 0 || section. y >= 16 || section. states . is_empty ( ) {
324+ // Void air chunks for lighting - not supported by Feather yet
325+ return Ok ( ( ) ) ;
326+ }
327+
343328 let data = & section. states ;
344329
345330 // Create palette
@@ -389,6 +374,13 @@ fn read_section_into_chunk(section: &LevelSection, chunk: &mut Chunk) -> Result<
389374 PackedArray :: from_u64_vec ( data, 4096 )
390375 } ;
391376
377+ if section. sky_light . is_empty ( ) {
378+ section. sky_light = vec ! [ 0 ; 2048 ] ;
379+ }
380+ if section. block_light . is_empty ( ) {
381+ section. block_light = vec ! [ 0 ; 2048 ] ;
382+ }
383+
392384 if section. block_light . len ( ) != 2048 || section. sky_light . len ( ) != 2048 {
393385 return Err ( Error :: IndexOutOfBounds ) ;
394386 }
@@ -402,10 +394,6 @@ fn read_section_into_chunk(section: &LevelSection, chunk: &mut Chunk) -> Result<
402394
403395 let chunk_section = ChunkSection :: new ( blocks, light) ;
404396
405- if section. y >= 16 {
406- return Err ( Error :: IndexOutOfBounds ) ;
407- }
408-
409397 chunk. set_section_at ( usize:: from ( section. y as u8 ) , Some ( chunk_section) ) ;
410398
411399 Ok ( ( ) )
@@ -454,14 +442,6 @@ fn chunk_to_chunk_root(
454442 . map ( |biome| biome. id ( ) as i32 )
455443 . collect ( ) ,
456444 entities : entities. into ( ) ,
457- // TODO[1.16]: add back heightmaps
458- heightmaps : Heightmaps {
459- light_blocking : vec ! [ 0 ; 256 ] ,
460- motion_blocking : vec ! [ 0 ; 256 ] ,
461- motion_blocking_no_leaves : vec ! [ 0 ; 256 ] ,
462- ocean_floor : vec ! [ 0 ; 256 ] ,
463- world_surface : vec ! [ 0 ; 256 ] ,
464- } ,
465445 awaiting_block_updates : vec ! [ vec![ ] ; 16 ] , // TODO
466446 awaiting_liquid_updates : vec ! [ vec![ ] ; 16 ] , // TODO
467447 scheduled_block_updates : vec ! [ ] , // TODO
@@ -640,7 +620,7 @@ impl Display for Error {
640620 }
641621 Error :: InvalidBlock ( name) => f. write_str ( & format ! ( "Chunk contains invalid block {}" , name) ) ?,
642622 Error :: ChunkNotExist => f. write_str ( "The chunk does not exist" ) ?,
643- Error :: UnsupportedDataVersion ( _) => f. write_str ( "The chunk uses an unsupported data version. Feather currently only supports 1.13.2 region files." ) ?,
623+ Error :: UnsupportedDataVersion ( _) => f. write_str ( "The chunk uses an unsupported data version. Feather currently only supports 1.16.5 region files." ) ?,
644624 Error :: InvalidBlockType => f. write_str ( "Chunk contains invalid block type" ) ?,
645625 Error :: MissingRootTag => f. write_str ( "Chunk is missing a root NBT tag" ) ?,
646626 Error :: IndexOutOfBounds => f. write_str ( "Section index out of bounds" ) ?,
@@ -675,7 +655,8 @@ pub fn load_region(dir: &PathBuf, pos: RegionPosition) -> Result<RegionHandle, E
675655
676656 let header = read_header ( & mut file) ?;
677657
678- let num_sectors = file. metadata ( ) . map_err ( Error :: Io ) ?. len ( ) / SECTOR_BYTES as u64 ;
658+ let num_sectors =
659+ ( file. metadata ( ) . map_err ( Error :: Io ) ?. len ( ) + SECTOR_BYTES as u64 - 1 ) / SECTOR_BYTES as u64 ;
679660
680661 let allocator = SectorAllocator :: new ( & header, num_sectors as u32 ) ;
681662
0 commit comments