Chunk.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "Chunk.h"
  2. #include "Constants.h"
  3. #include "Globals.h"
  4. #include "Registries.h"
  5. Chunk::Chunk(Framework::Punkt location)
  6. : ReferenceCounter(),
  7. location(location),
  8. isLoading(0)
  9. {}
  10. Chunk::Chunk(Framework::Punkt location, Framework::StreamReader* zReader)
  11. : Chunk(location)
  12. {
  13. load(zReader);
  14. }
  15. Chunk::~Chunk()
  16. {
  17. char msg = 1; // remove observer
  18. network->zFactoryClient()->chunkAPIRequest(location, &msg, 1);
  19. }
  20. void Chunk::api(char* message)
  21. {
  22. switch (message[0])
  23. {
  24. case 0: // set block
  25. {
  26. int index = *(int*)(message + 1);
  27. int id = *(int*)(message + 5);
  28. Framework::Vec3<int> location((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
  29. location.x += this->location.x - CHUNK_SIZE / 2;
  30. location.y += this->location.y - CHUNK_SIZE / 2;
  31. if (blockTypes[id]->doesNeedInstance())
  32. {
  33. Block* zB = blockTypes[id]->createBlock(location);
  34. setBlock(zB);
  35. }
  36. else
  37. {
  38. Block* zB = zBlockAt(location);
  39. if (zB)
  40. removeBlock(zB);
  41. }
  42. break;
  43. }
  44. case 1: // update light
  45. {
  46. int index = *(int*)(message + 1);
  47. Framework::Vec3<int> location((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
  48. for (int i = 0; i < 6; i++)
  49. {
  50. Framework::Vec3<int> pos = location + getDirection(getDirectionFromIndex(i));
  51. if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
  52. {
  53. if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0 && pos.y < CHUNK_SIZE)
  54. {
  55. pos.x += this->location.x - CHUNK_SIZE / 2;
  56. pos.y += this->location.y - CHUNK_SIZE / 2;
  57. Block* zB = zBlockAt(pos);
  58. if (zB)
  59. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)(message + 5));
  60. }
  61. else
  62. {
  63. pos.x += this->location.x - CHUNK_SIZE / 2;
  64. pos.y += this->location.y - CHUNK_SIZE / 2;
  65. Block* zB = currentGame->zBlockAt(pos);
  66. if (zB)
  67. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)(message + 5));
  68. }
  69. }
  70. }
  71. }
  72. }
  73. }
  74. Block* Chunk::zBlockAt(Framework::Vec3<int> location)
  75. {
  76. cs.lock();
  77. for (Block* b : blocks)
  78. {
  79. if (b->getLocation() == location)
  80. {
  81. cs.unlock();
  82. return b;
  83. }
  84. }
  85. cs.unlock();
  86. return 0;
  87. }
  88. void Chunk::setBlock(Block* block)
  89. {
  90. cs.lock();
  91. Framework::Vec3<int> pos = block->getLocation();
  92. for (Framework::Iterator<Block*> iterator = blocks.begin(); iterator; iterator++)
  93. {
  94. if (pos == iterator->getLocation())
  95. {
  96. iterator->release();
  97. iterator.set(block);
  98. cs.unlock();
  99. return;
  100. }
  101. }
  102. blocks.add(block);
  103. cs.unlock();
  104. if (!isLoading)
  105. updateVisibility();
  106. }
  107. void Chunk::removeBlock(Block* zBlock)
  108. {
  109. cs.lock();
  110. int index = 0;
  111. for (Framework::Iterator<Block*> iterator = blocks.begin(); iterator; iterator++, index++)
  112. {
  113. if (zBlock == (Block*)iterator)
  114. {
  115. blocks.remove(index);
  116. cs.unlock();
  117. if (!isLoading)
  118. updateVisibility();
  119. return;
  120. }
  121. }
  122. cs.unlock();
  123. }
  124. void Chunk::load(Framework::StreamReader* zReader)
  125. {
  126. isLoading = 1;
  127. Framework::Vec3<int> pos = { 0, 0, 0 };
  128. unsigned short id;
  129. zReader->lese((char*)&id, 2);
  130. while (id)
  131. {
  132. int index;
  133. zReader->lese((char*)&index, 4);
  134. pos = Vec3<int>((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
  135. if (blockTypes[id]->doesNeedInstance())
  136. setBlock(blockTypes[id]->createBlock({ pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z }));
  137. zReader->lese((char*)&id, 2);
  138. }
  139. int index = 0;
  140. // light
  141. zReader->lese((char*)&index, 4);
  142. char lightData[6];
  143. while (index >= 0)
  144. {
  145. zReader->lese(lightData, 6);
  146. Framework::Vec3<int> location((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
  147. for (int i = 0; i < 6; i++)
  148. {
  149. Framework::Vec3<int> pos = location + getDirection(getDirectionFromIndex(i));
  150. if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
  151. {
  152. if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0 && pos.y < CHUNK_SIZE)
  153. {
  154. pos.x += this->location.x - CHUNK_SIZE / 2;
  155. pos.y += this->location.y - CHUNK_SIZE / 2;
  156. Block* zB = zBlockAt(pos);
  157. if (zB)
  158. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)lightData);
  159. }
  160. else
  161. {
  162. pos.x += this->location.x - CHUNK_SIZE / 2;
  163. pos.y += this->location.y - CHUNK_SIZE / 2;
  164. Block* zB = currentGame->zBlockAt(pos);
  165. if (zB)
  166. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)lightData);
  167. }
  168. }
  169. }
  170. zReader->lese((char*)&index, 4);
  171. }
  172. isLoading = 0;
  173. updateVisibility();
  174. }
  175. Framework::Punkt Chunk::getCenter() const
  176. {
  177. return location;
  178. }
  179. Framework::Vec3<int> Chunk::getMin() const
  180. {
  181. return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
  182. }
  183. Framework::Vec3<int> Chunk::getMax() const
  184. {
  185. return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
  186. }
  187. void Chunk::forAll(std::function<void(Model3D*)> f)
  188. {
  189. cs.lock();
  190. for (Block* b : blocks)
  191. f(b);
  192. cs.unlock();
  193. }
  194. void Chunk::updateVisibility()
  195. {
  196. cs.lock();
  197. for (Block* b : blocks)
  198. {
  199. Framework::Vec3<int> pos = Framework::Vec3<int>((int)floor(b->getPos().x), (int)floor(b->getPos().y), (int)floor(b->getPos().z));
  200. for (int i = 0; i < 6; i++)
  201. {
  202. Block* c = zBlockAt(pos + getDirection(getDirectionFromIndex(i)));
  203. b->setSideVisible(getDirectionFromIndex(i), !c || c->isTransparent());
  204. }
  205. }
  206. cs.unlock();
  207. }