steel_core/chunk/light/
packet.rs1use steel_protocol::packets::game::LightUpdatePacketData;
2use steel_utils::{ChunkPos, SectionPos, codec::BitSet};
3
4use super::{ChunkLightData, ChunkLightLayerStorage, LightSectionData};
5
6#[must_use]
8pub fn build_chunk_light_update_packet(
9 light: &ChunkLightData,
10 has_skylight: bool,
11) -> LightUpdatePacketData {
12 let range = light.sky.range();
13 let mut sky_y_mask = range.empty_bit_set();
14 let mut block_y_mask = range.empty_bit_set();
15 let mut empty_sky_y_mask = range.empty_bit_set();
16 let mut empty_block_y_mask = range.empty_bit_set();
17 let mut sky_updates = Vec::new();
18 let mut block_updates = Vec::new();
19
20 for section_index in 0..range.section_count() {
21 if has_skylight {
22 prepare_chunk_section_data(
23 &light.sky,
24 section_index,
25 &mut sky_y_mask,
26 &mut empty_sky_y_mask,
27 &mut sky_updates,
28 );
29 }
30 prepare_chunk_section_data(
31 &light.block,
32 section_index,
33 &mut block_y_mask,
34 &mut empty_block_y_mask,
35 &mut block_updates,
36 );
37 }
38
39 LightUpdatePacketData {
40 sky_y_mask,
41 block_y_mask,
42 empty_sky_y_mask,
43 empty_block_y_mask,
44 sky_updates,
45 block_updates,
46 }
47}
48
49#[must_use]
54pub fn build_chunk_light_update_packet_for_sections(
55 chunk_pos: ChunkPos,
56 light: &ChunkLightData,
57 has_skylight: bool,
58 sky_sections: &[SectionPos],
59 block_sections: &[SectionPos],
60) -> LightUpdatePacketData {
61 let range = light.sky.range();
62 let mut sky_y_mask = range.empty_bit_set();
63 let mut block_y_mask = range.empty_bit_set();
64 let mut empty_sky_y_mask = range.empty_bit_set();
65 let mut empty_block_y_mask = range.empty_bit_set();
66 let mut sky_updates = Vec::new();
67 let mut block_updates = Vec::new();
68
69 for section_index in 0..range.section_count() {
70 let Some(section_y) = range.section_y(section_index) else {
71 continue;
72 };
73 let section_pos = SectionPos::new(chunk_pos.0.x, section_y, chunk_pos.0.y);
74
75 if has_skylight && sky_sections.contains(§ion_pos) {
76 prepare_chunk_section_data(
77 &light.sky,
78 section_index,
79 &mut sky_y_mask,
80 &mut empty_sky_y_mask,
81 &mut sky_updates,
82 );
83 }
84
85 if block_sections.contains(§ion_pos) {
86 prepare_chunk_section_data(
87 &light.block,
88 section_index,
89 &mut block_y_mask,
90 &mut empty_block_y_mask,
91 &mut block_updates,
92 );
93 }
94 }
95
96 LightUpdatePacketData {
97 sky_y_mask,
98 block_y_mask,
99 empty_sky_y_mask,
100 empty_block_y_mask,
101 sky_updates,
102 block_updates,
103 }
104}
105
106fn prepare_chunk_section_data(
107 storage: &ChunkLightLayerStorage,
108 section_index: usize,
109 mask: &mut BitSet,
110 empty_mask: &mut BitSet,
111 updates: &mut Vec<Vec<u8>>,
112) {
113 let Some(section) = storage.sections().get(section_index) else {
114 return;
115 };
116 let Some(data) = section.visible_data() else {
117 return;
118 };
119
120 prepare_section_data(data, section_index, mask, empty_mask, updates);
121}
122
123fn prepare_section_data(
124 data: &LightSectionData,
125 section_index: usize,
126 mask: &mut BitSet,
127 empty_mask: &mut BitSet,
128 updates: &mut Vec<Vec<u8>>,
129) {
130 if data.is_empty() {
131 empty_mask.set(section_index, true);
132 return;
133 }
134
135 let bytes = data.to_bytes();
136 mask.set(section_index, true);
137 updates.push(bytes.as_ref().to_vec());
138}