@@ -103,78 +103,81 @@ impl BlockStates {
103103 data,
104104 palette,
105105 } => {
106- // Step 1: Read existing packed data into a list of normal integers
107106 let mut normalised_ints = Vec :: with_capacity ( 4096 ) ;
108107 let mut values_read = 0 ;
109108
110109 for long in data {
111110 let mut bit_offset = 0 ;
112-
113111 while bit_offset + * bits_per_block as usize <= 64 {
114112 if values_read >= 4096 {
115113 break ;
116114 }
117115
118- // Extract value at the current bit offset
119116 let value =
120117 read_nbit_i32 ( long, * bits_per_block as usize , bit_offset as u32 ) ?;
118+
121119 let max_int_value = ( 1 << new_bit_size) - 1 ;
122120 if value > max_int_value {
123121 return Err ( WorldError :: InvalidBlockStateData ( format ! (
124122 "Value {value} exceeds maximum value for {new_bit_size}-bit block state"
125123 ) ) ) ;
126124 }
125+
127126 normalised_ints. push ( value) ;
128127 values_read += 1 ;
129-
130128 bit_offset += * bits_per_block as usize ;
131129 }
132-
133- // Stop reading if we’ve already hit 4096 values
134130 if values_read >= 4096 {
135131 break ;
136132 }
137133 }
138134
139- // Check if we read exactly 4096 block states
140135 if normalised_ints. len ( ) != 4096 {
141136 return Err ( WorldError :: InvalidBlockStateData ( format ! (
142137 "Expected 4096 block states, but got {}" ,
143138 normalised_ints. len( )
144139 ) ) ) ;
145140 }
146141
147- // Step 2: Write the normalised integers into the new packed format
148142 let mut new_data = Vec :: new ( ) ;
149143 let mut current_long: i64 = 0 ;
150144 let mut bit_position = 0 ;
151145
152146 for & value in & normalised_ints {
153- current_long |= ( value as i64 ) << bit_position;
154- bit_position += new_bit_size;
155-
156- if bit_position >= 64 {
147+ if bit_position + new_bit_size > 64 {
157148 new_data. push ( current_long) ;
158- current_long = ( value as i64 ) >> ( new_bit_size - ( bit_position - 64 ) ) ;
159- bit_position -= 64 ;
149+ current_long = 0 ;
150+ bit_position = 0 ;
160151 }
152+
153+ current_long |= ( value as i64 ) << bit_position;
154+ bit_position += new_bit_size;
161155 }
162156
163- // Push any remaining bits in the final long
157+ // just in case there's remaining data to push, and avoid pushing empty longs
164158 if bit_position > 0 {
165159 new_data. push ( current_long) ;
166160 }
167161
168- // Verify the size of the new data matches expectations
169- let expected_size = ( 4096 * new_bit_size) . div_ceil ( 64 ) ;
170- if new_data. len ( ) != expected_size {
162+ // validation of size
163+ // the original logic is not suitable here
164+ // fuck it, each long waste is uncertain
165+ if new_data. is_empty ( ) {
166+ return Err ( WorldError :: InvalidBlockStateData (
167+ "Resizing resulted in empty data" . to_string ( ) ,
168+ ) ) ;
169+ }
170+
171+ let blocks_per_long = 64 / new_bit_size;
172+ let expected_longs = 4096usize . div_ceil ( blocks_per_long) ;
173+ if new_data. len ( ) != expected_longs {
171174 return Err ( WorldError :: InvalidBlockStateData ( format ! (
172175 "Expected packed data size of {}, but got {}" ,
173- expected_size ,
176+ expected_longs ,
174177 new_data. len( )
175178 ) ) ) ;
176179 }
177- // Update the chunk with the new packed data and a bit size
180+
178181 self . block_data = PaletteType :: Indirect {
179182 bits_per_block : new_bit_size as u8 ,
180183 data : new_data,
@@ -218,26 +221,24 @@ impl Chunk {
218221 z : i32 ,
219222 block : BlockStateId ,
220223 ) -> Result < ( ) , WorldError > {
221- // Get old block
222224 let old_block = self . get_block ( x, y, z) ?;
223225 if old_block == block {
224- // debug!("Block is the same as the old block");
225226 return Ok ( ( ) ) ;
226227 }
227- // Get section
228+
228229 let section = self
229230 . sections
230231 . iter_mut ( )
231232 . find ( |section| section. y == ( y >> 4 ) as i8 )
232233 . ok_or ( WorldError :: SectionOutOfBounds ( y >> 4 ) ) ?;
233234
235+ // from single palette to indirect palette if needed
234236 let mut converted = false ;
235237 let mut new_contents = PaletteType :: Indirect {
236238 bits_per_block : 4 ,
237239 data : vec ! [ ] ,
238240 palette : vec ! [ ] ,
239241 } ;
240-
241242 if let PaletteType :: Single ( val) = & section. block_states . block_data {
242243 new_contents = PaletteType :: Indirect {
243244 bits_per_block : 4 ,
@@ -246,22 +247,22 @@ impl Chunk {
246247 } ;
247248 converted = true ;
248249 }
249-
250250 if converted {
251251 section. block_states . block_data = new_contents;
252252 }
253253
254- // Do different things based on the palette type
255- match & mut section. block_states . block_data {
254+ let ( block_palette_index, needs_resize, target_bits) = match & mut section
255+ . block_states
256+ . block_data
257+ {
256258 PaletteType :: Single ( _val) => {
257259 panic ! ( "Single palette type should have been converted to indirect palette type" ) ;
258260 }
259261 PaletteType :: Indirect {
260262 bits_per_block,
261- data,
262263 palette,
264+ ..
263265 } => {
264- // debug!("Indirect mode");
265266 match section. block_states . block_counts . entry ( old_block) {
266267 Entry :: Occupied ( mut occ_entry) => {
267268 let count = occ_entry. get_mut ( ) ;
@@ -289,38 +290,58 @@ impl Chunk {
289290 empty_entry. insert ( 0 ) ;
290291 }
291292 }
292- // Add new block
293+
294+ // Add new block to counts
293295 if let Some ( e) = section. block_states . block_counts . get ( & block) {
294296 section. block_states . block_counts . insert ( block, e + 1 ) ;
295297 } else {
296- // debug!("Adding block to block counts");
297298 section. block_states . block_counts . insert ( block, 1 ) ;
298299 }
299- // let required_bits = max((palette.len() as f32).log2().ceil() as u8, 4);
300- // if *bits_per_block != required_bits {
301- // section.block_states.resize(required_bits as usize)?;
302- // }
303- // Get block index
304- let block_palette_index = palette
300+
301+ // find in palette
302+ let index = palette
305303 . iter ( )
306304 . position ( |p| * p == block. to_varint ( ) )
307305 . unwrap_or_else ( || {
308- // Add block to palette if it doesn't exist
309- let index = palette. len ( ) as i16 ;
306+ let idx = palette. len ( ) ;
310307 palette. push ( block. to_varint ( ) ) ;
311- index as usize
308+ idx
312309 } ) ;
313- // Set block
310+
311+ // judge if we need to resize
312+ let required_bits = ( ( palette. len ( ) as f32 ) . log2 ( ) . ceil ( ) as u8 ) . clamp ( 4 , 15 ) ; // 15 is max in minecraft protocol
313+
314+ let resize = required_bits > * bits_per_block;
315+
316+ ( index, resize, required_bits)
317+ }
318+ PaletteType :: Direct { .. } => todo ! ( "Implement direct palette for set_block" ) ,
319+ } ;
320+
321+ if needs_resize {
322+ // debug!("Resizing section block states to {} bits", target_bits);
323+ section. block_states . resize ( target_bits as usize ) ?;
324+ }
325+
326+ match & mut section. block_states . block_data {
327+ PaletteType :: Indirect {
328+ bits_per_block,
329+ data,
330+ ..
331+ } => {
314332 let blocks_per_i64 = ( 64f64 / * bits_per_block as f64 ) . floor ( ) as usize ;
315333 let index =
316334 ( ( y. abs ( ) & 0xf ) * 256 + ( z. abs ( ) & 0xf ) * 16 + ( x. abs ( ) & 0xf ) ) as usize ;
317335 let i64_index = index / blocks_per_i64;
336+
318337 let packed_u64 =
319338 data. get_mut ( i64_index)
320339 . ok_or ( WorldError :: InvalidBlockStateData ( format ! (
321340 "Invalid block state data at index {i64_index}"
322341 ) ) ) ?;
342+
323343 let offset = ( index % blocks_per_i64) * * bits_per_block as usize ;
344+
324345 if let Err ( e) = ferrumc_general_purpose:: data_packing:: u32:: write_nbit_u32 (
325346 packed_u64,
326347 offset as u32 ,
@@ -332,25 +353,23 @@ impl Chunk {
332353 ) ) ) ;
333354 }
334355 }
335- PaletteType :: Direct { .. } => {
336- todo ! ( "Implement direct palette for set_block" ) ;
356+ _ => {
357+ return Err ( WorldError :: InvalidBlockStateData (
358+ "Unexpected palette type" . to_string ( ) ,
359+ ) )
337360 }
338361 }
339362
340363 section. block_states . non_air_blocks = section
341364 . block_states
342365 . block_counts
343366 . iter ( )
344- . filter ( |( block, _) | {
345- // Air, void air and cave air respectively
346- ![ 0 , 12958 , 12959 ] . contains ( & block. 0 )
347- } )
367+ . filter ( |( block, _) | ![ 0 , 12958 , 12959 ] . contains ( & block. 0 ) )
348368 . map ( |( _, count) | * count as u16 )
349369 . sum ( ) ;
350370
351- self . sections
352- . iter_mut ( )
353- . for_each ( |section| section. optimise ( ) . unwrap ( ) ) ;
371+ section. optimise ( ) ?;
372+
354373 Ok ( ( ) )
355374 }
356375
0 commit comments