Skip to main content

nurtex_protocol/types/
chunk.rs

1use std::hash::{Hash, Hasher};
2
3use nurtex_codec::Buffer;
4
5use crate::types::BlockPos;
6
7use super::{ChunkData, Palette, PaletteKind, read_palette};
8
9/// Мировой чанк
10#[derive(Clone, Debug, PartialEq)]
11pub struct Chunk {
12  /// Позиция чанка
13  pub position: ChunkPos,
14
15  /// Минимальная высота
16  pub min_y: i32,
17
18  /// Список секций чанка
19  pub sections: Vec<ChunkSection>,
20}
21
22/// Позиция чанка
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct ChunkPos {
25  pub x: i32,
26  pub z: i32,
27}
28
29impl ChunkPos {
30  /// Метод создания новой позиции чанка
31  pub fn new(x: i32, z: i32) -> Self {
32    Self { x, z }
33  }
34}
35
36impl Hash for ChunkPos {
37  fn hash<H: Hasher>(&self, state: &mut H) {
38    self.x.hash(state);
39    self.z.hash(state);
40  }
41}
42
43impl ChunkPos {
44  pub fn from_block(pos: BlockPos) -> Self {
45    Self {
46      x: pos.x.div_euclid(16),
47      z: pos.z.div_euclid(16),
48    }
49  }
50}
51
52/// Секция чанка
53#[derive(Clone, Debug, PartialEq)]
54pub struct ChunkSection {
55  /// Количество блоков, не относящихся к воздуху
56  pub non_air_block_count: u16,
57
58  /// Блоки чанка (всего 4096)
59  pub blocks: Palette,
60
61  /// Биомы чанка
62  pub biomes: Palette,
63}
64
65impl Chunk {
66  /// Декодировка секций чанка
67  pub fn decode(chunk_x: i32, chunk_z: i32, chunk_data: &ChunkData, section_count: usize, min_y: i32) -> Option<Self> {
68    let mut cur = std::io::Cursor::new(&chunk_data.sections[..]);
69    let mut sections = Vec::with_capacity(section_count);
70
71    for _ in 0..section_count {
72      let non_air_block_count = u16::read_buf(&mut cur)?;
73      let blocks = read_palette(&mut cur, 16 * 16 * 16, PaletteKind::Blocks)?;
74      let biomes = read_palette(&mut cur, 4 * 4 * 4, PaletteKind::Biomes)?;
75
76      sections.push(ChunkSection {
77        non_air_block_count,
78        blocks,
79        biomes,
80      });
81    }
82
83    Some(Self {
84      position: ChunkPos::new(chunk_x, chunk_z),
85      min_y: min_y,
86      sections: sections,
87    })
88  }
89
90  /// Декодировка секций чанка до конца данныхs
91  pub fn decode_to_end(chunk_x: i32, chunk_z: i32, chunk_data: &ChunkData, min_y: i32) -> Option<Self> {
92    let mut cur = std::io::Cursor::new(&chunk_data.sections[..]);
93    let mut sections = Vec::new();
94
95    while (cur.position() as usize) < cur.get_ref().len() {
96      let before = cur.position();
97
98      let non_air_block_count = u16::read_buf(&mut cur)?;
99      let blocks = read_palette(&mut cur, 16 * 16 * 16, PaletteKind::Blocks)?;
100      let biomes = read_palette(&mut cur, 4 * 4 * 4, PaletteKind::Biomes)?;
101
102      sections.push(ChunkSection {
103        non_air_block_count,
104        blocks,
105        biomes,
106      });
107
108      if cur.position() == before {
109        return None;
110      }
111    }
112
113    Some(Self {
114      position: ChunkPos::new(chunk_x, chunk_z),
115      min_y: min_y,
116      sections: sections,
117    })
118  }
119
120  /// Метод получения блока по мировым координатам
121  pub fn get_block(&self, pos: BlockPos) -> Option<u32> {
122    if pos.y < self.min_y {
123      return None;
124    }
125
126    let rel_y = (pos.y - self.min_y) as usize;
127    let section_index = rel_y / 16;
128    let local_y = rel_y % 16;
129    let local_x = pos.x.rem_euclid(16) as usize;
130    let local_z = pos.z.rem_euclid(16) as usize;
131
132    let section = self.sections.get(section_index)?;
133
134    section.blocks.get_by_index((local_y * 16 * 16) + (local_z * 16) + local_x)
135  }
136
137  /// Метод получения блока по координатам относительно текущего чанка
138  pub fn get_block_relative(&self, x: usize, y: usize, z: usize) -> Option<u32> {
139    if x >= 16 || z >= 16 {
140      return None;
141    }
142
143    let section_index = y / 16;
144    let local_y = y % 16;
145    let section = self.sections.get(section_index)?;
146    let index = (local_y * 16 * 16) + (z * 16) + x;
147
148    section.blocks.get_by_index(index)
149  }
150}