Game.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  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. ticker(new TickOrganizer()),
  284. path((const char*)(worldsDir + "/" + name)),
  285. stop(0),
  286. tickId(0),
  287. nextEntityId(0),
  288. generator(0),
  289. loader(0),
  290. chat(0),
  291. playerRegister(new PlayerRegister(path)),
  292. totalTickTime(0),
  293. tickCounter(0),
  294. averageTickTime(0),
  295. ticksPerSecond(0),
  296. totalTime(0)
  297. {
  298. if (!DateiExistiert(worldsDir + "/" + name))
  299. DateiPfadErstellen(worldsDir + "/" + name + "/");
  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. }
  332. void Game::thread()
  333. {
  334. ZeitMesser waitForLock;
  335. ZeitMesser removeOldClients;
  336. ZeitMesser tickEntities;
  337. ZeitMesser worldUpdates;
  338. ZeitMesser clientReply;
  339. ZeitMesser removeOldChunks;
  340. ZeitMesser m;
  341. ZeitMesser total;
  342. total.messungStart();
  343. double tickTime = 0;
  344. double sleepTime = 0;
  345. int nextTimeSync = MAX_TICKS_PER_SECOND;
  346. while (!stop)
  347. {
  348. m.messungStart();
  349. ticker->nextTick();
  350. actionsCs.lock();
  351. while (actions.getEintragAnzahl() > 0)
  352. {
  353. actions.get(0)();
  354. actions.remove(0);
  355. }
  356. actionsCs.unlock();
  357. Array<int> removed;
  358. double waitTotal = 0;
  359. waitForLock.messungStart();
  360. cs.lock();
  361. waitForLock.messungEnde();
  362. waitTotal += waitForLock.getSekunden();
  363. removeOldClients.messungStart();
  364. int index = 0;
  365. nextTimeSync--;
  366. for (auto player : *clients)
  367. {
  368. if (!player->isOnline())
  369. {
  370. chat->removeObserver(player->zEntity()->getId());
  371. chat->broadcastMessage(
  372. Framework::Text(player->zEntity()->getName())
  373. + " left the game.",
  374. Chat::CHANNEL_INFO);
  375. Datei pFile;
  376. pFile.setDatei(path + "/player/"
  377. + getPlayerId(player->zEntity()->getName()));
  378. pFile.erstellen();
  379. if (pFile.open(Datei::Style::schreiben))
  380. StaticRegistry<EntityType>::INSTANCE
  381. .zElement(EntityTypeEnum::PLAYER)
  382. ->saveEntity(player->zEntity(), &pFile);
  383. pFile.close();
  384. removed.add(index, 0);
  385. Dimension* dim
  386. = zDimension(player->zEntity()->getDimensionId());
  387. dim->removeSubscriptions(player->zEntity());
  388. this->requestWorldUpdate(
  389. new EntityRemovedUpdate(player->zEntity()->getId(),
  390. player->zEntity()->getDimensionId(),
  391. player->zEntity()->getPosition()));
  392. }
  393. else
  394. {
  395. if (nextTimeSync <= 0 && player->zEntity())
  396. {
  397. Dimension* zDim
  398. = zDimension(player->zEntity()->getDimensionId());
  399. if (zDim)
  400. {
  401. NetworkMessage* msg = new NetworkMessage();
  402. msg->syncTime(zDim->getCurrentDayTime(),
  403. zDim->getNightDuration(),
  404. zDim->getNightTransitionDuration(),
  405. zDim->getDayDuration());
  406. player->sendResponse(msg);
  407. }
  408. }
  409. }
  410. index++;
  411. }
  412. if (nextTimeSync <= 0)
  413. {
  414. nextTimeSync = MAX_TICKS_PER_SECOND;
  415. }
  416. for (auto i : removed)
  417. clients->remove(i);
  418. removeOldClients.messungEnde();
  419. cs.unlock();
  420. tickEntities.messungStart();
  421. for (auto dim : *dimensions)
  422. dim->tickEntities();
  423. tickEntities.messungEnde();
  424. waitForLock.messungStart();
  425. cs.lock();
  426. waitForLock.messungEnde();
  427. waitTotal += waitForLock.getSekunden();
  428. worldUpdates.messungStart();
  429. while (updates->hat(0))
  430. {
  431. WorldUpdate* update = updates->z(0);
  432. for (auto client : *clients)
  433. client->sendWorldUpdate(
  434. dynamic_cast<WorldUpdate*>(update->getThis()));
  435. if (!zDimension(update->getAffectedDimension()))
  436. {
  437. Dimension* dim = typeRegistry->createDimension(
  438. update->getAffectedDimension());
  439. if (dim)
  440. addDimension(dim);
  441. else
  442. {
  443. std::cout << "ERROR: could not create dimension "
  444. << update->getAffectedDimension()
  445. << ". No Factory was provided.\n";
  446. }
  447. }
  448. if (zDimension(update->getAffectedDimension()))
  449. update->onUpdate(zDimension(update->getAffectedDimension()));
  450. updates->remove(0);
  451. }
  452. worldUpdates.messungEnde();
  453. cs.unlock();
  454. clientReply.messungStart();
  455. for (auto client : *clients)
  456. client->reply();
  457. clientReply.messungEnde();
  458. waitForLock.messungStart();
  459. cs.lock();
  460. waitForLock.messungEnde();
  461. waitTotal += waitForLock.getSekunden();
  462. removeOldChunks.messungStart();
  463. for (auto dim : *dimensions)
  464. dim->removeOldChunks();
  465. removeOldChunks.messungEnde();
  466. cs.unlock();
  467. m.messungEnde();
  468. double sec = m.getSekunden();
  469. tickCounter++;
  470. totalTickTime += sec;
  471. sleepTime += 1.0 / MAX_TICKS_PER_SECOND - tickTime;
  472. if (sleepTime > 0)
  473. {
  474. Sleep((int)(sleepTime * 1000));
  475. }
  476. total.messungEnde();
  477. total.messungStart();
  478. tickTime = total.getSekunden();
  479. totalTime += tickTime;
  480. if (totalTime >= 1)
  481. {
  482. averageTickTime = totalTickTime / tickCounter;
  483. ticksPerSecond = tickCounter;
  484. totalTickTime = 0;
  485. tickCounter = 0;
  486. totalTime = 0;
  487. std::cout << std::flush; // update info in console
  488. }
  489. else if (sec > 1)
  490. {
  491. std::cout << "WARNING: tick needed " << sec
  492. << " seconds. The game will run sower then normal.\n";
  493. std::cout << "waiting: " << waitTotal << "\nremoveOldClients: "
  494. << removeOldClients.getSekunden()
  495. << "\ntickEntities:" << tickEntities.getSekunden()
  496. << "\nworldUpdates: " << worldUpdates.getSekunden()
  497. << "\nclientReply: " << clientReply.getSekunden()
  498. << "\nremoveOldChunks:" << removeOldChunks.getSekunden()
  499. << "\n";
  500. }
  501. }
  502. save();
  503. generator->exitAndWait();
  504. loader->exitAndWait();
  505. ticker->exitAndWait();
  506. for (Dimension* dim : *dimensions)
  507. dim->requestStopAndWait();
  508. std::cout << "Game thread exited\n";
  509. }
  510. void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
  511. {
  512. char type;
  513. zRequest->lese(&type, 1);
  514. NetworkMessage* response = new NetworkMessage();
  515. switch (type)
  516. {
  517. case 1: // world
  518. {
  519. Dimension* dim = zDimension(zOrigin->zEntity()->getDimensionId());
  520. if (!dim)
  521. {
  522. dim = typeRegistry->createDimension(
  523. zOrigin->zEntity()->getDimensionId());
  524. if (!dim)
  525. {
  526. std::cout << "ERROR: could not create dimension "
  527. << zOrigin->zEntity()->getDimensionId() << ". No Factory was provided.\n";
  528. return;
  529. }
  530. addDimension(dim);
  531. }
  532. dim->api(zRequest, response, zOrigin->zEntity());
  533. break;
  534. }
  535. case 2: // player
  536. zOrigin->zEntity()->playerApi(zRequest, response);
  537. break;
  538. case 3: // entity
  539. {
  540. int id;
  541. zRequest->lese((char*)&id, 4);
  542. for (Dimension* dim : *dimensions)
  543. {
  544. Entity* entity = dim->zEntity(id);
  545. if (entity)
  546. {
  547. entity->api(zRequest, response, zOrigin->zEntity());
  548. break;
  549. }
  550. }
  551. break;
  552. }
  553. case 4:
  554. { // inventory
  555. bool isEntity;
  556. zRequest->lese((char*)&isEntity, 1);
  557. Inventory* target;
  558. if (isEntity)
  559. {
  560. int id;
  561. zRequest->lese((char*)&id, 4);
  562. target = zEntity(id);
  563. }
  564. else
  565. {
  566. int dim;
  567. Vec3<int> pos;
  568. zRequest->lese((char*)&dim, 4);
  569. zRequest->lese((char*)&pos.x, 4);
  570. zRequest->lese((char*)&pos.y, 4);
  571. zRequest->lese((char*)&pos.z, 4);
  572. target = zBlockAt(pos, dim);
  573. }
  574. if (target)
  575. target->inventoryApi(zRequest, response, zOrigin->zEntity());
  576. break;
  577. }
  578. case 5:
  579. { // crafting uiml request
  580. int id;
  581. zRequest->lese((char*)&id, 4);
  582. Text uiml = recipies.getCrafingUIML(
  583. StaticRegistry<ItemType>::INSTANCE.zElement(id));
  584. Text dialogId = "crafting_";
  585. dialogId += id;
  586. response->openDialog(dialogId);
  587. int msgSize = 4 + uiml.getLength();
  588. char* msg = new char[msgSize];
  589. *(int*)msg = uiml.getLength();
  590. memcpy(msg + 4, uiml.getText(), uiml.getLength());
  591. response->setMessage(msg, msgSize);
  592. break;
  593. }
  594. case 6:
  595. { // chat message
  596. chat->chatApi(zRequest, zOrigin->zEntity(), response);
  597. break;
  598. }
  599. case 7: // other dimension
  600. {
  601. int dimensionId;
  602. zRequest->lese((char*)&dimensionId, 4);
  603. Dimension* dim = zDimension(dimensionId);
  604. if (dim)
  605. {
  606. dim->api(zRequest, response, zOrigin->zEntity());
  607. }
  608. break;
  609. }
  610. default:
  611. std::cout << "received unknown api request in game with type "
  612. << (int)type << "\n";
  613. }
  614. if (!response->isEmpty())
  615. {
  616. if (response->isBroadcast())
  617. broadcastMessage(response);
  618. else
  619. zOrigin->sendResponse(response);
  620. }
  621. else
  622. {
  623. response->release();
  624. }
  625. }
  626. void Game::updateLightning(int dimensionId, Vec3<int> location)
  627. {
  628. Dimension* zDim = zDimension(dimensionId);
  629. if (zDim) zDim->updateLightning(location);
  630. }
  631. void Game::updateLightningWithoutWait(int dimensionId, Vec3<int> location)
  632. {
  633. Dimension* zDim = zDimension(dimensionId);
  634. if (zDim) zDim->updateLightningWithoutWait(location);
  635. }
  636. void Game::broadcastMessage(NetworkMessage* response)
  637. {
  638. for (auto client : *clients)
  639. client->sendResponse(
  640. dynamic_cast<NetworkMessage*>(response->getThis()));
  641. }
  642. void Game::sendMessage(NetworkMessage* response, Entity* zTargetPlayer)
  643. {
  644. for (auto client : *clients)
  645. {
  646. if (client->zEntity()->getId() == zTargetPlayer->getId())
  647. {
  648. client->sendResponse(response);
  649. return;
  650. }
  651. }
  652. response->release();
  653. }
  654. bool Game::requestWorldUpdate(WorldUpdate* update)
  655. {
  656. cs.lock();
  657. for (WorldUpdate* u : *updates)
  658. {
  659. if (u->getMaxAffectedPoint().x >= update->getMinAffectedPoint().x
  660. && u->getMinAffectedPoint().x <= update->getMaxAffectedPoint().x
  661. && u->getMaxAffectedPoint().y >= update->getMinAffectedPoint().y
  662. && u->getMinAffectedPoint().y <= update->getMaxAffectedPoint().y
  663. && u->getMaxAffectedPoint().z >= update->getMinAffectedPoint().z
  664. && u->getMinAffectedPoint().z <= update->getMaxAffectedPoint().z
  665. && u->getType() == update->getType())
  666. {
  667. cs.unlock();
  668. update->release();
  669. return 0;
  670. }
  671. }
  672. updates->add(update);
  673. cs.unlock();
  674. return 1;
  675. }
  676. bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
  677. {
  678. if (playerRegister->checkSecret(name, secret))
  679. return 1;
  680. else
  681. {
  682. std::cout << "player " << name.getText()
  683. << " tryed to connect with an invalid secret.\n";
  684. return 0;
  685. }
  686. }
  687. bool Game::existsPlayer(Framework::Text name)
  688. {
  689. return playerRegister->hasPlayer(name);
  690. }
  691. Framework::Text Game::createPlayer(Framework::Text name)
  692. {
  693. return playerRegister->addPlayer(name);
  694. }
  695. GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
  696. {
  697. cs.lock();
  698. int id = playerRegister->getPlayerId(name);
  699. Datei pFile;
  700. pFile.setDatei(path + "/player/" + id);
  701. Player* player;
  702. bool isNew = 0;
  703. if (!pFile.existiert() || !pFile.open(Datei::Style::lesen))
  704. {
  705. player = (Player*)StaticRegistry<EntityType>::INSTANCE
  706. .zElement(EntityTypeEnum::PLAYER)
  707. ->createEntityAt(
  708. Vec3<float>(0.5, 0.5, 0), DimensionEnum::OVERWORLD);
  709. player->setName(name);
  710. isNew = 1;
  711. }
  712. else
  713. {
  714. player = (Player*)StaticRegistry<EntityType>::INSTANCE
  715. .zElement(EntityTypeEnum::PLAYER)
  716. ->loadEntity(&pFile);
  717. pFile.close();
  718. }
  719. if (player->getId() >= nextEntityId)
  720. {
  721. nextEntityId = player->getId() + 1;
  722. }
  723. GameClient* gameClient = new GameClient(player, client);
  724. gameClient->sendTypes();
  725. clients->add(gameClient);
  726. if (!zDimension(player->getDimensionId()))
  727. {
  728. Dimension* dim
  729. = typeRegistry->createDimension(player->getDimensionId());
  730. if (!dim)
  731. {
  732. std::cout << "ERROR: could not create dimension "
  733. << (int)player->getDimensionId() << ". No Factory was provided.\n";
  734. return 0;
  735. }
  736. NetworkMessage *msg = new NetworkMessage();
  737. msg->syncTime(dim->getCurrentDayTime(),
  738. dim->getNightDuration(),
  739. dim->getNightTransitionDuration(),
  740. dim->getDayDuration());
  741. gameClient->sendResponse(msg);
  742. this->addDimension(dim);
  743. }
  744. // subscribe the new player as an observer of the new chunk
  745. Dimension* dim = zDimension(player->getDimensionId());
  746. InMemoryBuffer* buffer = new InMemoryBuffer();
  747. buffer->schreibe("\0", 1);
  748. Punkt center = getChunkCenter(
  749. (int)player->getPosition().x, (int)player->getPosition().y);
  750. buffer->schreibe((char*)&center.x, 4);
  751. buffer->schreibe((char*)&center.y, 4);
  752. buffer->schreibe("\0", 1);
  753. dim->api(buffer, 0, player);
  754. buffer->release();
  755. while (isNew
  756. && !dim->zChunk(getChunkCenter(
  757. (int)player->getPosition().x, (int)player->getPosition().y)))
  758. {
  759. cs.unlock();
  760. Sleep(1000);
  761. cs.lock();
  762. }
  763. if (isNew)
  764. {
  765. Either<Block*, int> b = BlockTypeEnum::AIR;
  766. int h = WORLD_HEIGHT;
  767. while (((b.isA() && (!(Block*)b || ((Block*)b)->isPassable()))
  768. || (b.isB()
  769. && StaticRegistry<BlockType>::INSTANCE.zElement(b)
  770. ->zDefault()
  771. ->isPassable()))
  772. && h > 0)
  773. b = zBlockAt({(int)player->getPosition().x,
  774. (int)player->getPosition().y,
  775. --h},
  776. player->getDimensionId());
  777. player->setPosition(
  778. {player->getPosition().x, player->getPosition().y, (float)h + 1.f});
  779. }
  780. requestWorldUpdate(new AddEntityUpdate(player, player->getDimensionId()));
  781. chat->addObserver(gameClient->zEntity()->getId());
  782. chat->broadcastMessage(name + " joined the game.", Chat::CHANNEL_INFO);
  783. cs.unlock();
  784. return dynamic_cast<GameClient*>(gameClient->getThis());
  785. }
  786. bool Game::isChunkLoaded(int x, int y, int dimension) const
  787. {
  788. Dimension* dim = zDimension(dimension);
  789. return (dim && dim->hasChunck(x, y));
  790. }
  791. bool Game::doesChunkExist(int x, int y, int dimension)
  792. {
  793. cs.lock();
  794. bool result = isChunkLoaded(x, y, dimension)
  795. || loader->existsChunk(x, y, dimension);
  796. cs.unlock();
  797. return result;
  798. }
  799. void Game::blockTargetChanged(Block* zBlock)
  800. {
  801. for (GameClient* client : *this->clients)
  802. {
  803. if (client->zEntity()->zTarget()
  804. && client->zEntity()->zTarget()->isBlock(
  805. zBlock->getPos(), NO_DIRECTION))
  806. {
  807. client->zEntity()->onTargetChange();
  808. }
  809. }
  810. }
  811. void Game::entityTargetChanged(Entity* zEntity)
  812. {
  813. for (GameClient* client : *this->clients)
  814. {
  815. if (client->zEntity()->zTarget()
  816. && client->zEntity()->zTarget()->isEntity(zEntity->getId()))
  817. {
  818. client->zEntity()->onTargetChange();
  819. }
  820. }
  821. }
  822. void Game::spawnItem(
  823. Framework::Vec3<float> location, int dimensionId, Item* stack)
  824. {
  825. spawnItem(location, dimensionId, new ItemStack(stack, 1));
  826. }
  827. void Game::spawnItem(
  828. Framework::Vec3<float> location, int dimensionId, ItemStack* stack)
  829. {
  830. ItemEntity* itemEntity
  831. = (ItemEntity*)StaticRegistry<EntityType>::INSTANCE
  832. .zElement(EntityTypeEnum::ITEM)
  833. ->createEntity(
  834. location, dimensionId, Game::INSTANCE->getNextEntityId());
  835. itemEntity->unsaveAddItem(stack, NO_DIRECTION, 0);
  836. stack->release();
  837. requestWorldUpdate(new AddEntityUpdate(itemEntity, dimensionId));
  838. }
  839. Framework::Either<Block*, int> Game::zBlockAt(
  840. Framework::Vec3<int> location, int dimension) const
  841. {
  842. Dimension* dim = zDimension(dimension);
  843. if (dim) return dim->zBlock(location);
  844. return 0;
  845. }
  846. Block* Game::zRealBlockInstance(Framework::Vec3<int> location, int dimension)
  847. {
  848. Dimension* dim = zDimension(dimension);
  849. if (dim) return dim->zRealBlockInstance(location);
  850. return 0;
  851. }
  852. int Game::getBlockType(Framework::Vec3<int> location, int dimension)
  853. {
  854. Dimension* dim = zDimension(dimension);
  855. if (dim) return dim->getBlockType(location);
  856. return 0;
  857. }
  858. Dimension* Game::zDimension(int id) const
  859. {
  860. for (auto dim : *dimensions)
  861. {
  862. if (dim->getDimensionId() == id) return dim;
  863. }
  864. return 0;
  865. }
  866. Framework::Punkt Game::getChunkCenter(int x, int y)
  867. {
  868. return Punkt(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE
  869. + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2,
  870. ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE
  871. + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2);
  872. }
  873. Area Game::getChunckArea(Punkt center) const
  874. {
  875. return {center.x - CHUNK_SIZE / 2,
  876. center.y - CHUNK_SIZE / 2,
  877. center.x + CHUNK_SIZE / 2 - 1,
  878. center.y + CHUNK_SIZE / 2 - 1,
  879. 0};
  880. }
  881. Framework::Text Game::getWorldDirectory() const
  882. {
  883. return path;
  884. }
  885. void Game::requestArea(Area area)
  886. {
  887. generator->requestGeneration(area);
  888. loader->requestLoading(area);
  889. }
  890. void Game::save() const
  891. {
  892. Datei d;
  893. d.setDatei(path + "/eid");
  894. d.open(Datei::Style::schreiben);
  895. d.schreibe((char*)&nextEntityId, 4);
  896. d.close();
  897. playerRegister->save();
  898. for (auto dim : *dimensions)
  899. dim->save(path);
  900. chat->save();
  901. std::cout << "Game was saved\n";
  902. }
  903. void Game::requestStop()
  904. {
  905. stop = 1;
  906. warteAufThread(1000000);
  907. }
  908. void Game::addDimension(Dimension* d)
  909. {
  910. dimensions->add(d);
  911. }
  912. int Game::getNextEntityId()
  913. {
  914. cs.lock();
  915. int result = nextEntityId++;
  916. cs.unlock();
  917. return result;
  918. }
  919. WorldGenerator* Game::zGenerator() const
  920. {
  921. return generator;
  922. }
  923. Game* Game::INSTANCE = 0;
  924. void Game::initialize(Framework::Text name, Framework::Text worldsDir)
  925. {
  926. if (!Game::INSTANCE)
  927. {
  928. Game::INSTANCE = new Game(name, worldsDir);
  929. Game::INSTANCE->initialize();
  930. }
  931. }
  932. Entity* Game::zEntity(int id, int dimensionId) const
  933. {
  934. Dimension* d = zDimension(dimensionId);
  935. if (d) return d->zEntity(id);
  936. return 0;
  937. }
  938. Entity* Game::zEntity(int id) const
  939. {
  940. for (Dimension* d : *dimensions)
  941. {
  942. Entity* e = d->zEntity(id);
  943. if (e) return e;
  944. }
  945. // for new players that are currently loading
  946. for (GameClient* client : *clients)
  947. {
  948. if (client->zEntity()->getId() == id)
  949. {
  950. return client->zEntity();
  951. }
  952. }
  953. return 0;
  954. }
  955. Entity* Game::zNearestEntity(int dimensionId,
  956. Framework::Vec3<float> pos,
  957. std::function<bool(Entity*)> filter)
  958. {
  959. Dimension* d = zDimension(dimensionId);
  960. if (!d) return 0;
  961. return d->zNearestEntity(pos, filter);
  962. }
  963. const RecipieLoader& Game::getRecipies() const
  964. {
  965. return recipies;
  966. }
  967. void Game::doLater(std::function<void()> action)
  968. {
  969. actionsCs.lock();
  970. actions.add(action);
  971. actionsCs.unlock();
  972. }
  973. TickOrganizer* Game::zTickOrganizer() const
  974. {
  975. return ticker;
  976. }
  977. Chat* Game::zChat() const
  978. {
  979. return chat;
  980. }
  981. Player* Game::zPlayerByName(const char* name) const
  982. {
  983. for (GameClient* client : *clients)
  984. {
  985. if (strcmp(client->zEntity()->getName(), name) == 0)
  986. {
  987. return client->zEntity();
  988. }
  989. }
  990. return 0;
  991. }
  992. TypeRegistry* Game::zTypeRegistry() const
  993. {
  994. return typeRegistry;
  995. }
  996. int Game::getPlayerId(const char* name) const
  997. {
  998. return playerRegister->getPlayerId(name);
  999. }
  1000. double Game::getAverageTickTime() const
  1001. {
  1002. return averageTickTime;
  1003. }
  1004. int Game::getTicksPerSecond() const
  1005. {
  1006. return ticksPerSecond;
  1007. }
  1008. int Game::getPlayerCount() const
  1009. {
  1010. return clients->getEintragAnzahl();
  1011. }
  1012. int Game::getChunkCount() const
  1013. {
  1014. int result = 0;
  1015. for (Dimension* dim : *dimensions)
  1016. {
  1017. result += dim->getChunkCount();
  1018. }
  1019. return result;
  1020. }