Dimension.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. #include "Dimension.h"
  2. #include <Logging.h>
  3. #include "ChunkMap.h"
  4. #include "Constants.h"
  5. #include "Datei.h"
  6. #include "DimensionMap.h"
  7. #include "Entity.h"
  8. #include "EntityType.h"
  9. #include "Game.h"
  10. #include "NoBlock.h"
  11. #include "Player.h"
  12. #include "TickOrganizer.h"
  13. using namespace Framework;
  14. Dimension::Dimension(int id)
  15. : Thread(),
  16. nextStructureId(1),
  17. dimensionId(id),
  18. gravity(9.8f),
  19. chunks(new RCTrie<Chunk>()),
  20. entities(new RCArray<Entity>()),
  21. structureManager(new MultiblockStructureManager(id)),
  22. map(new DimensionMap(id)),
  23. stop(0),
  24. currentDayTime(0.0),
  25. nightDuration(300.0),
  26. nightTransitionDuration(30.0),
  27. dayDuration(600.0)
  28. {
  29. Datei d;
  30. d.setDatei(
  31. Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(id) + "/meta.dim");
  32. if (d.existiert())
  33. {
  34. d.open(Datei::Style::lesen);
  35. d.lese((char*)&nextStructureId, 8);
  36. d.lese((char*)&currentDayTime, 8);
  37. d.close();
  38. }
  39. start();
  40. }
  41. Dimension::~Dimension()
  42. {
  43. entities->release();
  44. chunks->release();
  45. map->release();
  46. delete structureManager;
  47. }
  48. void Dimension::configureDayNightCyncle(
  49. double nightDuration, double nightTransitionDuration, double dayDuration)
  50. {
  51. this->nightDuration = nightDuration;
  52. this->nightTransitionDuration = nightTransitionDuration;
  53. this->dayDuration = dayDuration;
  54. }
  55. void Dimension::api(Framework::InMemoryBuffer* zRequest,
  56. NetworkMessage* zResponse,
  57. Entity* zSource)
  58. {
  59. DoLaterHandler laterHandler;
  60. char type;
  61. zRequest->lese(&type, 1);
  62. switch (type)
  63. {
  64. case 0: // chunk message
  65. {
  66. Punkt center;
  67. zRequest->lese((char*)&center.x, 4);
  68. zRequest->lese((char*)&center.y, 4);
  69. cs.lock();
  70. Chunk* cC = zChunk(Game::getChunkCenter(center.x, center.y));
  71. if (!cC)
  72. {
  73. // TODO: have a max amount of waiting requests per player
  74. waitingRequests.add(
  75. {dynamic_cast<InMemoryBuffer*>(zRequest->getThis()),
  76. center,
  77. zSource->getId()});
  78. Game::INSTANCE->requestArea({center.x - CHUNK_SIZE / 2,
  79. center.y - CHUNK_SIZE / 2,
  80. center.x + CHUNK_SIZE / 2 - 1,
  81. center.y + CHUNK_SIZE / 2 - 1,
  82. dimensionId});
  83. }
  84. else
  85. {
  86. cC->api(zRequest, zSource, laterHandler);
  87. }
  88. cs.unlock();
  89. break;
  90. }
  91. case 1: // block message
  92. {
  93. Vec3<int> location;
  94. zRequest->lese((char*)&location.x, 4);
  95. zRequest->lese((char*)&location.y, 4);
  96. zRequest->lese((char*)&location.z, 4);
  97. Framework::Either<Block*, int> block = zBlock(location, 0);
  98. if (block.isA())
  99. {
  100. block.getA()->api(zRequest, zResponse);
  101. }
  102. break;
  103. }
  104. case 2: // map request
  105. {
  106. map->api(zRequest, zResponse, zSource, this);
  107. break;
  108. }
  109. }
  110. }
  111. void Dimension::tickEntities()
  112. {
  113. this->currentDayTime += 1.0 / MAX_TICKS_PER_SECOND;
  114. if (this->currentDayTime
  115. > dayDuration + nightDuration + nightTransitionDuration * 2)
  116. {
  117. this->currentDayTime
  118. -= dayDuration + nightDuration + nightTransitionDuration * 2;
  119. }
  120. for (auto entity : *entities)
  121. {
  122. if (!entity->isRemoved()
  123. && (entity->isMoving()
  124. || zChunk(Game::getChunkCenter((int)entity->getPosition().x,
  125. (int)entity->getPosition().y))))
  126. entity->prepareTick(this);
  127. }
  128. int index = 0;
  129. for (auto entity : *entities)
  130. {
  131. if (!entity->isRemoved()
  132. && (entity->isMoving()
  133. || zChunk(Game::getChunkCenter((int)entity->getPosition().x,
  134. (int)entity->getPosition().y))))
  135. entity->tick(this);
  136. index++;
  137. }
  138. }
  139. void Dimension::thread()
  140. {
  141. // light calculation
  142. int index = 0;
  143. ZeitMesser messer;
  144. messer.messungStart();
  145. double time = 0;
  146. bool isForeground = 0;
  147. Framework::Array<Framework::Vec3<int>> internalLightUpdateQueue;
  148. unsigned char tmp[3];
  149. while (!stop)
  150. {
  151. Vec3<int> position;
  152. if (internalLightUpdateQueue.getEintragAnzahl())
  153. {
  154. position = internalLightUpdateQueue.get(0);
  155. internalLightUpdateQueue.remove(0);
  156. }
  157. else
  158. {
  159. removedChunksCs.lock();
  160. if (removedChunks.getEintragAnzahl() > 0)
  161. {
  162. Chunk* removedChunk = removedChunks.z(0);
  163. removedChunksCs.unlock();
  164. Text filePath = Game::INSTANCE->getWorldDirectory() + "/dim/"
  165. + getDimensionId() + "/";
  166. filePath.appendHex(removedChunk->getCenter().x);
  167. filePath += "_";
  168. filePath.appendHex(removedChunk->getCenter().y);
  169. filePath += ".chunk";
  170. Datei d;
  171. d.setDatei(filePath);
  172. d.erstellen();
  173. d.open(Datei::Style::schreiben);
  174. removedChunk->save(&d);
  175. char addr[8];
  176. getAddrOfWorld(removedChunk->getCenter(), addr);
  177. map->removeMap(addr, 8);
  178. d.close();
  179. removedChunksCs.lock();
  180. removedChunks.remove(0);
  181. }
  182. removedChunksCs.unlock();
  183. if (priorizedLightUpdateQueue.getEintragAnzahl())
  184. {
  185. prioLightCs.lock();
  186. position = priorizedLightUpdateQueue.get(0);
  187. priorizedLightUpdateQueue.remove(0);
  188. prioLightCs.unlock();
  189. isForeground = 1;
  190. }
  191. else
  192. {
  193. if (!lightUpdateQueue.getEintragAnzahl())
  194. {
  195. messer.messungEnde();
  196. time += messer.getSekunden();
  197. Sleep(500);
  198. messer.messungStart();
  199. continue;
  200. }
  201. lightCs.lock();
  202. position = lightUpdateQueue.get(0);
  203. lightUpdateQueue.remove(0);
  204. lightCs.unlock();
  205. isForeground = 0;
  206. }
  207. }
  208. Chunk* chunk
  209. = zChunk(Game::INSTANCE->getChunkCenter(position.x, position.y));
  210. if (position.z >= 0 && position.z < WORLD_HEIGHT)
  211. {
  212. if (chunk)
  213. {
  214. Vec3<int> chunkPos = chunkCoordinates(position);
  215. unsigned char* light = chunk->getLightData(chunkPos);
  216. unsigned char dayLight[6] = {255, 255, 255, 0, 0, 0};
  217. unsigned char noLight[6] = {0, 0, 0, 0, 0, 0};
  218. unsigned char newLight[6] = {0, 0, 0, 0, 0, 0};
  219. // add neighbor light emission
  220. for (int i = 0; i < 6; i++)
  221. {
  222. unsigned char* neighborLeight;
  223. Vec3<int> neighborPos
  224. = position + getDirection(getDirectionFromIndex(i));
  225. if (neighborPos.z < 0)
  226. {
  227. neighborLeight = noLight;
  228. }
  229. else if (neighborPos.z >= WORLD_HEIGHT)
  230. {
  231. neighborLeight = dayLight;
  232. }
  233. else
  234. {
  235. Chunk* neighborChunk
  236. = zChunk(Game::INSTANCE->getChunkCenter(
  237. neighborPos.x, neighborPos.y));
  238. if (neighborChunk)
  239. neighborLeight = neighborChunk->getLightData(
  240. chunkCoordinates(neighborPos));
  241. else
  242. neighborLeight = noLight;
  243. }
  244. for (int j = 0; j < 3; j++)
  245. newLight[j] = (unsigned char)MAX(newLight[j],
  246. i == getDirectionIndex(TOP)
  247. ? neighborLeight[j]
  248. : (unsigned char)((float)neighborLeight[j]
  249. * 0.8f));
  250. for (int j = 3; j < 6; j++)
  251. newLight[j] = (unsigned char)MAX(newLight[j],
  252. (unsigned char)((float)neighborLeight[j] * 0.85f));
  253. }
  254. const Block* current = zBlockOrDefault(position);
  255. // add own light emission
  256. current->getLightEmisionColor(tmp);
  257. for (int j = 3; j < 6; j++)
  258. newLight[j] = (unsigned char)MAX(newLight[j], tmp[j - 3]);
  259. current->filterPassingLight(newLight);
  260. current->filterPassingLight(newLight + 3);
  261. for (int i = 0; i < 6; i++)
  262. {
  263. if (newLight[i] != light[i])
  264. {
  265. chunk->setLightData(chunkPos, newLight, isForeground);
  266. for (int j = 0; j < 6; j++)
  267. internalLightUpdateQueue.add(
  268. position
  269. + getDirection(getDirectionFromIndex(j)),
  270. 0);
  271. break;
  272. }
  273. }
  274. }
  275. }
  276. index++;
  277. if (index > 100000)
  278. {
  279. messer.messungEnde();
  280. time += messer.getSekunden();
  281. Logging::debug()
  282. << "100000 light updates needed " << time << " seconds";
  283. time = 0;
  284. index = 0;
  285. messer.messungStart();
  286. }
  287. }
  288. Logging::info() << Text("Dimension ") + this->getDimensionId()
  289. + " update Thread exited.";
  290. }
  291. void Dimension::getAddrOf(Punkt cPos, char* addr) const
  292. {
  293. *(int*)addr = cPos.x;
  294. *((int*)addr + 1) = cPos.y;
  295. }
  296. void Dimension::getAddrOfWorld(Punkt wPos, char* addr) const
  297. {
  298. if (wPos.x < 0) wPos.x -= CHUNK_SIZE;
  299. if (wPos.y < 0) // needed because otherwise would (-8, -8) have the same
  300. // adress as (8, 8)
  301. wPos.y -= CHUNK_SIZE;
  302. wPos /= CHUNK_SIZE;
  303. getAddrOf(wPos, addr);
  304. }
  305. void Dimension::saveStructure(MultiblockStructure* zStructure) const
  306. {
  307. structureManager->saveStructure(zStructure);
  308. }
  309. Chunk* Dimension::zChunk(Punkt wPos) const
  310. {
  311. char addr[8];
  312. getAddrOfWorld(wPos, addr);
  313. return chunks->z(addr, 8);
  314. }
  315. Framework::Either<Block*, int> Dimension::zBlock(
  316. Vec3<int> location, OUT Chunk** zChunk)
  317. {
  318. Chunk* c
  319. = this->zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
  320. if (zChunk)
  321. {
  322. *zChunk = c;
  323. }
  324. if (c)
  325. {
  326. location = chunkCoordinates(location);
  327. return c->zBlockAt(location);
  328. }
  329. return 0;
  330. }
  331. Block* Dimension::zRealBlockInstance(Framework::Vec3<int> location)
  332. {
  333. Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
  334. if (c)
  335. {
  336. location = chunkCoordinates(location);
  337. c->instantiateBlock(location);
  338. auto result = c->zBlockAt(location);
  339. return result.isA() ? result.getA() : 0;
  340. }
  341. return 0;
  342. }
  343. const Block* Dimension::zBlockOrDefault(Framework::Vec3<int> location)
  344. {
  345. Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
  346. if (c)
  347. {
  348. location = chunkCoordinates(location);
  349. return c->zBlockConst(location);
  350. }
  351. return &NoBlock::INSTANCE;
  352. }
  353. int Dimension::getBlockType(Framework::Vec3<int> location)
  354. {
  355. Chunk* c = zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
  356. if (c)
  357. {
  358. location = chunkCoordinates(location);
  359. return c->getBlockTypeAt(location);
  360. }
  361. return BlockTypeEnum::NO_BLOCK;
  362. }
  363. void Dimension::placeBlock(
  364. Framework::Vec3<int> location, Framework::Either<Block*, int> block)
  365. {
  366. if (block.isB() && block.getB() == BlockTypeEnum::NO_BLOCK) return;
  367. Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
  368. if (c)
  369. {
  370. location = chunkCoordinates(location);
  371. if (block.isA())
  372. c->putBlockAt(location, block);
  373. else
  374. {
  375. c->putBlockAt(location, 0);
  376. c->putBlockTypeAt(location, block);
  377. }
  378. }
  379. else if (block.isA())
  380. block.getA()->release();
  381. }
  382. void Dimension::sendBlockInfo(Framework::Vec3<int> location)
  383. {
  384. Chunk* c = zChunk(Game::getChunkCenter(location.x, location.y));
  385. if (c)
  386. {
  387. location = chunkCoordinates(location);
  388. c->sendBlockInfo(location);
  389. }
  390. }
  391. void Dimension::addEntity(Entity* entity)
  392. {
  393. entities->add(entity);
  394. }
  395. void Dimension::setChunk(Chunk* chunk, Punkt center)
  396. {
  397. char addr[8];
  398. getAddrOfWorld(center, addr);
  399. if (chunk) map->loadMap(addr, 8, chunk);
  400. chunkCs.lock();
  401. Chunk* old = chunks->get(addr, 8);
  402. if (old)
  403. {
  404. Game::INSTANCE->zTickOrganizer()->removeTickSource(old);
  405. old->prepareRemove();
  406. for (int i = 0; i < chunkList.getEintragAnzahl(); i++)
  407. {
  408. if (chunkList.get(i) == old)
  409. {
  410. chunkList.remove(i);
  411. break;
  412. }
  413. }
  414. }
  415. chunks->set(addr, 8, chunk);
  416. if (chunk)
  417. {
  418. chunkList.add(chunk);
  419. chunk->setAdded();
  420. }
  421. getAddrOfWorld(center + Punkt(CHUNK_SIZE, 0), addr);
  422. Chunk* zChunk = chunks->z(addr, 8);
  423. if (zChunk)
  424. {
  425. zChunk->setNeighbor(WEST, chunk);
  426. if (chunk)
  427. {
  428. chunk->setNeighbor(EAST, zChunk);
  429. }
  430. }
  431. getAddrOfWorld(center + Punkt(-CHUNK_SIZE, 0), addr);
  432. zChunk = chunks->z(addr, 8);
  433. if (zChunk)
  434. {
  435. zChunk->setNeighbor(EAST, chunk);
  436. if (chunk) chunk->setNeighbor(WEST, zChunk);
  437. }
  438. getAddrOfWorld(center + Punkt(0, CHUNK_SIZE), addr);
  439. zChunk = chunks->z(addr, 8);
  440. if (zChunk)
  441. {
  442. zChunk->setNeighbor(NORTH, chunk);
  443. if (chunk) chunk->setNeighbor(SOUTH, zChunk);
  444. }
  445. getAddrOfWorld(center + Punkt(0, -CHUNK_SIZE), addr);
  446. zChunk = chunks->z(addr, 8);
  447. if (zChunk)
  448. {
  449. zChunk->setNeighbor(SOUTH, chunk);
  450. if (chunk) chunk->setNeighbor(NORTH, zChunk);
  451. }
  452. DoLaterHandler laterHandler;
  453. if (chunk)
  454. {
  455. cs.lock();
  456. int index = 0;
  457. for (ArrayIterator<RequestQueue> iterator = waitingRequests.begin();
  458. iterator;)
  459. {
  460. Entity* zE = Game::INSTANCE->zEntity(iterator.val().sourceId);
  461. if (zE)
  462. {
  463. if (iterator.val().chunkCenter == chunk->getCenter())
  464. {
  465. chunk->api(iterator.val().request, zE, laterHandler);
  466. iterator.val().request->release();
  467. iterator.remove();
  468. continue;
  469. }
  470. }
  471. else
  472. {
  473. iterator.val().request->release();
  474. iterator.remove();
  475. continue;
  476. }
  477. iterator++;
  478. index++;
  479. }
  480. cs.unlock();
  481. Game::INSTANCE->zTickOrganizer()->addTickSource(chunk);
  482. }
  483. chunkCs.unlock();
  484. if (old)
  485. {
  486. old->onUnloaded();
  487. removedChunksCs.lock();
  488. removedChunks.add(old);
  489. removedChunksCs.unlock();
  490. }
  491. if (chunk) chunk->onLoaded();
  492. laterHandler.execute();
  493. if (chunk)
  494. {
  495. updateLightAtChunkBorders(center);
  496. chunk->updateLightSources();
  497. }
  498. }
  499. void Dimension::save(Text worldDir) const
  500. {
  501. Datei d;
  502. d.setDatei(Game::INSTANCE->getWorldDirectory() + "/dim/" + Text(dimensionId)
  503. + "/meta.dim");
  504. d.erstellen();
  505. d.open(Datei::Style::schreiben);
  506. d.schreibe((char*)&nextStructureId, 8);
  507. d.schreibe((char*)&currentDayTime, 8);
  508. d.close();
  509. for (auto chunk = chunkList.begin(); chunk; chunk++)
  510. {
  511. if (!chunk._) continue;
  512. Datei* file = new Datei();
  513. Text filePath = worldDir + "/dim/" + dimensionId + "/";
  514. filePath.appendHex(chunk->getCenter().x);
  515. filePath += "_";
  516. filePath.appendHex(chunk->getCenter().y);
  517. filePath += ".chunk";
  518. file->setDatei(filePath);
  519. if (file->open(Datei::Style::schreiben)) chunk->save(file);
  520. file->close();
  521. file->release();
  522. char addr[8];
  523. getAddrOfWorld(chunk->getCenter(), addr);
  524. map->saveMap(addr, 8);
  525. }
  526. Text filePath = worldDir + "/dim/" + dimensionId + "/entities";
  527. Datei* file = new Datei();
  528. file->setDatei(filePath);
  529. if (file->open(Datei::Style::schreiben))
  530. {
  531. for (Entity* entity : *entities)
  532. {
  533. if (entity->zType()->getId() != EntityTypeEnum::PLAYER)
  534. {
  535. if (!entity->isRemoved())
  536. {
  537. int type = entity->zType()->getId();
  538. file->schreibe((char*)&type, 4);
  539. Game::INSTANCE->zEntityType(type)->saveEntity(entity, file);
  540. }
  541. }
  542. else
  543. {
  544. Datei pFile;
  545. pFile.setDatei(worldDir + "/player/"
  546. + Game::INSTANCE->getPlayerId(
  547. ((Player*)entity)->getName()));
  548. if (pFile.open(Datei::Style::schreiben))
  549. Game::INSTANCE->zEntityType(EntityTypeEnum::PLAYER)
  550. ->saveEntity(entity, &pFile);
  551. }
  552. }
  553. file->close();
  554. }
  555. for (MultiblockStructure* structure : structures)
  556. {
  557. saveStructure(structure);
  558. }
  559. }
  560. int Dimension::getDimensionId() const
  561. {
  562. return dimensionId;
  563. }
  564. bool Dimension::hasChunck(int x, int y)
  565. {
  566. if (zChunk(Punkt(x, y))) return 1;
  567. removedChunksCs.lock();
  568. for (Chunk* c : removedChunks)
  569. {
  570. if (c->getCenter().x == x && c->getCenter().y == y)
  571. {
  572. removedChunksCs.unlock();
  573. return 1;
  574. }
  575. }
  576. removedChunksCs.unlock();
  577. return 0;
  578. }
  579. bool Dimension::reviveChunk(int x, int y)
  580. {
  581. chunkCs.lock();
  582. if (zChunk(Punkt(x, y)))
  583. {
  584. chunkCs.unlock();
  585. return 1;
  586. }
  587. removedChunksCs.lock();
  588. int index = 0;
  589. for (ArrayIterator<Chunk*> i = removedChunks.begin(); i; i++)
  590. {
  591. if (i->getCenter().x == x && i->getCenter().y == y)
  592. {
  593. setChunk(dynamic_cast<Chunk*>(i->getThis()), Punkt(x, y));
  594. if (index > 0) i.remove();
  595. removedChunksCs.unlock();
  596. chunkCs.unlock();
  597. return 1;
  598. }
  599. index++;
  600. }
  601. removedChunksCs.unlock();
  602. chunkCs.unlock();
  603. return 0;
  604. }
  605. float Dimension::getGravity() const
  606. {
  607. return gravity;
  608. }
  609. void Dimension::removeOldChunks()
  610. {
  611. chunkCs.lock();
  612. int index = 0;
  613. for (Chunk* chunk : chunkList)
  614. {
  615. if (!chunk->hasObservers()) setChunk(0, chunk->getCenter());
  616. index++;
  617. }
  618. chunkCs.unlock();
  619. structurCs.lock();
  620. ArrayIterator<MultiblockStructure*> i = structures.begin();
  621. while (i)
  622. {
  623. if (i->isEmpty())
  624. {
  625. i.remove();
  626. continue;
  627. }
  628. else if (i->isFullyUnloaded())
  629. {
  630. saveStructure(i);
  631. i.remove();
  632. continue;
  633. }
  634. i++;
  635. }
  636. structurCs.unlock();
  637. }
  638. Entity* Dimension::zEntity(int id)
  639. {
  640. for (auto entity : *entities)
  641. {
  642. if (!entity->isRemoved() && entity->getId() == id) return entity;
  643. }
  644. return 0;
  645. }
  646. Entity* Dimension::zNearestEntity(
  647. Framework::Vec3<float> pos, std::function<bool(Entity*)> filter)
  648. {
  649. Entity* result = 0;
  650. float sqDist = 0;
  651. for (auto entity : *entities)
  652. {
  653. if (!entity->isRemoved() && filter(entity))
  654. {
  655. float d = pos.abstandSq(entity->getPosition());
  656. if (!result || d < sqDist)
  657. {
  658. result = entity;
  659. sqDist = d;
  660. }
  661. }
  662. }
  663. return result;
  664. }
  665. void Dimension::removeEntity(int id)
  666. {
  667. int index = 0;
  668. for (auto entity : *entities)
  669. {
  670. if (entity->getId() == id)
  671. {
  672. entities->remove(index);
  673. return;
  674. }
  675. index++;
  676. }
  677. }
  678. void Dimension::removeSubscriptions(Entity* zEntity)
  679. {
  680. for (Chunk* chunk : chunkList)
  681. chunk->removeObserver(zEntity);
  682. }
  683. void Dimension::updateLightning(Vec3<int> location)
  684. {
  685. lightCs.lock();
  686. lightUpdateQueue.add(location, 0);
  687. lightCs.unlock();
  688. }
  689. void Dimension::updateLightningWithoutWait(Framework::Vec3<int> location)
  690. {
  691. prioLightCs.lock();
  692. priorizedLightUpdateQueue.add(location, 0);
  693. prioLightCs.unlock();
  694. }
  695. void Dimension::updateLightAtChunkBorders(Punkt chunkCenter)
  696. {
  697. if (lightUpdateQueue.getEintragAnzahl() > 300000)
  698. {
  699. Logging::warning()
  700. << "light calculation queue is over 300000 blocks long";
  701. }
  702. bool xn = zChunk(chunkCenter - Punkt(CHUNK_SIZE, 0)) != 0;
  703. bool xp = zChunk(chunkCenter + Punkt(CHUNK_SIZE, 0)) != 0;
  704. bool yn = zChunk(chunkCenter - Punkt(0, CHUNK_SIZE)) != 0;
  705. bool yp = zChunk(chunkCenter + Punkt(0, CHUNK_SIZE)) != 0;
  706. for (int i = WORLD_HEIGHT - 1; i >= 0; i--)
  707. {
  708. for (int j = 0; j < CHUNK_SIZE; j++)
  709. {
  710. if (xn)
  711. {
  712. updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 - 1,
  713. chunkCenter.y - CHUNK_SIZE / 2 + j,
  714. i));
  715. updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2,
  716. chunkCenter.y - CHUNK_SIZE / 2 + j,
  717. i));
  718. }
  719. if (xp)
  720. {
  721. updateLightning(Vec3<int>(chunkCenter.x + CHUNK_SIZE / 2 - 1,
  722. chunkCenter.y - CHUNK_SIZE / 2 + j,
  723. i));
  724. updateLightning(Vec3<int>(chunkCenter.x + CHUNK_SIZE / 2,
  725. chunkCenter.y - CHUNK_SIZE / 2 + j,
  726. i));
  727. }
  728. if (yn)
  729. {
  730. updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
  731. chunkCenter.y - CHUNK_SIZE / 2 - 1,
  732. i));
  733. updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
  734. chunkCenter.y - CHUNK_SIZE / 2,
  735. i));
  736. }
  737. if (yp)
  738. {
  739. updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
  740. chunkCenter.y + CHUNK_SIZE / 2 - 1,
  741. i));
  742. updateLightning(Vec3<int>(chunkCenter.x - CHUNK_SIZE / 2 + j,
  743. chunkCenter.y + CHUNK_SIZE / 2,
  744. i));
  745. }
  746. }
  747. }
  748. }
  749. __int64 Dimension::getNextStructureId()
  750. {
  751. return nextStructureId++;
  752. }
  753. void Dimension::addStructure(MultiblockStructure* structure)
  754. {
  755. structurCs.lock();
  756. structures.add(structure);
  757. structurCs.unlock();
  758. }
  759. MultiblockStructure* Dimension::zStructureByPosition(
  760. Framework::Vec3<int> uniquePosition)
  761. {
  762. __int64 id = structureManager->getStructureId(uniquePosition);
  763. if (id > 0)
  764. {
  765. return zStructureById(id);
  766. }
  767. return 0;
  768. }
  769. MultiblockStructure* Dimension::zStructureById(__int64 id)
  770. {
  771. structurCs.lock();
  772. for (MultiblockStructure* str : structures)
  773. {
  774. if (str->getStructureId() == id)
  775. {
  776. structurCs.unlock();
  777. return str;
  778. }
  779. }
  780. MultiblockStructure* structure = structureManager->loadStructure(id);
  781. if (structure)
  782. {
  783. structures.add(structure);
  784. structurCs.unlock();
  785. return structure;
  786. }
  787. Logging::warning() << "did not find Structure information file '"
  788. << std::hex << id << "'.";
  789. structurCs.unlock();
  790. return 0;
  791. }
  792. void Dimension::requestStopAndWait()
  793. {
  794. stop = 1;
  795. warteAufThread(1000000);
  796. }
  797. void Dimension::updateMap(int x, int y, int height)
  798. {
  799. chunkCs.lock();
  800. int h1 = height % 2 == 0 ? height : height - 1;
  801. int h2 = h1 + 1;
  802. const Block* b1 = zBlockOrDefault({x, y, h1});
  803. const Block* b2 = zBlockOrDefault({x, y, h2});
  804. bool visible = 1;
  805. if (h2 != WORLD_HEIGHT - 1)
  806. {
  807. const Block* b3 = zBlockOrDefault({x, y, h2 + 1});
  808. visible = b3->isPassable() || b3->isTransparent();
  809. }
  810. int color1
  811. = (b2->isPassable() || b2->isTransparent()) ? b1->getMapColor() : 0;
  812. int color2 = visible ? b2->getMapColor() : 0;
  813. int color1m = 0;
  814. int color2m = 0;
  815. if (h1 > 0)
  816. {
  817. const Block* b1m = zBlockOrDefault({x, y, h1 - 2});
  818. const Block* b2m = zBlockOrDefault({x, y, h1 - 1});
  819. color1m = (b2m->isPassable() || b2m->isTransparent())
  820. ? b1m->getMapColor()
  821. : 0;
  822. color2m = (b1->isPassable() || b1->isTransparent()) ? b2m->getMapColor()
  823. : 0;
  824. }
  825. char addr[8];
  826. Punkt center = Game::INSTANCE->getChunkCenter(x, y);
  827. getAddrOfWorld(center, addr);
  828. ChunkMap* cMap = map->getMap(addr, 8, center);
  829. if (cMap)
  830. {
  831. Framework::Vec3<int> chunkLocation = chunkCoordinates({x, y, height});
  832. if (cMap->update((char)chunkLocation.x,
  833. (char)chunkLocation.y,
  834. (unsigned char)(chunkLocation.z / 2),
  835. color1,
  836. color2)
  837. || (h1 > 0
  838. && cMap->update((char)chunkLocation.x,
  839. (char)chunkLocation.y,
  840. (unsigned char)(chunkLocation.z / 2 - 1),
  841. color1m,
  842. color2m)))
  843. {
  844. map->onMapUpdated(addr, 8);
  845. }
  846. }
  847. chunkCs.unlock();
  848. }
  849. int Dimension::getChunkCount()
  850. {
  851. return chunkList.getEintragAnzahl();
  852. }
  853. double Dimension::getCurrentDayTime() const
  854. {
  855. return currentDayTime;
  856. }
  857. double Dimension::getNightDuration() const
  858. {
  859. return nightDuration;
  860. }
  861. double Dimension::getNightTransitionDuration() const
  862. {
  863. return nightTransitionDuration;
  864. }
  865. double Dimension::getDayDuration() const
  866. {
  867. return dayDuration;
  868. }