PlantConfig.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. #include "PlantConfig.h"
  2. #include "Chunk.h"
  3. #include "Dimension.h"
  4. #include "Game.h"
  5. #include "JNoise.h"
  6. PlantConfig::PlantConfig()
  7. : Framework::ReferenceCounter(),
  8. condition(0),
  9. noise(0),
  10. noiseConfig(0),
  11. threshold(0.0),
  12. locations(0),
  13. plantBlockTypeName(""),
  14. plantblockTypeId(0),
  15. plantHeight(0),
  16. direction(PlantDirection::UP),
  17. orientationConfig(0)
  18. {}
  19. PlantConfig::~PlantConfig()
  20. {
  21. if (condition)
  22. {
  23. condition->release();
  24. }
  25. if (noise)
  26. {
  27. noise->release();
  28. }
  29. if (noiseConfig)
  30. {
  31. noiseConfig->release();
  32. }
  33. if (orientationConfig)
  34. {
  35. orientationConfig->release();
  36. }
  37. }
  38. void PlantConfig::initialize(JExpressionMemory* zMemory)
  39. {
  40. condition->compile(zMemory);
  41. if (noise)
  42. {
  43. noise->release();
  44. }
  45. noise = JNoise::parseNoise(noiseConfig, zMemory);
  46. plantblockTypeId = Game::INSTANCE->getBlockTypeId(plantBlockTypeName);
  47. }
  48. double PlantConfig::doesGeneratePlant(int x,
  49. int y,
  50. int z,
  51. int dimensionId,
  52. Chunk* zChunk,
  53. bool underground,
  54. bool underwater,
  55. bool surface,
  56. int seaFluidBlockTypeId)
  57. {
  58. if (underwater && !(locations & PlantLocation::UNDERWATER))
  59. {
  60. return 0.0;
  61. }
  62. if (surface && !(locations & PlantLocation::SURFACE))
  63. {
  64. return 0.0;
  65. }
  66. if (!underwater && underground && !(locations & PlantLocation::CAVE))
  67. {
  68. return 0.0;
  69. }
  70. if (!underwater && !underground && !surface
  71. && !(locations & PlantLocation::ABOVE_SURFACE))
  72. {
  73. return 0.0;
  74. }
  75. if (z + plantHeight > WORLD_HEIGHT)
  76. {
  77. return 0.0;
  78. }
  79. if (!condition->getValue())
  80. {
  81. return 0.0;
  82. }
  83. if (!noise)
  84. {
  85. return 0.0;
  86. }
  87. return noise->getNoise((double)x, (double)y, (double)z) - threshold;
  88. }
  89. void PlantConfig::generatePlantAt(
  90. int x, int y, int z, int dimensionId, Chunk* zChunk)
  91. {
  92. Direction frontDirection = orientationConfig
  93. ? orientationConfig->calculateOrientation(
  94. {x, y, z}, dimensionId, zChunk)
  95. : NO_DIRECTION;
  96. for (int i = 0; i < plantHeight; i++)
  97. {
  98. Framework::Vec3<int> pos(x, y, z);
  99. if (direction == PlantDirection::UP)
  100. {
  101. pos = {x, y, z + i};
  102. }
  103. else if (direction == PlantDirection::DOWN)
  104. {
  105. pos = {x, y, z - i};
  106. }
  107. int currentType = zChunk->getBlockTypeAtWC(pos.x, pos.y, pos.z);
  108. if (currentType != BlockTypeEnum::AIR
  109. && currentType != BlockTypeEnum::NO_BLOCK)
  110. {
  111. break;
  112. }
  113. if (orientationConfig
  114. && frontDirection
  115. != Game::INSTANCE->zBlockType(plantblockTypeId)
  116. ->getDefaultFrontDirection())
  117. {
  118. Block* block = Game::INSTANCE->zBlockType(plantblockTypeId)
  119. ->createBlockAt(pos, dimensionId, 0);
  120. block->setFrontDirection(frontDirection);
  121. zChunk->putBlockAt(Dimension::chunkCoordinates(pos), block);
  122. }
  123. else
  124. {
  125. zChunk->putBlockTypeAt(
  126. Dimension::chunkCoordinates(pos), plantblockTypeId);
  127. }
  128. }
  129. }
  130. void PlantConfig::setCondition(JBoolExpression* condition)
  131. {
  132. if (this->condition)
  133. {
  134. this->condition->release();
  135. }
  136. this->condition = condition;
  137. }
  138. JBoolExpression* PlantConfig::zCondition() const
  139. {
  140. return condition;
  141. }
  142. void PlantConfig::setNoiseConfig(Framework::JSON::JSONObject* noiseConfig)
  143. {
  144. if (this->noiseConfig)
  145. {
  146. this->noiseConfig->release();
  147. }
  148. this->noiseConfig = noiseConfig;
  149. }
  150. Framework::JSON::JSONObject* PlantConfig::zNoiseConfig() const
  151. {
  152. return noiseConfig;
  153. }
  154. void PlantConfig::setThreshold(double threshold)
  155. {
  156. this->threshold = threshold;
  157. }
  158. double PlantConfig::getThreshold() const
  159. {
  160. return threshold;
  161. }
  162. void PlantConfig::setLocations(int locations)
  163. {
  164. this->locations = locations;
  165. }
  166. int PlantConfig::getLocations() const
  167. {
  168. return locations;
  169. }
  170. void PlantConfig::setPlantBlockTypeName(Framework::Text name)
  171. {
  172. this->plantBlockTypeName = name;
  173. }
  174. Framework::Text PlantConfig::getPlantBlockTypeName() const
  175. {
  176. return plantBlockTypeName;
  177. }
  178. void PlantConfig::setPlantHeight(int height)
  179. {
  180. this->plantHeight = height;
  181. }
  182. int PlantConfig::getPlantHeight() const
  183. {
  184. return plantHeight;
  185. }
  186. void PlantConfig::setDirection(int direction)
  187. {
  188. this->direction = direction;
  189. }
  190. int PlantConfig::getDirection() const
  191. {
  192. return direction;
  193. }
  194. void PlantConfig::setOrientationConfig(OrientationConfig* orientationConfig)
  195. {
  196. if (this->orientationConfig)
  197. {
  198. this->orientationConfig->release();
  199. }
  200. this->orientationConfig = orientationConfig;
  201. }
  202. OrientationConfig* PlantConfig::zOrientationConfig() const
  203. {
  204. return orientationConfig;
  205. }
  206. PlantConfigFactory::PlantConfigFactory()
  207. : ObjectTypeFactory<PlantConfig>()
  208. {}
  209. PlantConfig* PlantConfigFactory::fromJson(
  210. Framework::JSON::JSONObject* zJson) const
  211. {
  212. PlantConfig* config = new PlantConfig();
  213. config->setCondition(
  214. Game::INSTANCE->zTypeRegistry()->fromJson<JBoolExpression>(
  215. zJson->zValue("condition")));
  216. config->setNoiseConfig(zJson->getValue("noise")->asObject());
  217. config->setThreshold(zJson->zValue("threshold")->asNumber()->getNumber());
  218. config->setLocations(0);
  219. Framework::JSON::JSONArray* zLocationsArray
  220. = zJson->zValue("locations")->asArray();
  221. for (int i = 0; i < zLocationsArray->getLength(); i++)
  222. {
  223. Framework::Text locationStr
  224. = zLocationsArray->zValue(i)->asString()->getString();
  225. if (locationStr.isEqual("CAVE"))
  226. {
  227. config->setLocations(config->getLocations() | PlantLocation::CAVE);
  228. }
  229. else if (locationStr.isEqual("UNDERWATER"))
  230. {
  231. config->setLocations(
  232. config->getLocations() | PlantLocation::UNDERWATER);
  233. }
  234. else if (locationStr.isEqual("SURFACE"))
  235. {
  236. config->setLocations(
  237. config->getLocations() | PlantLocation::SURFACE);
  238. }
  239. else if (locationStr.isEqual("ABOVE_SURFACE"))
  240. {
  241. config->setLocations(
  242. config->getLocations() | PlantLocation::ABOVE_SURFACE);
  243. }
  244. }
  245. config->setPlantBlockTypeName(
  246. zJson->zValue("plantBlock")->asString()->getString());
  247. config->setPlantHeight(
  248. (int)zJson->zValue("plantHeight")->asNumber()->getNumber());
  249. Framework::Text locationStr
  250. = zJson->zValue("direction")->asString()->getString();
  251. if (locationStr.isEqual("UP"))
  252. {
  253. config->setDirection(PlantDirection::UP);
  254. }
  255. else if (locationStr.isEqual("DOWN"))
  256. {
  257. config->setDirection(PlantDirection::DOWN);
  258. }
  259. if (zJson->hasValue("orientation"))
  260. {
  261. config->setOrientationConfig(
  262. Game::INSTANCE->zTypeRegistry()->fromJson<OrientationConfig>(
  263. zJson->zValue("orientation")));
  264. }
  265. return config;
  266. }
  267. Framework::JSON::JSONObject* PlantConfigFactory::toJsonObject(
  268. PlantConfig* zObject) const
  269. {
  270. Framework::JSON::JSONObject* zJson = new Framework::JSON::JSONObject();
  271. zJson->addValue("condition",
  272. Game::INSTANCE->zTypeRegistry()->toJson<JBoolExpression>(
  273. zObject->zCondition()));
  274. zJson->addValue("noise",
  275. dynamic_cast<Framework::JSON::JSONObject*>(
  276. zObject->zNoiseConfig()->getThis()));
  277. zJson->addValue(
  278. "threshold", new Framework::JSON::JSONNumber(zObject->getThreshold()));
  279. Framework::JSON::JSONArray* zLocationsArray
  280. = new Framework::JSON::JSONArray();
  281. int locations = zObject->getLocations();
  282. if (locations & PlantLocation::CAVE)
  283. {
  284. zLocationsArray->addValue(new Framework::JSON::JSONString("CAVE"));
  285. }
  286. if (locations & PlantLocation::UNDERWATER)
  287. {
  288. zLocationsArray->addValue(
  289. new Framework::JSON::JSONString("UNDERWATER"));
  290. }
  291. if (locations & PlantLocation::SURFACE)
  292. {
  293. zLocationsArray->addValue(new Framework::JSON::JSONString("SURFACE"));
  294. }
  295. if (locations & PlantLocation::ABOVE_SURFACE)
  296. {
  297. zLocationsArray->addValue(
  298. new Framework::JSON::JSONString("ABOVE_SURFACE"));
  299. }
  300. zJson->addValue("locations", zLocationsArray);
  301. zJson->addValue("plantBlock",
  302. new Framework::JSON::JSONString(zObject->getPlantBlockTypeName()));
  303. zJson->addValue("plantHeight",
  304. new Framework::JSON::JSONNumber(zObject->getPlantHeight()));
  305. if (zObject->getDirection() == PlantDirection::UP)
  306. {
  307. zJson->addValue("direction", new Framework::JSON::JSONString("UP"));
  308. }
  309. else if (zObject->getDirection() == PlantDirection::DOWN)
  310. {
  311. zJson->addValue("direction", new Framework::JSON::JSONString("DOWN"));
  312. }
  313. if (zObject->zOrientationConfig())
  314. {
  315. zJson->addValue("orientation",
  316. Game::INSTANCE->zTypeRegistry()->toJson<OrientationConfig>(
  317. zObject->zOrientationConfig()));
  318. }
  319. return zJson;
  320. }
  321. JSONObjectValidationBuilder* PlantConfigFactory::addToValidator(
  322. JSONObjectValidationBuilder* builder) const
  323. {
  324. return builder
  325. ->withRequiredAttribute("condition",
  326. Game::INSTANCE->zTypeRegistry()->getValidator<JBoolExpression>())
  327. ->withRequiredAttribute("noise", JNoise::getValidator(false))
  328. ->withRequiredNumber("threshold")
  329. ->withDefault(0.5)
  330. ->finishNumber()
  331. ->withRequiredArray("locations")
  332. ->addAcceptedStringInArray()
  333. ->whichIsOneOf({"CAVE", "UNDERWATER", "SURFACE", "ABOVE_SURFACE"})
  334. ->finishString()
  335. ->finishArray()
  336. ->withRequiredAttribute("plantBlock",
  337. Game::INSTANCE->zTypeRegistry()->getValidator<Framework::Text>(
  338. BlockTypeNameFactory::TYPE_ID))
  339. ->withRequiredNumber("plantHeight")
  340. ->whichIsGreaterOrEqual(1)
  341. ->finishNumber()
  342. ->withRequiredString("direction")
  343. ->whichIsOneOf({"UP", "DOWN"})
  344. ->withDefault("UP")
  345. ->finishString()
  346. ->withOptionalAttribute("orientation",
  347. Game::INSTANCE->zTypeRegistry()->getValidator<OrientationConfig>());
  348. }