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 {
93 start: ChunkPos,
94 number_of_points: u32,
95
96 dir: ChunkPos,
97
98 segment_len: u32,
99 pos: ChunkPos,
100 segment_passed: u32,
101 current_iter: u32,
102}
103impl SquareChunkIterator {
104 pub fn new(start: ChunkPos, max_distance: u32) -> Self {
105 Self {
106 start,
107 number_of_points: u32::pow(max_distance * 2 - 1, 2),
108
109 dir: ChunkPos { x: 1, z: 0 },
110
111 segment_len: 1,
112 pos: ChunkPos::default(),
113 segment_passed: 0,
114 current_iter: 0,
115 }
116 }
117
118 pub fn set_max_distance(&mut self, max_distance: u32) {
134 self.number_of_points = u32::pow(max_distance * 2 - 1, 2);
135 }
136}
137impl Iterator for SquareChunkIterator {
138 type Item = ChunkPos;
139
140 fn next(&mut self) -> Option<Self::Item> {
141 if self.current_iter > self.number_of_points {
142 return None;
143 }
144
145 let output = self.start + self.dir;
146
147 self.pos.x += self.dir.x;
149 self.pos.z += self.dir.z;
150 self.segment_passed += 1;
151
152 if self.segment_passed == self.segment_len {
153 self.segment_passed = 0;
155
156 (self.dir.x, self.dir.z) = (-self.dir.z, self.dir.x);
158
159 if self.dir.z == 0 {
161 self.segment_len += 1;
162 }
163 }
164 self.current_iter += 1;
165 Some(output)
166 }
167}
168
169pub struct ChunkIterator {
181 pub max_distance: u32,
182 pub start: ChunkPos,
183 pub pos: ChunkPos,
184 pub layer: u32,
185 pub leg: i32,
186}
187impl ChunkIterator {
188 pub fn new(start: ChunkPos, max_distance: u32) -> Self {
189 Self {
190 max_distance,
191 start,
192 pos: ChunkPos { x: 2, z: -1 },
193 layer: 1,
194 leg: -1,
195 }
196 }
197}
198impl Iterator for ChunkIterator {
199 type Item = ChunkPos;
200
201 fn next(&mut self) -> Option<Self::Item> {
202 match self.leg {
203 -1 => {
204 self.leg = 0;
205 return Some(self.start);
206 }
207 0 => {
208 if self.max_distance == 1 {
209 return None;
210 }
211 self.pos.x -= 1;
212 self.pos.z += 1;
213 if self.pos.x == 0 {
214 self.leg = 1;
215 }
216 }
217 1 => {
218 self.pos.x -= 1;
219 self.pos.z -= 1;
220 if self.pos.z == 0 {
221 self.leg = 2;
222 }
223 }
224 2 => {
225 self.pos.x += 1;
226 self.pos.z -= 1;
227 if self.pos.x == 0 {
228 self.leg = 3;
229 }
230 }
231 3 => {
232 self.pos.x += 1;
233 self.pos.z += 1;
234 if self.pos.z == 0 {
235 self.pos.x += 1;
236 self.leg = 0;
237 self.layer += 1;
238 if self.layer == self.max_distance {
239 return None;
240 }
241 }
242 }
243 _ => unreachable!(),
244 }
245 Some(self.start + self.pos)
246 }
247}