Game.cpp 35 KB

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