Chunk.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. #include <InMemoryBuffer.h>
  2. #include "Chunk.h"
  3. #include "Constants.h"
  4. #include "Game.h"
  5. #include "NoBlock.h"
  6. Chunk::Chunk(Framework::Punkt location, int dimensionId)
  7. : ReferenceCounter(),
  8. dimensionId(dimensionId),
  9. location(location),
  10. added(0)
  11. {
  12. blocks = new Block * [CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT];
  13. blockIds = new unsigned short[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT];
  14. lightData = new unsigned char[CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * 6];
  15. memset(blocks, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof(Block*));
  16. memset(blockIds, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * sizeof(unsigned short));
  17. memset(lightData, 0, CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT * 6);
  18. zNeighbours[0] = 0;
  19. zNeighbours[1] = 0;
  20. zNeighbours[2] = 0;
  21. zNeighbours[3] = 0;
  22. }
  23. Chunk::Chunk(Framework::Punkt location, int dimensionId, Framework::StreamReader* zReader)
  24. : Chunk(location, dimensionId)
  25. {
  26. load(zReader);
  27. }
  28. Chunk::~Chunk()
  29. {
  30. for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
  31. {
  32. if (blocks[i])
  33. blocks[i]->release();
  34. }
  35. delete[] blocks;
  36. delete[] blockIds;
  37. delete[] lightData;
  38. }
  39. void Chunk::addLightSource(int index)
  40. {
  41. for (int i : lightSources)
  42. {
  43. if (i == index)
  44. return;
  45. }
  46. lightSources.add(index);
  47. }
  48. void Chunk::removeLightSource(int index)
  49. {
  50. for (auto i = lightSources.begin(); i; i++)
  51. {
  52. if (i.val() == index)
  53. {
  54. i.remove();
  55. return;
  56. }
  57. }
  58. }
  59. Framework::Either<Block*, int> Chunk::zBlockNeighbor(Framework::Vec3<int> location)
  60. {
  61. if (location.x >= 0 && location.x < CHUNK_SIZE && location.y >= 0 && location.y < CHUNK_SIZE && location.z >= 0 && location.z < WORLD_HEIGHT)
  62. {
  63. int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
  64. if (blocks[index])
  65. return blocks[index];
  66. else
  67. return (int)blockIds[index];
  68. }
  69. if (added && location.z >= 0 && location.z < WORLD_HEIGHT)
  70. return Game::INSTANCE->zBlockAt({ location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId);
  71. return 0;
  72. }
  73. void Chunk::notifyObservers(NetworkMessage& msg)
  74. {
  75. Array<int> remove;
  76. int index = 0;
  77. for (int id : observers)
  78. {
  79. Entity* zE = Game::INSTANCE->zEntity(id);
  80. if (!zE)
  81. remove.add(index, 0);
  82. else
  83. Game::INSTANCE->sendMessage(&msg, zE);
  84. index++;
  85. }
  86. for (int i : remove)
  87. observers.remove(i);
  88. }
  89. void Chunk::addObserver(Entity* zEntity)
  90. {
  91. for (int id : observers)
  92. {
  93. if (id == zEntity->getId())
  94. return;
  95. }
  96. observers.add(zEntity->getId());
  97. InMemoryBuffer buffer;
  98. buffer.schreibe("\4", 1);
  99. buffer.schreibe((char*)&location.x, 4);
  100. buffer.schreibe((char*)&location.y, 4);
  101. sendToClient(&buffer);
  102. NetworkMessage msg;
  103. msg.addressDimension();
  104. char* message = new char[buffer.getSize()];
  105. buffer.lese(message, (int)buffer.getSize());
  106. msg.setMessage(message, (int)buffer.getSize(), 1);
  107. msg.setUseBackground();
  108. Game::INSTANCE->sendMessage(&msg, zEntity);
  109. }
  110. void Chunk::removeObserver(Entity* zEntity)
  111. {
  112. int index = 0;
  113. for (int id : observers)
  114. {
  115. if (id == zEntity->getId())
  116. {
  117. observers.remove(index);
  118. return;
  119. }
  120. index++;
  121. }
  122. }
  123. void Chunk::api(Framework::StreamReader* zRequest, Entity* zSource)
  124. {
  125. // TODO: answer api messages
  126. char type;
  127. zRequest->lese(&type, 1);
  128. switch (type)
  129. {
  130. case 0:
  131. // register observer
  132. addObserver(zSource);
  133. break;
  134. case 1:
  135. // unsubscribe
  136. removeObserver(zSource);
  137. break;
  138. }
  139. }
  140. void Chunk::initializeLightning()
  141. {
  142. unsigned char dayLight[6] = { 255, 255, 255, 0, 0, 0 };
  143. unsigned char noLight[6] = { 0, 0, 0, 0, 0, 0 };
  144. while (true)
  145. {
  146. bool changes = false;
  147. for (int z = WORLD_HEIGHT - 1; z >= 0; z--)
  148. {
  149. for (int x = 0; x < CHUNK_SIZE; x++)
  150. {
  151. for (int y = 0; y < CHUNK_SIZE; y++)
  152. {
  153. int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
  154. unsigned char* light = getLightData(Vec3<int>(x, y, z));
  155. unsigned char newLight[6] = { 0, 0, 0, 0, 0, 0 };
  156. for (int i = 0; i < 6; i++)
  157. {
  158. unsigned char* neighborLeight;
  159. Vec3<int> neighborPos = Vec3<int>(x, y, z) + getDirection(getDirectionFromIndex(i));
  160. if (neighborPos.z < 0 || neighborPos.x < 0 || neighborPos.y < 0 || neighborPos.x >= CHUNK_SIZE || neighborPos.y >= CHUNK_SIZE)
  161. {
  162. neighborLeight = noLight;
  163. }
  164. else if (neighborPos.z >= WORLD_HEIGHT)
  165. {
  166. neighborLeight = dayLight;
  167. }
  168. else
  169. {
  170. neighborLeight = getLightData(Vec3<int>(x, y, neighborPos.z));
  171. }
  172. for (int j = 0; j < 3; j++)
  173. newLight[j] = (unsigned char)MAX(newLight[j], i == getDirectionIndex(TOP) ? neighborLeight[j] : neighborLeight[j] - 16);
  174. for (int j = 3; j < 6; j++)
  175. newLight[j] = (unsigned char)MAX(newLight[j], neighborLeight[j] - 16);
  176. }
  177. const Block* current = blocks[index] ? blocks[index] : StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])->zDefault();
  178. // add own light emission
  179. for (int j = 3; j < 6; j++)
  180. newLight[j] = (unsigned char)MAX(newLight[j], current->getLightEmisionColor()[j - 3]);
  181. current->filterPassingLight(newLight);
  182. current->filterPassingLight(newLight + 3);
  183. for (int i = 0; i < 6; i++)
  184. {
  185. if (newLight[i] != light[i])
  186. {
  187. memcpy(light, newLight, 6);
  188. }
  189. }
  190. }
  191. }
  192. }
  193. if (!changes)
  194. break;
  195. }
  196. }
  197. Framework::Either<Block*, int> Chunk::zBlockAt(Framework::Vec3<int> location) const
  198. {
  199. int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
  200. assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT);
  201. if (blocks[index])
  202. return blocks[index];
  203. else
  204. return (int)blockIds[index];
  205. }
  206. const Block* Chunk::zBlockConst(Framework::Vec3<int> location) const
  207. {
  208. auto b = zBlockAt(location);
  209. if (b.isA())
  210. return b;
  211. if (b.getB())
  212. return StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())->zDefault();
  213. return 0;
  214. }
  215. void Chunk::instantiateBlock(Framework::Vec3<int> location)
  216. {
  217. auto b = zBlockAt(location);
  218. if (b.isA())
  219. return;
  220. if (!b.getB())
  221. generateBlock(location);
  222. b = zBlockAt(location);
  223. if (b.isB())
  224. putBlockAt(location, StaticRegistry<BlockType>::INSTANCE.zElement(b.getB())->createBlockAt({ location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, 0));
  225. }
  226. void Chunk::generateBlock(Framework::Vec3<int> location)
  227. {
  228. int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
  229. if (blockIds[index])
  230. return;
  231. auto generated = Game::INSTANCE->zGenerator()->generateSingleBlock({ location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z }, dimensionId);
  232. if (generated.isA())
  233. putBlockAt(location, generated);
  234. else
  235. putBlockTypeAt(location, generated);
  236. }
  237. void Chunk::putBlockAt(Framework::Vec3<int> location, Block* block)
  238. {
  239. int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
  240. assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT&& index >= 0);
  241. Block* old = blocks[index];
  242. bool change = 0;
  243. bool wasLightSource = old ? old->zBlockType()->isLightSource() : StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])->isLightSource();
  244. bool isLightSource = 0;
  245. if (block)
  246. {
  247. change = blockIds[index] != (unsigned short)block->zBlockType()->getId();
  248. blockIds[index] = (unsigned short)block->zBlockType()->getId();
  249. isLightSource = block->zBlockType()->isLightSource();
  250. }
  251. else
  252. {
  253. change = old != 0;
  254. }
  255. blocks[index] = block;
  256. Either<Block*, int> neighbor = zBlockNeighbor(location + getDirection(NORTH));
  257. if (neighbor.isA())
  258. ((Block*)neighbor)->setNeighbour(SOUTH, block);
  259. if (block)
  260. block->setNeighbour(NORTH, neighbor);
  261. neighbor = zBlockNeighbor(location + getDirection(EAST));
  262. if (neighbor.isA())
  263. ((Block*)neighbor)->setNeighbour(WEST, block);
  264. if (block)
  265. block->setNeighbour(EAST, neighbor);
  266. neighbor = zBlockNeighbor(location + getDirection(SOUTH));
  267. if (neighbor.isA())
  268. ((Block*)neighbor)->setNeighbour(NORTH, block);
  269. if (block)
  270. block->setNeighbour(SOUTH, neighbor);
  271. neighbor = zBlockNeighbor(location + getDirection(WEST));
  272. if (neighbor.isA())
  273. ((Block*)neighbor)->setNeighbour(EAST, block);
  274. if (block)
  275. block->setNeighbour(WEST, neighbor);
  276. neighbor = zBlockNeighbor(location + getDirection(TOP));
  277. if (neighbor.isA())
  278. ((Block*)neighbor)->setNeighbour(BOTTOM, block);
  279. if (block)
  280. block->setNeighbour(TOP, neighbor);
  281. neighbor = zBlockNeighbor(location + getDirection(BOTTOM));
  282. if (neighbor.isA())
  283. ((Block*)neighbor)->setNeighbour(TOP, block);
  284. if (block)
  285. block->setNeighbour(BOTTOM, neighbor);
  286. if (old)
  287. old->release();
  288. if (change)
  289. {
  290. if (isLightSource != wasLightSource)
  291. {
  292. if (isLightSource)
  293. addLightSource(index);
  294. else
  295. removeLightSource(index);
  296. }
  297. if (added)
  298. {
  299. Game::INSTANCE->updateLightning(getDimensionId(), Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z));
  300. }
  301. char msg[9];
  302. msg[0] = 0; // set block
  303. *(int*)(msg + 1) = index;
  304. *(int*)(msg + 5) = block ? block->zBlockType()->getId() : NoBlockBlockType::ID;
  305. NetworkMessage message;
  306. message.addressChunck(this);
  307. message.setMessage(msg, 9, 0);
  308. notifyObservers(message);
  309. }
  310. }
  311. void Chunk::putBlockTypeAt(Framework::Vec3<int> location, int type)
  312. {
  313. int index = (location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z;
  314. assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT);
  315. bool wasLightSource = StaticRegistry<BlockType>::INSTANCE.zElement(blockIds[index])->isLightSource();
  316. bool isLightSource = StaticRegistry<BlockType>::INSTANCE.zElement(type)->isLightSource();
  317. if (blockIds[index] != (unsigned short)type)
  318. {
  319. blockIds[index] = (unsigned short)type;
  320. Either<Block*, int> neighbor = zBlockNeighbor(location + getDirection(NORTH));
  321. if (neighbor.isA())
  322. ((Block*)neighbor)->setNeighbourType(SOUTH, type);
  323. neighbor = zBlockNeighbor(location + getDirection(EAST));
  324. if (neighbor.isA())
  325. ((Block*)neighbor)->setNeighbourType(WEST, type);
  326. neighbor = zBlockNeighbor(location + getDirection(SOUTH));
  327. if (neighbor.isA())
  328. ((Block*)neighbor)->setNeighbourType(NORTH, type);
  329. neighbor = zBlockNeighbor(location + getDirection(WEST));
  330. if (neighbor.isA())
  331. ((Block*)neighbor)->setNeighbourType(EAST, type);
  332. neighbor = zBlockNeighbor(location + getDirection(TOP));
  333. if (neighbor.isA())
  334. ((Block*)neighbor)->setNeighbourType(BOTTOM, type);
  335. neighbor = zBlockNeighbor(location + getDirection(BOTTOM));
  336. if (neighbor.isA())
  337. ((Block*)neighbor)->setNeighbourType(TOP, type);
  338. if (isLightSource != wasLightSource)
  339. {
  340. if (isLightSource)
  341. addLightSource(index);
  342. else
  343. removeLightSource(index);
  344. }
  345. if (added)
  346. {
  347. Game::INSTANCE->updateLightning(getDimensionId(), Vec3<int>(location.x + this->location.x - CHUNK_SIZE / 2, location.y + this->location.y - CHUNK_SIZE / 2, location.z));
  348. }
  349. char msg[9];
  350. msg[0] = 0; // set block
  351. *(int*)(msg + 1) = index;
  352. *(int*)(msg + 5) = type;
  353. NetworkMessage message;
  354. message.addressChunck(this);
  355. message.setMessage(msg, 9, 0);
  356. notifyObservers(message);
  357. }
  358. }
  359. void Chunk::setNeighbor(Direction dir, Chunk* zChunk)
  360. {
  361. zNeighbours[getDirectionIndex(dir)] = zChunk;
  362. for (int i = 0; i < CHUNK_SIZE; i++)
  363. {
  364. for (int z = 0; z < WORLD_HEIGHT; z++)
  365. {
  366. if (dir == NORTH)
  367. {
  368. int index = i * CHUNK_SIZE * WORLD_HEIGHT + z;
  369. if (blocks[index])
  370. {
  371. int j = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
  372. if (zChunk && zChunk->blocks[j])
  373. blocks[index]->setNeighbour(NORTH, zChunk->blocks[j]);
  374. else
  375. {
  376. blocks[index]->setNeighbour(NORTH, 0);
  377. blocks[index]->setNeighbourType(NORTH, zChunk ? zChunk->blockIds[j] : 0);
  378. }
  379. }
  380. }
  381. else if (dir == EAST)
  382. {
  383. int index = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
  384. if (blocks[index])
  385. {
  386. int j = i * WORLD_HEIGHT + z;
  387. if (zChunk && zChunk->blocks[j])
  388. blocks[index]->setNeighbour(EAST, zChunk->blocks[j]);
  389. else
  390. {
  391. blocks[index]->setNeighbour(EAST, 0);
  392. blocks[index]->setNeighbourType(EAST, zChunk ? zChunk->blockIds[j] : 0);
  393. }
  394. }
  395. }
  396. else if (dir == SOUTH)
  397. {
  398. int index = (i * CHUNK_SIZE + CHUNK_SIZE - 1) * WORLD_HEIGHT + z;
  399. if (blocks[index])
  400. {
  401. int j = i * CHUNK_SIZE * WORLD_HEIGHT + z;
  402. if (zChunk && zChunk->blocks[j])
  403. blocks[index]->setNeighbour(SOUTH, zChunk->blocks[j]);
  404. else
  405. {
  406. blocks[index]->setNeighbour(SOUTH, 0);
  407. blocks[index]->setNeighbourType(SOUTH, zChunk ? zChunk->blockIds[j] : 0);
  408. }
  409. }
  410. }
  411. else if (dir == WEST)
  412. {
  413. int index = i * WORLD_HEIGHT + z;
  414. if (blocks[index])
  415. {
  416. int j = ((CHUNK_SIZE - 1) * CHUNK_SIZE + i) * WORLD_HEIGHT + z;
  417. if (zChunk && zChunk->blocks[j])
  418. blocks[index]->setNeighbour(WEST, zChunk->blocks[j]);
  419. else
  420. {
  421. blocks[index]->setNeighbour(WEST, 0);
  422. blocks[index]->setNeighbourType(WEST, zChunk ? zChunk->blockIds[j] : 0);
  423. }
  424. }
  425. }
  426. }
  427. }
  428. }
  429. void Chunk::load(Framework::StreamReader* zReader)
  430. {
  431. unsigned short id = 0;
  432. zReader->lese((char*)&id, 2);
  433. Framework::Vec3<int> pos;
  434. bool d = 0;
  435. while (id)
  436. {
  437. zReader->lese((char*)&pos.x, 4);
  438. zReader->lese((char*)&pos.y, 4);
  439. zReader->lese((char*)&pos.z, 4);
  440. zReader->lese((char*)&d, 1);
  441. if (d)
  442. putBlockAt(pos, StaticRegistry<BlockType>::INSTANCE.zElement(id)->loadBlock(Framework::Vec3<int>(pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z), zReader));
  443. else
  444. putBlockTypeAt(pos, id);
  445. zReader->lese((char*)&id, 2);
  446. }
  447. initializeLightning();
  448. }
  449. void Chunk::save(Framework::StreamWriter* zWriter)
  450. {
  451. for (int x = 0; x < CHUNK_SIZE; x++)
  452. {
  453. for (int y = 0; y < CHUNK_SIZE; y++)
  454. {
  455. for (int z = 0; z < WORLD_HEIGHT; z++)
  456. {
  457. int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
  458. unsigned short blockType = blocks[index] ? (unsigned short)blocks[index]->zBlockType()->getId() : blockIds[index];
  459. if (blockType)
  460. {
  461. zWriter->schreibe((char*)&blockType, 2);
  462. zWriter->schreibe((char*)&x, 4);
  463. zWriter->schreibe((char*)&y, 4);
  464. zWriter->schreibe((char*)&z, 4);
  465. if (blocks[index])
  466. {
  467. bool d = 1;
  468. zWriter->schreibe((char*)&d, 1);
  469. StaticRegistry<BlockType>::INSTANCE.zElement(blockType)->saveBlock(blocks[index], zWriter);
  470. }
  471. else
  472. {
  473. bool d = 0;
  474. zWriter->schreibe((char*)&d, 1);
  475. }
  476. }
  477. }
  478. }
  479. }
  480. unsigned short end = 0;
  481. zWriter->schreibe((char*)&end, 2);
  482. }
  483. void Chunk::sendToClient(Framework::StreamWriter* zWriter)
  484. {
  485. for (int x = 0; x < CHUNK_SIZE; x++)
  486. {
  487. for (int y = 0; y < CHUNK_SIZE; y++)
  488. {
  489. for (int z = 0; z < WORLD_HEIGHT; z++)
  490. {
  491. int index = (x * CHUNK_SIZE + y) * WORLD_HEIGHT + z;
  492. unsigned short blockType = blocks[index] ? (unsigned short)blocks[index]->zBlockType()->getId() : blockIds[index];
  493. if (blockType)
  494. {
  495. bool visible = 0;
  496. if (!visible)
  497. {
  498. if (!blocks[index])
  499. {
  500. if (CONST_BLOCK(0, blockIds[index])->isTransparent() || CONST_BLOCK(0, blockIds[index])->isPassable())
  501. visible = 1;
  502. else
  503. {
  504. for (int d = 0; d < 6 && !visible; d++)
  505. {
  506. auto n = zBlockNeighbor(getDirection((Directions)getDirectionFromIndex(d)) + Framework::Vec3<int>(x, y, z));
  507. if (n.isA() && (((Block*)n)->isPassable() || ((Block*)n)->isTransparent()))
  508. visible = 1;
  509. if (n.isB() && (CONST_BLOCK(0, n)->isTransparent() || CONST_BLOCK(0, n)->isPassable()))
  510. visible = 1;
  511. }
  512. }
  513. }
  514. else
  515. visible = blocks[index]->isVisible();
  516. }
  517. if (visible && (blocks[index] || blockType != AirBlockBlockType::ID))
  518. {
  519. zWriter->schreibe((char*)&blockType, 2);
  520. zWriter->schreibe((char*)&x, 4);
  521. zWriter->schreibe((char*)&y, 4);
  522. zWriter->schreibe((char*)&z, 4);
  523. }
  524. }
  525. }
  526. }
  527. }
  528. unsigned short end = 0;
  529. zWriter->schreibe((char*)&end, 2);
  530. }
  531. void Chunk::removeUnusedBlocks()
  532. {
  533. for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
  534. {
  535. if (blocks[i])
  536. {
  537. if (!blocks[i]->isVisible())
  538. {
  539. int x = (i / WORLD_HEIGHT) / CHUNK_SIZE;
  540. int y = (i / WORLD_HEIGHT) % CHUNK_SIZE;
  541. int z = i % WORLD_HEIGHT;
  542. putBlockAt({ x,y,z }, 0);
  543. putBlockTypeAt({ x, y, z }, NoBlockBlockType::ID);
  544. }
  545. }
  546. else if (blockIds[i])
  547. {
  548. int x = (i / WORLD_HEIGHT) / CHUNK_SIZE;
  549. int y = (i / WORLD_HEIGHT) % CHUNK_SIZE;
  550. int z = i % WORLD_HEIGHT;
  551. bool visible = 0;
  552. if (CONST_BLOCK(0, blockIds[i])->isTransparent() || CONST_BLOCK(0, blockIds[i])->isPassable())
  553. visible = 1;
  554. else
  555. {
  556. for (int d = 0; d < 6 && !visible; d++)
  557. {
  558. auto n = zBlockNeighbor(getDirection((Directions)getDirectionFromIndex(d)) + Framework::Vec3<int>(x, y, z));
  559. if (n.isA() && (((Block*)n)->isPassable() || ((Block*)n)->isTransparent()))
  560. visible = 1;
  561. if (n.isB() && (CONST_BLOCK(0, n)->isTransparent() || CONST_BLOCK(0, n)->isPassable()))
  562. visible = 1;
  563. }
  564. }
  565. if (!visible)
  566. {
  567. putBlockAt({ x,y,z }, 0);
  568. putBlockTypeAt({ x, y, z }, NoBlockBlockType::ID);
  569. }
  570. }
  571. }
  572. int count = 0;
  573. for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT; i++)
  574. {
  575. if (blockIds[i] && blockIds[i] != AirBlockBlockType::ID)
  576. count++;
  577. }
  578. std::cout << "chunk " << location.x << ", " << location.y << " was generated with " << count << " blocks.\n";
  579. }
  580. int Chunk::getDimensionId() const
  581. {
  582. return dimensionId;
  583. }
  584. Framework::Punkt Chunk::getCenter() const
  585. {
  586. return location;
  587. }
  588. Framework::Vec3<int> Chunk::getMin() const
  589. {
  590. return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
  591. }
  592. Framework::Vec3<int> Chunk::getMax() const
  593. {
  594. return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
  595. }
  596. void Chunk::prepareRemove()
  597. {
  598. added = 0;
  599. for (int i = 0; i < 4; i++)
  600. {
  601. if (zNeighbours[i])
  602. {
  603. zNeighbours[i]->setNeighbor(getOppositeDirection(getDirectionFromIndex(i)), 0);
  604. zNeighbours[i] = 0;
  605. }
  606. }
  607. }
  608. void Chunk::setAdded()
  609. {
  610. added = 1;
  611. }
  612. bool Chunk::hasObservers() const
  613. {
  614. return observers.getEintragAnzahl() > 0;
  615. }
  616. unsigned char* Chunk::getLightData(Framework::Vec3<int> location) const
  617. {
  618. int index = ((location.x * CHUNK_SIZE + location.y) * WORLD_HEIGHT + location.z) * 6;
  619. assert(index < CHUNK_SIZE* CHUNK_SIZE* WORLD_HEIGHT);
  620. return lightData + index;
  621. }