WorldGenerator.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include "WorldGenerator.h"
  2. #include <Betriebssystem.h>
  3. #include <functional>
  4. #include "Game.h"
  5. #include "NoiseInterpolator.h"
  6. #include "OverworldDimension.h"
  7. using namespace Framework;
  8. using namespace Framework::JSON;
  9. using namespace Framework::JSON::Validator;
  10. WorldGenerator::WorldGenerator(int seed)
  11. : Thread(),
  12. exit(0),
  13. seed(seed)
  14. {
  15. setName("World Generator");
  16. std::cout << "loading world generator configs. Changes at the config giles "
  17. "may lead to a sudden change in landscape.\n";
  18. JSONValidator* validator = buildConfigValidator();
  19. loadConfig("data/generator", validator);
  20. validator->release();
  21. addMissingDimensions();
  22. start();
  23. }
  24. WorldGenerator::~WorldGenerator() {}
  25. Framework::JSON::Validator::JSONValidator*
  26. WorldGenerator::buildConfigValidator()
  27. {
  28. JSONValidator* configValidator
  29. = JSONValidator::buildForArray()
  30. ->removeInvalidEntries()
  31. ->addAcceptedTypeInArray(Game::INSTANCE->zTypeRegistry()
  32. ->getDimensionGeneratorValidator())
  33. ->finishArray();
  34. Datei syntaxFile(new Text("data/syntax/generatorValidation.xml"));
  35. syntaxFile.erstellen();
  36. Text syntaxContent = configValidator->zConstraints()->toString();
  37. syntaxFile.open(Datei::Style::schreiben);
  38. syntaxFile.schreibe(syntaxContent, syntaxContent.getLength());
  39. syntaxFile.close();
  40. return configValidator;
  41. }
  42. void WorldGenerator::loadConfig(
  43. const char* path, Framework::JSON::Validator::JSONValidator* zValidator)
  44. {
  45. std::cout << "loading dimension configs from '" << path << "'" << std::endl;
  46. Datei file(new Text(path));
  47. if (file.istOrdner())
  48. {
  49. RCArray<Text>* fileNames = file.getDateiListe();
  50. if (fileNames)
  51. {
  52. for (Text* name : *fileNames)
  53. {
  54. loadConfig(Text(path) + "/" + *name, zValidator);
  55. }
  56. fileNames->release();
  57. }
  58. }
  59. else
  60. {
  61. JSONValue* json = loadJSONFromFile(path);
  62. if (!json)
  63. {
  64. std::cout << "ERROR: the file does not contain valid json\n";
  65. }
  66. else
  67. {
  68. Framework::RCArray<JSONValidationResult> invalidParts;
  69. JSONValue* valid = zValidator->getValidParts(json, &invalidParts);
  70. for (JSONValidationResult* invalidPart : invalidParts)
  71. {
  72. invalidPart->printInvalidInfo();
  73. }
  74. json->release();
  75. if (valid)
  76. {
  77. for (JSONValue* config : *valid->asArray())
  78. loadDimensionConfig(config);
  79. valid->release();
  80. }
  81. }
  82. }
  83. }
  84. void WorldGenerator::loadDimensionConfig(Framework::JSON::JSONValue* zConfig)
  85. {
  86. DimensionGenerator* generator
  87. = Game::INSTANCE->zTypeRegistry()->createDimensionGenerator(
  88. zConfig, seed);
  89. if (generator)
  90. {
  91. dimensionGenerators.add(generator);
  92. }
  93. else
  94. {
  95. std::cout << "ERROR: could not find dimension factory for config \n"
  96. << zConfig->toString() << "\n";
  97. }
  98. }
  99. void WorldGenerator::addMissingDimensions()
  100. {
  101. for (DimensionGeneratorFactory* factory : Game::INSTANCE->zTypeRegistry()->getDimensionGeneratorFactories())
  102. {
  103. bool found = 0;
  104. for (DimensionGenerator* generator : dimensionGenerators)
  105. {
  106. if (generator->getDimensionId() == factory->getDimensionId())
  107. {
  108. found = 1;
  109. break;
  110. }
  111. }
  112. if (!found)
  113. {
  114. std::cout << "WARNING: missing config for dimension '"
  115. << factory->getName() << "' with id "
  116. << factory->getDimensionId()
  117. << ". Default config will be used.";
  118. JSONValue* defaultConfig = factory->getDefaultConfig();
  119. Datei file(new Text(
  120. Text("data/generator/") + factory->getName() + ".json"));
  121. if (!file.existiert())
  122. {
  123. file.erstellen();
  124. file.open(Datei::Style::schreiben);
  125. Text conficContent
  126. = Text("[") + defaultConfig->toString() + "]";
  127. file.schreibe(conficContent, conficContent.getLength());
  128. file.close();
  129. std::cout << "Default config was written to '" << *file.zPfad()
  130. << "'\n";
  131. }
  132. loadDimensionConfig(defaultConfig);
  133. defaultConfig->release();
  134. }
  135. }
  136. }
  137. DimensionGenerator* WorldGenerator::zGenerator(int dimensionId)
  138. {
  139. for (DimensionGenerator* generator : dimensionGenerators)
  140. {
  141. if (generator->getDimensionId() == dimensionId) return generator;
  142. }
  143. return 0;
  144. }
  145. void WorldGenerator::thread()
  146. {
  147. while (!exit)
  148. {
  149. cs.lock();
  150. Area next;
  151. bool hasNext = 0;
  152. if (requestQueue.getEintragAnzahl() > 0)
  153. {
  154. next = requestQueue.get(0);
  155. requestQueue.remove(0);
  156. hasNext = 1;
  157. }
  158. cs.unlock();
  159. if (!hasNext)
  160. {
  161. Sleep(1000);
  162. continue;
  163. }
  164. Punkt start = Game::INSTANCE->getChunkCenter(next.startX, next.startY);
  165. Punkt end = Game::INSTANCE->getChunkCenter(next.endX, next.endY);
  166. int xDir = start.x > end.x ? -1 : 1;
  167. int yDir = start.y > end.y ? -1 : 1;
  168. for (int x = start.x; xDir < 0 ? x >= end.x : x <= end.x;
  169. x += CHUNK_SIZE * xDir)
  170. {
  171. for (int y = start.y; yDir < 0 ? y >= end.y : y <= end.y;
  172. y += CHUNK_SIZE * yDir)
  173. {
  174. if (!Game::INSTANCE->doesChunkExist(x, y, next.dimensionId))
  175. {
  176. Chunk* generatedChunk
  177. = zGenerator(next.dimensionId)->generateChunk(x, y);
  178. ZeitMesser zm;
  179. zm.messungStart();
  180. generatedChunk->initializeLightning();
  181. zm.messungEnde();
  182. std::cout << "light calculation: " << zm.getSekunden()
  183. << "\n";
  184. zm.messungStart();
  185. generatedChunk->removeUnusedBlocks();
  186. zm.messungEnde();
  187. std::cout << "unused block removal: " << zm.getSekunden()
  188. << "\n";
  189. zm.messungStart();
  190. Dimension* dim
  191. = Game::INSTANCE->zDimension(next.dimensionId);
  192. if (!dim)
  193. {
  194. dim = new Dimension(next.dimensionId);
  195. Game::INSTANCE->addDimension(dim);
  196. }
  197. dim->setChunk(generatedChunk, Punkt(x, y));
  198. zm.messungEnde();
  199. std::cout << "adding chunk to map: " << zm.getSekunden()
  200. << "\n";
  201. }
  202. }
  203. }
  204. }
  205. std::cout << "World Generator thread exited\n";
  206. }
  207. void WorldGenerator::requestGeneration(Area request)
  208. {
  209. cs.lock();
  210. requestQueue.add(request);
  211. cs.unlock();
  212. }
  213. void WorldGenerator::exitAndWait()
  214. {
  215. exit = 1;
  216. warteAufThread(10000);
  217. ende();
  218. }
  219. Framework::Either<Block*, int> WorldGenerator::generateSingleBlock(
  220. Framework::Vec3<int> location, int dimensionId)
  221. {
  222. return zGenerator(dimensionId)->generateBlock(location);
  223. }
  224. bool WorldGenerator::spawnStructure(Framework::Vec3<int> location,
  225. int dimensionId,
  226. std::function<bool(GeneratorTemplate* tmpl)> filter)
  227. {
  228. return zGenerator(dimensionId)->spawnStructure(location, filter);
  229. }