@@ -3,16 +3,19 @@ use crate::palette::Palette;
33use crate :: prelude:: Schematic ;
44use blocks_report:: InternalId ;
55use minecraft_protocol:: prelude:: Coordinates ;
6- use std:: collections:: HashMap ;
76use std:: mem;
87use thiserror:: Error ;
98
9+ const UNSEEN_ID_INDEX : u32 = u32:: MAX ;
10+
11+ const LOOKUP_TABLE_SIZE : usize = InternalId :: MAX as usize + 1 ;
12+
1013/// A helper struct to hold reusable buffers for palette generation.
1114/// This avoids re-allocating the HashMap and palette Vec for every chunk.
1215/// The main block data is now handled on the stack.
1316pub struct ChunkProcessor {
1417 palette : Vec < InternalId > ,
15- id_to_palette_index : HashMap < InternalId , u32 > ,
18+ id_to_palette_index : Vec < u32 > ,
1619}
1720
1821#[ derive( Debug , Error ) ]
@@ -27,17 +30,17 @@ impl ChunkProcessor {
2730 pub fn new ( ) -> Self {
2831 Self {
2932 palette : Vec :: with_capacity ( Self :: MAX_PALETTED_SIZE ) ,
30- id_to_palette_index : HashMap :: with_capacity ( Self :: MAX_PALETTED_SIZE ) ,
33+ id_to_palette_index : vec ! [ UNSEEN_ID_INDEX ; LOOKUP_TABLE_SIZE ] ,
3134 }
3235 }
3336
34- /// Resets the internal buffers to be ready for the next chunk.
3537 fn prepare_for_next_chunk ( & mut self ) {
3638 self . palette . clear ( ) ;
37- self . id_to_palette_index . clear ( ) ;
39+ for & id in & self . palette {
40+ self . id_to_palette_index [ id as usize ] = UNSEEN_ID_INDEX ;
41+ }
3842 }
3943
40- /// Processes a 16x16x16 section using a stack-allocated array for block data.
4144 pub fn process_section (
4245 & mut self ,
4346 schematic : & Schematic ,
@@ -72,13 +75,13 @@ impl ChunkProcessor {
7275 first_id = Some ( internal_id) ;
7376 }
7477
75- self . id_to_palette_index
76- . entry ( internal_id )
77- . or_insert_with ( || {
78- let index = self . palette . len ( ) as u32 ;
79- self . palette . push ( internal_id) ;
80- index
81- } ) ;
78+ let palette_index_slot = & mut self . id_to_palette_index [ internal_id as usize ] ;
79+
80+ if * palette_index_slot == UNSEEN_ID_INDEX {
81+ let new_index = self . palette . len ( ) as u32 ;
82+ self . palette . push ( internal_id) ;
83+ * palette_index_slot = new_index ;
84+ }
8285 }
8386 }
8487 }
@@ -96,7 +99,9 @@ impl ChunkProcessor {
9699 if bits_per_entry <= 8 {
97100 let bits_per_entry = bits_per_entry. clamp ( 4 , 8 ) as u8 ;
98101
99- let paletted_data = block_ids. iter ( ) . map ( |id| self . id_to_palette_index [ id] ) ;
102+ let paletted_data = block_ids
103+ . iter ( )
104+ . map ( |& id| self . id_to_palette_index [ id as usize ] ) ;
100105 let packed_data = pack_direct ( paletted_data, bits_per_entry) ;
101106
102107 Ok ( Palette :: paletted (
0 commit comments