Chunk.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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. World::INSTANCE->zClient()->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. {
  60. bool visible = zB->isVisible();
  61. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)(message + 5));
  62. if (zB->isVisible() != visible)
  63. {
  64. vcs.lock();
  65. if (zB->isVisible())
  66. visibleBlocks.add(zB);
  67. else
  68. {
  69. for (Framework::Iterator<Block*> iterator = visibleBlocks.begin(); iterator; iterator++)
  70. {
  71. if (zB == (Block*)iterator)
  72. {
  73. iterator.remove();
  74. break;
  75. }
  76. }
  77. }
  78. vcs.unlock();
  79. }
  80. }
  81. }
  82. else
  83. {
  84. pos.x += this->location.x - CHUNK_SIZE / 2;
  85. pos.y += this->location.y - CHUNK_SIZE / 2;
  86. Block* zB = World::INSTANCE->zBlockAt(pos);
  87. if (zB)
  88. {
  89. bool visible = zB->isVisible();
  90. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)(message + 5));
  91. if (zB->isVisible() != visible)
  92. {
  93. Chunk* c = World::INSTANCE->zChunk(World::INSTANCE->getChunkCenter(pos.x, pos.y));
  94. c->vcs.lock();
  95. if (zB->isVisible())
  96. c->visibleBlocks.add(zB);
  97. else
  98. {
  99. for (Framework::Iterator<Block*> iterator = c->visibleBlocks.begin(); iterator; iterator++)
  100. {
  101. if (zB == (Block*)iterator)
  102. {
  103. iterator.remove();
  104. break;
  105. }
  106. }
  107. }
  108. c->vcs.unlock();
  109. }
  110. }
  111. }
  112. }
  113. }
  114. }
  115. }
  116. }
  117. Block* Chunk::zBlockAt(Framework::Vec3<int> location)
  118. {
  119. cs.lock();
  120. for (Block* b : blocks)
  121. {
  122. if (b->getLocation() == location)
  123. {
  124. cs.unlock();
  125. return b;
  126. }
  127. }
  128. cs.unlock();
  129. return 0;
  130. }
  131. void Chunk::setBlock(Block* block)
  132. {
  133. cs.lock();
  134. Framework::Vec3<int> pos = block->getLocation();
  135. for (Framework::Iterator<Block*> iterator = blocks.begin(); iterator; iterator++)
  136. {
  137. if (pos == iterator->getLocation())
  138. {
  139. vcs.lock();
  140. for (Framework::Iterator<Block*> vi = visibleBlocks.begin(); vi; vi++)
  141. {
  142. if ((Block*)iterator == (Block*)vi)
  143. {
  144. iterator.remove();
  145. break;
  146. }
  147. }
  148. vcs.unlock();
  149. iterator->release();
  150. iterator.set(block);
  151. break;
  152. }
  153. }
  154. blocks.add(block);
  155. cs.unlock();
  156. }
  157. void Chunk::removeBlock(Block* zBlock)
  158. {
  159. cs.lock();
  160. vcs.lock();
  161. for (Framework::Iterator<Block*> iterator = visibleBlocks.begin(); iterator; iterator++)
  162. {
  163. if (zBlock == (Block*)iterator)
  164. {
  165. iterator.remove();
  166. break;
  167. }
  168. }
  169. vcs.unlock();
  170. for (Framework::Iterator<Block*> iterator = blocks.begin(); iterator; iterator++)
  171. {
  172. if (zBlock == (Block*)iterator)
  173. {
  174. iterator.remove();
  175. break;
  176. }
  177. }
  178. cs.unlock();
  179. }
  180. void Chunk::load(Framework::StreamReader* zReader)
  181. {
  182. isLoading = 1;
  183. Framework::Vec3<int> pos = { 0, 0, 0 };
  184. unsigned short id;
  185. zReader->lese((char*)&id, 2);
  186. while (id)
  187. {
  188. int index;
  189. zReader->lese((char*)&index, 4);
  190. pos = Vec3<int>((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
  191. if (blockTypes[id]->doesNeedInstance())
  192. setBlock(blockTypes[id]->createBlock({ pos.x + location.x - CHUNK_SIZE / 2, pos.y + location.y - CHUNK_SIZE / 2, pos.z }));
  193. zReader->lese((char*)&id, 2);
  194. }
  195. int index = 0;
  196. // light
  197. zReader->lese((char*)&index, 4);
  198. char lightData[6];
  199. while (index >= 0)
  200. {
  201. zReader->lese(lightData, 6);
  202. Framework::Vec3<int> location((index / WORLD_HEIGHT) / CHUNK_SIZE, (index / WORLD_HEIGHT) % CHUNK_SIZE, index % WORLD_HEIGHT);
  203. for (int i = 0; i < 6; i++)
  204. {
  205. Framework::Vec3<int> pos = location + getDirection(getDirectionFromIndex(i));
  206. if (pos.z >= 0 && pos.z < WORLD_HEIGHT)
  207. {
  208. if (pos.x >= 0 && pos.x < CHUNK_SIZE && pos.y >= 0 && pos.y < CHUNK_SIZE)
  209. {
  210. pos.x += this->location.x - CHUNK_SIZE / 2;
  211. pos.y += this->location.y - CHUNK_SIZE / 2;
  212. Block* zB = zBlockAt(pos);
  213. if (zB)
  214. {
  215. bool visible = zB->isVisible();
  216. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)lightData);
  217. if (zB->isVisible() && !visible)
  218. visibleBlocks.add(zB);
  219. }
  220. }
  221. else
  222. {
  223. pos.x += this->location.x - CHUNK_SIZE / 2;
  224. pos.y += this->location.y - CHUNK_SIZE / 2;
  225. Block* zB = World::INSTANCE->zBlockAt(pos);
  226. if (zB)
  227. {
  228. bool visible = zB->isVisible();
  229. zB->setLightData(getOppositeDirection(getDirectionFromIndex(i)), (unsigned char*)lightData);
  230. if (zB->isVisible() && !visible)
  231. {
  232. Chunk* c = World::INSTANCE->zChunk(World::INSTANCE->getChunkCenter(pos.x, pos.y));
  233. c->vcs.lock();
  234. c->visibleBlocks.add(zB);
  235. c->vcs.unlock();
  236. }
  237. }
  238. }
  239. }
  240. }
  241. zReader->lese((char*)&index, 4);
  242. }
  243. isLoading = 0;
  244. }
  245. Framework::Punkt Chunk::getCenter() const
  246. {
  247. return location;
  248. }
  249. Framework::Vec3<int> Chunk::getMin() const
  250. {
  251. return { location.x - CHUNK_SIZE / 2, location.y - CHUNK_SIZE / 2, 0 };
  252. }
  253. Framework::Vec3<int> Chunk::getMax() const
  254. {
  255. return { location.x + CHUNK_SIZE / 2, location.y + CHUNK_SIZE / 2, WORLD_HEIGHT };
  256. }
  257. void Chunk::forAll(std::function<void(Model3D*)> f)
  258. {
  259. vcs.lock();
  260. for (Block* b : visibleBlocks)
  261. f(b);
  262. vcs.unlock();
  263. }