DimensionGenerator.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include "DimensionGenerator.h"
  2. #include <iostream>
  3. #include "Constants.h"
  4. #include "Game.h"
  5. #include "NoBlock.h"
  6. #include "Noise.h"
  7. #include "RandNoise.h"
  8. #include "WormCaveGenerator.h"
  9. DimensionGeneratorFactory::DimensionGeneratorFactory(
  10. Framework::Text name, int dimensionId)
  11. : ReferenceCounter(),
  12. name(name),
  13. dimensionId(dimensionId)
  14. {}
  15. Framework::Text DimensionGeneratorFactory::getName() const
  16. {
  17. return name;
  18. }
  19. int DimensionGeneratorFactory::getDimensionId() const
  20. {
  21. return dimensionId;
  22. }
  23. WorldHeightLayer::WorldHeightLayer(
  24. Framework::JSON::JSONValue* zConfig, JExpressionMemory* zMemory)
  25. : ReferenceCounter()
  26. {
  27. noise = JNoise::parseNoise(zConfig->asObject()->zValue("noise"), zMemory);
  28. name = zConfig->asObject()->zValue("name")->asString()->getString();
  29. value = JExpressionParser::parseFloatExpression(
  30. zConfig->asObject()->zValue("value"));
  31. zMemory->setNoise(name, dynamic_cast<Noise*>(noise->getThis()));
  32. }
  33. WorldHeightLayer::~WorldHeightLayer()
  34. {
  35. noise->release();
  36. value->release();
  37. }
  38. void WorldHeightLayer::calculateValue(JExpressionMemory* zMemory)
  39. {
  40. zMemory->setFloatVariable(name, value->getValue(zMemory));
  41. }
  42. Framework::JSON::Validator::JSONValidator* WorldHeightLayer::getValidator()
  43. {
  44. return JSON::Validator::JSONValidator::buildForObject()
  45. ->withRequiredString("name")
  46. ->finishString()
  47. ->withRequiredAttribute("noise", JNoise::getValidator(false))
  48. ->withRequiredAttribute("value", JExpressionParser::getFloatValidator())
  49. ->finishObject();
  50. }
  51. DimensionGenerator::DimensionGenerator(
  52. Framework::JSON::JSONValue* zConfig, int worldSeed, int dimensionId)
  53. : ReferenceCounter(),
  54. jExpressionMemory(new JExpressionMemory()),
  55. dimensionId(dimensionId)
  56. {
  57. jExpressionMemory->setFloatVariable("worldSeed", (float)worldSeed);
  58. JFloatExpression* expr = JExpressionParser::parseFloatExpression(
  59. zConfig->asObject()->zValue("dimensionSeed"));
  60. jExpressionMemory->setFloatVariable(
  61. "dimensionSeed", expr->getValue(jExpressionMemory));
  62. for (Framework::JSON::JSONValue* value :
  63. *zConfig->asObject()->zValue("heightLayers")->asArray())
  64. {
  65. heightLayers.add(new WorldHeightLayer(value, jExpressionMemory));
  66. }
  67. }
  68. DimensionGenerator::~DimensionGenerator()
  69. {
  70. jExpressionMemory->release();
  71. }
  72. JExpressionMemory* DimensionGenerator::zMemory() const
  73. {
  74. return jExpressionMemory;
  75. }
  76. void DimensionGenerator::calculateHeightLayers()
  77. {
  78. for (WorldHeightLayer* layer : heightLayers)
  79. {
  80. layer->calculateValue(jExpressionMemory);
  81. }
  82. }
  83. int DimensionGenerator::getDimensionId() const
  84. {
  85. return dimensionId;
  86. }
  87. BiomedCavedDimensionGenerator::BiomedCavedDimensionGenerator(
  88. Framework::JSON::JSONValue* zConfig, int worldSeed, int dimensionId)
  89. : DimensionGenerator(zConfig, worldSeed, dimensionId),
  90. caveGenerator(new WormCaveGenerator(75, 150, 1, 6, 0.1f, worldSeed - 1))
  91. {
  92. biomNoise = JNoise::parseNoise(
  93. zConfig->asObject()->zValue("biomNoise"), zMemory());
  94. bool first = 1;
  95. for (Framework::JSON::JSONValue* value :
  96. *zConfig->asObject()->zValue("bioms")->asArray())
  97. {
  98. BiomGenerator* gen = new BiomGenerator(value, zMemory());
  99. biomGenerators.add(gen);
  100. if (first)
  101. {
  102. minStructureOffset = gen->getMinStructureOffset();
  103. maxStructureOffset = gen->getMaxStructureOffset();
  104. first = 0;
  105. }
  106. else
  107. {
  108. Framework::Vec3<int> min = gen->getMinStructureOffset();
  109. Framework::Vec3<int> max = gen->getMaxStructureOffset();
  110. if (minStructureOffset.x > min.x) minStructureOffset.x = min.x;
  111. if (minStructureOffset.y > min.y) minStructureOffset.y = min.y;
  112. if (minStructureOffset.z > min.z) minStructureOffset.z = min.z;
  113. if (maxStructureOffset.x < max.x) maxStructureOffset.x = max.x;
  114. if (maxStructureOffset.y < max.y) maxStructureOffset.y = max.y;
  115. if (maxStructureOffset.z < max.z) maxStructureOffset.z = max.z;
  116. }
  117. }
  118. }
  119. BiomedCavedDimensionGenerator::~BiomedCavedDimensionGenerator()
  120. {
  121. biomNoise->release();
  122. caveGenerator->release();
  123. }
  124. BiomGenerator* BiomedCavedDimensionGenerator::zBiomGenerator()
  125. {
  126. for (BiomGenerator* generator : biomGenerators)
  127. {
  128. if (generator->isApplicable(zMemory())) return generator;
  129. }
  130. return 0;
  131. }
  132. Framework::RCArray<GeneratedStructure>*
  133. BiomedCavedDimensionGenerator::getGeneratedStructoresForArea(
  134. Framework::Vec3<int> minPos, Framework::Vec3<int> maxPos)
  135. {
  136. int minSearchX = minPos.x - maxStructureOffset.x;
  137. int minSearchY = minPos.y - maxStructureOffset.y;
  138. int minSearchZ = MAX(minPos.z - maxStructureOffset.z, 0);
  139. int maxSearchX = maxPos.x - minStructureOffset.x;
  140. int maxSearchY = maxPos.y - minStructureOffset.y;
  141. int maxSearchZ = MIN(maxPos.z - minStructureOffset.z, WORLD_HEIGHT - 1);
  142. Framework::RCArray<GeneratedStructure>* result
  143. = new Framework::RCArray<GeneratedStructure>();
  144. for (int x = minSearchX; x <= maxSearchX; x++)
  145. {
  146. for (int y = minSearchY; y <= maxSearchY; y++)
  147. {
  148. zMemory()->setFloatVariable("x", (float)x);
  149. zMemory()->setFloatVariable("y", (float)y);
  150. calculateHeightLayers();
  151. BiomGenerator* gen = zBiomGenerator();
  152. for (int z = minSearchZ; z <= maxSearchZ; z++)
  153. {
  154. zMemory()->setFloatVariable("z", (float)z);
  155. gen->generateStructures(x,
  156. y,
  157. z,
  158. getDimensionId(),
  159. zMemory(),
  160. minPos,
  161. maxPos,
  162. result);
  163. }
  164. }
  165. }
  166. return result;
  167. }
  168. Chunk* BiomedCavedDimensionGenerator::generateChunk(int centerX, int centerY)
  169. {
  170. zMemory()->lock();
  171. std::cout << "generating chunk " << centerX << ", " << centerY << "\n";
  172. double structureTime = 0;
  173. double structureTime2 = 0;
  174. double structureTime3 = 0;
  175. double caveTime = 0;
  176. double caveTime2 = 0;
  177. double blockGenTime = 0;
  178. double biomTime = 0;
  179. double layerTime = 0;
  180. ZeitMesser zm;
  181. ZeitMesser zmGlobal;
  182. zm.messungStart();
  183. zmGlobal.messungStart();
  184. Framework::RCArray<GeneratedStructure>* structures
  185. = getGeneratedStructoresForArea(
  186. Framework::Vec3<int>(
  187. centerX - CHUNK_SIZE / 2, centerY - CHUNK_SIZE / 2, 0),
  188. Framework::Vec3<int>(centerX + CHUNK_SIZE / 2,
  189. centerY + CHUNK_SIZE / 2,
  190. WORLD_HEIGHT - 1));
  191. zm.messungEnde();
  192. structureTime += zm.getSekunden();
  193. zm.messungStart();
  194. CaveChunkGenerator* caveGen
  195. = caveGenerator->getGeneratorForChunk(centerX, centerY);
  196. zm.messungEnde();
  197. caveTime += zm.getSekunden();
  198. Chunk* chunk = new Chunk(Framework::Punkt(centerX, centerY), getDimensionId());
  199. zMemory()->setCurrentChunk(dynamic_cast<Chunk*>(chunk->getThis()));
  200. for (int x = -CHUNK_SIZE / 2; x < CHUNK_SIZE / 2; x++)
  201. {
  202. for (int y = -CHUNK_SIZE / 2; y < CHUNK_SIZE / 2; y++)
  203. {
  204. zMemory()->setFloatVariable("x", (float)x + (float)centerX);
  205. zMemory()->setFloatVariable("y", (float)y + (float)centerY);
  206. // calculate height layers
  207. zm.messungStart();
  208. calculateHeightLayers();
  209. zm.messungEnde();
  210. layerTime += zm.getSekunden();
  211. // calculate biom
  212. zm.messungStart();
  213. BiomGenerator* biom = zBiomGenerator();
  214. zm.messungEnde();
  215. biomTime += zm.getSekunden();
  216. // generate blocks
  217. for (int z = 0; z < WORLD_HEIGHT; z++)
  218. {
  219. zMemory()->setFloatVariable(
  220. "z", (float)z);
  221. Framework::Either<Block*, int> generated = BlockTypeEnum::AIR;
  222. bool structureAffected = 0;
  223. // check if the block is inside of a structure
  224. zm.messungStart();
  225. for (auto structure : *structures)
  226. {
  227. if (structure->isBlockAffected(
  228. Framework::Vec3<int>(x + centerX, y + centerY, z)))
  229. {
  230. zm.messungEnde();
  231. structureTime2 += zm.getSekunden();
  232. zm.messungStart();
  233. generated = structure->generateBlockAt(
  234. Framework::Vec3<int>(x + centerX, y + centerY, z),
  235. getDimensionId());
  236. structureAffected = 1;
  237. zm.messungEnde();
  238. structureTime3 += zm.getSekunden();
  239. zm.messungStart();
  240. break;
  241. }
  242. }
  243. zm.messungEnde();
  244. structureTime2 += zm.getSekunden();
  245. if (!structureAffected)
  246. {
  247. // check if block is a cave block
  248. zm.messungStart();
  249. bool inCave
  250. = caveGen->isInCave(x + centerX, y + centerY, z);
  251. zm.messungEnde();
  252. caveTime2 += zm.getSekunden();
  253. if (!inCave)
  254. {
  255. // generate biom block
  256. zm.messungStart();
  257. generated = biom->generateBlock(x + centerX,
  258. y + centerY,
  259. z,
  260. getDimensionId(),
  261. zMemory(),
  262. chunk);
  263. zm.messungEnde();
  264. blockGenTime += zm.getSekunden();
  265. }
  266. }
  267. if (generated.isA())
  268. chunk->putBlockAt(
  269. Framework::Vec3<int>(
  270. x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z),
  271. generated);
  272. else
  273. chunk->putBlockTypeAt(
  274. Framework::Vec3<int>(
  275. x + CHUNK_SIZE / 2, y + CHUNK_SIZE / 2, z),
  276. generated);
  277. }
  278. }
  279. }
  280. caveGen->release();
  281. structures->release();
  282. zmGlobal.messungEnde();
  283. std::cout << "structureGenerationTime: " << structureTime << "\n";
  284. std::cout << "structure.isBlockAffected: " << structureTime2 << "\n";
  285. std::cout << "structure.generateBlockAt: " << structureTime3 << "\n";
  286. std::cout << "caveGenerationTime: " << caveTime << "\n";
  287. std::cout << "caveEvaluationTime: " << caveTime2 << "\n";
  288. std::cout << "blockGenTime: " << blockGenTime << "\n";
  289. std::cout << "biomTime: " << biomTime << "\n";
  290. std::cout << "layerTime: " << layerTime << "\n";
  291. std::cout << "totalTime: " << zmGlobal.getSekunden() << "\n";
  292. zMemory()->unlock();
  293. return chunk;
  294. }
  295. Framework::Either<Block*, int> BiomedCavedDimensionGenerator::generateBlock(
  296. Framework::Vec3<int> location)
  297. {
  298. Chunk* zChunk
  299. = Game::INSTANCE->zDimension(getDimensionId())
  300. ->zChunk(Game::INSTANCE->getChunkCenter(location.x, location.y));
  301. if (!zChunk)
  302. {
  303. return BlockTypeEnum::NO_BLOCK;
  304. }
  305. zMemory()->lock();
  306. zMemory()->setCurrentChunk(dynamic_cast<Chunk*>(zChunk->getThis()));
  307. Framework::RCArray<GeneratedStructure>* structures
  308. = getGeneratedStructoresForArea(location, location);
  309. zMemory()->setFloatVariable("x", (float)location.x);
  310. zMemory()->setFloatVariable("y", (float)location.y);
  311. calculateHeightLayers();
  312. BiomGenerator* biom = zBiomGenerator();
  313. zMemory()->setFloatVariable("z", (float)location.z);
  314. for (auto structure : *structures)
  315. {
  316. if (structure->isBlockAffected(location))
  317. {
  318. auto generated = structure->generateBlockAt(location, getDimensionId());
  319. structures->release();
  320. zMemory()->unlock();
  321. return generated;
  322. }
  323. }
  324. structures->release();
  325. Punkt chunkCenter = Game::getChunkCenter(location.x, location.y);
  326. CaveChunkGenerator* caveGen
  327. = caveGenerator->getGeneratorForChunk(chunkCenter.x, chunkCenter.y);
  328. if (caveGen->isInCave(location.x, location.y, location.z))
  329. {
  330. caveGen->release();
  331. zMemory()->unlock();
  332. return BlockTypeEnum::AIR;
  333. }
  334. caveGen->release();
  335. auto generated = biom->generateBlock(location.x,
  336. location.y,
  337. location.z,
  338. getDimensionId(),
  339. zMemory(),
  340. zChunk);
  341. zMemory()->unlock();
  342. return generated;
  343. }
  344. bool BiomedCavedDimensionGenerator::spawnStructure(
  345. Framework::Vec3<int> location,
  346. std::function<bool(GeneratorTemplate* tmpl)> filter)
  347. {
  348. zMemory()->lock();
  349. zMemory()->setFloatVariable("x", (float)location.x);
  350. zMemory()->setFloatVariable("y", (float)location.y);
  351. BiomGenerator* biom = zBiomGenerator();
  352. zMemory()->unlock();
  353. for (StructureTemplateCollection *tc : biom->getTemplates())
  354. {
  355. for (GeneratorTemplate* t : tc->getStructures())
  356. {
  357. if (filter(t))
  358. {
  359. RandNoise noise((int)time(0));
  360. GeneratedStructure* genStr
  361. = t->generateAt(location, &noise, getDimensionId());
  362. if (genStr)
  363. {
  364. int minSearchX = location.x + t->getMinAffectedOffset().x;
  365. int minSearchY = location.y + t->getMinAffectedOffset().y;
  366. int minSearchZ
  367. = MAX(location.z + t->getMinAffectedOffset().z, 0);
  368. int maxSearchX = location.x + t->getMaxAffectedOffset().x;
  369. int maxSearchY = location.y + t->getMaxAffectedOffset().y;
  370. int maxSearchZ
  371. = MIN(location.z + t->getMaxAffectedOffset().z,
  372. WORLD_HEIGHT - 1);
  373. for (int x = minSearchX; x <= maxSearchX; x++)
  374. {
  375. for (int y = minSearchY; y <= maxSearchY; y++)
  376. {
  377. for (int z = minSearchZ; z <= maxSearchZ; z++)
  378. {
  379. if (genStr->isBlockAffected(
  380. Framework::Vec3<int>(x, y, z)))
  381. {
  382. auto gen = genStr->generateBlockAt(
  383. Framework::Vec3<int>(x, y, z),
  384. getDimensionId());
  385. Game::INSTANCE->zDimension(getDimensionId())
  386. ->placeBlock(
  387. Framework::Vec3<int>(x, y, z), gen);
  388. }
  389. }
  390. }
  391. }
  392. genStr->release();
  393. zMemory()->unlock();
  394. return 1;
  395. }
  396. }
  397. }
  398. }
  399. return 0;
  400. }