World.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #include "World.h"
  2. #include <AsynchronCall.h>
  3. #include <DX12Buffer.h>
  4. #include <GraphicsApi.h>
  5. #include <iostream>
  6. #include <Network.h>
  7. #include <World3D.h>
  8. #include "Constants.h"
  9. #include "Dimension.h"
  10. #include "FactoryClient.h"
  11. #include "Game.h"
  12. #include "Globals.h"
  13. #include "PlayerKam.h"
  14. using namespace Network;
  15. using namespace Framework;
  16. World* World::INSTANCE = 0;
  17. World::World(Screen3D* zScreen, FactoryClient* client)
  18. : Thread(),
  19. client(client)
  20. {
  21. renderedWorld = new World3D();
  22. renderedWorld->addDiffuseLight(DiffuseLight{
  23. Vec3<float>(0.5f, 0.5f, -1.f), Vec3<float>(1.f, 1.f, 1.f)});
  24. currentDimension = new Dimension();
  25. renderedWorld->addCollection(
  26. dynamic_cast<Model3DCollection*>(currentDimension->getThis()));
  27. zScreenPtr = zScreen;
  28. kam = new PlayerKam(zScreen);
  29. kam->setWorld(renderedWorld);
  30. zScreen->addKamera(kam);
  31. firstMessage = 1;
  32. ownEntityId = -1;
  33. currentTarget = 0;
  34. dayLightFactor = 1;
  35. time = 0;
  36. dayLength = 1000;
  37. transitionLength = 0;
  38. nightLength = 0;
  39. selectionModel = new FactoryCraftModel();
  40. selectionModel->setModelData(zScreen->zGraphicsApi()->getModel("cube"));
  41. selectionModel->setSize(1.005f);
  42. selectionModel->setVisible(0);
  43. unsigned char light[3] = {0xff, 0xff, 0xff};
  44. selectionModel->setAverageLight(light);
  45. selectionModel->setModelTextur(new Model3DTexture());
  46. for (int i = 0; i < 6; i++)
  47. {
  48. selectionModel->zTexture()->setPolygonTexture(i,
  49. zScreen->zGraphicsApi()->createOrGetTexture(
  50. "data/textures/blocks.ltdb/selectedblock.p"));
  51. }
  52. selectionModel->setAlpha(1);
  53. selectionModel->setUseEffectAlpha(1);
  54. renderedWorld->addDrawable(selectionModel);
  55. start();
  56. }
  57. World::~World()
  58. {
  59. zScreenPtr->removeKamera(kam);
  60. currentDimension->release();
  61. if (currentTarget) currentTarget->release();
  62. client->release();
  63. World::INSTANCE = 0;
  64. }
  65. int World::update(bool background)
  66. {
  67. if (background && currentDimension->getId() < 0) return 0;
  68. NetworkReader* serverMessageReader = 0;
  69. unsigned char type = 0;
  70. int messageCount = 0;
  71. while (background
  72. ? serverMessageReader = client->getNextBackgroundMessage()
  73. : serverMessageReader = client->getNextForegroundMessage())
  74. {
  75. messageCount++;
  76. serverMessageReader->read((char*)&type, 1);
  77. if (type == 3) // API MESSAGE
  78. {
  79. int length;
  80. serverMessageReader->read((char*)&length, 4);
  81. char* data = new char[length];
  82. serverMessageReader->read(data, length);
  83. switch (data[0])
  84. {
  85. case 1: // dimension message
  86. {
  87. int dimId = *(int*)(data + 1);
  88. if (dimId == currentDimension->getId())
  89. {
  90. currentDimension->api(data + 5);
  91. }
  92. break;
  93. }
  94. case 2: // gui message
  95. ((Game*)(Menu*)menuRegister->get("game"))->api(data + 1);
  96. break;
  97. case 3: // set target
  98. {
  99. switch (data[1])
  100. {
  101. case 0:
  102. setTarget(0);
  103. ((Game*)(Menu*)menuRegister->get("game"))
  104. ->setTargetUIML("");
  105. break;
  106. case 1:
  107. {
  108. setTarget(zEntity(*(int*)(data + 2)));
  109. short len = *(short*)(data + 6);
  110. char* uiml = new char[len + 8];
  111. memcpy(uiml, data + 8, len);
  112. uiml[len] = 0;
  113. ((Game*)(Menu*)menuRegister->get("game"))
  114. ->setTargetUIML(uiml);
  115. delete[] uiml;
  116. break;
  117. }
  118. case 2:
  119. {
  120. setTarget(zBlockAt(Vec3<int>(*(int*)(data + 2),
  121. *(int*)(data + 6),
  122. *(int*)(data + 10))));
  123. Direction side = *(Direction*)(data + 14);
  124. short len = *(short*)(data + 15);
  125. char* uiml = new char[len + 1];
  126. memcpy(uiml, data + 17, len);
  127. uiml[len] = 0;
  128. ((Game*)(Menu*)menuRegister->get("game"))
  129. ->setTargetUIML(uiml);
  130. delete[] uiml;
  131. break;
  132. }
  133. }
  134. break;
  135. }
  136. case 4: // chat message
  137. {
  138. ((Game*)(Menu*)menuRegister->get("game"))
  139. ->zChat()
  140. ->addMessage(data + 1);
  141. break;
  142. }
  143. case 5: // chat options
  144. {
  145. ((Game*)(Menu*)menuRegister->get("game"))
  146. ->zChat()
  147. ->initOptions(data + 1);
  148. break;
  149. }
  150. case 6: // map data
  151. {
  152. ByteArrayReader reader(data + 1, length - 1, 0);
  153. ChunkMap* map = new ChunkMap(&reader);
  154. ((Game*)(Menu*)menuRegister->get("game"))
  155. ->zMap()
  156. ->addChunk(map);
  157. break;
  158. }
  159. case 7: // map player data
  160. {
  161. ((Game*)(Menu*)menuRegister->get("game"))
  162. ->zMap()
  163. ->updatePlayerData(data + 1);
  164. break;
  165. }
  166. case 8: // time sync
  167. {
  168. nightLength = *(double*)(data + 9);
  169. transitionLength = *(double*)(data + 17);
  170. dayLength = *(double*)(data + 25);
  171. time = *(double*)(data + 1);
  172. break;
  173. }
  174. }
  175. delete[] data;
  176. }
  177. if (type == 4) // POSITION UPDATE
  178. {
  179. int old = ownEntityId;
  180. serverMessageReader->read((char*)&ownEntityId, 4);
  181. int dimensionId = 0;
  182. serverMessageReader->read((char*)&dimensionId, 4);
  183. currentDimension->setId(dimensionId);
  184. kam->setEntityId(ownEntityId);
  185. Entity* p = zEntity(ownEntityId);
  186. if (p) p->setPlayerControlled();
  187. if (old != ownEntityId) client->sendPlayerAction("\5", 1);
  188. }
  189. client->endMessageReading(background);
  190. }
  191. client->endMessageReading(background);
  192. if (!background)
  193. {
  194. Entity* player = getCurrentPlayerEntity();
  195. if (player)
  196. {
  197. currentDimension->removeDistantChunks(
  198. {(int)player->getPos().x, (int)player->getPos().y});
  199. Framework::Point currentChunk
  200. = getChunkCenter((int)player->getX(), (int)player->getY());
  201. for (int x = 0; x <= CHUNK_VISIBILITY_RANGE; x++)
  202. {
  203. for (int y = 0; y <= CHUNK_VISIBILITY_RANGE; y++)
  204. {
  205. std::function<void(Framework::Point)> requestChunk =
  206. [this](Framework::Point center) {
  207. Chunk* zC = currentDimension->zChunk(center);
  208. if (!zC)
  209. {
  210. char msg[1];
  211. msg[0]
  212. = 0; // add observer and request chaunk data
  213. Framework::Point pos = center;
  214. subLock.lockRead();
  215. bool found = 0;
  216. for (Framework::Point p : subscriptions)
  217. {
  218. if (p == pos)
  219. {
  220. found = 1;
  221. break;
  222. }
  223. }
  224. if (!found)
  225. {
  226. client->chunkAPIRequest(pos, msg, 1);
  227. subLock.lockWrite();
  228. subscriptions.add(pos);
  229. subLock.unlockWrite();
  230. }
  231. subLock.unlockRead();
  232. }
  233. };
  234. requestChunk(
  235. currentChunk + Point(x * CHUNK_SIZE, y * CHUNK_SIZE));
  236. if (y > 0)
  237. requestChunk(currentChunk
  238. + Point(x * CHUNK_SIZE, -y * CHUNK_SIZE));
  239. if (x > 0)
  240. {
  241. requestChunk(currentChunk
  242. + Point(-x * CHUNK_SIZE, y * CHUNK_SIZE));
  243. if (y > 0)
  244. requestChunk(
  245. currentChunk
  246. + Point(-x * CHUNK_SIZE, -y * CHUNK_SIZE));
  247. }
  248. }
  249. }
  250. }
  251. }
  252. return messageCount;
  253. }
  254. void World::onTick(double time)
  255. {
  256. // selectionModel->tick(0.1);
  257. this->time += time;
  258. if (this->time >= dayLength + nightLength + transitionLength * 2)
  259. {
  260. this->time -= dayLength + nightLength + transitionLength * 2;
  261. }
  262. if (this->time > dayLength && this->time < dayLength + transitionLength)
  263. {
  264. dayLightFactor
  265. = 1.f
  266. - (float)((this->time - dayLength) / transitionLength) * 0.95f;
  267. }
  268. else if (this->time > dayLength + transitionLength
  269. && this->time < dayLength + transitionLength + nightLength)
  270. {
  271. // night
  272. dayLightFactor = 0.05f;
  273. if (renderedWorld->getDiffuseLightCount() > 0)
  274. {
  275. renderedWorld->removeDiffuseLight(0);
  276. }
  277. }
  278. else if (this->time > dayLength + transitionLength + nightLength)
  279. {
  280. dayLightFactor
  281. = (float)((this->time - dayLength - nightLength - transitionLength)
  282. / transitionLength)
  283. * 0.95f
  284. + 0.05f;
  285. }
  286. else
  287. {
  288. dayLightFactor = 1.f;
  289. }
  290. if (this->time < dayLength + transitionLength
  291. || this->time > dayLength + transitionLength + nightLength)
  292. {
  293. float currentDayTime
  294. = (float)(this->time < dayLength + transitionLength
  295. ? this->time + transitionLength
  296. : this->time - dayLength + transitionLength
  297. + nightLength);
  298. Vec3<float> sunPos = Vec3<float>(-200.f, 50.f, 0.f);
  299. sunPos.rotateY((
  300. float)((currentDayTime / (dayLength + transitionLength * 2)) * PI));
  301. sunPos.normalize();
  302. if (!renderedWorld->getDiffuseLightCount())
  303. {
  304. renderedWorld->addDiffuseLight(
  305. {-sunPos, Vec3<float>(1.0, 1.0, 1.0)});
  306. }
  307. else
  308. {
  309. renderedWorld->getDiffuseLight(0).direction = -sunPos;
  310. }
  311. }
  312. }
  313. void World::setChunk(Chunk* chunk)
  314. {
  315. currentDimension->setChunk(chunk, chunk->getCenter());
  316. }
  317. void World::thread()
  318. {
  319. new AsynchronCall("World Update", [this]() {
  320. Timer tm;
  321. tm.measureStart();
  322. double sum = 0;
  323. int updates = 0;
  324. int messages = 0;
  325. double wait = 0;
  326. while (client->isConnected())
  327. {
  328. if (World::INSTANCE != this)
  329. {
  330. return;
  331. }
  332. messages += update(0);
  333. updates++;
  334. tm.measureEnd();
  335. sum += tm.getSekunden();
  336. wait += 10 - tm.getSekunden();
  337. tm.measureStart();
  338. if ((int)wait > 0)
  339. {
  340. Sleep((int)wait);
  341. }
  342. if (sum > 1.0)
  343. {
  344. std::cout << "updates: " << updates
  345. << ", messages: " << (double)messages
  346. << ", seconds: " << sum << "\n";
  347. sum = 0;
  348. updates = 0;
  349. messages = 0;
  350. }
  351. }
  352. std::cout << "foreground connection lost\n";
  353. });
  354. while (client->isConnected())
  355. {
  356. if (World::INSTANCE != this)
  357. {
  358. return;
  359. }
  360. update(1);
  361. Sleep(100);
  362. }
  363. Sleep(1000);
  364. std::cout << "background connection lost\n";
  365. menuRegister->get("game")->hide();
  366. menuRegister->get("serverSelection")->show();
  367. zScreenPtr->postAction([this]() {
  368. if (World::INSTANCE == this)
  369. {
  370. World::INSTANCE = 0;
  371. release();
  372. }
  373. });
  374. }
  375. Block* World::zBlockAt(Framework::Vec3<int> location) const
  376. {
  377. return currentDimension->zBlock(location);
  378. }
  379. Block* World::getBlockAt(Framework::Vec3<int> location) const
  380. {
  381. return currentDimension->getBlock(location);
  382. }
  383. Dimension* World::zDimension() const
  384. {
  385. return currentDimension;
  386. }
  387. void World::setVisibility(Entity* zEntity, bool visible)
  388. {
  389. if (visible)
  390. renderedWorld->addDrawable(
  391. dynamic_cast<Framework::Model3D*>(zEntity->getThis()));
  392. else
  393. renderedWorld->removeDrawable(zEntity);
  394. }
  395. Framework::Point World::getChunkCenter(int x, int y) const
  396. {
  397. return Point(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE
  398. + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2,
  399. ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE
  400. + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2);
  401. }
  402. Entity* World::zEntity(int id) const
  403. {
  404. Entity* e = currentDimension->zEntity(id);
  405. if (e) return e;
  406. return 0;
  407. }
  408. Entity* World::getEntity(int id) const
  409. {
  410. Entity* e = currentDimension->getEntity(id);
  411. if (e) return e;
  412. return 0;
  413. }
  414. void World::removeEntity(int id)
  415. {
  416. currentDimension->removeEntity(id);
  417. }
  418. PlayerKam* World::zKamera() const
  419. {
  420. return kam;
  421. }
  422. int World::getCurrentPlayerId() const
  423. {
  424. return ownEntityId;
  425. }
  426. Entity* World::getCurrentPlayerEntity() const
  427. {
  428. return zEntity(ownEntityId);
  429. }
  430. void World::setTarget(Framework::Model3D* zTarget)
  431. {
  432. if (zTarget != currentTarget)
  433. {
  434. targetLock.lock();
  435. if (!zTarget)
  436. {
  437. selectionModel->setVisible(0);
  438. }
  439. else
  440. {
  441. selectionModel->setPosition(
  442. zTarget->getPos().x, zTarget->getPos().y, zTarget->getPos().z);
  443. Block* b = dynamic_cast<Block*>(zTarget);
  444. if (b)
  445. {
  446. selectionModel->setDestroyedState(b->getEffectPercentage());
  447. }
  448. else
  449. {
  450. selectionModel->setDestroyedState(0);
  451. }
  452. selectionModel->setVisible(1);
  453. }
  454. if (currentTarget)
  455. {
  456. currentTarget->setAmbientFactor(
  457. currentTarget->getAmbientFactor() - 0.2f);
  458. currentTarget->release();
  459. currentTarget = 0;
  460. }
  461. if (zTarget)
  462. {
  463. currentTarget
  464. = dynamic_cast<Framework::Model3D*>(zTarget->getThis());
  465. if (currentTarget)
  466. currentTarget->setAmbientFactor(
  467. currentTarget->getAmbientFactor() + 0.2f);
  468. }
  469. targetLock.unlock();
  470. }
  471. }
  472. void World::onChunkAdded(Framework::Point pos)
  473. {
  474. subLock.lockWrite();
  475. int index = 0;
  476. for (Framework::Point p : subscriptions)
  477. {
  478. if (p == pos)
  479. {
  480. subscriptions.remove(index);
  481. break;
  482. }
  483. index++;
  484. }
  485. subLock.unlockWrite();
  486. }
  487. Framework::Model3D* World::getCurrentTarget() const
  488. {
  489. while (targetLock.isLocked())
  490. Sleep(1);
  491. return currentTarget
  492. ? dynamic_cast<Framework::Model3D*>(currentTarget->getThis())
  493. : 0;
  494. }
  495. FactoryCraftModel* World::zSelectedEffectModel() const
  496. {
  497. return selectionModel;
  498. }
  499. Chunk* World::zChunk(Framework::Point center)
  500. {
  501. return currentDimension->zChunk(center);
  502. }
  503. Framework::Lock& World::getChunkReadLock()
  504. {
  505. return currentDimension->getReadLock();
  506. }
  507. FactoryClient* World::zClient() const
  508. {
  509. return client;
  510. }
  511. float World::getDayLightFactor() const
  512. {
  513. return dayLightFactor;
  514. }