Game.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  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 "JsonUtils.h"
  8. #include "MultiblockTree.h"
  9. #include "NetworkMessage.h"
  10. #include "NoBlock.h"
  11. #include "OverworldDimension.h"
  12. #include "Player.h"
  13. #include "PlayerHand.h"
  14. #include "Zeit.h"
  15. using namespace Framework;
  16. GameClient::GameClient(Player* zPlayer, FCKlient* client)
  17. : Thread(),
  18. zPlayer(zPlayer),
  19. client(client),
  20. viewDistance(DEFAULT_VIEW_DISTANCE),
  21. first(1),
  22. online(1),
  23. finished(0),
  24. backgroundFinished(0),
  25. foregroundFinished(0)
  26. {
  27. new AsynchronCall("Game Client Updates", [this]() {
  28. while (online)
  29. {
  30. other.lock();
  31. if (updateQueue.hat(0))
  32. {
  33. WorldUpdate* update = updateQueue.get(0);
  34. updateQueue.remove(0);
  35. other.unlock();
  36. background.lock();
  37. this->client->zBackgroundWriter()->schreibe(
  38. (char*)&Message::WORLD_UPDATE, 1);
  39. update->writeAndCheck(this->client->zBackgroundWriter());
  40. background.unlock();
  41. update->release();
  42. }
  43. else
  44. {
  45. other.unlock();
  46. updateSync.wait();
  47. }
  48. }
  49. finished = 1;
  50. });
  51. start();
  52. }
  53. GameClient::~GameClient()
  54. {
  55. online = 0;
  56. updateSync.notify();
  57. emptyForegroundQueueSync.notifyAll();
  58. emptyBackgroundQueueSync.notifyAll();
  59. foregroundQueueSync.notify();
  60. backgroundQueueSync.notify();
  61. while (!finished || !foregroundFinished || !backgroundFinished)
  62. Sleep(100);
  63. client->release();
  64. }
  65. void GameClient::thread()
  66. {
  67. new AsynchronCall("Game Client Background", [this]() {
  68. while (online)
  69. {
  70. queueCs.lock();
  71. if (backgroundQueue.hat(0))
  72. {
  73. NetworkMessage* message = backgroundQueue.get(0);
  74. backgroundQueue.remove(0);
  75. queueCs.unlock();
  76. background.lock();
  77. message->writeTo(client->zBackgroundWriter());
  78. background.unlock();
  79. message->release();
  80. }
  81. else
  82. {
  83. queueCs.unlock();
  84. emptyBackgroundQueueSync.notifyAll();
  85. while (!backgroundQueueSync.wait(1000))
  86. {
  87. emptyBackgroundQueueSync.notifyAll();
  88. }
  89. }
  90. }
  91. backgroundFinished = 1;
  92. });
  93. while (online)
  94. {
  95. queueCs.lock();
  96. if (foregroundQueue.hat(0))
  97. {
  98. NetworkMessage* message = foregroundQueue.get(0);
  99. foregroundQueue.remove(0);
  100. queueCs.unlock();
  101. foreground.lock();
  102. message->writeTo(client->zForegroundWriter());
  103. foreground.unlock();
  104. message->release();
  105. }
  106. else
  107. {
  108. queueCs.unlock();
  109. emptyForegroundQueueSync.notifyAll();
  110. while (!foregroundQueueSync.wait(1000))
  111. {
  112. emptyForegroundQueueSync.notifyAll();
  113. }
  114. }
  115. }
  116. foregroundFinished = 1;
  117. }
  118. void GameClient::sendWorldUpdate(WorldUpdate* update)
  119. {
  120. bool add = 0;
  121. if (zPlayer->getDimensionId() == update->getAffectedDimension())
  122. {
  123. auto pos = (Vec3<int>)zPlayer->getPosition();
  124. int dist = update->distanceTo(pos.x, pos.y);
  125. if (dist < viewDistance * CHUNK_SIZE)
  126. {
  127. other.lock();
  128. updateQueue.add(update);
  129. other.unlock();
  130. updateSync.notify();
  131. add = 1;
  132. }
  133. }
  134. if (!add) update->release();
  135. }
  136. void GameClient::reply()
  137. {
  138. other.lock();
  139. for (auto req : requests)
  140. Game::INSTANCE->api(req, this);
  141. requests.leeren();
  142. other.unlock();
  143. if (first)
  144. {
  145. foreground.lock();
  146. int id = zPlayer->getId();
  147. client->zForegroundWriter()->schreibe(
  148. (char*)&Message::POSITION_UPDATE, 1);
  149. client->zForegroundWriter()->schreibe((char*)&id, 4);
  150. id = zPlayer->getDimensionId();
  151. client->zForegroundWriter()->schreibe((char*)&id, 4);
  152. foreground.unlock();
  153. first = 0;
  154. }
  155. }
  156. void GameClient::logout()
  157. {
  158. online = 0;
  159. updateSync.notify();
  160. emptyForegroundQueueSync.notifyAll();
  161. emptyBackgroundQueueSync.notifyAll();
  162. foregroundQueueSync.notify();
  163. backgroundQueueSync.notify();
  164. }
  165. void GameClient::addMessage(StreamReader* reader)
  166. {
  167. short len = 0;
  168. reader->lese((char*)&len, 2);
  169. InMemoryBuffer* buffer = new InMemoryBuffer();
  170. char* tmp = new char[len];
  171. reader->lese(tmp, len);
  172. buffer->schreibe(tmp, len);
  173. delete[] tmp;
  174. other.lock();
  175. requests.add(buffer);
  176. other.unlock();
  177. }
  178. bool GameClient::isOnline() const
  179. {
  180. return online;
  181. }
  182. void GameClient::sendResponse(NetworkMessage* response)
  183. {
  184. queueCs.lock();
  185. if (response->isUseBackground())
  186. {
  187. if (backgroundQueue.getEintragAnzahl() > 20)
  188. {
  189. queueCs.unlock();
  190. while (!emptyBackgroundQueueSync.wait(1000))
  191. {
  192. backgroundQueueSync.notify();
  193. }
  194. queueCs.lock();
  195. }
  196. backgroundQueue.add(response);
  197. queueCs.unlock();
  198. backgroundQueueSync.notify();
  199. }
  200. else
  201. {
  202. if (foregroundQueue.getEintragAnzahl() > 100)
  203. {
  204. queueCs.unlock();
  205. std::cout << "WARNING: Game paused because nework connection to "
  206. << zPlayer->getName() << " is to slow.\n";
  207. ZeitMesser m;
  208. m.messungStart();
  209. while (foregroundQueue.getEintragAnzahl() > 0)
  210. {
  211. foregroundQueueSync.notify();
  212. emptyForegroundQueueSync.wait(100);
  213. }
  214. m.messungEnde();
  215. std::cout << "WARNING: Game resumed after " << m.getSekunden()
  216. << " seconds.\n";
  217. queueCs.lock();
  218. }
  219. foregroundQueue.add(response);
  220. queueCs.unlock();
  221. foregroundQueueSync.notify();
  222. }
  223. }
  224. Player* GameClient::zEntity() const
  225. {
  226. return zPlayer;
  227. }
  228. void GameClient::sendTypes()
  229. {
  230. foreground.lock();
  231. int count = 0;
  232. for (int i = 0; i < Game::INSTANCE->getBlockTypeCount(); i++)
  233. {
  234. if (Game::INSTANCE->zBlockType(i)) count++;
  235. }
  236. client->zForegroundWriter()->schreibe((char*)&count, 4);
  237. for (int i = 0; i < Game::INSTANCE->getBlockTypeCount(); i++)
  238. {
  239. const BlockType* t = Game::INSTANCE->zBlockType(i);
  240. if (t)
  241. {
  242. t->writeTypeInfo(client->zForegroundWriter());
  243. }
  244. }
  245. count = 0;
  246. for (int i = 0; i < Game::INSTANCE->getItemTypeCount(); i++)
  247. {
  248. if (Game::INSTANCE->zItemType(i)) count++;
  249. }
  250. client->zForegroundWriter()->schreibe((char*)&count, 4);
  251. for (int i = 0; i < Game::INSTANCE->getItemTypeCount(); i++)
  252. {
  253. const ItemType* t = Game::INSTANCE->zItemType(i);
  254. if (t)
  255. {
  256. int id = t->getId();
  257. client->zForegroundWriter()->schreibe((char*)&id, 4);
  258. char len = (char)t->getName().getLength();
  259. client->zForegroundWriter()->schreibe((char*)&len, 1);
  260. client->zForegroundWriter()->schreibe(t->getName().getText(), len);
  261. short tlen = (short)t->getTooltipUIML().getLength();
  262. client->zForegroundWriter()->schreibe((char*)&tlen, 2);
  263. client->zForegroundWriter()->schreibe(
  264. t->getTooltipUIML().getText(), tlen);
  265. if (t->zModel())
  266. {
  267. t->zModel()->writeTo(client->zForegroundWriter());
  268. }
  269. else
  270. {
  271. ModelInfo("", Framework::RCArray<Framework::Text>(), false, 1.f)
  272. .writeTo(client->zForegroundWriter());
  273. }
  274. }
  275. }
  276. count = 0;
  277. for (int i = 0; i < Game::INSTANCE->getEntityTypeCount(); i++)
  278. {
  279. if (Game::INSTANCE->zEntityType(i)) count++;
  280. }
  281. client->zForegroundWriter()->schreibe((char*)&count, 4);
  282. for (int i = 0; i < count; i++)
  283. {
  284. const EntityType* t = Game::INSTANCE->zEntityType(i);
  285. int id = t->getId();
  286. client->zForegroundWriter()->schreibe((char*)&id, 4);
  287. if (t->zModel())
  288. {
  289. t->zModel()->writeTo(client->zForegroundWriter());
  290. }
  291. else
  292. {
  293. ModelInfo("", Framework::RCArray<Framework::Text>(), false, 1.f)
  294. .writeTo(client->zForegroundWriter());
  295. }
  296. }
  297. foreground.unlock();
  298. }
  299. Game::Game(Framework::Text name, Framework::Text worldsDir)
  300. : Thread(),
  301. name(name),
  302. typeRegistry(new TypeRegistry()),
  303. dimensions(new RCArray<Dimension>()),
  304. updates(new RCArray<WorldUpdate>()),
  305. clients(new RCArray<GameClient>()),
  306. questManager(new QuestManager()),
  307. ticker(new TickOrganizer()),
  308. path((const char*)(worldsDir + "/" + name)),
  309. stop(0),
  310. tickId(0),
  311. nextEntityId(0),
  312. generator(0),
  313. loader(0),
  314. chat(0),
  315. playerRegister(new PlayerRegister(path)),
  316. uiController(new UIController()),
  317. totalTickTime(0),
  318. tickCounter(0),
  319. averageTickTime(0),
  320. ticksPerSecond(0),
  321. totalTime(0),
  322. blockTypes(0),
  323. blockTypeCount(0),
  324. itemTypes(0),
  325. itemTypeCount(0),
  326. entityTypes(0),
  327. entityTypeCount(0),
  328. multiblockStructureTypes(0),
  329. multiblockStructureTypeCount(0)
  330. {
  331. if (!DateiExistiert(path)) DateiPfadErstellen(path + "/");
  332. Datei d;
  333. d.setDatei(path + "/eid");
  334. if (d.existiert())
  335. {
  336. d.open(Datei::Style::lesen);
  337. d.lese((char*)&nextEntityId, 4);
  338. d.close();
  339. }
  340. start();
  341. }
  342. Game::~Game()
  343. {
  344. dimensions->release();
  345. updates->release();
  346. clients->release();
  347. generator->release();
  348. loader->release();
  349. chat->release();
  350. playerRegister->release();
  351. typeRegistry->release();
  352. uiController->release();
  353. for (int i = 0; i < blockTypeCount; i++)
  354. {
  355. if (blockTypes[i]) blockTypes[i]->release();
  356. }
  357. delete[] blockTypes;
  358. for (int i = 0; i < itemTypeCount; i++)
  359. {
  360. if (itemTypes[i]) itemTypes[i]->release();
  361. }
  362. delete[] itemTypes;
  363. for (int i = 0; i < entityTypeCount; i++)
  364. {
  365. if (entityTypes[i]) entityTypes[i]->release();
  366. }
  367. delete[] entityTypes;
  368. for (int i = 0; i < multiblockStructureTypeCount; i++)
  369. {
  370. if (multiblockStructureTypes[i]) multiblockStructureTypes[i]->release();
  371. }
  372. delete[] multiblockStructureTypes;
  373. }
  374. void Game::initialize()
  375. {
  376. // TODO load mods libraries
  377. // load block types
  378. std::cout << "Loading block types\n";
  379. Framework::Array<BlockType*> blockTypeArray;
  380. Framework::JSON::Validator::JSONValidator* validator
  381. = Framework::JSON::Validator::JSONValidator::buildForArray()
  382. ->addAcceptedTypeInArray(typeRegistry->getValidator<BlockType>())
  383. ->removeInvalidEntries()
  384. ->finishArray();
  385. loadAllJsonsFromDirectory("data/blocks",
  386. [this, &blockTypeArray, validator](
  387. Framework::JSON::JSONValue* zValue, Framework::Text path) {
  388. Framework::RCArray<Framework::JSON::Validator::JSONValidationResult>
  389. validationResults;
  390. Framework::JSON::JSONValue* validParts
  391. = validator->getValidParts(zValue, &validationResults);
  392. for (Framework::JSON::Validator::JSONValidationResult* result :
  393. validationResults)
  394. {
  395. result->printInvalidInfo();
  396. }
  397. if (validParts)
  398. {
  399. for (Framework::JSON::JSONValue* value : *validParts->asArray())
  400. {
  401. BlockType* blockType
  402. = typeRegistry->fromJson<BlockType>(value);
  403. if (blockType)
  404. {
  405. blockTypeArray.add(blockType);
  406. }
  407. }
  408. validParts->release();
  409. }
  410. });
  411. validator->release();
  412. std::cout << "Loaded " << blockTypeArray.getEintragAnzahl()
  413. << " block types from data/blocks\n";
  414. blockTypes = new BlockType*[2 + blockTypeArray.getEintragAnzahl()];
  415. blockTypes[0]
  416. = new NoBlockBlockType(&NoBlock::INSTANCE, "__not_yet_generated");
  417. blockTypes[1] = new NoBlockBlockType(&AirBlock::INSTANCE, "Air");
  418. blockTypeCount = 2;
  419. for (BlockType* blockType : blockTypeArray)
  420. {
  421. blockTypes[blockTypeCount++] = blockType;
  422. }
  423. for (int i = 0; i < blockTypeCount; i++)
  424. {
  425. blockTypes[i]->setTypeId(i);
  426. }
  427. std::cout << "Loading item types\n";
  428. Framework::Array<ItemType*> itemTypeArray;
  429. validator
  430. = Framework::JSON::Validator::JSONValidator::buildForArray()
  431. ->addAcceptedTypeInArray(typeRegistry->getValidator<ItemType>())
  432. ->removeInvalidEntries()
  433. ->finishArray();
  434. loadAllJsonsFromDirectory("data/items",
  435. [this, &itemTypeArray, validator](
  436. Framework::JSON::JSONValue* zValue, Framework::Text path) {
  437. Framework::RCArray<Framework::JSON::Validator::JSONValidationResult>
  438. validationResults;
  439. Framework::JSON::JSONValue* validParts
  440. = validator->getValidParts(zValue, &validationResults);
  441. for (Framework::JSON::Validator::JSONValidationResult* result :
  442. validationResults)
  443. {
  444. result->printInvalidInfo();
  445. }
  446. if (validParts)
  447. {
  448. for (Framework::JSON::JSONValue* value : *validParts->asArray())
  449. {
  450. ItemType* itemType
  451. = typeRegistry->fromJson<ItemType>(value);
  452. if (itemType)
  453. {
  454. itemTypeArray.add(itemType);
  455. }
  456. }
  457. validParts->release();
  458. }
  459. });
  460. validator->release();
  461. std::cout << "Loaded " << itemTypeArray.getEintragAnzahl()
  462. << " item types from data/items\n";
  463. itemTypes
  464. = new ItemType*[blockTypeCount + itemTypeArray.getEintragAnzahl()];
  465. itemTypes[0] = new PlayerHandItemType();
  466. itemTypeCount = 1;
  467. for (int i = 0; i < blockTypeCount; i++)
  468. {
  469. ItemType* itemType = blockTypes[i]->createItemType();
  470. if (itemType)
  471. {
  472. itemTypes[itemTypeCount++] = itemType;
  473. }
  474. }
  475. for (ItemType* itemType : itemTypeArray)
  476. {
  477. itemTypes[itemTypeCount++] = itemType;
  478. }
  479. for (int i = 0; i < itemTypeCount; i++)
  480. {
  481. itemTypes[i]->setTypeId(i);
  482. }
  483. std::cout << "Loading entity types\n";
  484. Framework::Array<EntityType*> entityTypeArray;
  485. /* validator
  486. = Framework::JSON::Validator::JSONValidator::buildForArray()
  487. ->addAcceptedTypeInArray(typeRegistry->getValidator<EntityType>())
  488. ->removeInvalidEntries()
  489. ->finishArray();
  490. loadAllJsonsFromDirectory("data/entities",
  491. [this, &entityTypeArray, validator](
  492. Framework::JSON::JSONValue* zValue, Framework::Text path) {
  493. Framework::RCArray<Framework::JSON::Validator::JSONValidationResult>
  494. validationResults;
  495. Framework::JSON::JSONValue* validParts
  496. = validator->getValidParts(zValue, &validationResults);
  497. for (Framework::JSON::Validator::JSONValidationResult* result :
  498. validationResults)
  499. {
  500. result->printInvalidInfo();
  501. }
  502. if (validParts)
  503. {
  504. for (Framework::JSON::JSONValue* value : *validParts->asArray())
  505. {
  506. EntityType* entityType
  507. = typeRegistry->fromJson<EntityType>(value);
  508. if (entityType)
  509. {
  510. entityTypeArray.add(entityType);
  511. }
  512. }
  513. validParts->release();
  514. }
  515. });
  516. validator->release();*/
  517. std::cout << "Loaded " << entityTypeArray.getEintragAnzahl()
  518. << " entity types from data/entities\n";
  519. entityTypes = new EntityType*[2 + entityTypeArray.getEintragAnzahl()];
  520. entityTypes[0] = new PlayerEntityType();
  521. entityTypes[1] = new ItemEntityType();
  522. entityTypeCount = 2;
  523. for (EntityType* entityType : entityTypeArray)
  524. {
  525. entityTypes[entityTypeCount++] = entityType;
  526. }
  527. for (int i = 0; i < entityTypeCount; i++)
  528. {
  529. entityTypes[i]->setTypeId(i);
  530. }
  531. // initialize loaded types
  532. bool allInitialized = false;
  533. while (!allInitialized)
  534. {
  535. allInitialized = true;
  536. for (int i = 0; i < blockTypeCount; i++)
  537. {
  538. if (blockTypes[i] && !blockTypes[i]->initialize(this))
  539. {
  540. std::cout << "ERROR: Could not initialize Block Type '"
  541. << blockTypes[i]->getName() << "'.\n";
  542. blockTypes[i]->release();
  543. blockTypes[i] = 0;
  544. allInitialized = false;
  545. }
  546. }
  547. }
  548. allInitialized = false;
  549. while (!allInitialized)
  550. {
  551. allInitialized = true;
  552. for (int i = 0; i < itemTypeCount; i++)
  553. {
  554. if (itemTypes[i] && !itemTypes[i]->initialize(this))
  555. {
  556. std::cout << "ERROR: Could not initialize Item Type '"
  557. << itemTypes[i]->getName() << "'.\n";
  558. itemTypes[i]->release();
  559. itemTypes[i] = 0;
  560. allInitialized = false;
  561. }
  562. }
  563. }
  564. allInitialized = false;
  565. while (!allInitialized)
  566. {
  567. allInitialized = true;
  568. for (int i = 0; i < entityTypeCount; i++)
  569. {
  570. if (entityTypes[i] && !entityTypes[i]->initialize(this))
  571. {
  572. std::cout << "ERROR: Could not initialize Entity Type '"
  573. << entityTypes[i]->getName() << "'.\n";
  574. entityTypes[i]->release();
  575. entityTypes[i] = 0;
  576. allInitialized = false;
  577. }
  578. }
  579. }
  580. for (int i = 0; i < blockTypeCount; i++)
  581. {
  582. if (blockTypes[i])
  583. {
  584. blockTypes[i]->initializeDefault();
  585. }
  586. }
  587. multiblockStructureTypes = new MultiblockStructureType*[1];
  588. multiblockStructureTypes[0] = new MultiblockTreeStructureType();
  589. multiblockStructureTypeCount = 1;
  590. // save syntax info
  591. Framework::DateiRemove("data/syntax");
  592. typeRegistry->writeSyntaxInfo("data/syntax");
  593. // initialize world generator and world loader
  594. int seed = 0;
  595. int index = 0;
  596. for (const char* n = name; *n; n++)
  597. seed += (int)pow((float)*n * 31, (float)++index);
  598. generator = new WorldGenerator(seed);
  599. loader = new WorldLoader();
  600. // load recipies
  601. recipies.loadRecipies("data/recipies");
  602. // initialize chat
  603. chat = new Chat();
  604. // load quests
  605. questManager->loadQuests();
  606. }
  607. void Game::thread()
  608. {
  609. ZeitMesser waitForLock;
  610. ZeitMesser removeOldClients;
  611. ZeitMesser tickEntities;
  612. ZeitMesser worldUpdates;
  613. ZeitMesser clientReply;
  614. ZeitMesser removeOldChunks;
  615. ZeitMesser m;
  616. ZeitMesser total;
  617. total.messungStart();
  618. double tickTime = 0;
  619. double sleepTime = 0;
  620. int nextTimeSync = MAX_TICKS_PER_SECOND;
  621. while (!stop)
  622. {
  623. m.messungStart();
  624. ticker->nextTick();
  625. actionsCs.lock();
  626. while (actions.getEintragAnzahl() > 0)
  627. {
  628. actions.get(0)();
  629. actions.remove(0);
  630. }
  631. actionsCs.unlock();
  632. Array<int> removed;
  633. double waitTotal = 0;
  634. waitForLock.messungStart();
  635. cs.lock();
  636. waitForLock.messungEnde();
  637. waitTotal += waitForLock.getSekunden();
  638. removeOldClients.messungStart();
  639. int index = 0;
  640. nextTimeSync--;
  641. for (auto player : *clients)
  642. {
  643. if (!player->isOnline())
  644. {
  645. uiController->removePlayerDialogs(player->zEntity()->getId());
  646. chat->removeObserver(player->zEntity()->getId());
  647. chat->broadcastMessage(
  648. Framework::Text(player->zEntity()->getName())
  649. + " left the game.",
  650. Chat::CHANNEL_INFO);
  651. Datei pFile;
  652. pFile.setDatei(path + "/player/"
  653. + getPlayerId(player->zEntity()->getName()));
  654. pFile.erstellen();
  655. if (pFile.open(Datei::Style::schreiben))
  656. zEntityType(EntityTypeEnum::PLAYER)
  657. ->saveEntity(player->zEntity(), &pFile);
  658. pFile.close();
  659. removed.add(index, 0);
  660. Dimension* dim
  661. = zDimension(player->zEntity()->getDimensionId());
  662. dim->removeSubscriptions(player->zEntity());
  663. this->requestWorldUpdate(
  664. new EntityRemovedUpdate(player->zEntity()->getId(),
  665. player->zEntity()->getDimensionId(),
  666. player->zEntity()->getPosition()));
  667. }
  668. else
  669. {
  670. if (nextTimeSync <= 0 && player->zEntity())
  671. {
  672. Dimension* zDim
  673. = zDimension(player->zEntity()->getDimensionId());
  674. if (zDim)
  675. {
  676. NetworkMessage* msg = new NetworkMessage();
  677. msg->syncTime(zDim->getCurrentDayTime(),
  678. zDim->getNightDuration(),
  679. zDim->getNightTransitionDuration(),
  680. zDim->getDayDuration());
  681. player->sendResponse(msg);
  682. }
  683. }
  684. }
  685. index++;
  686. }
  687. if (nextTimeSync <= 0)
  688. {
  689. nextTimeSync = MAX_TICKS_PER_SECOND;
  690. }
  691. for (auto i : removed)
  692. clients->remove(i);
  693. removeOldClients.messungEnde();
  694. cs.unlock();
  695. tickEntities.messungStart();
  696. for (auto dim : *dimensions)
  697. dim->tickEntities();
  698. tickEntities.messungEnde();
  699. waitForLock.messungStart();
  700. cs.lock();
  701. waitForLock.messungEnde();
  702. waitTotal += waitForLock.getSekunden();
  703. worldUpdates.messungStart();
  704. while (updates->hat(0))
  705. {
  706. WorldUpdate* update = updates->z(0);
  707. for (auto client : *clients)
  708. client->sendWorldUpdate(
  709. dynamic_cast<WorldUpdate*>(update->getThis()));
  710. if (!zDimension(update->getAffectedDimension()))
  711. {
  712. Dimension* dim = typeRegistry->createDimension(
  713. update->getAffectedDimension());
  714. if (dim)
  715. addDimension(dim);
  716. else
  717. {
  718. std::cout << "ERROR: could not create dimension "
  719. << update->getAffectedDimension()
  720. << ". No Factory was provided.\n";
  721. }
  722. }
  723. if (zDimension(update->getAffectedDimension()))
  724. update->onUpdate(zDimension(update->getAffectedDimension()));
  725. updates->remove(0);
  726. }
  727. worldUpdates.messungEnde();
  728. cs.unlock();
  729. clientReply.messungStart();
  730. for (auto client : *clients)
  731. client->reply();
  732. clientReply.messungEnde();
  733. waitForLock.messungStart();
  734. cs.lock();
  735. waitForLock.messungEnde();
  736. waitTotal += waitForLock.getSekunden();
  737. removeOldChunks.messungStart();
  738. for (auto dim : *dimensions)
  739. dim->removeOldChunks();
  740. removeOldChunks.messungEnde();
  741. cs.unlock();
  742. m.messungEnde();
  743. double sec = m.getSekunden();
  744. tickCounter++;
  745. totalTickTime += sec;
  746. sleepTime += 1.0 / MAX_TICKS_PER_SECOND - tickTime;
  747. if (sleepTime > 0)
  748. {
  749. Sleep((int)(sleepTime * 1000));
  750. }
  751. total.messungEnde();
  752. total.messungStart();
  753. tickTime = total.getSekunden();
  754. totalTime += tickTime;
  755. if (totalTime >= 1)
  756. {
  757. averageTickTime = totalTickTime / tickCounter;
  758. ticksPerSecond = tickCounter;
  759. totalTickTime = 0;
  760. tickCounter = 0;
  761. totalTime = 0;
  762. std::cout << std::flush; // update info in console
  763. }
  764. else if (sec > 1)
  765. {
  766. std::cout << "WARNING: tick needed " << sec
  767. << " seconds. The game will run sower then normal.\n";
  768. std::cout << "waiting: " << waitTotal << "\nremoveOldClients: "
  769. << removeOldClients.getSekunden()
  770. << "\ntickEntities:" << tickEntities.getSekunden()
  771. << "\nworldUpdates: " << worldUpdates.getSekunden()
  772. << "\nclientReply: " << clientReply.getSekunden()
  773. << "\nremoveOldChunks:" << removeOldChunks.getSekunden()
  774. << "\n";
  775. }
  776. }
  777. save();
  778. generator->exitAndWait();
  779. loader->exitAndWait();
  780. ticker->exitAndWait();
  781. for (Dimension* dim : *dimensions)
  782. dim->requestStopAndWait();
  783. std::cout << "Game thread exited\n";
  784. }
  785. void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
  786. {
  787. char type;
  788. zRequest->lese(&type, 1);
  789. NetworkMessage* response = new NetworkMessage();
  790. switch (type)
  791. {
  792. case 1: // world
  793. {
  794. Dimension* dim = zDimension(zOrigin->zEntity()->getDimensionId());
  795. if (!dim)
  796. {
  797. dim = typeRegistry->createDimension(
  798. zOrigin->zEntity()->getDimensionId());
  799. if (!dim)
  800. {
  801. std::cout << "ERROR: could not create dimension "
  802. << zOrigin->zEntity()->getDimensionId()
  803. << ". No Factory was provided.\n";
  804. return;
  805. }
  806. addDimension(dim);
  807. }
  808. dim->api(zRequest, response, zOrigin->zEntity());
  809. break;
  810. }
  811. case 2: // player
  812. zOrigin->zEntity()->playerApi(zRequest, response);
  813. break;
  814. case 3: // entity
  815. {
  816. int id;
  817. zRequest->lese((char*)&id, 4);
  818. for (Dimension* dim : *dimensions)
  819. {
  820. Entity* entity = dim->zEntity(id);
  821. if (entity)
  822. {
  823. entity->api(zRequest, response, zOrigin->zEntity());
  824. break;
  825. }
  826. }
  827. break;
  828. }
  829. case 4:
  830. { // inventory
  831. bool isEntity;
  832. zRequest->lese((char*)&isEntity, 1);
  833. Inventory* target;
  834. if (isEntity)
  835. {
  836. int id;
  837. zRequest->lese((char*)&id, 4);
  838. target = zEntity(id);
  839. }
  840. else
  841. {
  842. int dim;
  843. Vec3<int> pos;
  844. zRequest->lese((char*)&dim, 4);
  845. zRequest->lese((char*)&pos.x, 4);
  846. zRequest->lese((char*)&pos.y, 4);
  847. zRequest->lese((char*)&pos.z, 4);
  848. target = zBlockAt(pos, dim);
  849. }
  850. if (target)
  851. target->inventoryApi(zRequest, response, zOrigin->zEntity());
  852. break;
  853. }
  854. case 5:
  855. { // crafting uiml request
  856. int id;
  857. zRequest->lese((char*)&id, 4);
  858. Text uiml = recipies.getCrafingUIML(id);
  859. Text dialogId = "crafting_";
  860. dialogId += id;
  861. uiController->addDialog(new UIDialog(dialogId,
  862. zOrigin->zEntity()->getId(),
  863. new Framework::XML::Element(uiml)));
  864. break;
  865. }
  866. case 6:
  867. { // chat message
  868. chat->chatApi(zRequest, zOrigin->zEntity(), response);
  869. break;
  870. }
  871. case 7: // other dimension
  872. {
  873. int dimensionId;
  874. zRequest->lese((char*)&dimensionId, 4);
  875. Dimension* dim = zDimension(dimensionId);
  876. if (dim)
  877. {
  878. dim->api(zRequest, response, zOrigin->zEntity());
  879. }
  880. break;
  881. }
  882. case 8: // ui message
  883. {
  884. uiController->api(zRequest, response, zOrigin->zEntity());
  885. break;
  886. }
  887. default:
  888. std::cout << "received unknown api request in game with type "
  889. << (int)type << "\n";
  890. }
  891. if (!response->isEmpty())
  892. {
  893. if (response->isBroadcast())
  894. broadcastMessage(response);
  895. else
  896. zOrigin->sendResponse(response);
  897. }
  898. else
  899. {
  900. response->release();
  901. }
  902. }
  903. void Game::updateLightning(int dimensionId, Vec3<int> location)
  904. {
  905. Dimension* zDim = zDimension(dimensionId);
  906. if (zDim) zDim->updateLightning(location);
  907. }
  908. void Game::updateLightningWithoutWait(int dimensionId, Vec3<int> location)
  909. {
  910. Dimension* zDim = zDimension(dimensionId);
  911. if (zDim) zDim->updateLightningWithoutWait(location);
  912. }
  913. void Game::broadcastMessage(NetworkMessage* response)
  914. {
  915. for (auto client : *clients)
  916. client->sendResponse(
  917. dynamic_cast<NetworkMessage*>(response->getThis()));
  918. response->release();
  919. }
  920. void Game::sendMessage(NetworkMessage* response, Entity* zTargetPlayer)
  921. {
  922. for (auto client : *clients)
  923. {
  924. if (client->zEntity()->getId() == zTargetPlayer->getId())
  925. {
  926. client->sendResponse(response);
  927. return;
  928. }
  929. }
  930. response->release();
  931. }
  932. bool Game::requestWorldUpdate(WorldUpdate* update)
  933. {
  934. cs.lock();
  935. updates->add(update);
  936. cs.unlock();
  937. return 1;
  938. }
  939. bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
  940. {
  941. if (playerRegister->checkSecret(name, secret))
  942. return 1;
  943. else
  944. {
  945. std::cout << "player " << name.getText()
  946. << " tryed to connect with an invalid secret.\n";
  947. return 0;
  948. }
  949. }
  950. bool Game::existsPlayer(Framework::Text name)
  951. {
  952. return playerRegister->hasPlayer(name);
  953. }
  954. Framework::Text Game::createPlayer(Framework::Text name)
  955. {
  956. return playerRegister->addPlayer(name);
  957. }
  958. GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
  959. {
  960. cs.lock();
  961. int id = playerRegister->getPlayerId(name);
  962. Datei pFile;
  963. pFile.setDatei(path + "/player/" + id);
  964. Player* player;
  965. bool isNew = 0;
  966. if (!pFile.existiert() || !pFile.open(Datei::Style::lesen))
  967. {
  968. player = (Player*)zEntityType(EntityTypeEnum::PLAYER)
  969. ->createEntityAt(
  970. Vec3<float>(0.5, 0.5, 0), DimensionEnum::OVERWORLD);
  971. player->setName(name);
  972. isNew = 1;
  973. }
  974. else
  975. {
  976. player
  977. = (Player*)zEntityType(EntityTypeEnum::PLAYER)->loadEntity(&pFile);
  978. pFile.close();
  979. }
  980. if (player->getId() >= nextEntityId)
  981. {
  982. nextEntityId = player->getId() + 1;
  983. }
  984. GameClient* gameClient = new GameClient(player, client);
  985. gameClient->sendTypes();
  986. clients->add(gameClient);
  987. if (!zDimension(player->getDimensionId()))
  988. {
  989. Dimension* dim
  990. = typeRegistry->createDimension(player->getDimensionId());
  991. if (!dim)
  992. {
  993. std::cout << "ERROR: could not create dimension "
  994. << (int)player->getDimensionId()
  995. << ". No Factory was provided.\n";
  996. return 0;
  997. }
  998. NetworkMessage* msg = new NetworkMessage();
  999. msg->syncTime(dim->getCurrentDayTime(),
  1000. dim->getNightDuration(),
  1001. dim->getNightTransitionDuration(),
  1002. dim->getDayDuration());
  1003. gameClient->sendResponse(msg);
  1004. this->addDimension(dim);
  1005. }
  1006. // subscribe the new player as an observer of the new chunk
  1007. Dimension* dim = zDimension(player->getDimensionId());
  1008. InMemoryBuffer* buffer = new InMemoryBuffer();
  1009. buffer->schreibe("\0", 1);
  1010. Punkt center = getChunkCenter(
  1011. (int)player->getPosition().x, (int)player->getPosition().y);
  1012. buffer->schreibe((char*)&center.x, 4);
  1013. buffer->schreibe((char*)&center.y, 4);
  1014. buffer->schreibe("\0", 1);
  1015. dim->api(buffer, 0, player);
  1016. buffer->release();
  1017. while (isNew
  1018. && !dim->zChunk(getChunkCenter(
  1019. (int)player->getPosition().x, (int)player->getPosition().y)))
  1020. {
  1021. cs.unlock();
  1022. Sleep(1000);
  1023. cs.lock();
  1024. }
  1025. if (isNew)
  1026. {
  1027. Either<Block*, int> b = BlockTypeEnum::AIR;
  1028. int h = WORLD_HEIGHT;
  1029. while (((b.isA() && (!(Block*)b || ((Block*)b)->isPassable()))
  1030. || (b.isB() && zBlockType(b)->zDefault()->isPassable()))
  1031. && h > 0)
  1032. b = zBlockAt({(int)player->getPosition().x,
  1033. (int)player->getPosition().y,
  1034. --h},
  1035. player->getDimensionId());
  1036. player->setPosition(
  1037. {player->getPosition().x, player->getPosition().y, (float)h + 1.f});
  1038. }
  1039. requestWorldUpdate(new AddEntityUpdate(player, player->getDimensionId()));
  1040. chat->addObserver(gameClient->zEntity()->getId());
  1041. chat->broadcastMessage(name + " joined the game.", Chat::CHANNEL_INFO);
  1042. cs.unlock();
  1043. return dynamic_cast<GameClient*>(gameClient->getThis());
  1044. }
  1045. bool Game::isChunkLoaded(int x, int y, int dimension) const
  1046. {
  1047. Dimension* dim = zDimension(dimension);
  1048. return (dim && dim->hasChunck(x, y));
  1049. }
  1050. bool Game::doesChunkExist(int x, int y, int dimension)
  1051. {
  1052. cs.lock();
  1053. bool result = isChunkLoaded(x, y, dimension)
  1054. || loader->existsChunk(x, y, dimension);
  1055. cs.unlock();
  1056. return result;
  1057. }
  1058. void Game::blockTargetChanged(Block* zBlock)
  1059. {
  1060. for (GameClient* client : *this->clients)
  1061. {
  1062. if (client->zEntity()->zTarget()
  1063. && client->zEntity()->zTarget()->isBlock(
  1064. zBlock->getPos(), NO_DIRECTION))
  1065. {
  1066. client->zEntity()->onTargetChange();
  1067. }
  1068. }
  1069. }
  1070. void Game::entityTargetChanged(Entity* zEntity)
  1071. {
  1072. for (GameClient* client : *this->clients)
  1073. {
  1074. if (client->zEntity()->zTarget()
  1075. && client->zEntity()->zTarget()->isEntity(zEntity->getId()))
  1076. {
  1077. client->zEntity()->onTargetChange();
  1078. }
  1079. }
  1080. }
  1081. void Game::spawnItem(
  1082. Framework::Vec3<float> location, int dimensionId, Item* stack)
  1083. {
  1084. spawnItem(location, dimensionId, new ItemStack(stack, 1));
  1085. }
  1086. void Game::spawnItem(
  1087. Framework::Vec3<float> location, int dimensionId, ItemStack* stack)
  1088. {
  1089. ItemEntity* itemEntity
  1090. = (ItemEntity*)zEntityType(EntityTypeEnum::ITEM)
  1091. ->createEntity(
  1092. location, dimensionId, Game::INSTANCE->getNextEntityId());
  1093. itemEntity->unsaveAddItem(stack, NO_DIRECTION, 0);
  1094. stack->release();
  1095. requestWorldUpdate(new AddEntityUpdate(itemEntity, dimensionId));
  1096. }
  1097. Framework::Either<Block*, int> Game::zBlockAt(
  1098. Framework::Vec3<int> location, int dimension) const
  1099. {
  1100. Dimension* dim = zDimension(dimension);
  1101. if (dim) return dim->zBlock(location);
  1102. return 0;
  1103. }
  1104. Block* Game::zRealBlockInstance(Framework::Vec3<int> location, int dimension)
  1105. {
  1106. Dimension* dim = zDimension(dimension);
  1107. if (dim) return dim->zRealBlockInstance(location);
  1108. return 0;
  1109. }
  1110. int Game::getBlockType(Framework::Vec3<int> location, int dimension)
  1111. {
  1112. Dimension* dim = zDimension(dimension);
  1113. if (dim) return dim->getBlockType(location);
  1114. return 0;
  1115. }
  1116. Dimension* Game::zDimension(int id) const
  1117. {
  1118. for (auto dim : *dimensions)
  1119. {
  1120. if (dim->getDimensionId() == id) return dim;
  1121. }
  1122. return 0;
  1123. }
  1124. Framework::Punkt Game::getChunkCenter(int x, int y)
  1125. {
  1126. return Punkt(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE
  1127. + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2,
  1128. ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE
  1129. + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2);
  1130. }
  1131. Area Game::getChunckArea(Punkt center) const
  1132. {
  1133. return {center.x - CHUNK_SIZE / 2,
  1134. center.y - CHUNK_SIZE / 2,
  1135. center.x + CHUNK_SIZE / 2 - 1,
  1136. center.y + CHUNK_SIZE / 2 - 1,
  1137. 0};
  1138. }
  1139. Framework::Text Game::getWorldDirectory() const
  1140. {
  1141. return path;
  1142. }
  1143. void Game::requestArea(Area area)
  1144. {
  1145. generator->requestGeneration(area);
  1146. loader->requestLoading(area);
  1147. }
  1148. void Game::save() const
  1149. {
  1150. questManager->saveQuests();
  1151. Datei d;
  1152. d.setDatei(path + "/eid");
  1153. d.open(Datei::Style::schreiben);
  1154. d.schreibe((char*)&nextEntityId, 4);
  1155. d.close();
  1156. playerRegister->save();
  1157. for (auto dim : *dimensions)
  1158. dim->save(path);
  1159. chat->save();
  1160. std::cout << "Game was saved\n";
  1161. }
  1162. void Game::requestStop()
  1163. {
  1164. stop = 1;
  1165. warteAufThread(1000000);
  1166. }
  1167. void Game::addDimension(Dimension* d)
  1168. {
  1169. dimensions->add(d);
  1170. }
  1171. int Game::getNextEntityId()
  1172. {
  1173. cs.lock();
  1174. int result = nextEntityId++;
  1175. cs.unlock();
  1176. return result;
  1177. }
  1178. WorldGenerator* Game::zGenerator() const
  1179. {
  1180. return generator;
  1181. }
  1182. Game* Game::INSTANCE = 0;
  1183. void Game::initialize(Framework::Text name, Framework::Text worldsDir)
  1184. {
  1185. if (!Game::INSTANCE)
  1186. {
  1187. Game::INSTANCE = new Game(name, worldsDir);
  1188. Game::INSTANCE->initialize();
  1189. }
  1190. }
  1191. Entity* Game::zEntity(int id, int dimensionId) const
  1192. {
  1193. Dimension* d = zDimension(dimensionId);
  1194. if (d) return d->zEntity(id);
  1195. return 0;
  1196. }
  1197. Entity* Game::zEntity(int id) const
  1198. {
  1199. for (Dimension* d : *dimensions)
  1200. {
  1201. Entity* e = d->zEntity(id);
  1202. if (e) return e;
  1203. }
  1204. // for new players that are currently loading
  1205. for (GameClient* client : *clients)
  1206. {
  1207. if (client->zEntity()->getId() == id)
  1208. {
  1209. return client->zEntity();
  1210. }
  1211. }
  1212. return 0;
  1213. }
  1214. Entity* Game::zNearestEntity(int dimensionId,
  1215. Framework::Vec3<float> pos,
  1216. std::function<bool(Entity*)> filter)
  1217. {
  1218. Dimension* d = zDimension(dimensionId);
  1219. if (!d) return 0;
  1220. return d->zNearestEntity(pos, filter);
  1221. }
  1222. const RecipieLoader& Game::getRecipies() const
  1223. {
  1224. return recipies;
  1225. }
  1226. void Game::doLater(std::function<void()> action)
  1227. {
  1228. actionsCs.lock();
  1229. actions.add(action);
  1230. actionsCs.unlock();
  1231. }
  1232. TickOrganizer* Game::zTickOrganizer() const
  1233. {
  1234. return ticker;
  1235. }
  1236. Chat* Game::zChat() const
  1237. {
  1238. return chat;
  1239. }
  1240. Player* Game::zPlayerByName(const char* name) const
  1241. {
  1242. for (GameClient* client : *clients)
  1243. {
  1244. if (strcmp(client->zEntity()->getName(), name) == 0)
  1245. {
  1246. return client->zEntity();
  1247. }
  1248. }
  1249. return 0;
  1250. }
  1251. TypeRegistry* Game::zTypeRegistry() const
  1252. {
  1253. return typeRegistry;
  1254. }
  1255. int Game::getPlayerId(const char* name) const
  1256. {
  1257. return playerRegister->getPlayerId(name);
  1258. }
  1259. QuestManager* Game::zQuestManager() const
  1260. {
  1261. return questManager;
  1262. }
  1263. UIController* Game::zUIController() const
  1264. {
  1265. return uiController;
  1266. }
  1267. double Game::getAverageTickTime() const
  1268. {
  1269. return averageTickTime;
  1270. }
  1271. int Game::getTicksPerSecond() const
  1272. {
  1273. return ticksPerSecond;
  1274. }
  1275. int Game::getPlayerCount() const
  1276. {
  1277. return clients->getEintragAnzahl();
  1278. }
  1279. int Game::getChunkCount() const
  1280. {
  1281. int result = 0;
  1282. for (Dimension* dim : *dimensions)
  1283. {
  1284. result += dim->getChunkCount();
  1285. }
  1286. return result;
  1287. }
  1288. const BlockType* Game::zBlockType(int id) const
  1289. {
  1290. return blockTypes[id];
  1291. }
  1292. const ItemType* Game::zItemType(int id) const
  1293. {
  1294. return itemTypes[id];
  1295. }
  1296. const EntityType* Game::zEntityType(int id) const
  1297. {
  1298. return entityTypes[id];
  1299. }
  1300. int Game::getBlockTypeId(const char* name) const
  1301. {
  1302. for (int i = 0; i < blockTypeCount; i++)
  1303. {
  1304. if (blockTypes[i]
  1305. && Framework::Text(blockTypes[i]->getName()).istGleich(name))
  1306. {
  1307. return i;
  1308. }
  1309. }
  1310. std::cout << "WARNING: no block type with name '" << name << "' found.\n";
  1311. return -1;
  1312. }
  1313. int Game::getItemTypeId(const char* name) const
  1314. {
  1315. for (int i = 0; i < itemTypeCount; i++)
  1316. {
  1317. if (itemTypes[i]
  1318. && Framework::Text(itemTypes[i]->getName()).istGleich(name))
  1319. {
  1320. return i;
  1321. }
  1322. }
  1323. std::cout << "WARNING: no item type with name '" << name << "' found.\n";
  1324. return -1;
  1325. }
  1326. int Game::getBlockTypeCount() const
  1327. {
  1328. return blockTypeCount;
  1329. }
  1330. int Game::getItemTypeCount() const
  1331. {
  1332. return itemTypeCount;
  1333. }
  1334. int Game::getEntityTypeCount() const
  1335. {
  1336. return entityTypeCount;
  1337. }
  1338. const MultiblockStructureType* Game::zMultiblockStructureType(int id) const
  1339. {
  1340. return multiblockStructureTypes[id];
  1341. }
  1342. int Game::getMultiblockStructureTypeCount() const
  1343. {
  1344. return multiblockStructureTypeCount;
  1345. }