steel_core/chunk/light/
section_storage.rs1use steel_utils::{SectionPos, codec::BitSet};
2
3use super::LIGHT_SECTION_PADDING;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct LightSectionRangeError {
8 pub min_y: i32,
10 pub height: i32,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct LightSectionRange {
21 min_section_y: i32,
22 section_count: i32,
23}
24
25impl LightSectionRange {
26 pub const fn from_world_height(
28 min_y: i32,
29 height: i32,
30 ) -> Result<Self, LightSectionRangeError> {
31 if height <= 0 {
32 return Err(LightSectionRangeError { min_y, height });
33 }
34
35 let Some(max_y) = min_y.checked_add(height - 1) else {
36 return Err(LightSectionRangeError { min_y, height });
37 };
38
39 let min_chunk_section_y = SectionPos::block_to_section_coord(min_y);
40 let max_chunk_section_y = SectionPos::block_to_section_coord(max_y);
41 let section_count =
42 max_chunk_section_y - min_chunk_section_y + 1 + LIGHT_SECTION_PADDING * 2;
43
44 Ok(Self {
45 min_section_y: min_chunk_section_y - LIGHT_SECTION_PADDING,
46 section_count,
47 })
48 }
49
50 #[must_use]
52 pub const fn min_section_y(self) -> i32 {
53 self.min_section_y
54 }
55
56 #[must_use]
58 pub const fn max_section_y_exclusive(self) -> i32 {
59 self.min_section_y + self.section_count
60 }
61
62 #[must_use]
64 pub const fn section_count(self) -> usize {
65 self.section_count as usize
66 }
67
68 #[must_use]
70 pub const fn min_chunk_section_y(self) -> i32 {
71 self.min_section_y + LIGHT_SECTION_PADDING
72 }
73
74 #[must_use]
76 pub const fn max_chunk_section_y_exclusive(self) -> i32 {
77 self.max_section_y_exclusive() - LIGHT_SECTION_PADDING
78 }
79
80 #[must_use]
82 pub const fn chunk_section_count(self) -> usize {
83 (self.section_count - LIGHT_SECTION_PADDING * 2) as usize
84 }
85
86 #[must_use]
88 pub const fn section_y(self, section_index: usize) -> Option<i32> {
89 if section_index >= self.section_count() {
90 return None;
91 }
92
93 Some(self.min_section_y + section_index as i32)
94 }
95
96 #[must_use]
98 pub const fn section_index(self, section_y: i32) -> Option<usize> {
99 if section_y < self.min_section_y || section_y >= self.max_section_y_exclusive() {
100 return None;
101 }
102
103 Some((section_y - self.min_section_y) as usize)
104 }
105
106 #[must_use]
108 pub const fn chunk_section_y(self, section_index: usize) -> Option<i32> {
109 if section_index >= self.chunk_section_count() {
110 return None;
111 }
112
113 Some(self.min_chunk_section_y() + section_index as i32)
114 }
115
116 #[must_use]
118 pub const fn chunk_section_index(self, section_y: i32) -> Option<usize> {
119 if section_y < self.min_chunk_section_y()
120 || section_y >= self.max_chunk_section_y_exclusive()
121 {
122 return None;
123 }
124
125 Some((section_y - self.min_chunk_section_y()) as usize)
126 }
127
128 #[must_use]
129 pub(super) fn empty_bit_set(self) -> BitSet {
130 BitSet(vec![0; self.section_count().div_ceil(64)].into_boxed_slice())
131 }
132}