azalea_world/
iterators.rs1use azalea_core::position::{BlockPos, ChunkPos};
5
6pub struct BlockIterator {
18 start: BlockPos,
19 max_distance: u32,
20
21 pos: BlockPos,
22 apothem: u32,
23 left: i32,
24 right: i32,
25}
26impl BlockIterator {
27 pub fn new(start: BlockPos, max_distance: u32) -> Self {
28 Self {
29 start,
30 max_distance,
31
32 pos: BlockPos {
33 x: -1,
34 y: -1,
35 z: -1,
36 },
37 apothem: 1,
38 left: 1,
39 right: 2,
40 }
41 }
42}
43
44impl Iterator for BlockIterator {
45 type Item = BlockPos;
46
47 fn next(&mut self) -> Option<Self::Item> {
48 if self.apothem > self.max_distance {
49 return None;
50 }
51
52 self.right -= 1;
53 if self.right < 0 {
54 self.left -= 1;
55 if self.left < 0 {
56 self.pos.z += 2;
57 if self.pos.z > 1 {
58 self.pos.y += 2;
59 if self.pos.y > 1 {
60 self.pos.x += 2;
61 if self.pos.x > 1 {
62 self.apothem += 1;
63 self.pos.x = -1;
64 }
65 self.pos.y = -1;
66 }
67 self.pos.z = -1;
68 }
69 self.left = self.apothem as i32;
70 }
71 self.right = self.left;
72 }
73 let x = self.pos.x * self.right;
74 let y = self.pos.y * ((self.apothem as i32) - self.left);
75 let z = self.pos.z * ((self.apothem as i32) - (i32::abs(x) + i32::abs(y)));
76 Some(BlockPos { x, y, z } + self.start)
77 }
78}
79
80pub struct SquareChunkIterator {
94 start: ChunkPos,
95 number_of_points: u32,
96
97 dir: ChunkPos,
98
99 segment_len: u32,
100 pos: ChunkPos,
101 segment_passed: u32,
102 current_iter: u32,
103}
104impl SquareChunkIterator {
105 pub fn new(start: ChunkPos, max_distance: u32) -> Self {
106 Self {
107 start,
108 number_of_points: u32::pow(max_distance * 2 - 1, 2),
109
110 dir: ChunkPos { x: 1, z: 0 },
111
112 segment_len: 1,
113 pos: ChunkPos::default(),
114 segment_passed: 0,
115 current_iter: 0,
116 }
117 }
118
119 pub fn set_max_distance(&mut self, max_distance: u32) {
135 self.number_of_points = u32::pow(max_distance * 2 - 1, 2);
136 }
137}
138impl Iterator for SquareChunkIterator {
139 type Item = ChunkPos;
140
141 fn next(&mut self) -> Option<Self::Item> {
142 if self.current_iter > self.number_of_points {
143 return None;
144 }
145
146 let output = self.start + self.dir;
147
148 self.pos.x += self.dir.x;
150 self.pos.z += self.dir.z;
151 self.segment_passed += 1;
152
153 if self.segment_passed == self.segment_len {
154 self.segment_passed = 0;
156
157 (self.dir.x, self.dir.z) = (-self.dir.z, self.dir.x);
159
160 if self.dir.z == 0 {
162 self.segment_len += 1;
163 }
164 }
165 self.current_iter += 1;
166 Some(output)
167 }
168}
169
170pub struct ChunkIterator {
182 pub max_distance: u32,
183 pub start: ChunkPos,
184 pub pos: ChunkPos,
185 pub layer: u32,
186 pub leg: i32,
187}
188impl ChunkIterator {
189 pub fn new(start: ChunkPos, max_distance: u32) -> Self {
190 Self {
191 max_distance,
192 start,
193 pos: ChunkPos { x: 2, z: -1 },
194 layer: 1,
195 leg: -1,
196 }
197 }
198}
199impl Iterator for ChunkIterator {
200 type Item = ChunkPos;
201
202 fn next(&mut self) -> Option<Self::Item> {
203 match self.leg {
204 -1 => {
205 self.leg = 0;
206 return Some(self.start);
207 }
208 0 => {
209 if self.max_distance == 1 {
210 return None;
211 }
212 self.pos.x -= 1;
213 self.pos.z += 1;
214 if self.pos.x == 0 {
215 self.leg = 1;
216 }
217 }
218 1 => {
219 self.pos.x -= 1;
220 self.pos.z -= 1;
221 if self.pos.z == 0 {
222 self.leg = 2;
223 }
224 }
225 2 => {
226 self.pos.x += 1;
227 self.pos.z -= 1;
228 if self.pos.x == 0 {
229 self.leg = 3;
230 }
231 }
232 3 => {
233 self.pos.x += 1;
234 self.pos.z += 1;
235 if self.pos.z == 0 {
236 self.pos.x += 1;
237 self.leg = 0;
238 self.layer += 1;
239 if self.layer == self.max_distance {
240 return None;
241 }
242 }
243 }
244 _ => unreachable!(),
245 }
246 Some(self.start + self.pos)
247 }
248}