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