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