Game.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416
  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. // initialize world generator and world loader
  591. int seed = 0;
  592. int index = 0;
  593. for (const char* n = name; *n; n++)
  594. seed += (int)pow((float)*n * 31, (float)++index);
  595. generator = new WorldGenerator(seed);
  596. loader = new WorldLoader();
  597. // load recipies
  598. recipies.loadRecipies("data/recipies");
  599. // initialize chat
  600. chat = new Chat();
  601. // load quests
  602. questManager->loadQuests();
  603. }
  604. void Game::thread()
  605. {
  606. ZeitMesser waitForLock;
  607. ZeitMesser removeOldClients;
  608. ZeitMesser tickEntities;
  609. ZeitMesser worldUpdates;
  610. ZeitMesser clientReply;
  611. ZeitMesser removeOldChunks;
  612. ZeitMesser m;
  613. ZeitMesser total;
  614. total.messungStart();
  615. double tickTime = 0;
  616. double sleepTime = 0;
  617. int nextTimeSync = MAX_TICKS_PER_SECOND;
  618. while (!stop)
  619. {
  620. m.messungStart();
  621. ticker->nextTick();
  622. actionsCs.lock();
  623. while (actions.getEintragAnzahl() > 0)
  624. {
  625. actions.get(0)();
  626. actions.remove(0);
  627. }
  628. actionsCs.unlock();
  629. Array<int> removed;
  630. double waitTotal = 0;
  631. waitForLock.messungStart();
  632. cs.lock();
  633. waitForLock.messungEnde();
  634. waitTotal += waitForLock.getSekunden();
  635. removeOldClients.messungStart();
  636. int index = 0;
  637. nextTimeSync--;
  638. for (auto player : *clients)
  639. {
  640. if (!player->isOnline())
  641. {
  642. uiController->removePlayerDialogs(player->zEntity()->getId());
  643. chat->removeObserver(player->zEntity()->getId());
  644. chat->broadcastMessage(
  645. Framework::Text(player->zEntity()->getName())
  646. + " left the game.",
  647. Chat::CHANNEL_INFO);
  648. Datei pFile;
  649. pFile.setDatei(path + "/player/"
  650. + getPlayerId(player->zEntity()->getName()));
  651. pFile.erstellen();
  652. if (pFile.open(Datei::Style::schreiben))
  653. zEntityType(EntityTypeEnum::PLAYER)
  654. ->saveEntity(player->zEntity(), &pFile);
  655. pFile.close();
  656. removed.add(index, 0);
  657. Dimension* dim
  658. = zDimension(player->zEntity()->getDimensionId());
  659. dim->removeSubscriptions(player->zEntity());
  660. this->requestWorldUpdate(
  661. new EntityRemovedUpdate(player->zEntity()->getId(),
  662. player->zEntity()->getDimensionId(),
  663. player->zEntity()->getPosition()));
  664. }
  665. else
  666. {
  667. if (nextTimeSync <= 0 && player->zEntity())
  668. {
  669. Dimension* zDim
  670. = zDimension(player->zEntity()->getDimensionId());
  671. if (zDim)
  672. {
  673. NetworkMessage* msg = new NetworkMessage();
  674. msg->syncTime(zDim->getCurrentDayTime(),
  675. zDim->getNightDuration(),
  676. zDim->getNightTransitionDuration(),
  677. zDim->getDayDuration());
  678. player->sendResponse(msg);
  679. }
  680. }
  681. }
  682. index++;
  683. }
  684. if (nextTimeSync <= 0)
  685. {
  686. nextTimeSync = MAX_TICKS_PER_SECOND;
  687. }
  688. for (auto i : removed)
  689. clients->remove(i);
  690. removeOldClients.messungEnde();
  691. cs.unlock();
  692. tickEntities.messungStart();
  693. for (auto dim : *dimensions)
  694. dim->tickEntities();
  695. tickEntities.messungEnde();
  696. waitForLock.messungStart();
  697. cs.lock();
  698. waitForLock.messungEnde();
  699. waitTotal += waitForLock.getSekunden();
  700. worldUpdates.messungStart();
  701. while (updates->hat(0))
  702. {
  703. WorldUpdate* update = updates->z(0);
  704. for (auto client : *clients)
  705. client->sendWorldUpdate(
  706. dynamic_cast<WorldUpdate*>(update->getThis()));
  707. if (!zDimension(update->getAffectedDimension()))
  708. {
  709. Dimension* dim = typeRegistry->createDimension(
  710. update->getAffectedDimension());
  711. if (dim)
  712. addDimension(dim);
  713. else
  714. {
  715. std::cout << "ERROR: could not create dimension "
  716. << update->getAffectedDimension()
  717. << ". No Factory was provided.\n";
  718. }
  719. }
  720. if (zDimension(update->getAffectedDimension()))
  721. update->onUpdate(zDimension(update->getAffectedDimension()));
  722. updates->remove(0);
  723. }
  724. worldUpdates.messungEnde();
  725. cs.unlock();
  726. clientReply.messungStart();
  727. for (auto client : *clients)
  728. client->reply();
  729. clientReply.messungEnde();
  730. waitForLock.messungStart();
  731. cs.lock();
  732. waitForLock.messungEnde();
  733. waitTotal += waitForLock.getSekunden();
  734. removeOldChunks.messungStart();
  735. for (auto dim : *dimensions)
  736. dim->removeOldChunks();
  737. removeOldChunks.messungEnde();
  738. cs.unlock();
  739. m.messungEnde();
  740. double sec = m.getSekunden();
  741. tickCounter++;
  742. totalTickTime += sec;
  743. sleepTime += 1.0 / MAX_TICKS_PER_SECOND - tickTime;
  744. if (sleepTime > 0)
  745. {
  746. Sleep((int)(sleepTime * 1000));
  747. }
  748. total.messungEnde();
  749. total.messungStart();
  750. tickTime = total.getSekunden();
  751. totalTime += tickTime;
  752. if (totalTime >= 1)
  753. {
  754. averageTickTime = totalTickTime / tickCounter;
  755. ticksPerSecond = tickCounter;
  756. totalTickTime = 0;
  757. tickCounter = 0;
  758. totalTime = 0;
  759. std::cout << std::flush; // update info in console
  760. }
  761. else if (sec > 1)
  762. {
  763. std::cout << "WARNING: tick needed " << sec
  764. << " seconds. The game will run sower then normal.\n";
  765. std::cout << "waiting: " << waitTotal << "\nremoveOldClients: "
  766. << removeOldClients.getSekunden()
  767. << "\ntickEntities:" << tickEntities.getSekunden()
  768. << "\nworldUpdates: " << worldUpdates.getSekunden()
  769. << "\nclientReply: " << clientReply.getSekunden()
  770. << "\nremoveOldChunks:" << removeOldChunks.getSekunden()
  771. << "\n";
  772. }
  773. }
  774. save();
  775. generator->exitAndWait();
  776. loader->exitAndWait();
  777. ticker->exitAndWait();
  778. for (Dimension* dim : *dimensions)
  779. dim->requestStopAndWait();
  780. std::cout << "Game thread exited\n";
  781. }
  782. void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
  783. {
  784. char type;
  785. zRequest->lese(&type, 1);
  786. NetworkMessage* response = new NetworkMessage();
  787. switch (type)
  788. {
  789. case 1: // world
  790. {
  791. Dimension* dim = zDimension(zOrigin->zEntity()->getDimensionId());
  792. if (!dim)
  793. {
  794. dim = typeRegistry->createDimension(
  795. zOrigin->zEntity()->getDimensionId());
  796. if (!dim)
  797. {
  798. std::cout << "ERROR: could not create dimension "
  799. << zOrigin->zEntity()->getDimensionId()
  800. << ". No Factory was provided.\n";
  801. return;
  802. }
  803. addDimension(dim);
  804. }
  805. dim->api(zRequest, response, zOrigin->zEntity());
  806. break;
  807. }
  808. case 2: // player
  809. zOrigin->zEntity()->playerApi(zRequest, response);
  810. break;
  811. case 3: // entity
  812. {
  813. int id;
  814. zRequest->lese((char*)&id, 4);
  815. for (Dimension* dim : *dimensions)
  816. {
  817. Entity* entity = dim->zEntity(id);
  818. if (entity)
  819. {
  820. entity->api(zRequest, response, zOrigin->zEntity());
  821. break;
  822. }
  823. }
  824. break;
  825. }
  826. case 4:
  827. { // inventory
  828. bool isEntity;
  829. zRequest->lese((char*)&isEntity, 1);
  830. Inventory* target;
  831. if (isEntity)
  832. {
  833. int id;
  834. zRequest->lese((char*)&id, 4);
  835. target = zEntity(id);
  836. }
  837. else
  838. {
  839. int dim;
  840. Vec3<int> pos;
  841. zRequest->lese((char*)&dim, 4);
  842. zRequest->lese((char*)&pos.x, 4);
  843. zRequest->lese((char*)&pos.y, 4);
  844. zRequest->lese((char*)&pos.z, 4);
  845. target = zBlockAt(pos, dim);
  846. }
  847. if (target)
  848. target->inventoryApi(zRequest, response, zOrigin->zEntity());
  849. break;
  850. }
  851. case 5:
  852. { // crafting uiml request
  853. int id;
  854. zRequest->lese((char*)&id, 4);
  855. Text uiml = recipies.getCrafingUIML(id);
  856. Text dialogId = "crafting_";
  857. dialogId += id;
  858. uiController->addDialog(new UIDialog(dialogId,
  859. zOrigin->zEntity()->getId(),
  860. new Framework::XML::Element(uiml)));
  861. break;
  862. }
  863. case 6:
  864. { // chat message
  865. chat->chatApi(zRequest, zOrigin->zEntity(), response);
  866. break;
  867. }
  868. case 7: // other dimension
  869. {
  870. int dimensionId;
  871. zRequest->lese((char*)&dimensionId, 4);
  872. Dimension* dim = zDimension(dimensionId);
  873. if (dim)
  874. {
  875. dim->api(zRequest, response, zOrigin->zEntity());
  876. }
  877. break;
  878. }
  879. case 8: // ui message
  880. {
  881. uiController->api(zRequest, response, zOrigin->zEntity());
  882. break;
  883. }
  884. default:
  885. std::cout << "received unknown api request in game with type "
  886. << (int)type << "\n";
  887. }
  888. if (!response->isEmpty())
  889. {
  890. if (response->isBroadcast())
  891. broadcastMessage(response);
  892. else
  893. zOrigin->sendResponse(response);
  894. }
  895. else
  896. {
  897. response->release();
  898. }
  899. }
  900. void Game::updateLightning(int dimensionId, Vec3<int> location)
  901. {
  902. Dimension* zDim = zDimension(dimensionId);
  903. if (zDim) zDim->updateLightning(location);
  904. }
  905. void Game::updateLightningWithoutWait(int dimensionId, Vec3<int> location)
  906. {
  907. Dimension* zDim = zDimension(dimensionId);
  908. if (zDim) zDim->updateLightningWithoutWait(location);
  909. }
  910. void Game::broadcastMessage(NetworkMessage* response)
  911. {
  912. for (auto client : *clients)
  913. client->sendResponse(
  914. dynamic_cast<NetworkMessage*>(response->getThis()));
  915. response->release();
  916. }
  917. void Game::sendMessage(NetworkMessage* response, Entity* zTargetPlayer)
  918. {
  919. for (auto client : *clients)
  920. {
  921. if (client->zEntity()->getId() == zTargetPlayer->getId())
  922. {
  923. client->sendResponse(response);
  924. return;
  925. }
  926. }
  927. response->release();
  928. }
  929. bool Game::requestWorldUpdate(WorldUpdate* update)
  930. {
  931. cs.lock();
  932. updates->add(update);
  933. cs.unlock();
  934. return 1;
  935. }
  936. bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
  937. {
  938. if (playerRegister->checkSecret(name, secret))
  939. return 1;
  940. else
  941. {
  942. std::cout << "player " << name.getText()
  943. << " tryed to connect with an invalid secret.\n";
  944. return 0;
  945. }
  946. }
  947. bool Game::existsPlayer(Framework::Text name)
  948. {
  949. return playerRegister->hasPlayer(name);
  950. }
  951. Framework::Text Game::createPlayer(Framework::Text name)
  952. {
  953. return playerRegister->addPlayer(name);
  954. }
  955. GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
  956. {
  957. cs.lock();
  958. int id = playerRegister->getPlayerId(name);
  959. Datei pFile;
  960. pFile.setDatei(path + "/player/" + id);
  961. Player* player;
  962. bool isNew = 0;
  963. if (!pFile.existiert() || !pFile.open(Datei::Style::lesen))
  964. {
  965. player = (Player*)zEntityType(EntityTypeEnum::PLAYER)
  966. ->createEntityAt(
  967. Vec3<float>(0.5, 0.5, 0), DimensionEnum::OVERWORLD);
  968. player->setName(name);
  969. isNew = 1;
  970. }
  971. else
  972. {
  973. player
  974. = (Player*)zEntityType(EntityTypeEnum::PLAYER)->loadEntity(&pFile);
  975. pFile.close();
  976. }
  977. if (player->getId() >= nextEntityId)
  978. {
  979. nextEntityId = player->getId() + 1;
  980. }
  981. GameClient* gameClient = new GameClient(player, client);
  982. gameClient->sendTypes();
  983. clients->add(gameClient);
  984. if (!zDimension(player->getDimensionId()))
  985. {
  986. Dimension* dim
  987. = typeRegistry->createDimension(player->getDimensionId());
  988. if (!dim)
  989. {
  990. std::cout << "ERROR: could not create dimension "
  991. << (int)player->getDimensionId()
  992. << ". No Factory was provided.\n";
  993. return 0;
  994. }
  995. NetworkMessage* msg = new NetworkMessage();
  996. msg->syncTime(dim->getCurrentDayTime(),
  997. dim->getNightDuration(),
  998. dim->getNightTransitionDuration(),
  999. dim->getDayDuration());
  1000. gameClient->sendResponse(msg);
  1001. this->addDimension(dim);
  1002. }
  1003. // subscribe the new player as an observer of the new chunk
  1004. Dimension* dim = zDimension(player->getDimensionId());
  1005. InMemoryBuffer* buffer = new InMemoryBuffer();
  1006. buffer->schreibe("\0", 1);
  1007. Punkt center = getChunkCenter(
  1008. (int)player->getPosition().x, (int)player->getPosition().y);
  1009. buffer->schreibe((char*)&center.x, 4);
  1010. buffer->schreibe((char*)&center.y, 4);
  1011. buffer->schreibe("\0", 1);
  1012. dim->api(buffer, 0, player);
  1013. buffer->release();
  1014. while (isNew
  1015. && !dim->zChunk(getChunkCenter(
  1016. (int)player->getPosition().x, (int)player->getPosition().y)))
  1017. {
  1018. cs.unlock();
  1019. Sleep(1000);
  1020. cs.lock();
  1021. }
  1022. if (isNew)
  1023. {
  1024. Either<Block*, int> b = BlockTypeEnum::AIR;
  1025. int h = WORLD_HEIGHT;
  1026. while (((b.isA() && (!(Block*)b || ((Block*)b)->isPassable()))
  1027. || (b.isB() && zBlockType(b)->zDefault()->isPassable()))
  1028. && h > 0)
  1029. b = zBlockAt({(int)player->getPosition().x,
  1030. (int)player->getPosition().y,
  1031. --h},
  1032. player->getDimensionId());
  1033. player->setPosition(
  1034. {player->getPosition().x, player->getPosition().y, (float)h + 1.f});
  1035. }
  1036. requestWorldUpdate(new AddEntityUpdate(player, player->getDimensionId()));
  1037. chat->addObserver(gameClient->zEntity()->getId());
  1038. chat->broadcastMessage(name + " joined the game.", Chat::CHANNEL_INFO);
  1039. cs.unlock();
  1040. return dynamic_cast<GameClient*>(gameClient->getThis());
  1041. }
  1042. bool Game::isChunkLoaded(int x, int y, int dimension) const
  1043. {
  1044. Dimension* dim = zDimension(dimension);
  1045. return (dim && dim->hasChunck(x, y));
  1046. }
  1047. bool Game::doesChunkExist(int x, int y, int dimension)
  1048. {
  1049. cs.lock();
  1050. bool result = isChunkLoaded(x, y, dimension)
  1051. || loader->existsChunk(x, y, dimension);
  1052. cs.unlock();
  1053. return result;
  1054. }
  1055. void Game::blockTargetChanged(Block* zBlock)
  1056. {
  1057. for (GameClient* client : *this->clients)
  1058. {
  1059. if (client->zEntity()->zTarget()
  1060. && client->zEntity()->zTarget()->isBlock(
  1061. zBlock->getPos(), NO_DIRECTION))
  1062. {
  1063. client->zEntity()->onTargetChange();
  1064. }
  1065. }
  1066. }
  1067. void Game::entityTargetChanged(Entity* zEntity)
  1068. {
  1069. for (GameClient* client : *this->clients)
  1070. {
  1071. if (client->zEntity()->zTarget()
  1072. && client->zEntity()->zTarget()->isEntity(zEntity->getId()))
  1073. {
  1074. client->zEntity()->onTargetChange();
  1075. }
  1076. }
  1077. }
  1078. void Game::spawnItem(
  1079. Framework::Vec3<float> location, int dimensionId, Item* stack)
  1080. {
  1081. spawnItem(location, dimensionId, new ItemStack(stack, 1));
  1082. }
  1083. void Game::spawnItem(
  1084. Framework::Vec3<float> location, int dimensionId, ItemStack* stack)
  1085. {
  1086. ItemEntity* itemEntity
  1087. = (ItemEntity*)zEntityType(EntityTypeEnum::ITEM)
  1088. ->createEntity(
  1089. location, dimensionId, Game::INSTANCE->getNextEntityId());
  1090. itemEntity->unsaveAddItem(stack, NO_DIRECTION, 0);
  1091. stack->release();
  1092. requestWorldUpdate(new AddEntityUpdate(itemEntity, dimensionId));
  1093. }
  1094. Framework::Either<Block*, int> Game::zBlockAt(
  1095. Framework::Vec3<int> location, int dimension) const
  1096. {
  1097. Dimension* dim = zDimension(dimension);
  1098. if (dim) return dim->zBlock(location);
  1099. return 0;
  1100. }
  1101. Block* Game::zRealBlockInstance(Framework::Vec3<int> location, int dimension)
  1102. {
  1103. Dimension* dim = zDimension(dimension);
  1104. if (dim) return dim->zRealBlockInstance(location);
  1105. return 0;
  1106. }
  1107. int Game::getBlockType(Framework::Vec3<int> location, int dimension)
  1108. {
  1109. Dimension* dim = zDimension(dimension);
  1110. if (dim) return dim->getBlockType(location);
  1111. return 0;
  1112. }
  1113. Dimension* Game::zDimension(int id) const
  1114. {
  1115. for (auto dim : *dimensions)
  1116. {
  1117. if (dim->getDimensionId() == id) return dim;
  1118. }
  1119. return 0;
  1120. }
  1121. Framework::Punkt Game::getChunkCenter(int x, int y)
  1122. {
  1123. return Punkt(((x < 0 ? x + 1 : x) / CHUNK_SIZE) * CHUNK_SIZE
  1124. + (x < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2,
  1125. ((y < 0 ? y + 1 : y) / CHUNK_SIZE) * CHUNK_SIZE
  1126. + (y < 0 ? -CHUNK_SIZE : CHUNK_SIZE) / 2);
  1127. }
  1128. Area Game::getChunckArea(Punkt center) const
  1129. {
  1130. return {center.x - CHUNK_SIZE / 2,
  1131. center.y - CHUNK_SIZE / 2,
  1132. center.x + CHUNK_SIZE / 2 - 1,
  1133. center.y + CHUNK_SIZE / 2 - 1,
  1134. 0};
  1135. }
  1136. Framework::Text Game::getWorldDirectory() const
  1137. {
  1138. return path;
  1139. }
  1140. void Game::requestArea(Area area)
  1141. {
  1142. generator->requestGeneration(area);
  1143. loader->requestLoading(area);
  1144. }
  1145. void Game::save() const
  1146. {
  1147. questManager->saveQuests();
  1148. Datei d;
  1149. d.setDatei(path + "/eid");
  1150. d.open(Datei::Style::schreiben);
  1151. d.schreibe((char*)&nextEntityId, 4);
  1152. d.close();
  1153. playerRegister->save();
  1154. for (auto dim : *dimensions)
  1155. dim->save(path);
  1156. chat->save();
  1157. std::cout << "Game was saved\n";
  1158. }
  1159. void Game::requestStop()
  1160. {
  1161. stop = 1;
  1162. warteAufThread(1000000);
  1163. }
  1164. void Game::addDimension(Dimension* d)
  1165. {
  1166. dimensions->add(d);
  1167. }
  1168. int Game::getNextEntityId()
  1169. {
  1170. cs.lock();
  1171. int result = nextEntityId++;
  1172. cs.unlock();
  1173. return result;
  1174. }
  1175. WorldGenerator* Game::zGenerator() const
  1176. {
  1177. return generator;
  1178. }
  1179. Game* Game::INSTANCE = 0;
  1180. void Game::initialize(Framework::Text name, Framework::Text worldsDir)
  1181. {
  1182. if (!Game::INSTANCE)
  1183. {
  1184. Game::INSTANCE = new Game(name, worldsDir);
  1185. Game::INSTANCE->initialize();
  1186. }
  1187. }
  1188. Entity* Game::zEntity(int id, int dimensionId) const
  1189. {
  1190. Dimension* d = zDimension(dimensionId);
  1191. if (d) return d->zEntity(id);
  1192. return 0;
  1193. }
  1194. Entity* Game::zEntity(int id) const
  1195. {
  1196. for (Dimension* d : *dimensions)
  1197. {
  1198. Entity* e = d->zEntity(id);
  1199. if (e) return e;
  1200. }
  1201. // for new players that are currently loading
  1202. for (GameClient* client : *clients)
  1203. {
  1204. if (client->zEntity()->getId() == id)
  1205. {
  1206. return client->zEntity();
  1207. }
  1208. }
  1209. return 0;
  1210. }
  1211. Entity* Game::zNearestEntity(int dimensionId,
  1212. Framework::Vec3<float> pos,
  1213. std::function<bool(Entity*)> filter)
  1214. {
  1215. Dimension* d = zDimension(dimensionId);
  1216. if (!d) return 0;
  1217. return d->zNearestEntity(pos, filter);
  1218. }
  1219. const RecipieLoader& Game::getRecipies() const
  1220. {
  1221. return recipies;
  1222. }
  1223. void Game::doLater(std::function<void()> action)
  1224. {
  1225. actionsCs.lock();
  1226. actions.add(action);
  1227. actionsCs.unlock();
  1228. }
  1229. TickOrganizer* Game::zTickOrganizer() const
  1230. {
  1231. return ticker;
  1232. }
  1233. Chat* Game::zChat() const
  1234. {
  1235. return chat;
  1236. }
  1237. Player* Game::zPlayerByName(const char* name) const
  1238. {
  1239. for (GameClient* client : *clients)
  1240. {
  1241. if (strcmp(client->zEntity()->getName(), name) == 0)
  1242. {
  1243. return client->zEntity();
  1244. }
  1245. }
  1246. return 0;
  1247. }
  1248. TypeRegistry* Game::zTypeRegistry() const
  1249. {
  1250. return typeRegistry;
  1251. }
  1252. int Game::getPlayerId(const char* name) const
  1253. {
  1254. return playerRegister->getPlayerId(name);
  1255. }
  1256. QuestManager* Game::zQuestManager() const
  1257. {
  1258. return questManager;
  1259. }
  1260. UIController* Game::zUIController() const
  1261. {
  1262. return uiController;
  1263. }
  1264. double Game::getAverageTickTime() const
  1265. {
  1266. return averageTickTime;
  1267. }
  1268. int Game::getTicksPerSecond() const
  1269. {
  1270. return ticksPerSecond;
  1271. }
  1272. int Game::getPlayerCount() const
  1273. {
  1274. return clients->getEintragAnzahl();
  1275. }
  1276. int Game::getChunkCount() const
  1277. {
  1278. int result = 0;
  1279. for (Dimension* dim : *dimensions)
  1280. {
  1281. result += dim->getChunkCount();
  1282. }
  1283. return result;
  1284. }
  1285. const BlockType* Game::zBlockType(int id) const
  1286. {
  1287. return blockTypes[id];
  1288. }
  1289. const ItemType* Game::zItemType(int id) const
  1290. {
  1291. return itemTypes[id];
  1292. }
  1293. const EntityType* Game::zEntityType(int id) const
  1294. {
  1295. return entityTypes[id];
  1296. }
  1297. int Game::getBlockTypeId(const char* name) const
  1298. {
  1299. for (int i = 0; i < blockTypeCount; i++)
  1300. {
  1301. if (blockTypes[i]
  1302. && Framework::Text(blockTypes[i]->getName()).istGleich(name))
  1303. {
  1304. return i;
  1305. }
  1306. }
  1307. std::cout << "WARNING: no block type with name '" << name << "' found.\n";
  1308. return -1;
  1309. }
  1310. int Game::getItemTypeId(const char* name) const
  1311. {
  1312. for (int i = 0; i < itemTypeCount; i++)
  1313. {
  1314. if (itemTypes[i]
  1315. && Framework::Text(itemTypes[i]->getName()).istGleich(name))
  1316. {
  1317. return i;
  1318. }
  1319. }
  1320. std::cout << "WARNING: no item type with name '" << name << "' found.\n";
  1321. return -1;
  1322. }
  1323. int Game::getBlockTypeCount() const
  1324. {
  1325. return blockTypeCount;
  1326. }
  1327. int Game::getItemTypeCount() const
  1328. {
  1329. return itemTypeCount;
  1330. }
  1331. int Game::getEntityTypeCount() const
  1332. {
  1333. return entityTypeCount;
  1334. }
  1335. const MultiblockStructureType* Game::zMultiblockStructureType(int id) const
  1336. {
  1337. return multiblockStructureTypes[id];
  1338. }
  1339. int Game::getMultiblockStructureTypeCount() const
  1340. {
  1341. return multiblockStructureTypeCount;
  1342. }