mc_core/world/anvil/
encode.rs1use std::collections::hash_map::Entry;
2use std::collections::HashMap;
3use std::io::Write;
4
5use crate::heightmap::HeightmapType;
6use crate::world::chunk::Chunk;
7use crate::block::BlockState;
8use crate::util::{PackedArray, PackedIterator};
9
10use nbt::encode::write_compound_tag;
11use nbt::CompoundTag;
12
13
14pub fn encode_chunk_to_writer(writer: &mut impl Write, chunk: &Chunk) {
16 let mut root = CompoundTag::new();
17 encode_chunk(&mut root, chunk);
18 write_compound_tag(writer, &root).unwrap();
19}
20
21pub fn encode_chunk(tag_root: &mut CompoundTag, chunk: &Chunk) {
22
23 let (cx, cz) = chunk.get_position();
24
25 tag_root.insert_i32("DataVersion", 2586);
26
27 tag_root.insert_compound_tag("Level", {
28
29 let mut tag_level = CompoundTag::new();
30
31 tag_level.insert_i32("xPos", cx);
32 tag_level.insert_i32("zPos", cz);
33 tag_level.insert_str("Status", "full");
36
37 tag_level.insert_i32_vec("Biomes", {
38 chunk.iter_biomes().map(|biome| biome.get_id()).collect()
39 });
40
41 tag_level.insert_compound_tag_vec("Sections", {
42 chunk.iter_loaded_sub_chunks()
43 .map(|(cy, sc)| {
44
45 let mut tag_section = CompoundTag::new();
46 tag_section.insert_i8("Y", cy);
47
48 let mut palette_indices = HashMap::new();
49 let mut tag_palette = Vec::new();
50 let mut packed_blocks = PackedArray::new(4096, 4, None);
51
52 for (idx, state) in sc.iter_blocks().enumerate() {
53 let sid = match palette_indices.entry(state.get_key()) {
54 Entry::Occupied(o) => *o.get(),
55 Entry::Vacant(v) => {
56 tag_palette.push(encode_block_state(state));
57 *v.insert(tag_palette.len() - 1)
58 }
59 };
60 packed_blocks.set_with_resize(idx, sid as u64);
61 }
62
63 tag_section.insert_compound_tag_vec("Palette", tag_palette);
64 tag_section.insert_i64_vec("BlockStates", packed_blocks.into_inner()
65 .into_iter()
66 .map(|val| val as i64)
67 .collect());
68
69 tag_section
70
71 })
72 });
73
74 let mut tag_heightmaps = CompoundTag::new();
75
76 for heightmap_type in chunk.get_env().heightmaps.iter_heightmap_types() {
77 if let Some(arr) = encode_heightmap(chunk, heightmap_type) {
78 tag_heightmaps.insert_i64_vec(heightmap_type.get_name(), arr);
79 }
80 }
81
82 tag_level
83
84 });
85
86}
87
88pub fn encode_block_state(state: &'static BlockState) -> CompoundTag {
89
90 let block = state.get_block();
91 let mut tag_block = CompoundTag::new();
92 tag_block.insert_str("Name", block.get_name());
93
94 if let Some(it) = state.iter_raw_states() {
95 let mut tag_props = CompoundTag::new();
96 for (name, value) in it {
97 tag_props.insert_str(name, value);
98 }
99 tag_block.insert_compound_tag("Properties", tag_props);
100 }
101
102 tag_block
103
104}
105
106pub fn encode_heightmap(chunk: &Chunk, heightmap_type: &'static HeightmapType) -> Option<Vec<i64>> {
107 let (byte_size, it) = chunk.iter_heightmap_raw_columns(heightmap_type)?;
108 Some(it.pack_aligned(byte_size).map(|v| v as i64).collect())
109}