]> git.localhorst.tv Git - blank.git/blob - tst/world/ChunkTest.cpp
6db245a2d7d5cd58182c0cef956abaa3c85745fa
[blank.git] / tst / world / ChunkTest.cpp
1 #include "ChunkTest.hpp"
2
3 #include "world/BlockType.hpp"
4 #include "world/Chunk.hpp"
5
6 #include <memory>
7
8 CPPUNIT_TEST_SUITE_REGISTRATION(blank::test::ChunkTest);
9
10 using std::unique_ptr;
11
12
13 namespace blank {
14 namespace test {
15
16 void ChunkTest::setUp() {
17         types = BlockTypeRegistry();
18
19         BlockType obstacle;
20         obstacle.visible = true;
21         obstacle.block_light = true;
22         types.Add(obstacle);
23
24         BlockType source;
25         source.visible = true;
26         source.luminosity = 5;
27         source.block_light = true;
28         types.Add(source);
29 }
30
31 void ChunkTest::tearDown() {
32 }
33
34
35 void ChunkTest::testBounds() {
36         CPPUNIT_ASSERT_MESSAGE(
37                 "valid position out of bounds",
38                 Chunk::InBounds(Chunk::Pos(0, 0, 0))
39         );
40         CPPUNIT_ASSERT_MESSAGE(
41                 "valid position out of bounds",
42                 Chunk::InBounds(Chunk::Pos(15, 0, 0))
43         );
44         CPPUNIT_ASSERT_MESSAGE(
45                 "valid position out of bounds",
46                 Chunk::InBounds(Chunk::Pos(0, 15, 0))
47         );
48         CPPUNIT_ASSERT_MESSAGE(
49                 "valid position out of bounds",
50                 Chunk::InBounds(Chunk::Pos(0, 0, 15))
51         );
52         CPPUNIT_ASSERT_MESSAGE(
53                 "valid position out of bounds",
54                 Chunk::InBounds(Chunk::Pos(15, 15, 15))
55         );
56         CPPUNIT_ASSERT_MESSAGE(
57                 "invalid position in bounds",
58                 !Chunk::InBounds(Chunk::Pos(-1, -1, -1))
59         );
60         CPPUNIT_ASSERT_MESSAGE(
61                 "invalid position in bounds",
62                 !Chunk::InBounds(Chunk::Pos(-1, 1, 0))
63         );
64         CPPUNIT_ASSERT_MESSAGE(
65                 "invalid position in bounds",
66                 !Chunk::InBounds(Chunk::Pos(16, -16, 0))
67         );
68         CPPUNIT_ASSERT_MESSAGE(
69                 "invalid position in bounds",
70                 !Chunk::InBounds(Chunk::Pos(16, 16, 16))
71         );
72 }
73
74 void ChunkTest::testBorder() {
75         CPPUNIT_ASSERT_MESSAGE(
76                 "position not border",
77                 Chunk::IsBorder(Chunk::Pos(0, 0, 0))
78         );
79         CPPUNIT_ASSERT_MESSAGE(
80                 "position not border",
81                 Chunk::IsBorder(Chunk::Pos(0, 0, 8))
82         );
83         CPPUNIT_ASSERT_MESSAGE(
84                 "position not border",
85                 Chunk::IsBorder(Chunk::Pos(0, 0, 15))
86         );
87         CPPUNIT_ASSERT_MESSAGE(
88                 "position not border",
89                 Chunk::IsBorder(Chunk::Pos(0, 8, 0))
90         );
91         CPPUNIT_ASSERT_MESSAGE(
92                 "position not border",
93                 Chunk::IsBorder(Chunk::Pos(0, 8, 8))
94         );
95         CPPUNIT_ASSERT_MESSAGE(
96                 "position not border",
97                 Chunk::IsBorder(Chunk::Pos(0, 8, 15))
98         );
99         CPPUNIT_ASSERT_MESSAGE(
100                 "position not border",
101                 Chunk::IsBorder(Chunk::Pos(0, 15, 0))
102         );
103         CPPUNIT_ASSERT_MESSAGE(
104                 "position not border",
105                 Chunk::IsBorder(Chunk::Pos(0, 15, 8))
106         );
107         CPPUNIT_ASSERT_MESSAGE(
108                 "position not border",
109                 Chunk::IsBorder(Chunk::Pos(0, 15, 15))
110         );
111         CPPUNIT_ASSERT_MESSAGE(
112                 "position not border",
113                 Chunk::IsBorder(Chunk::Pos(8, 0, 0))
114         );
115         CPPUNIT_ASSERT_MESSAGE(
116                 "position not border",
117                 Chunk::IsBorder(Chunk::Pos(8, 0, 8))
118         );
119         CPPUNIT_ASSERT_MESSAGE(
120                 "position not border",
121                 Chunk::IsBorder(Chunk::Pos(8, 0, 15))
122         );
123         CPPUNIT_ASSERT_MESSAGE(
124                 "position not border",
125                 Chunk::IsBorder(Chunk::Pos(8, 8, 0))
126         );
127         CPPUNIT_ASSERT_MESSAGE(
128                 "position is border",
129                 !Chunk::IsBorder(Chunk::Pos(8, 8, 8))
130         );
131         CPPUNIT_ASSERT_MESSAGE(
132                 "position not border",
133                 Chunk::IsBorder(Chunk::Pos(8, 8, 15))
134         );
135         CPPUNIT_ASSERT_MESSAGE(
136                 "position not border",
137                 Chunk::IsBorder(Chunk::Pos(8, 15, 0))
138         );
139         CPPUNIT_ASSERT_MESSAGE(
140                 "position not border",
141                 Chunk::IsBorder(Chunk::Pos(8, 15, 8))
142         );
143         CPPUNIT_ASSERT_MESSAGE(
144                 "position not border",
145                 Chunk::IsBorder(Chunk::Pos(8, 15, 15))
146         );
147         CPPUNIT_ASSERT_MESSAGE(
148                 "position not border",
149                 Chunk::IsBorder(Chunk::Pos(15, 0, 0))
150         );
151         CPPUNIT_ASSERT_MESSAGE(
152                 "position not border",
153                 Chunk::IsBorder(Chunk::Pos(15, 0, 8))
154         );
155         CPPUNIT_ASSERT_MESSAGE(
156                 "position not border",
157                 Chunk::IsBorder(Chunk::Pos(15, 0, 15))
158         );
159         CPPUNIT_ASSERT_MESSAGE(
160                 "position not border",
161                 Chunk::IsBorder(Chunk::Pos(15, 8, 0))
162         );
163         CPPUNIT_ASSERT_MESSAGE(
164                 "position not border",
165                 Chunk::IsBorder(Chunk::Pos(15, 8, 8))
166         );
167         CPPUNIT_ASSERT_MESSAGE(
168                 "position not border",
169                 Chunk::IsBorder(Chunk::Pos(15, 8, 15))
170         );
171         CPPUNIT_ASSERT_MESSAGE(
172                 "position not border",
173                 Chunk::IsBorder(Chunk::Pos(15, 15, 0))
174         );
175         CPPUNIT_ASSERT_MESSAGE(
176                 "position not border",
177                 Chunk::IsBorder(Chunk::Pos(15, 15, 8))
178         );
179         CPPUNIT_ASSERT_MESSAGE(
180                 "position not border",
181                 Chunk::IsBorder(Chunk::Pos(15, 15, 15))
182         );
183
184         CPPUNIT_ASSERT_MESSAGE(
185                 "position not border",
186                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 0, 0)))
187         );
188         CPPUNIT_ASSERT_MESSAGE(
189                 "position not border",
190                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 0, 8)))
191         );
192         CPPUNIT_ASSERT_MESSAGE(
193                 "position not border",
194                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 0, 15)))
195         );
196         CPPUNIT_ASSERT_MESSAGE(
197                 "position not border",
198                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 8, 0)))
199         );
200         CPPUNIT_ASSERT_MESSAGE(
201                 "position not border",
202                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 8, 8)))
203         );
204         CPPUNIT_ASSERT_MESSAGE(
205                 "position not border",
206                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 8, 15)))
207         );
208         CPPUNIT_ASSERT_MESSAGE(
209                 "position not border",
210                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 15, 0)))
211         );
212         CPPUNIT_ASSERT_MESSAGE(
213                 "position not border",
214                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 15, 8)))
215         );
216         CPPUNIT_ASSERT_MESSAGE(
217                 "position not border",
218                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(0, 15, 15)))
219         );
220         CPPUNIT_ASSERT_MESSAGE(
221                 "position not border",
222                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 0, 0)))
223         );
224         CPPUNIT_ASSERT_MESSAGE(
225                 "position not border",
226                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 0, 8)))
227         );
228         CPPUNIT_ASSERT_MESSAGE(
229                 "position not border",
230                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 0, 15)))
231         );
232         CPPUNIT_ASSERT_MESSAGE(
233                 "position not border",
234                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 8, 0)))
235         );
236         CPPUNIT_ASSERT_MESSAGE(
237                 "position is border",
238                 !Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 8, 8)))
239         );
240         CPPUNIT_ASSERT_MESSAGE(
241                 "position not border",
242                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 8, 15)))
243         );
244         CPPUNIT_ASSERT_MESSAGE(
245                 "position not border",
246                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 15, 0)))
247         );
248         CPPUNIT_ASSERT_MESSAGE(
249                 "position not border",
250                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 15, 8)))
251         );
252         CPPUNIT_ASSERT_MESSAGE(
253                 "position not border",
254                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(8, 15, 15)))
255         );
256         CPPUNIT_ASSERT_MESSAGE(
257                 "position not border",
258                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 0, 0)))
259         );
260         CPPUNIT_ASSERT_MESSAGE(
261                 "position not border",
262                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 0, 8)))
263         );
264         CPPUNIT_ASSERT_MESSAGE(
265                 "position not border",
266                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 0, 15)))
267         );
268         CPPUNIT_ASSERT_MESSAGE(
269                 "position not border",
270                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 8, 0)))
271         );
272         CPPUNIT_ASSERT_MESSAGE(
273                 "position not border",
274                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 8, 8)))
275         );
276         CPPUNIT_ASSERT_MESSAGE(
277                 "position not border",
278                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 8, 15)))
279         );
280         CPPUNIT_ASSERT_MESSAGE(
281                 "position not border",
282                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 15, 0)))
283         );
284         CPPUNIT_ASSERT_MESSAGE(
285                 "position not border",
286                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 15, 8)))
287         );
288         CPPUNIT_ASSERT_MESSAGE(
289                 "position not border",
290                 Chunk::IsBorder(Chunk::ToIndex(Chunk::Pos(15, 15, 15)))
291         );
292 }
293
294 void ChunkTest::testNeighbor() {
295         unique_ptr<Chunk> chunk(new Chunk(types));
296         chunk->Position({0, 0, 0});
297         for (int i = 0; i < Block::FACE_COUNT; ++i) {
298                 CPPUNIT_ASSERT_MESSAGE(
299                         "sole chunk has neighbor",
300                         !chunk->HasNeighbor(Block::Face(i))
301                 );
302         }
303
304         unique_ptr<Chunk> neighbor(new Chunk(types));
305         for (int i = 0; i < Block::FACE_COUNT; ++i) {
306                 Block::Face face = Block::Face(i);
307                 neighbor->Position(Block::FaceNormal(face));
308                 chunk->SetNeighbor(*neighbor);
309                 CPPUNIT_ASSERT_MESSAGE(
310                         "chunk did not link right neighbor",
311                         chunk->HasNeighbor(face)
312                 );
313                 CPPUNIT_ASSERT_MESSAGE(
314                         "chunk did not link right neighbor",
315                         neighbor->HasNeighbor(Block::Opposite(face))
316                 );
317                 CPPUNIT_ASSERT_EQUAL_MESSAGE(
318                         "chunk did not link correct neighbor",
319                         &*neighbor, &chunk->GetNeighbor(face)
320                 );
321                 CPPUNIT_ASSERT_EQUAL_MESSAGE(
322                         "chunk did not link correct neighbor",
323                         &*chunk, &neighbor->GetNeighbor(Block::Opposite(face))
324                 );
325                 chunk->ClearNeighbors();
326         }
327
328         neighbor->Position({1, 1, 1});
329         chunk->SetNeighbor(*neighbor);
330         for (int i = 0; i < Block::FACE_COUNT; ++i) {
331                 CPPUNIT_ASSERT_MESSAGE(
332                         "chunk linked with non-neighbor",
333                         !chunk->HasNeighbor(Block::Face(i))
334                 );
335         }
336 }
337
338
339 void ChunkTest::testBlock() {
340         unique_ptr<Chunk> chunk(new Chunk(types));
341
342         for (int index = 0; index < Chunk::size; ++index) {
343                 CPPUNIT_ASSERT_EQUAL_MESSAGE(
344                         "default chunk has non-default block",
345                         Block(), chunk->BlockAt(index)
346                 );
347         }
348
349         Block block(1, Block::FACE_LEFT, Block::TURN_RIGHT);
350         chunk->SetBlock(0, block);
351         CPPUNIT_ASSERT_EQUAL_MESSAGE(
352                 "wrong type on set block",
353                 block.type, chunk->BlockAt(0).type
354         );
355         CPPUNIT_ASSERT_EQUAL_MESSAGE(
356                 "wrong orientation on set block",
357                 block.orient, chunk->BlockAt(0).orient
358         );
359         for (int index = 1; index < Chunk::size; ++index) {
360                 CPPUNIT_ASSERT_EQUAL_MESSAGE(
361                         "changing block at index 0 affected some other block",
362                         Block(), chunk->BlockAt(index)
363                 );
364         }
365 }
366
367 void ChunkTest::testLight() {
368         unique_ptr<Chunk> chunk(new Chunk(types));
369
370         for (int index = 0; index < Chunk::size; ++index) {
371                 CPPUNIT_ASSERT_EQUAL_MESSAGE(
372                         "default chunk has non-zero light level",
373                         0, chunk->GetLight(index)
374                 );
375         }
376
377         chunk->SetLight(0, 15);
378         CPPUNIT_ASSERT_EQUAL_MESSAGE(
379                 "wrong light level on set index",
380                 15, chunk->GetLight(0)
381         );
382         for (int index = 1; index < Chunk::size; ++index) {
383                 CPPUNIT_ASSERT_EQUAL_MESSAGE(
384                         "changing light at index 0 affected some other index",
385                         0, chunk->GetLight(index)
386                 );
387         }
388 }
389
390 void ChunkTest::testLightPropagation() {
391         unique_ptr<Chunk> chunk(new Chunk(types));
392
393         // 0 air, 1 solid, 2 solid and emits light level of 5
394         chunk->SetBlock(Chunk::Pos(7, 7, 7), Block(2));
395         CPPUNIT_ASSERT_EQUAL_MESSAGE(
396                 "adding luminant block did not set correct light level",
397                 5, chunk->GetLight(Chunk::Pos(7, 7, 7))
398         );
399
400         CPPUNIT_ASSERT_EQUAL_MESSAGE(
401                 "light did not propagate correctly in +X",
402                 4, chunk->GetLight(Chunk::Pos(8, 7, 7))
403         );
404         CPPUNIT_ASSERT_EQUAL_MESSAGE(
405                 "light did not propagate correctly in -X",
406                 4, chunk->GetLight(Chunk::Pos(6, 7, 7))
407         );
408         CPPUNIT_ASSERT_EQUAL_MESSAGE(
409                 "light did not propagate correctly in +Y",
410                 4, chunk->GetLight(Chunk::Pos(7, 8, 7))
411         );
412         CPPUNIT_ASSERT_EQUAL_MESSAGE(
413                 "light did not propagate correctly in -Y",
414                 4, chunk->GetLight(Chunk::Pos(7, 6, 7))
415         );
416         CPPUNIT_ASSERT_EQUAL_MESSAGE(
417                 "light did not propagate correctly in +Z",
418                 4, chunk->GetLight(Chunk::Pos(7, 7, 8))
419         );
420         CPPUNIT_ASSERT_EQUAL_MESSAGE(
421                 "light did not propagate correctly in -Z",
422                 4, chunk->GetLight(Chunk::Pos(7, 7, 6))
423         );
424
425         CPPUNIT_ASSERT_EQUAL_MESSAGE(
426                 "light did not propagate correctly in 2D diagonal",
427                 3, chunk->GetLight(Chunk::Pos(8, 8, 7))
428         );
429         CPPUNIT_ASSERT_EQUAL_MESSAGE(
430                 "light did not propagate correctly in 2D diagonal",
431                 3, chunk->GetLight(Chunk::Pos(7, 6, 8))
432         );
433         CPPUNIT_ASSERT_EQUAL_MESSAGE(
434                 "light did not propagate correctly in 2D diagonal",
435                 3, chunk->GetLight(Chunk::Pos(6, 7, 8))
436         );
437
438         CPPUNIT_ASSERT_EQUAL_MESSAGE(
439                 "light did not propagate correctly in 3D diagonal",
440                 2, chunk->GetLight(Chunk::Pos(8, 6, 6))
441         );
442         CPPUNIT_ASSERT_EQUAL_MESSAGE(
443                 "light did not propagate correctly in 3D diagonal",
444                 2, chunk->GetLight(Chunk::Pos(6, 6, 8))
445         );
446         CPPUNIT_ASSERT_EQUAL_MESSAGE(
447                 "light did not propagate correctly in 3D diagonal",
448                 2, chunk->GetLight(Chunk::Pos(6, 8, 8))
449         );
450
451         // now block the light to the left
452         chunk->SetBlock(Chunk::Pos(6, 7, 7), Block(1));
453         CPPUNIT_ASSERT_EQUAL_MESSAGE(
454                 "non-zero light level in solid block",
455                 0, chunk->GetLight(Chunk::Pos(6, 7, 7))
456         );
457         CPPUNIT_ASSERT_EQUAL_MESSAGE(
458                 "adding obstacle affected unrelated index",
459                 5, chunk->GetLight(Chunk::Pos(7, 7, 7))
460         );
461         CPPUNIT_ASSERT_EQUAL_MESSAGE(
462                 "adding obstacle affected unrelated index",
463                 4, chunk->GetLight(Chunk::Pos(8, 7, 7))
464         );
465         CPPUNIT_ASSERT_EQUAL_MESSAGE(
466                 "adding obstacle affected unrelated index",
467                 4, chunk->GetLight(Chunk::Pos(7, 8, 7))
468         );
469         CPPUNIT_ASSERT_EQUAL_MESSAGE(
470                 "adding obstacle affected unrelated index",
471                 4, chunk->GetLight(Chunk::Pos(7, 6, 7))
472         );
473         CPPUNIT_ASSERT_EQUAL_MESSAGE(
474                 "adding obstacle affected unrelated index",
475                 4, chunk->GetLight(Chunk::Pos(7, 7, 8))
476         );
477         CPPUNIT_ASSERT_EQUAL_MESSAGE(
478                 "adding obstacle affected unrelated index",
479                 4, chunk->GetLight(Chunk::Pos(7, 7, 6))
480         );
481         CPPUNIT_ASSERT_EQUAL_MESSAGE(
482                 "adding obstacle affected unrelated index",
483                 3, chunk->GetLight(Chunk::Pos(6, 6, 7))
484         );
485         CPPUNIT_ASSERT_EQUAL_MESSAGE(
486                 "adding obstacle affected unrelated index",
487                 3, chunk->GetLight(Chunk::Pos(6, 8, 7))
488         );
489         CPPUNIT_ASSERT_EQUAL_MESSAGE(
490                 "adding obstacle affected unrelated index",
491                 3, chunk->GetLight(Chunk::Pos(6, 7, 6))
492         );
493         CPPUNIT_ASSERT_EQUAL_MESSAGE(
494                 "adding obstacle affected unrelated index",
495                 3, chunk->GetLight(Chunk::Pos(6, 7, 6))
496         );
497         CPPUNIT_ASSERT_EQUAL_MESSAGE(
498                 "adding obstacle affected unrelated index",
499                 2, chunk->GetLight(Chunk::Pos(5, 6, 7))
500         );
501         CPPUNIT_ASSERT_EQUAL_MESSAGE(
502                 "adding obstacle affected unrelated index",
503                 2, chunk->GetLight(Chunk::Pos(5, 8, 7))
504         );
505         CPPUNIT_ASSERT_EQUAL_MESSAGE(
506                 "adding obstacle affected unrelated index",
507                 2, chunk->GetLight(Chunk::Pos(5, 7, 6))
508         );
509         CPPUNIT_ASSERT_EQUAL_MESSAGE(
510                 "adding obstacle affected unrelated index",
511                 2, chunk->GetLight(Chunk::Pos(5, 7, 6))
512         );
513         CPPUNIT_ASSERT_EQUAL_MESSAGE(
514                 "adding obstacle resulted in unexpected light level behind it",
515                 1, chunk->GetLight(Chunk::Pos(5, 7, 7))
516         );
517
518         // and remove it again
519         chunk->SetBlock(Chunk::Pos(6, 7, 7), Block(0));
520         CPPUNIT_ASSERT_EQUAL_MESSAGE(
521                 "removing obstacle did not refill light correctly",
522                 4, chunk->GetLight(Chunk::Pos(6, 7, 7))
523         );
524         CPPUNIT_ASSERT_EQUAL_MESSAGE(
525                 "removing obstacle did not refill light correctly",
526                 3, chunk->GetLight(Chunk::Pos(5, 7, 7))
527         );
528         CPPUNIT_ASSERT_EQUAL_MESSAGE(
529                 "removing obstacle did not refill light correctly",
530                 2, chunk->GetLight(Chunk::Pos(4, 7, 7))
531         );
532 }
533
534 }
535 }