Game.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. #include "Game.h"
  2. #include "AddEntityUpdate.h"
  3. #include "AsynchronCall.h"
  4. #include "Entity.h"
  5. #include "EntityRemovedUpdate.h"
  6. #include "ItemEntity.h"
  7. #include "NetworkMessage.h"
  8. #include "NoBlock.h"
  9. #include "OverworldDimension.h"
  10. #include "Player.h"
  11. #include "Zeit.h"
  12. using namespace Framework;
  13. GameClient::GameClient(Player* zPlayer, FCKlient* client)
  14. : Thread(),
  15. zPlayer(zPlayer),
  16. client(client),
  17. viewDistance(DEFAULT_VIEW_DISTANCE),
  18. first(1),
  19. online(1),
  20. finished(0),
  21. backgroundFinished(0),
  22. foregroundFinished(0)
  23. {
  24. new AsynchronCall("Game Client Updates", [this]() {
  25. while (online)
  26. {
  27. other.lock();
  28. if (updateQueue.hat(0))
  29. {
  30. WorldUpdate* update = updateQueue.get(0);
  31. updateQueue.remove(0);
  32. other.unlock();
  33. background.lock();
  34. this->client->zBackgroundWriter()->schreibe(
  35. (char*)&Message::WORLD_UPDATE, 1);
  36. update->writeAndCheck(this->client->zBackgroundWriter());
  37. background.unlock();
  38. update->release();
  39. }
  40. else
  41. {
  42. other.unlock();
  43. updateSync.wait();
  44. }
  45. }
  46. finished = 1;
  47. });
  48. start();
  49. }
  50. GameClient::~GameClient()
  51. {
  52. online = 0;
  53. updateSync.notify();
  54. emptyForegroundQueueSync.notifyAll();
  55. emptyBackgroundQueueSync.notifyAll();
  56. foregroundQueueSync.notify();
  57. backgroundQueueSync.notify();
  58. while (!finished || !foregroundFinished || !backgroundFinished)
  59. Sleep(100);
  60. client->release();
  61. }
  62. void GameClient::thread()
  63. {
  64. new AsynchronCall("Game Client Background", [this]() {
  65. while (online)
  66. {
  67. queueCs.lock();
  68. if (backgroundQueue.hat(0))
  69. {
  70. NetworkMessage* message = backgroundQueue.get(0);
  71. backgroundQueue.remove(0);
  72. queueCs.unlock();
  73. background.lock();
  74. message->writeTo(client->zBackgroundWriter());
  75. background.unlock();
  76. message->release();
  77. }
  78. else
  79. {
  80. queueCs.unlock();
  81. emptyBackgroundQueueSync.notifyAll();
  82. while (!backgroundQueueSync.wait(1000))
  83. {
  84. emptyBackgroundQueueSync.notifyAll();
  85. }
  86. }
  87. }
  88. backgroundFinished = 1;
  89. });
  90. while (online)
  91. {
  92. queueCs.lock();
  93. if (foregroundQueue.hat(0))
  94. {
  95. NetworkMessage* message = foregroundQueue.get(0);
  96. foregroundQueue.remove(0);
  97. queueCs.unlock();
  98. foreground.lock();
  99. message->writeTo(client->zForegroundWriter());
  100. foreground.unlock();
  101. message->release();
  102. }
  103. else
  104. {
  105. queueCs.unlock();
  106. emptyForegroundQueueSync.notifyAll();
  107. while (!foregroundQueueSync.wait(1000))
  108. {
  109. emptyForegroundQueueSync.notifyAll();
  110. }
  111. }
  112. }
  113. foregroundFinished = 1;
  114. }
  115. void GameClient::sendWorldUpdate(WorldUpdate* update)
  116. {
  117. bool add = 0;
  118. if (zPlayer->getDimensionId() == update->getAffectedDimension())
  119. {
  120. auto pos = (Vec3<int>)zPlayer->getPosition();
  121. int dist = update->distanceTo(pos.x, pos.y);
  122. if (dist < viewDistance * CHUNK_SIZE)
  123. {
  124. other.lock();
  125. int index = 0;
  126. for (auto update2 : updateQueue)
  127. {
  128. int dist2 = update2->distanceTo(pos.x, pos.y);
  129. if (dist2 > dist) break;
  130. index++;
  131. }
  132. updateQueue.add(update, index);
  133. other.unlock();
  134. updateSync.notify();
  135. add = 1;
  136. }
  137. }
  138. if (!add) update->release();
  139. }
  140. void GameClient::reply()
  141. {
  142. other.lock();
  143. for (auto req : requests)
  144. Game::INSTANCE->api(req, this);
  145. requests.leeren();
  146. other.unlock();
  147. if (first)
  148. {
  149. foreground.lock();
  150. int id = zPlayer->getId();
  151. client->zForegroundWriter()->schreibe(
  152. (char*)&Message::POSITION_UPDATE, 1);
  153. client->zForegroundWriter()->schreibe((char*)&id, 4);
  154. id = zPlayer->getDimensionId();
  155. client->zForegroundWriter()->schreibe((char*)&id, 4);
  156. foreground.unlock();
  157. first = 0;
  158. }
  159. }
  160. void GameClient::logout()
  161. {
  162. online = 0;
  163. updateSync.notify();
  164. emptyForegroundQueueSync.notifyAll();
  165. emptyBackgroundQueueSync.notifyAll();
  166. foregroundQueueSync.notify();
  167. backgroundQueueSync.notify();
  168. }
  169. void GameClient::addMessage(StreamReader* reader)
  170. {
  171. short len = 0;
  172. reader->lese((char*)&len, 2);
  173. InMemoryBuffer* buffer = new InMemoryBuffer();
  174. char* tmp = new char[len];
  175. reader->lese(tmp, len);
  176. buffer->schreibe(tmp, len);
  177. delete[] tmp;
  178. other.lock();
  179. requests.add(buffer);
  180. other.unlock();
  181. }
  182. bool GameClient::isOnline() const
  183. {
  184. return online;
  185. }
  186. void GameClient::sendResponse(NetworkMessage* response)
  187. {
  188. queueCs.lock();
  189. if (response->isUseBackground())
  190. {
  191. if (backgroundQueue.getEintragAnzahl() > 20)
  192. {
  193. queueCs.unlock();
  194. while (!emptyBackgroundQueueSync.wait(1000))
  195. {
  196. backgroundQueueSync.notify();
  197. }
  198. queueCs.lock();
  199. }
  200. backgroundQueue.add(response);
  201. queueCs.unlock();
  202. backgroundQueueSync.notify();
  203. }
  204. else
  205. {
  206. if (foregroundQueue.getEintragAnzahl() > 100)
  207. {
  208. queueCs.unlock();
  209. std::cout << "WARNING: Game paused because nework connection to "
  210. << zPlayer->getName() << " is to slow.\n";
  211. ZeitMesser m;
  212. m.messungStart();
  213. while (foregroundQueue.getEintragAnzahl() > 0)
  214. {
  215. foregroundQueueSync.notify();
  216. emptyForegroundQueueSync.wait(100);
  217. }
  218. m.messungEnde();
  219. std::cout << "WARNING: Game resumed after " << m.getSekunden()
  220. << " seconds.\n";
  221. queueCs.lock();
  222. }
  223. foregroundQueue.add(response);
  224. queueCs.unlock();
  225. foregroundQueueSync.notify();
  226. }
  227. }
  228. Player* GameClient::zEntity() const
  229. {
  230. return zPlayer;
  231. }
  232. void GameClient::sendTypes()
  233. {
  234. foreground.lock();
  235. int count = StaticRegistry<BlockType>::INSTANCE.getCount();
  236. client->zForegroundWriter()->schreibe((char*)&count, 4);
  237. for (int i = 0; i < count; i++)
  238. {
  239. BlockType* t = StaticRegistry<BlockType>::INSTANCE.zElement(i);
  240. t->writeTypeInfo(client->zForegroundWriter());
  241. }
  242. count = 0;
  243. for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
  244. {
  245. if (StaticRegistry<ItemType>::INSTANCE.zElement(i)) count++;
  246. }
  247. client->zForegroundWriter()->schreibe((char*)&count, 4);
  248. for (int i = 0; i < StaticRegistry<ItemType>::INSTANCE.getCount(); i++)
  249. {
  250. if (StaticRegistry<ItemType>::INSTANCE.zElement(i))
  251. {
  252. ItemType* t = StaticRegistry<ItemType>::INSTANCE.zElement(i);
  253. int id = t->getId();
  254. client->zForegroundWriter()->schreibe((char*)&id, 4);
  255. char len = (char)t->getName().getLength();
  256. client->zForegroundWriter()->schreibe((char*)&len, 1);
  257. client->zForegroundWriter()->schreibe(t->getName().getText(), len);
  258. short tlen = (short)t->getTooltipUIML().getLength();
  259. client->zForegroundWriter()->schreibe((char*)&tlen, 2);
  260. client->zForegroundWriter()->schreibe(
  261. t->getTooltipUIML().getText(), tlen);
  262. t->getModel().writeTo(client->zForegroundWriter());
  263. }
  264. }
  265. count = StaticRegistry<EntityType>::INSTANCE.getCount();
  266. client->zForegroundWriter()->schreibe((char*)&count, 4);
  267. for (int i = 0; i < count; i++)
  268. {
  269. EntityType* t = StaticRegistry<EntityType>::INSTANCE.zElement(i);
  270. int id = t->getId();
  271. client->zForegroundWriter()->schreibe((char*)&id, 4);
  272. t->getModel().writeTo(client->zForegroundWriter());
  273. }
  274. foreground.unlock();
  275. }
  276. Game::Game(Framework::Text name, Framework::Text worldsDir)
  277. : Thread(),
  278. name(name),
  279. typeRegistry(new TypeRegistry()),
  280. dimensions(new RCArray<Dimension>()),
  281. updates(new RCArray<WorldUpdate>()),
  282. clients(new RCArray<GameClient>()),
  283. questManager(new QuestManager()),
  284. ticker(new TickOrganizer()),
  285. path((const char*)(worldsDir + "/" + name)),
  286. stop(0),
  287. tickId(0),
  288. nextEntityId(0),
  289. generator(0),
  290. loader(0),
  291. chat(0),
  292. playerRegister(new PlayerRegister(path)),
  293. totalTickTime(0),
  294. tickCounter(0),
  295. averageTickTime(0),
  296. ticksPerSecond(0),
  297. totalTime(0)
  298. {
  299. if (!DateiExistiert(path)) DateiPfadErstellen(path + "/");
  300. Datei d;
  301. d.setDatei(path + "/eid");
  302. if (d.existiert())
  303. {
  304. d.open(Datei::Style::lesen);
  305. d.lese((char*)&nextEntityId, 4);
  306. d.close();
  307. }
  308. start();
  309. }
  310. Game::~Game()
  311. {
  312. dimensions->release();
  313. updates->release();
  314. clients->release();
  315. generator->release();
  316. loader->release();
  317. chat->release();
  318. playerRegister->release();
  319. typeRegistry->release();
  320. }
  321. void Game::initialize()
  322. {
  323. int seed = 0;
  324. int index = 0;
  325. for (const char* n = name; *n; n++)
  326. seed += (int)pow((float)*n * 31, (float)++index);
  327. generator = new WorldGenerator(seed);
  328. loader = new WorldLoader();
  329. recipies.loadRecipies("data/recipies");
  330. chat = new Chat();
  331. questManager->loadQuests();
  332. }
  333. void Game::thread()
  334. {
  335. ZeitMesser waitForLock;
  336. ZeitMesser removeOldClients;
  337. ZeitMesser tickEntities;
  338. ZeitMesser worldUpdates;
  339. ZeitMesser clientReply;
  340. ZeitMesser removeOldChunks;
  341. ZeitMesser m;
  342. ZeitMesser total;
  343. total.messungStart();
  344. double tickTime = 0;
  345. double sleepTime = 0;
  346. int nextTimeSync = MAX_TICKS_PER_SECOND;
  347. while (!stop)
  348. {
  349. m.messungStart();
  350. ticker->nextTick();
  351. actionsCs.lock();
  352. while (actions.getEintragAnzahl() > 0)
  353. {
  354. actions.get(0)();
  355. actions.remove(0);
  356. }
  357. actionsCs.unlock();
  358. Array<int> removed;
  359. double waitTotal = 0;
  360. waitForLock.messungStart();
  361. cs.lock();
  362. waitForLock.messungEnde();
  363. waitTotal += waitForLock.getSekunden();
  364. removeOldClients.messungStart();
  365. int index = 0;
  366. nextTimeSync--;
  367. for (auto player : *clients)
  368. {
  369. if (!player->isOnline())
  370. {
  371. chat->removeObserver(player->zEntity()->getId());
  372. chat->broadcastMessage(
  373. Framework::Text(player->zEntity()->getName())
  374. + " left the game.",
  375. Chat::CHANNEL_INFO);
  376. Datei pFile;
  377. pFile.setDatei(path + "/player/"
  378. + getPlayerId(player->zEntity()->getName()));
  379. pFile.erstellen();
  380. if (pFile.open(Datei::Style::schreiben))
  381. StaticRegistry<EntityType>::INSTANCE
  382. .zElement(EntityTypeEnum::PLAYER)
  383. ->saveEntity(player->zEntity(), &pFile);
  384. pFile.close();
  385. removed.add(index, 0);
  386. Dimension* dim
  387. = zDimension(player->zEntity()->getDimensionId());
  388. dim->removeSubscriptions(player->zEntity());
  389. this->requestWorldUpdate(
  390. new EntityRemovedUpdate(player->zEntity()->getId(),
  391. player->zEntity()->getDimensionId(),
  392. player->zEntity()->getPosition()));
  393. }
  394. else
  395. {
  396. if (nextTimeSync <= 0 && player->zEntity())
  397. {
  398. Dimension* zDim
  399. = zDimension(player->zEntity()->getDimensionId());
  400. if (zDim)
  401. {
  402. NetworkMessage* msg = new NetworkMessage();
  403. msg->syncTime(zDim->getCurrentDayTime(),
  404. zDim->getNightDuration(),
  405. zDim->getNightTransitionDuration(),
  406. zDim->getDayDuration());
  407. player->sendResponse(msg);
  408. }
  409. }
  410. }
  411. index++;
  412. }
  413. if (nextTimeSync <= 0)
  414. {
  415. nextTimeSync = MAX_TICKS_PER_SECOND;
  416. }
  417. for (auto i : removed)
  418. clients->remove(i);
  419. removeOldClients.messungEnde();
  420. cs.unlock();
  421. tickEntities.messungStart();
  422. for (auto dim : *dimensions)
  423. dim->tickEntities();
  424. tickEntities.messungEnde();
  425. waitForLock.messungStart();
  426. cs.lock();
  427. waitForLock.messungEnde();
  428. waitTotal += waitForLock.getSekunden();
  429. worldUpdates.messungStart();
  430. while (updates->hat(0))
  431. {
  432. WorldUpdate* update = updates->z(0);
  433. for (auto client : *clients)
  434. client->sendWorldUpdate(
  435. dynamic_cast<WorldUpdate*>(update->getThis()));
  436. if (!zDimension(update->getAffectedDimension()))
  437. {
  438. Dimension* dim = typeRegistry->createDimension(
  439. update->getAffectedDimension());
  440. if (dim)
  441. addDimension(dim);
  442. else
  443. {
  444. std::cout << "ERROR: could not create dimension "
  445. << update->getAffectedDimension()
  446. << ". No Factory was provided.\n";
  447. }
  448. }
  449. if (zDimension(update->getAffectedDimension()))
  450. update->onUpdate(zDimension(update->getAffectedDimension()));
  451. updates->remove(0);
  452. }
  453. worldUpdates.messungEnde();
  454. cs.unlock();
  455. clientReply.messungStart();
  456. for (auto client : *clients)
  457. client->reply();
  458. clientReply.messungEnde();
  459. waitForLock.messungStart();
  460. cs.lock();
  461. waitForLock.messungEnde();
  462. waitTotal += waitForLock.getSekunden();
  463. removeOldChunks.messungStart();
  464. for (auto dim : *dimensions)
  465. dim->removeOldChunks();
  466. removeOldChunks.messungEnde();
  467. cs.unlock();
  468. m.messungEnde();
  469. double sec = m.getSekunden();
  470. tickCounter++;
  471. totalTickTime += sec;
  472. sleepTime += 1.0 / MAX_TICKS_PER_SECOND - tickTime;
  473. if (sleepTime > 0)
  474. {
  475. Sleep((int)(sleepTime * 1000));
  476. }
  477. total.messungEnde();
  478. total.messungStart();
  479. tickTime = total.getSekunden();
  480. totalTime += tickTime;
  481. if (totalTime >= 1)
  482. {
  483. averageTickTime = totalTickTime / tickCounter;
  484. ticksPerSecond = tickCounter;
  485. totalTickTime = 0;
  486. tickCounter = 0;
  487. totalTime = 0;
  488. std::cout << std::flush; // update info in console
  489. }
  490. else if (sec > 1)
  491. {
  492. std::cout << "WARNING: tick needed " << sec
  493. << " seconds. The game will run sower then normal.\n";
  494. std::cout << "waiting: " << waitTotal << "\nremoveOldClients: "
  495. << removeOldClients.getSekunden()
  496. << "\ntickEntities:" << tickEntities.getSekunden()
  497. << "\nworldUpdates: " << worldUpdates.getSekunden()
  498. << "\nclientReply: " << clientReply.getSekunden()
  499. << "\nremoveOldChunks:" << removeOldChunks.getSekunden()
  500. << "\n";
  501. }
  502. }
  503. save();
  504. generator->exitAndWait();
  505. loader->exitAndWait();
  506. ticker->exitAndWait();
  507. for (Dimension* dim : *dimensions)
  508. dim->requestStopAndWait();
  509. std::cout << "Game thread exited\n";
  510. }
  511. void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
  512. {
  513. char type;
  514. zRequest->lese(&type, 1);
  515. NetworkMessage* response = new NetworkMessage();
  516. switch (type)
  517. {
  518. case 1: // world
  519. {
  520. Dimension* dim = zDimension(zOrigin->zEntity()->getDimensionId());
  521. if (!dim)
  522. {
  523. dim = typeRegistry->createDimension(
  524. zOrigin->zEntity()->getDimensionId());
  525. if (!dim)
  526. {
  527. std::cout << "ERROR: could not create dimension "
  528. << zOrigin->zEntity()->getDimensionId()
  529. << ". No Factory was provided.\n";
  530. return;
  531. }
  532. addDimension(dim);
  533. }
  534. dim->api(zRequest, response, zOrigin->zEntity());
  535. break;
  536. }
  537. case 2: // player
  538. zOrigin->zEntity()->playerApi(zRequest, response);
  539. break;
  540. case 3: // entity
  541. {
  542. int id;
  543. zRequest->lese((char*)&id, 4);
  544. for (Dimension* dim : *dimensions)
  545. {
  546. Entity* entity = dim->zEntity(id);
  547. if (entity)
  548. {
  549. entity->api(zRequest, response, zOrigin->zEntity());
  550. break;
  551. }
  552. }
  553. break;
  554. }
  555. case 4:
  556. { // inventory
  557. bool isEntity;
  558. zRequest->lese((char*)&isEntity, 1);
  559. Inventory* target;
  560. if (isEntity)
  561. {
  562. int id;
  563. zRequest->lese((char*)&id, 4);
  564. target = zEntity(id);
  565. }
  566. else
  567. {
  568. int dim;
  569. Vec3<int> pos;
  570. zRequest->lese((char*)&dim, 4);
  571. zRequest->lese((char*)&pos.x, 4);
  572. zRequest->lese((char*)&pos.y, 4);
  573. zRequest->lese((char*)&pos.z, 4);
  574. target = zBlockAt(pos, dim);
  575. }
  576. if (target)
  577. target->inventoryApi(zRequest, response, zOrigin->zEntity());
  578. break;
  579. }
  580. case 5:
  581. { // crafting uiml request
  582. int id;
  583. zRequest->lese((char*)&id, 4);
  584. Text uiml = recipies.getCrafingUIML(
  585. StaticRegistry<ItemType>::INSTANCE.zElement(id));
  586. Text dialogId = "crafting_";
  587. dialogId += id;
  588. response->openDialog(dialogId);
  589. int msgSize = 4 + uiml.getLength();
  590. char* msg = new char[msgSize];
  591. *(int*)msg = uiml.getLength();
  592. memcpy(msg + 4, uiml.getText(), uiml.getLength());
  593. response->setMessage(msg, msgSize);
  594. break;
  595. }
  596. case 6:
  597. { // chat message
  598. chat->chatApi(zRequest, zOrigin->zEntity(), response);
  599. break;
  600. }
  601. case 7: // other dimension
  602. {
  603. int dimensionId;
  604. zRequest->lese((char*)&dimensionId, 4);
  605. Dimension* dim = zDimension(dimensionId);
  606. if (dim)
  607. {
  608. dim->api(zRequest, response, zOrigin->zEntity());
  609. }
  610. break;
  611. }
  612. default:
  613. std::cout << "received unknown api request in game with type "
  614. << (int)type << "\n";
  615. }
  616. if (!response->isEmpty())
  617. {
  618. if (response->isBroadcast())
  619. broadcastMessage(response);
  620. else
  621. zOrigin->sendResponse(response);
  622. }
  623. else
  624. {
  625. response->release();
  626. }
  627. }
  628. void Game::updateLightning(int dimensionId, Vec3<int> location)
  629. {
  630. Dimension* zDim = zDimension(dimensionId);
  631. if (zDim) zDim->updateLightning(location);
  632. }
  633. void Game::updateLightningWithoutWait(int dimensionId, Vec3<int> location)
  634. {
  635. Dimension* zDim = zDimension(dimensionId);
  636. if (zDim) zDim->updateLightningWithoutWait(location);
  637. }
  638. void Game::broadcastMessage(NetworkMessage* response)
  639. {
  640. for (auto client : *clients)
  641. client->sendResponse(
  642. dynamic_cast<NetworkMessage*>(response->getThis()));
  643. }
  644. void Game::sendMessage(NetworkMessage* response, Entity* zTargetPlayer)
  645. {
  646. for (auto client : *clients)
  647. {
  648. if (client->zEntity()->getId() == zTargetPlayer->getId())
  649. {
  650. client->sendResponse(response);
  651. return;
  652. }
  653. }
  654. response->release();
  655. }
  656. bool Game::requestWorldUpdate(WorldUpdate* update)
  657. {
  658. cs.lock();
  659. for (WorldUpdate* u : *updates)
  660. {
  661. if (u->getMaxAffectedPoint().x >= update->getMinAffectedPoint().x
  662. && u->getMinAffectedPoint().x <= update->getMaxAffectedPoint().x
  663. && u->getMaxAffectedPoint().y >= update->getMinAffectedPoint().y
  664. && u->getMinAffectedPoint().y <= update->getMaxAffectedPoint().y
  665. && u->getMaxAffectedPoint().z >= update->getMinAffectedPoint().z
  666. && u->getMinAffectedPoint().z <= update->getMaxAffectedPoint().z
  667. && u->getType() == update->getType())
  668. {
  669. cs.unlock();
  670. update->release();
  671. return 0;
  672. }
  673. }
  674. updates->add(update);
  675. cs.unlock();
  676. return 1;
  677. }
  678. bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
  679. {
  680. if (playerRegister->checkSecret(name, secret))
  681. return 1;
  682. else
  683. {
  684. std::cout << "player " << name.getText()
  685. << " tryed to connect with an invalid secret.\n";
  686. return 0;
  687. }
  688. }
  689. bool Game::existsPlayer(Framework::Text name)
  690. {
  691. return playerRegister->hasPlayer(name);
  692. }
  693. Framework::Text Game::createPlayer(Framework::Text name)
  694. {
  695. return playerRegister->addPlayer(name);
  696. }
  697. GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
  698. {
  699. cs.lock();
  700. int id = playerRegister->getPlayerId(name);
  701. Datei pFile;
  702. pFile.setDatei(path + "/player/" + id);
  703. Player* player;
  704. bool isNew = 0;
  705. if (!pFile.existiert() || !pFile.open(Datei::Style::lesen))
  706. {
  707. player = (Player*)StaticRegistry<EntityType>::INSTANCE
  708. .zElement(EntityTypeEnum::PLAYER)
  709. ->createEntityAt(
  710. Vec3<float>(0.5, 0.5, 0), DimensionEnum::OVERWORLD);
  711. player->setName(name);
  712. isNew = 1;
  713. }
  714. else
  715. {
  716. player = (Player*)StaticRegistry<EntityType>::INSTANCE
  717. .zElement(EntityTypeEnum::PLAYER)
  718. ->loadEntity(&pFile);
  719. pFile.close();
  720. }
  721. if (player->getId() >= nextEntityId)
  722. {
  723. nextEntityId = player->getId() + 1;
  724. }
  725. GameClient* gameClient = new GameClient(player, client);
  726. gameClient->sendTypes();
  727. clients->add(gameClient);
  728. if (!zDimension(player->getDimensionId()))
  729. {
  730. Dimension* dim
  731. = typeRegistry->createDimension(player->getDimensionId());
  732. if (!dim)
  733. {
  734. std::cout << "ERROR: could not create dimension "
  735. << (int)player->getDimensionId()
  736. << ". No Factory was provided.\n";
  737. return 0;
  738. }
  739. NetworkMessage* msg = new NetworkMessage();
  740. msg->syncTime(dim->getCurrentDayTime(),
  741. dim->getNightDuration(),
  742. dim->getNightTransitionDuration(),
  743. dim->getDayDuration());
  744. gameClient->sendResponse(msg);
  745. this->addDimension(dim);
  746. }
  747. // subscribe the new player as an observer of the new chunk
  748. Dimension* dim = zDimension(player->getDimensionId());
  749. InMemoryBuffer* buffer = new InMemoryBuffer();
  750. buffer->schreibe("\0", 1);
  751. Punkt center = getChunkCenter(
  752. (int)player->getPosition().x, (int)player->getPosition().y);
  753. buffer->schreibe((char*)&center.x, 4);
  754. buffer->schreibe((char*)&center.y, 4);
  755. buffer->schreibe("\0", 1);
  756. dim->api(buffer, 0, player);
  757. buffer->release();
  758. while (isNew
  759. && !dim->zChunk(getChunkCenter(
  760. (int)player->getPosition().x, (int)player->getPosition().y)))
  761. {
  762. cs.unlock();
  763. Sleep(1000);
  764. cs.lock();
  765. }
  766. if (isNew)
  767. {
  768. Either<Block*, int> b = BlockTypeEnum::AIR;
  769. int h = WORLD_HEIGHT;
  770. while (((b.isA() && (!(Block*)b || ((Block*)b)->isPassable()))
  771. || (b.isB()
  772. && StaticRegistry<BlockType>::INSTANCE.zElement(b)
  773. ->zDefault()
  774. ->isPassable()))
  775. && h > 0)
  776. b = zBlockAt({(int)player->getPosition().x,
  777. (int)player->getPosition().y,
  778. --h},
  779. player->getDimensionId());
  780. player->setPosition(
  781. {player->getPosition().x, player->getPosition().y, (float)h + 1.f});
  782. }
  783. requestWorldUpdate(new AddEntityUpdate(player, player->getDimensionId()));
  784. chat->addObserver(gameClient->zEntity()->getId());
  785. chat->broadcastMessage(name + " joined the game.", Chat::CHANNEL_INFO);
  786. cs.unlock();
  787. return dynamic_cast<GameClient*>(gameClient->getThis());
  788. }
  789. bool Game::isChunkLoaded(int x, int y, int dimension) const
  790. {
  791. Dimension* dim = zDimension(dimension);
  792. return (dim && dim->hasChunck(x, y));
  793. }
  794. bool Game::doesChunkExist(int x, int y, int dimension)
  795. {
  796. cs.lock();
  797. bool result = isChunkLoaded(x, y, dimension)
  798. || loader->existsChunk(x, y, dimension);
  799. cs.unlock();
  800. return result;
  801. }
  802. void Game::blockTargetChanged(Block* zBlock)
  803. {
  804. for (GameClient* client : *this->clients)
  805. {
  806. if (client->zEntity()->zTarget()
  807. && client->zEntity()->zTarget()->isBlock(
  808. zBlock->getPos(), NO_DIRECTION))
  809. {
  810. client->zEntity()->onTargetChange();
  811. }
  812. }
  813. }
  814. void Game::entityTargetChanged(Entity* zEntity)
  815. {
  816. for (GameClient* client : *this->clients)
  817. {
  818. if (client->zEntity()->zTarget()
  819. && client->zEntity()->zTarget()->isEntity(zEntity->getId()))
  820. {
  821. client->zEntity()->onTargetChange();
  822. }
  823. }
  824. }
  825. void Game::spawnItem(
  826. Framework::Vec3<float> location, int dimensionId, Item* stack)
  827. {
  828. spawnItem(location, dimensionId, new ItemStack(stack, 1));
  829. }
  830. void Game::spawnItem(
  831. Framework::Vec3<float> location, int dimensionId, ItemStack* stack)
  832. {
  833. ItemEntity* itemEntity
  834. = (ItemEntity*)StaticRegistry<EntityType>::INSTANCE
  835. .zElement(EntityTypeEnum::ITEM)
  836. ->createEntity(
  837. location, dimensionId, Game::INSTANCE->getNextEntityId());
  838. itemEntity->unsaveAddItem(stack, NO_DIRECTION, 0);
  839. stack->release();
  840. requestWorldUpdate(new AddEntityUpdate(itemEntity, dimensionId));
  841. }
  842. Framework::Either<Block*, int> Game::zBlockAt(
  843. Framework::Vec3<int> location, int dimension) const
  844. {
  845. Dimension* dim = zDimension(dimension);
  846. if (dim) return dim->zBlock(location);
  847. return 0;
  848. }
  849. Block* Game::zRealBlockInstance(Framework::Vec3<int> location, int dimension)
  850. {
  851. Dimension* dim = zDimension(dimension);
  852. if (dim) return dim->zRealBlockInstance(location);
  853. return 0;
  854. }
  855. int Game::getBlockType(Framework::Vec3<int> location, int dimension)
  856. {
  857. Dimension* dim = zDimension(dimension);
  858. if (dim) return dim->getBlockType(location);
  859. return 0;
  860. }
  861. Dimension* Game::zDimension(int id) const
  862. {
  863. for (auto dim : *dimensions)
  864. {
  865. if (dim->getDimensionId() == id) return dim;
  866. }
  867. return 0;
  868. }
  869. Framework::Punkt Game::getChunkCenter(int x, int y)
  870. {
  871. return Punkt(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE
  872. + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2,
  873. ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE
  874. + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2);
  875. }
  876. Area Game::getChunckArea(Punkt center) const
  877. {
  878. return {center.x - CHUNK_SIZE / 2,
  879. center.y - CHUNK_SIZE / 2,
  880. center.x + CHUNK_SIZE / 2 - 1,
  881. center.y + CHUNK_SIZE / 2 - 1,
  882. 0};
  883. }
  884. Framework::Text Game::getWorldDirectory() const
  885. {
  886. return path;
  887. }
  888. void Game::requestArea(Area area)
  889. {
  890. generator->requestGeneration(area);
  891. loader->requestLoading(area);
  892. }
  893. void Game::save() const
  894. {
  895. questManager->saveQuests();
  896. Datei d;
  897. d.setDatei(path + "/eid");
  898. d.open(Datei::Style::schreiben);
  899. d.schreibe((char*)&nextEntityId, 4);
  900. d.close();
  901. playerRegister->save();
  902. for (auto dim : *dimensions)
  903. dim->save(path);
  904. chat->save();
  905. std::cout << "Game was saved\n";
  906. }
  907. void Game::requestStop()
  908. {
  909. stop = 1;
  910. warteAufThread(1000000);
  911. }
  912. void Game::addDimension(Dimension* d)
  913. {
  914. dimensions->add(d);
  915. }
  916. int Game::getNextEntityId()
  917. {
  918. cs.lock();
  919. int result = nextEntityId++;
  920. cs.unlock();
  921. return result;
  922. }
  923. WorldGenerator* Game::zGenerator() const
  924. {
  925. return generator;
  926. }
  927. Game* Game::INSTANCE = 0;
  928. void Game::initialize(Framework::Text name, Framework::Text worldsDir)
  929. {
  930. if (!Game::INSTANCE)
  931. {
  932. Game::INSTANCE = new Game(name, worldsDir);
  933. Game::INSTANCE->initialize();
  934. }
  935. }
  936. Entity* Game::zEntity(int id, int dimensionId) const
  937. {
  938. Dimension* d = zDimension(dimensionId);
  939. if (d) return d->zEntity(id);
  940. return 0;
  941. }
  942. Entity* Game::zEntity(int id) const
  943. {
  944. for (Dimension* d : *dimensions)
  945. {
  946. Entity* e = d->zEntity(id);
  947. if (e) return e;
  948. }
  949. // for new players that are currently loading
  950. for (GameClient* client : *clients)
  951. {
  952. if (client->zEntity()->getId() == id)
  953. {
  954. return client->zEntity();
  955. }
  956. }
  957. return 0;
  958. }
  959. Entity* Game::zNearestEntity(int dimensionId,
  960. Framework::Vec3<float> pos,
  961. std::function<bool(Entity*)> filter)
  962. {
  963. Dimension* d = zDimension(dimensionId);
  964. if (!d) return 0;
  965. return d->zNearestEntity(pos, filter);
  966. }
  967. const RecipieLoader& Game::getRecipies() const
  968. {
  969. return recipies;
  970. }
  971. void Game::doLater(std::function<void()> action)
  972. {
  973. actionsCs.lock();
  974. actions.add(action);
  975. actionsCs.unlock();
  976. }
  977. TickOrganizer* Game::zTickOrganizer() const
  978. {
  979. return ticker;
  980. }
  981. Chat* Game::zChat() const
  982. {
  983. return chat;
  984. }
  985. Player* Game::zPlayerByName(const char* name) const
  986. {
  987. for (GameClient* client : *clients)
  988. {
  989. if (strcmp(client->zEntity()->getName(), name) == 0)
  990. {
  991. return client->zEntity();
  992. }
  993. }
  994. return 0;
  995. }
  996. TypeRegistry* Game::zTypeRegistry() const
  997. {
  998. return typeRegistry;
  999. }
  1000. int Game::getPlayerId(const char* name) const
  1001. {
  1002. return playerRegister->getPlayerId(name);
  1003. }
  1004. QuestManager* Game::zQuestManager() const
  1005. {
  1006. return questManager;
  1007. }
  1008. double Game::getAverageTickTime() const
  1009. {
  1010. return averageTickTime;
  1011. }
  1012. int Game::getTicksPerSecond() const
  1013. {
  1014. return ticksPerSecond;
  1015. }
  1016. int Game::getPlayerCount() const
  1017. {
  1018. return clients->getEintragAnzahl();
  1019. }
  1020. int Game::getChunkCount() const
  1021. {
  1022. int result = 0;
  1023. for (Dimension* dim : *dimensions)
  1024. {
  1025. result += dim->getChunkCount();
  1026. }
  1027. return result;
  1028. }