JsonExpression.cpp 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782
  1. #include "JsonExpression.h"
  2. #include "Chunk.h"
  3. #include "Game.h"
  4. JExpressionMemory::JExpressionMemory()
  5. : ReferenceCounter(),
  6. currentChunk(0)
  7. {}
  8. JExpressionMemory::~JExpressionMemory()
  9. {
  10. if (currentChunk) currentChunk->release();
  11. }
  12. void JExpressionMemory::lock()
  13. {
  14. cs.lock();
  15. }
  16. void JExpressionMemory::unlock()
  17. {
  18. cs.unlock();
  19. }
  20. Noise* JExpressionMemory::zNoiseP(Framework::Text name)
  21. {
  22. return noises.z(name, name.getLength());
  23. }
  24. void JExpressionMemory::setNoise(Framework::Text name, Noise* noise)
  25. {
  26. noises.set(name, name.getLength(), noise);
  27. }
  28. void JExpressionMemory::setCurrentChunk(Chunk* chunk)
  29. {
  30. if (currentChunk) currentChunk->release();
  31. currentChunk = chunk;
  32. }
  33. float* JExpressionMemory::getFloatVariableP(const Framework::Text& name)
  34. {
  35. if (!floatVariables.contains(name, name.getLength()))
  36. {
  37. floatVariables.set(name, name.getLength(), 0.f);
  38. }
  39. return floatVariables.getP(name, name.getLength());
  40. }
  41. bool* JExpressionMemory::getBoolVariableP(const Framework::Text& name)
  42. {
  43. if (!boolVariables.contains(name, name.getLength()))
  44. {
  45. boolVariables.set(name, name.getLength(), 0);
  46. }
  47. return boolVariables.getP(name, name.getLength());
  48. }
  49. Chunk** JExpressionMemory::zzCurrentChunk()
  50. {
  51. return &currentChunk;
  52. }
  53. JFloatExpression::JFloatExpression()
  54. : ReferenceCounter(),
  55. compiled(0)
  56. {}
  57. float JFloatExpression::getValue()
  58. {
  59. return compiled();
  60. }
  61. FloatFunc JFloatExpression::compile(JExpressionMemory* zMemory)
  62. {
  63. if (compiled)
  64. {
  65. if (zMemory != memory)
  66. {
  67. throw "Cannot compile the same expression for different memories";
  68. }
  69. return compiled;
  70. }
  71. memory = zMemory;
  72. return compiled = buildAssembly(zMemory).compileToFunction<FloatFunc>();
  73. }
  74. JBoolExpression::JBoolExpression()
  75. : ReferenceCounter(),
  76. compiled(0)
  77. {}
  78. bool JBoolExpression::getValue()
  79. {
  80. return compiled();
  81. }
  82. BoolFunc JBoolExpression::compile(JExpressionMemory* zMemory)
  83. {
  84. if (compiled)
  85. {
  86. if (zMemory != memory)
  87. {
  88. throw "Cannot compile the same expression for different "
  89. "memories";
  90. }
  91. return compiled;
  92. }
  93. memory = zMemory;
  94. return compiled = buildAssembly(zMemory).compileToFunction<BoolFunc>();
  95. }
  96. JVariableFloatExpression::JVariableFloatExpression()
  97. : JFloatExpression()
  98. {}
  99. Framework::Assembly::AssemblyBlock& JVariableFloatExpression::buildAssembly(
  100. JExpressionMemory* zMemory)
  101. {
  102. codeBlock.addLoadValue(
  103. zMemory->getFloatVariableP(name), Framework::Assembly::MM0);
  104. return codeBlock;
  105. }
  106. void JVariableFloatExpression::setName(Framework::Text name)
  107. {
  108. this->name = name;
  109. }
  110. Framework::Text JVariableFloatExpression::getName() const
  111. {
  112. return name;
  113. }
  114. JVariableFloatExpressionFactory::JVariableFloatExpressionFactory()
  115. : SubTypeFactory()
  116. {}
  117. JVariableFloatExpression* JVariableFloatExpressionFactory::fromJson(
  118. Framework::JSON::JSONObject* zJson) const
  119. {
  120. JVariableFloatExpression* result = new JVariableFloatExpression();
  121. result->setName(zJson->zValue("name")->asString()->getString());
  122. return result;
  123. }
  124. Framework::JSON::JSONObject* JVariableFloatExpressionFactory::toJsonObject(
  125. JVariableFloatExpression* zObject) const
  126. {
  127. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  128. result->addValue(
  129. "name", new Framework::JSON::JSONString(zObject->getName()));
  130. return result;
  131. }
  132. JSONObjectValidationBuilder* JVariableFloatExpressionFactory::addToValidator(
  133. JSONObjectValidationBuilder* builder) const
  134. {
  135. return builder->withRequiredString("name")->finishString();
  136. }
  137. const char* JVariableFloatExpressionFactory::getTypeToken() const
  138. {
  139. return "variable";
  140. }
  141. JVariableBoolExpression::JVariableBoolExpression()
  142. : JBoolExpression()
  143. {}
  144. Framework::Assembly::AssemblyBlock& JVariableBoolExpression::buildAssembly(
  145. JExpressionMemory* zMemory)
  146. {
  147. codeBlock.addLoadValue(
  148. (char*)zMemory->getBoolVariableP(name), Framework::Assembly::RAX);
  149. return codeBlock;
  150. }
  151. void JVariableBoolExpression::setName(Framework::Text name)
  152. {
  153. this->name = name;
  154. }
  155. Framework::Text JVariableBoolExpression::getName() const
  156. {
  157. return name;
  158. }
  159. JVariableBoolExpressionFactory::JVariableBoolExpressionFactory()
  160. : SubTypeFactory()
  161. {}
  162. JVariableBoolExpression* JVariableBoolExpressionFactory::fromJson(
  163. Framework::JSON::JSONObject* zJson) const
  164. {
  165. JVariableBoolExpression* result = new JVariableBoolExpression();
  166. result->setName(zJson->zValue("name")->asString()->getString());
  167. return result;
  168. }
  169. Framework::JSON::JSONObject* JVariableBoolExpressionFactory::toJsonObject(
  170. JVariableBoolExpression* zObject) const
  171. {
  172. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  173. result->addValue(
  174. "name", new Framework::JSON::JSONString(zObject->getName()));
  175. return result;
  176. }
  177. JSONObjectValidationBuilder* JVariableBoolExpressionFactory::addToValidator(
  178. JSONObjectValidationBuilder* builder) const
  179. {
  180. return builder->withRequiredString("name")->finishString();
  181. }
  182. const char* JVariableBoolExpressionFactory::getTypeToken() const
  183. {
  184. return "variable";
  185. }
  186. JConstantFloatExpression::JConstantFloatExpression()
  187. : JFloatExpression(),
  188. value(0)
  189. {}
  190. Framework::Assembly::AssemblyBlock& JConstantFloatExpression::buildAssembly(
  191. JExpressionMemory* zMemory)
  192. {
  193. codeBlock.addLoadValue(&value, Framework::Assembly::MM0);
  194. return codeBlock;
  195. }
  196. void JConstantFloatExpression::setValue(float value)
  197. {
  198. this->value = value;
  199. }
  200. float JConstantFloatExpression::getValue() const
  201. {
  202. return value;
  203. }
  204. JConstantFloatExpressionFactory::JConstantFloatExpressionFactory()
  205. : SubTypeFactory()
  206. {}
  207. JConstantFloatExpression* JConstantFloatExpressionFactory::fromJson(
  208. Framework::JSON::JSONObject* zJson) const
  209. {
  210. JConstantFloatExpression* result = new JConstantFloatExpression();
  211. result->setValue((float)zJson->zValue("value")->asNumber()->getNumber());
  212. return result;
  213. }
  214. Framework::JSON::JSONObject* JConstantFloatExpressionFactory::toJsonObject(
  215. JConstantFloatExpression* zObject) const
  216. {
  217. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  218. result->addValue(
  219. "value", new Framework::JSON::JSONNumber(zObject->getValue()));
  220. return result;
  221. }
  222. JSONObjectValidationBuilder* JConstantFloatExpressionFactory::addToValidator(
  223. JSONObjectValidationBuilder* builder) const
  224. {
  225. return builder->withRequiredNumber("value")->finishNumber();
  226. }
  227. const char* JConstantFloatExpressionFactory::getTypeToken() const
  228. {
  229. return "constant";
  230. }
  231. JConstantBoolExpression::JConstantBoolExpression()
  232. : JBoolExpression()
  233. {}
  234. Framework::Assembly::AssemblyBlock& JConstantBoolExpression::buildAssembly(
  235. JExpressionMemory* zMemory)
  236. {
  237. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)(value ? 1 : 0));
  238. return codeBlock;
  239. }
  240. void JConstantBoolExpression::setValue(bool value)
  241. {
  242. this->value = value;
  243. }
  244. bool JConstantBoolExpression::getValue() const
  245. {
  246. return value;
  247. }
  248. JConstantBoolExpressionFactory::JConstantBoolExpressionFactory()
  249. : SubTypeFactory()
  250. {}
  251. JConstantBoolExpression* JConstantBoolExpressionFactory::fromJson(
  252. Framework::JSON::JSONObject* zJson) const
  253. {
  254. JConstantBoolExpression* result = new JConstantBoolExpression();
  255. result->setValue(zJson->zValue("value")->asBool()->getBool());
  256. return result;
  257. }
  258. Framework::JSON::JSONObject* JConstantBoolExpressionFactory::toJsonObject(
  259. JConstantBoolExpression* zObject) const
  260. {
  261. Framework::JSON::JSONObject* zResult = new Framework::JSON::JSONObject();
  262. zResult->addValue(
  263. "value", new Framework::JSON::JSONBool(zObject->getValue()));
  264. return zResult;
  265. }
  266. JSONObjectValidationBuilder* JConstantBoolExpressionFactory::addToValidator(
  267. JSONObjectValidationBuilder* builder) const
  268. {
  269. return builder->withRequiredBool("value")->finishBool();
  270. }
  271. const char* JConstantBoolExpressionFactory::getTypeToken() const
  272. {
  273. return "constant";
  274. }
  275. JNoiseFloatExpression::JNoiseFloatExpression()
  276. : JFloatExpression(),
  277. x(0),
  278. y(0),
  279. z(0)
  280. {}
  281. JNoiseFloatExpression::~JNoiseFloatExpression()
  282. {
  283. if (x) x->release();
  284. if (y) y->release();
  285. if (z) z->release();
  286. }
  287. Framework::Assembly::AssemblyBlock& JNoiseFloatExpression::buildAssembly(
  288. JExpressionMemory* zMemory)
  289. {
  290. Noise* noise = zMemory->zNoiseP(name);
  291. if (!noise)
  292. {
  293. Framework::Logging::error() << "no noise with name '" << name.getText()
  294. << "' found, behavior is undefined\n";
  295. return codeBlock;
  296. }
  297. Framework::Assembly::AssemblyBlock& xBlock = x->buildAssembly(zMemory);
  298. Framework::Assembly::AssemblyBlock& yBlock = y->buildAssembly(zMemory);
  299. Framework::Assembly::AssemblyBlock& zBlock = z->buildAssembly(zMemory);
  300. Framework::Assembly::FPRegister xTarget = Framework::Assembly::MM0;
  301. if (xBlock.isReplacementPossible(
  302. Framework::Assembly::MM0, Framework::Assembly::MM1))
  303. {
  304. xBlock.replaceRegister(
  305. Framework::Assembly::MM0, Framework::Assembly::MM1);
  306. xTarget = Framework::Assembly::MM1;
  307. }
  308. Framework::Assembly::FPRegister yTarget = Framework::Assembly::MM0;
  309. if (yBlock.isReplacementPossible(
  310. Framework::Assembly::MM0, Framework::Assembly::MM2))
  311. {
  312. yBlock.replaceRegister(
  313. Framework::Assembly::MM0, Framework::Assembly::MM2);
  314. yTarget = Framework::Assembly::MM2;
  315. }
  316. Framework::Assembly::FPRegister zTarget = Framework::Assembly::MM0;
  317. if (zBlock.isReplacementPossible(
  318. Framework::Assembly::MM0, Framework::Assembly::MM3))
  319. {
  320. zBlock.replaceRegister(
  321. Framework::Assembly::MM0, Framework::Assembly::MM3);
  322. zTarget = Framework::Assembly::MM3;
  323. }
  324. codeBlock.addBlock(&zBlock, {}, {}, {}, 0, &zTarget);
  325. if (zTarget != Framework::Assembly::MM3)
  326. {
  327. codeBlock.addMoveValue(Framework::Assembly::MM3,
  328. zTarget,
  329. Framework::Assembly::SINGLE_FLOAT,
  330. Framework::Assembly::X);
  331. }
  332. codeBlock.addBlock(&yBlock,
  333. {},
  334. {Framework::Assembly::MM3},
  335. {Framework::Assembly::SINGLE_FLOAT},
  336. 0,
  337. &yTarget);
  338. if (yTarget != Framework::Assembly::MM2)
  339. {
  340. codeBlock.addMoveValue(Framework::Assembly::MM2,
  341. yTarget,
  342. Framework::Assembly::SINGLE_FLOAT,
  343. Framework::Assembly::X);
  344. }
  345. codeBlock.addBlock(&xBlock,
  346. {},
  347. {Framework::Assembly::MM2, Framework::Assembly::MM3},
  348. {Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::SINGLE_FLOAT},
  349. 0,
  350. &xTarget);
  351. if (xTarget != Framework::Assembly::MM1)
  352. {
  353. codeBlock.addMoveValue(Framework::Assembly::MM1,
  354. xTarget,
  355. Framework::Assembly::SINGLE_FLOAT,
  356. Framework::Assembly::X);
  357. }
  358. codeBlock.addLoadAddress(noise, Framework::Assembly::RCX);
  359. codeBlock.addMemberCall<float (Noise::*)(float, float, float)>(
  360. &Noise::getNoise,
  361. Framework::Assembly::FLOAT_VALUE,
  362. {Framework::Assembly::RCX},
  363. {Framework::Assembly::MM1,
  364. Framework::Assembly::MM2,
  365. Framework::Assembly::MM3});
  366. return codeBlock;
  367. }
  368. void JNoiseFloatExpression::setName(Framework::Text name)
  369. {
  370. this->name = name;
  371. }
  372. Framework::Text JNoiseFloatExpression::getName() const
  373. {
  374. return name;
  375. }
  376. void JNoiseFloatExpression::setX(JFloatExpression* x)
  377. {
  378. if (this->x) this->x->release();
  379. this->x = x;
  380. }
  381. JFloatExpression* JNoiseFloatExpression::zX() const
  382. {
  383. return x;
  384. }
  385. void JNoiseFloatExpression::setY(JFloatExpression* y)
  386. {
  387. if (this->y) this->y->release();
  388. this->y = y;
  389. }
  390. JFloatExpression* JNoiseFloatExpression::zY() const
  391. {
  392. return y;
  393. }
  394. void JNoiseFloatExpression::setZ(JFloatExpression* z)
  395. {
  396. if (this->z) this->z->release();
  397. this->z = z;
  398. }
  399. JFloatExpression* JNoiseFloatExpression::zZ() const
  400. {
  401. return z;
  402. }
  403. JNoiseFloatExpressionFactory::JNoiseFloatExpressionFactory()
  404. : SubTypeFactory()
  405. {}
  406. JNoiseFloatExpression* JNoiseFloatExpressionFactory::fromJson(
  407. Framework::JSON::JSONObject* zJson) const
  408. {
  409. JNoiseFloatExpression* result = new JNoiseFloatExpression();
  410. result->setName(zJson->zValue("name")->asString()->getString());
  411. result->setX(Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(
  412. zJson->zValue("x")));
  413. result->setY(Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(
  414. zJson->zValue("y")));
  415. result->setZ(Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(
  416. zJson->zValue("z")));
  417. return result;
  418. }
  419. Framework::JSON::JSONObject* JNoiseFloatExpressionFactory::toJsonObject(
  420. JNoiseFloatExpression* zObject) const
  421. {
  422. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  423. result->addValue(
  424. "name", new Framework::JSON::JSONString(zObject->getName()));
  425. result->addValue(
  426. "x", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zX()));
  427. result->addValue(
  428. "y", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zY()));
  429. result->addValue(
  430. "z", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zZ()));
  431. return result;
  432. }
  433. JSONObjectValidationBuilder* JNoiseFloatExpressionFactory::addToValidator(
  434. JSONObjectValidationBuilder* builder) const
  435. {
  436. return builder->withRequiredString("name")
  437. ->finishString()
  438. ->withRequiredAttribute("x",
  439. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>())
  440. ->withRequiredAttribute("y",
  441. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>())
  442. ->withRequiredAttribute("z",
  443. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>());
  444. }
  445. const char* JNoiseFloatExpressionFactory::getTypeToken() const
  446. {
  447. return "noise";
  448. }
  449. JOperatorFloatExpression::JOperatorFloatExpression()
  450. : JFloatExpression()
  451. {}
  452. Framework::Assembly::AssemblyBlock& JOperatorFloatExpression::buildAssembly(
  453. JExpressionMemory* zMemory)
  454. {
  455. bool first = 1;
  456. if (!values.getEntryCount())
  457. {
  458. codeBlock.addMoveValue(Framework::Assembly::MM0, 0.f);
  459. }
  460. for (JFloatExpression* expression : values)
  461. {
  462. if (first)
  463. {
  464. first = 0;
  465. codeBlock.addBlock(
  466. &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0);
  467. }
  468. else
  469. {
  470. Framework::Assembly::AssemblyBlock& exprBlock
  471. = expression->buildAssembly(zMemory);
  472. if (exprBlock.isReplacementPossible(
  473. Framework::Assembly::MM0, Framework::Assembly::MM1))
  474. {
  475. exprBlock.replaceRegister(
  476. Framework::Assembly::MM0, Framework::Assembly::MM1);
  477. }
  478. else
  479. {
  480. exprBlock.addMoveValue(Framework::Assembly::MM1,
  481. Framework::Assembly::MM0,
  482. Framework::Assembly::SINGLE_FLOAT,
  483. Framework::Assembly::X);
  484. }
  485. codeBlock.addBlock(&exprBlock,
  486. {},
  487. {Framework::Assembly::MM0},
  488. {Framework::Assembly::SINGLE_FLOAT},
  489. 0,
  490. 0);
  491. if (op.isEqual("+"))
  492. {
  493. codeBlock.addAddition(Framework::Assembly::MM0,
  494. Framework::Assembly::MM1,
  495. Framework::Assembly::SINGLE_FLOAT,
  496. Framework::Assembly::X);
  497. }
  498. else if (op.isEqual("-"))
  499. {
  500. codeBlock.addSubtraction(Framework::Assembly::MM0,
  501. Framework::Assembly::MM1,
  502. Framework::Assembly::SINGLE_FLOAT,
  503. Framework::Assembly::X);
  504. }
  505. else if (op.isEqual("*"))
  506. {
  507. codeBlock.addMultiplication(Framework::Assembly::MM0,
  508. Framework::Assembly::MM1,
  509. Framework::Assembly::SINGLE_FLOAT,
  510. Framework::Assembly::X);
  511. }
  512. else if (op.isEqual("/"))
  513. {
  514. codeBlock.addDivision(Framework::Assembly::MM0,
  515. Framework::Assembly::MM1,
  516. Framework::Assembly::SINGLE_FLOAT,
  517. Framework::Assembly::X);
  518. }
  519. }
  520. }
  521. return codeBlock;
  522. }
  523. void JOperatorFloatExpression::setOperator(Framework::Text op)
  524. {
  525. this->op = op;
  526. }
  527. Framework::Text JOperatorFloatExpression::getOperator()
  528. {
  529. return op;
  530. }
  531. void JOperatorFloatExpression::addValue(JFloatExpression* value)
  532. {
  533. values.add(value);
  534. }
  535. const Framework::RCArray<JFloatExpression>&
  536. JOperatorFloatExpression::getValues() const
  537. {
  538. return values;
  539. }
  540. JOperatorFloatExpressionFactory::JOperatorFloatExpressionFactory()
  541. : SubTypeFactory()
  542. {}
  543. JOperatorFloatExpression* JOperatorFloatExpressionFactory::fromJson(
  544. Framework::JSON::JSONObject* zJson) const
  545. {
  546. JOperatorFloatExpression* result = new JOperatorFloatExpression();
  547. result->setOperator(zJson->zValue("operator")->asString()->getString());
  548. for (Framework::JSON::JSONValue* value :
  549. *zJson->zValue("values")->asArray())
  550. {
  551. result->addValue(
  552. Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(value));
  553. }
  554. return result;
  555. }
  556. Framework::JSON::JSONObject* JOperatorFloatExpressionFactory::toJsonObject(
  557. JOperatorFloatExpression* zObject) const
  558. {
  559. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  560. result->addValue(
  561. "operator", new Framework::JSON::JSONString(zObject->getOperator()));
  562. Framework::JSON::JSONArray* values = new Framework::JSON::JSONArray();
  563. for (JFloatExpression* expression : zObject->getValues())
  564. {
  565. values->addValue(
  566. Game::INSTANCE->zTypeRegistry()->toJson<JFloatExpression>(
  567. expression));
  568. }
  569. result->addValue("values", values);
  570. return result;
  571. }
  572. JSONObjectValidationBuilder* JOperatorFloatExpressionFactory::addToValidator(
  573. JSONObjectValidationBuilder* builder) const
  574. {
  575. return builder->withRequiredString("operator")
  576. ->whichIsOneOf({"+", "-", "*", "/"})
  577. ->finishString()
  578. ->withRequiredArray("values")
  579. ->addAcceptedTypeInArray(
  580. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>())
  581. ->finishArray();
  582. }
  583. const char* JOperatorFloatExpressionFactory::getTypeToken() const
  584. {
  585. return "operator";
  586. }
  587. JBoolOperatorBoolExpression::JBoolOperatorBoolExpression()
  588. : JBoolExpression()
  589. {}
  590. Framework::Assembly::AssemblyBlock& JBoolOperatorBoolExpression::buildAssembly(
  591. JExpressionMemory* zMemory)
  592. {
  593. bool first = 1;
  594. if (!values.getEntryCount())
  595. {
  596. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
  597. }
  598. for (JBoolExpression* expression : values)
  599. {
  600. if (first)
  601. {
  602. first = 0;
  603. codeBlock.addBlock(
  604. &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0);
  605. }
  606. else
  607. {
  608. Framework::Assembly::AssemblyBlock& exprBlock
  609. = expression->buildAssembly(zMemory);
  610. if (exprBlock.isReplacementPossible(
  611. Framework::Assembly::RAX, Framework::Assembly::RCX))
  612. {
  613. exprBlock.replaceRegister(
  614. Framework::Assembly::RAX, Framework::Assembly::RCX);
  615. }
  616. else
  617. {
  618. exprBlock.addMoveValue(Framework::Assembly::RCX,
  619. Framework::Assembly::RAX,
  620. Framework::Assembly::LOWER8);
  621. }
  622. codeBlock.addBlock(
  623. &exprBlock, {Framework::Assembly::RAX}, {}, {}, 0, 0);
  624. if (op.isEqual("&&"))
  625. {
  626. codeBlock.addAnd(Framework::Assembly::RAX,
  627. Framework::Assembly::RCX,
  628. Framework::Assembly::LOWER8);
  629. }
  630. else if (op.isEqual("||"))
  631. {
  632. codeBlock.addOr(Framework::Assembly::RAX,
  633. Framework::Assembly::RCX,
  634. Framework::Assembly::LOWER8);
  635. }
  636. }
  637. }
  638. return codeBlock;
  639. }
  640. void JBoolOperatorBoolExpression::setOperator(Framework::Text op)
  641. {
  642. this->op = op;
  643. }
  644. Framework::Text JBoolOperatorBoolExpression::getOperator()
  645. {
  646. return op;
  647. }
  648. void JBoolOperatorBoolExpression::addValue(JBoolExpression* value)
  649. {
  650. values.add(value);
  651. }
  652. const Framework::RCArray<JBoolExpression>&
  653. JBoolOperatorBoolExpression::getValues() const
  654. {
  655. return values;
  656. }
  657. JBoolOperatorBoolExpressionFactory::JBoolOperatorBoolExpressionFactory()
  658. : SubTypeFactory()
  659. {}
  660. JBoolOperatorBoolExpression* JBoolOperatorBoolExpressionFactory::fromJson(
  661. Framework::JSON::JSONObject* zJson) const
  662. {
  663. JBoolOperatorBoolExpression* result = new JBoolOperatorBoolExpression();
  664. for (Framework::JSON::JSONValue* value :
  665. *zJson->zValue("values")->asArray())
  666. {
  667. result->addValue(
  668. Game::INSTANCE->zTypeRegistry()->fromJson<JBoolExpression>(value));
  669. }
  670. result->setOperator(zJson->zValue("operator")->asString()->getString());
  671. return result;
  672. }
  673. Framework::JSON::JSONObject* JBoolOperatorBoolExpressionFactory::toJsonObject(
  674. JBoolOperatorBoolExpression* zObject) const
  675. {
  676. Framework::JSON::JSONObject* zResult = new Framework::JSON::JSONObject();
  677. Framework::JSON::JSONArray* values = new Framework::JSON::JSONArray();
  678. for (JBoolExpression* expression : zObject->getValues())
  679. {
  680. values->addValue(
  681. Game::INSTANCE->zTypeRegistry()->toJson<JBoolExpression>(
  682. expression));
  683. }
  684. zResult->addValue("values", values);
  685. zResult->addValue(
  686. "operator", new Framework::JSON::JSONString(zObject->getOperator()));
  687. return zResult;
  688. }
  689. JSONObjectValidationBuilder* JBoolOperatorBoolExpressionFactory::addToValidator(
  690. JSONObjectValidationBuilder* builder) const
  691. {
  692. return builder->withRequiredString("operator")
  693. ->whichIsOneOf({"&&", "||"})
  694. ->finishString()
  695. ->withRequiredArray("values")
  696. ->addAcceptedTypeInArray(
  697. Game::INSTANCE->zTypeRegistry()->getValidator<JBoolExpression>())
  698. ->finishArray();
  699. }
  700. const char* JBoolOperatorBoolExpressionFactory::getTypeToken() const
  701. {
  702. return "operator";
  703. }
  704. JFloatOperatorBoolExpression::JFloatOperatorBoolExpression()
  705. : JBoolExpression()
  706. {}
  707. Framework::Assembly::AssemblyBlock& JFloatOperatorBoolExpression::buildAssembly(
  708. JExpressionMemory* zMemory)
  709. {
  710. bool first = 1;
  711. Framework::Assembly::FPRegister lastResultSorage = Framework::Assembly::MM0;
  712. for (JFloatExpression* expression : values)
  713. {
  714. if (first)
  715. {
  716. first = 0;
  717. codeBlock.addBlock(
  718. &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0);
  719. }
  720. else
  721. {
  722. Framework::Assembly::FPRegister currentResultSorage
  723. = lastResultSorage == Framework::Assembly::MM0
  724. ? Framework::Assembly::MM1
  725. : Framework::Assembly::MM0;
  726. Framework::Assembly::AssemblyBlock& exprBlock
  727. = expression->buildAssembly(zMemory);
  728. if (currentResultSorage != Framework::Assembly::MM0)
  729. {
  730. if (exprBlock.isReplacementPossible(
  731. Framework::Assembly::MM0, currentResultSorage))
  732. {
  733. exprBlock.replaceRegister(
  734. Framework::Assembly::MM0, currentResultSorage);
  735. }
  736. else
  737. {
  738. exprBlock.addMoveValue(currentResultSorage,
  739. Framework::Assembly::MM0,
  740. Framework::Assembly::SINGLE_FLOAT,
  741. Framework::Assembly::X);
  742. }
  743. }
  744. codeBlock.addBlock(&exprBlock,
  745. {},
  746. {lastResultSorage},
  747. {Framework::Assembly::SINGLE_FLOAT},
  748. 0,
  749. 0);
  750. Framework::Assembly::Operation jumpOp = Framework::Assembly::NOP;
  751. bool needConversion = false;
  752. if (op.isEqual(">"))
  753. {
  754. jumpOp = Framework::Assembly::JBE; // jump if below or equal
  755. }
  756. else if (op.isEqual("<"))
  757. {
  758. jumpOp = Framework::Assembly::JNB; // jump if not below
  759. }
  760. else if (op.isEqual(">="))
  761. {
  762. jumpOp = Framework::Assembly::JB; // jump if below
  763. }
  764. else if (op.isEqual("<="))
  765. {
  766. jumpOp = Framework::Assembly::JA; // jump if above
  767. }
  768. else if (op.isEqual("=="))
  769. {
  770. jumpOp = Framework::Assembly::JNE; // jump if not equal
  771. }
  772. else if (op.isEqual("!="))
  773. {
  774. jumpOp = Framework::Assembly::JE; // jump if equal
  775. }
  776. else
  777. {
  778. needConversion = true;
  779. if (op.isEqual(">i"))
  780. {
  781. jumpOp = Framework::Assembly::JLE; // jump if less or equal
  782. }
  783. else if (op.isEqual("<i"))
  784. {
  785. jumpOp = Framework::Assembly::JGE; // jump if greater or
  786. // equal
  787. }
  788. else if (op.isEqual(">=i"))
  789. {
  790. jumpOp = Framework::Assembly::JL; // jump if less
  791. }
  792. else if (op.isEqual("<=i"))
  793. {
  794. jumpOp = Framework::Assembly::JG; // jump if greater
  795. }
  796. else if (op.isEqual("==i"))
  797. {
  798. jumpOp = Framework::Assembly::JNE; // jump if not equal
  799. }
  800. else if (op.isEqual("!=i"))
  801. {
  802. jumpOp = Framework::Assembly::JE; // jump if equal
  803. }
  804. }
  805. if (needConversion)
  806. {
  807. codeBlock.addConversion(Framework::Assembly::RAX,
  808. lastResultSorage,
  809. Framework::Assembly::SINGLE_FLOAT,
  810. Framework::Assembly::LOWER32);
  811. codeBlock.addConversion(Framework::Assembly::RCX,
  812. currentResultSorage,
  813. Framework::Assembly::SINGLE_FLOAT,
  814. Framework::Assembly::LOWER32);
  815. codeBlock.addCompare(Framework::Assembly::RAX,
  816. Framework::Assembly::RCX,
  817. Framework::Assembly::LOWER32);
  818. }
  819. else
  820. {
  821. codeBlock.addCompare(lastResultSorage,
  822. currentResultSorage,
  823. Framework::Assembly::SINGLE_FLOAT);
  824. }
  825. codeBlock.addJump(jumpOp, "end_false");
  826. lastResultSorage = currentResultSorage;
  827. }
  828. }
  829. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1);
  830. codeBlock.addJump(Framework::Assembly::JMP, "end");
  831. codeBlock.defineJumpTarget("end_false");
  832. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
  833. codeBlock.defineJumpTarget("end");
  834. return codeBlock;
  835. }
  836. void JFloatOperatorBoolExpression::setOperator(Framework::Text op)
  837. {
  838. this->op = op;
  839. }
  840. Framework::Text JFloatOperatorBoolExpression::getOperator()
  841. {
  842. return op;
  843. }
  844. void JFloatOperatorBoolExpression::addValue(JFloatExpression* value)
  845. {
  846. values.add(value);
  847. }
  848. const Framework::RCArray<JFloatExpression>&
  849. JFloatOperatorBoolExpression::getValues() const
  850. {
  851. return values;
  852. }
  853. JFloatOperatorBoolExpressionFactory::JFloatOperatorBoolExpressionFactory()
  854. : SubTypeFactory()
  855. {}
  856. JFloatOperatorBoolExpression* JFloatOperatorBoolExpressionFactory::fromJson(
  857. Framework::JSON::JSONObject* zJson) const
  858. {
  859. JFloatOperatorBoolExpression* result = new JFloatOperatorBoolExpression();
  860. result->setOperator(zJson->zValue("operator")->asString()->getString());
  861. for (Framework::JSON::JSONValue* value :
  862. *zJson->zValue("values")->asArray())
  863. {
  864. result->addValue(
  865. Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(value));
  866. }
  867. return result;
  868. }
  869. Framework::JSON::JSONObject* JFloatOperatorBoolExpressionFactory::toJsonObject(
  870. JFloatOperatorBoolExpression* zObject) const
  871. {
  872. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  873. result->addValue(
  874. "operator", new Framework::JSON::JSONString(zObject->getOperator()));
  875. Framework::JSON::JSONArray* values = new Framework::JSON::JSONArray();
  876. for (JFloatExpression* expression : zObject->getValues())
  877. {
  878. values->addValue(
  879. Game::INSTANCE->zTypeRegistry()->toJson<JFloatExpression>(
  880. expression));
  881. }
  882. result->addValue("values", values);
  883. return result;
  884. }
  885. JSONObjectValidationBuilder*
  886. JFloatOperatorBoolExpressionFactory::addToValidator(
  887. JSONObjectValidationBuilder* builder) const
  888. {
  889. return builder->withRequiredString("operator")
  890. ->whichIsOneOf({">",
  891. "<",
  892. ">=",
  893. "<=",
  894. "==",
  895. "!=",
  896. "<i",
  897. ">i",
  898. ">=i",
  899. "<=i",
  900. "==i",
  901. "!=i"})
  902. ->finishString()
  903. ->withRequiredArray("values")
  904. ->addAcceptedTypeInArray(
  905. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>())
  906. ->finishArray();
  907. }
  908. const char* JFloatOperatorBoolExpressionFactory::getTypeToken() const
  909. {
  910. return "comparsion";
  911. }
  912. JSpecificBlockBoolExpression::JSpecificBlockBoolExpression()
  913. : JBoolExpression(),
  914. filter(0),
  915. x(0),
  916. y(0),
  917. z(0)
  918. {}
  919. JSpecificBlockBoolExpression::~JSpecificBlockBoolExpression()
  920. {
  921. if (filter) filter->release();
  922. if (x) x->release();
  923. if (y) y->release();
  924. if (z) z->release();
  925. }
  926. bool JSpecificBlockBoolExpression::isValidPosition(
  927. int x, int y, Chunk* currentChunk)
  928. {
  929. return currentChunk
  930. && Game::getChunkCenter(x, y) == currentChunk->getCenter();
  931. }
  932. Framework::Assembly::AssemblyBlock& JSpecificBlockBoolExpression::buildAssembly(
  933. JExpressionMemory* zMemory)
  934. {
  935. Framework::Assembly::AssemblyBlock& xBlock = x->buildAssembly(zMemory);
  936. Framework::Assembly::AssemblyBlock& yBlock = y->buildAssembly(zMemory);
  937. Framework::Assembly::AssemblyBlock& zBlock = z->buildAssembly(zMemory);
  938. Framework::Assembly::FPRegister xTarget = Framework::Assembly::MM0;
  939. if (xBlock.isReplacementPossible(
  940. Framework::Assembly::MM0, Framework::Assembly::MM1))
  941. {
  942. xBlock.replaceRegister(
  943. Framework::Assembly::MM0, Framework::Assembly::MM1);
  944. xTarget = Framework::Assembly::MM1;
  945. }
  946. Framework::Assembly::FPRegister yTarget = Framework::Assembly::MM0;
  947. if (yBlock.isReplacementPossible(
  948. Framework::Assembly::MM0, Framework::Assembly::MM2))
  949. {
  950. yBlock.replaceRegister(
  951. Framework::Assembly::MM0, Framework::Assembly::MM2);
  952. yTarget = Framework::Assembly::MM2;
  953. }
  954. Framework::Assembly::FPRegister zTarget = Framework::Assembly::MM0;
  955. if (zBlock.isReplacementPossible(
  956. Framework::Assembly::MM0, Framework::Assembly::MM3))
  957. {
  958. zBlock.replaceRegister(
  959. Framework::Assembly::MM0, Framework::Assembly::MM3);
  960. zTarget = Framework::Assembly::MM3;
  961. }
  962. codeBlock.addBlock(&zBlock, {}, {}, {}, 0, &zTarget);
  963. codeBlock.addConversion(Framework::Assembly::R9,
  964. zTarget,
  965. Framework::Assembly::SINGLE_FLOAT,
  966. Framework::Assembly::LOWER32,
  967. 1);
  968. codeBlock.addTest(Framework::Assembly::R9,
  969. Framework::Assembly::R9,
  970. Framework::Assembly::LOWER32);
  971. codeBlock.addJump(Framework::Assembly::JL, "end_false");
  972. codeBlock.addCompare(Framework::Assembly::R9, WORLD_HEIGHT);
  973. codeBlock.addJump(Framework::Assembly::JGE, "end_false");
  974. codeBlock.addBlock(&yBlock, {Framework::Assembly::R9}, {}, {}, 0, &yTarget);
  975. codeBlock.addConversion(Framework::Assembly::R8,
  976. yTarget,
  977. Framework::Assembly::SINGLE_FLOAT,
  978. Framework::Assembly::LOWER32,
  979. 1);
  980. codeBlock.addBlock(&xBlock,
  981. {Framework::Assembly::R8, Framework::Assembly::R9},
  982. {},
  983. {},
  984. 0,
  985. &xTarget);
  986. codeBlock.addConversion(Framework::Assembly::RDX,
  987. xTarget,
  988. Framework::Assembly::SINGLE_FLOAT,
  989. Framework::Assembly::LOWER32,
  990. 1);
  991. codeBlock.addLoadAddress(this, Framework::Assembly::RCX);
  992. codeBlock.addPush(Framework::Assembly::RDX, Framework::Assembly::LOWER32);
  993. codeBlock.addPush(Framework::Assembly::R8, Framework::Assembly::LOWER32);
  994. codeBlock.addPush(Framework::Assembly::R9, Framework::Assembly::LOWER32);
  995. codeBlock.addLoadValue(
  996. (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::R9);
  997. codeBlock.addMemberCall<bool (JSpecificBlockBoolExpression::*)(
  998. int, int, Chunk*)>(&JSpecificBlockBoolExpression::isValidPosition,
  999. Framework::Assembly::INT_VALUE,
  1000. {Framework::Assembly::R9},
  1001. {});
  1002. codeBlock.addPop(Framework::Assembly::R9, Framework::Assembly::LOWER32);
  1003. codeBlock.addPop(Framework::Assembly::R8, Framework::Assembly::LOWER32);
  1004. codeBlock.addPop(Framework::Assembly::RDX, Framework::Assembly::LOWER32);
  1005. codeBlock.addTest(Framework::Assembly::RAX,
  1006. Framework::Assembly::RAX,
  1007. Framework::Assembly::LOWER8);
  1008. codeBlock.addJump(Framework::Assembly::JZ, "end");
  1009. codeBlock.addLoadValue(
  1010. (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::RCX);
  1011. codeBlock.addMemberCall<const Block* (Chunk::*)(int, int, int) const>(
  1012. &Chunk::zBlockConstWC,
  1013. Framework::Assembly::INT_VALUE,
  1014. {Framework::Assembly::RCX,
  1015. Framework::Assembly::RDX,
  1016. Framework::Assembly::R8,
  1017. Framework::Assembly::R9},
  1018. {});
  1019. codeBlock.addMoveValue(Framework::Assembly::RDX, Framework::Assembly::RAX);
  1020. codeBlock.addLoadValue((__int64*)&filter, Framework::Assembly::RCX);
  1021. codeBlock.addMemberCall<bool (BlockFilter::*)(const Block*) const>(
  1022. &BlockFilter::test,
  1023. Framework::Assembly::INT_VALUE,
  1024. {Framework::Assembly::RCX, Framework::Assembly::RDX},
  1025. {});
  1026. codeBlock.addTest(Framework::Assembly::RAX,
  1027. Framework::Assembly::RAX,
  1028. Framework::Assembly::LOWER8);
  1029. codeBlock.addJump(Framework::Assembly::JZ, "end");
  1030. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1);
  1031. codeBlock.addJump(Framework::Assembly::JMP, "end");
  1032. codeBlock.defineJumpTarget("end_false");
  1033. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
  1034. codeBlock.defineJumpTarget("end");
  1035. return codeBlock;
  1036. }
  1037. void JSpecificBlockBoolExpression::setFilter(BlockFilter* filter)
  1038. {
  1039. if (this->filter)
  1040. {
  1041. this->filter->release();
  1042. }
  1043. this->filter = filter;
  1044. }
  1045. BlockFilter* JSpecificBlockBoolExpression::zFilter() const
  1046. {
  1047. return filter;
  1048. }
  1049. void JSpecificBlockBoolExpression::setX(JFloatExpression* x)
  1050. {
  1051. if (this->x) this->x->release();
  1052. this->x = x;
  1053. }
  1054. JFloatExpression* JSpecificBlockBoolExpression::zX() const
  1055. {
  1056. return x;
  1057. }
  1058. void JSpecificBlockBoolExpression::setY(JFloatExpression* y)
  1059. {
  1060. if (this->y) this->y->release();
  1061. this->y = y;
  1062. }
  1063. JFloatExpression* JSpecificBlockBoolExpression::zY() const
  1064. {
  1065. return y;
  1066. }
  1067. void JSpecificBlockBoolExpression::setZ(JFloatExpression* z)
  1068. {
  1069. if (this->z) this->z->release();
  1070. this->z = z;
  1071. }
  1072. JFloatExpression* JSpecificBlockBoolExpression::zZ() const
  1073. {
  1074. return z;
  1075. }
  1076. JSpecificBlockBoolExpressionFactory::JSpecificBlockBoolExpressionFactory()
  1077. : SubTypeFactory()
  1078. {}
  1079. JSpecificBlockBoolExpression* JSpecificBlockBoolExpressionFactory::fromJson(
  1080. Framework::JSON::JSONObject* zJson) const
  1081. {
  1082. JSpecificBlockBoolExpression* result = new JSpecificBlockBoolExpression();
  1083. result->setFilter(Game::INSTANCE->zTypeRegistry()->fromJson<BlockFilter>(
  1084. zJson->zValue("condition")));
  1085. result->setX(Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(
  1086. zJson->zValue("x")));
  1087. result->setY(Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(
  1088. zJson->zValue("y")));
  1089. result->setZ(Game::INSTANCE->zTypeRegistry()->fromJson<JFloatExpression>(
  1090. zJson->zValue("z")));
  1091. return result;
  1092. }
  1093. Framework::JSON::JSONObject* JSpecificBlockBoolExpressionFactory::toJsonObject(
  1094. JSpecificBlockBoolExpression* zObject) const
  1095. {
  1096. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  1097. result->addValue("condition",
  1098. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zFilter()));
  1099. result->addValue(
  1100. "x", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zX()));
  1101. result->addValue(
  1102. "y", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zY()));
  1103. result->addValue(
  1104. "z", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zZ()));
  1105. return result;
  1106. }
  1107. JSONObjectValidationBuilder*
  1108. JSpecificBlockBoolExpressionFactory::addToValidator(
  1109. JSONObjectValidationBuilder* builder) const
  1110. {
  1111. return builder
  1112. ->withRequiredAttribute("condition",
  1113. Game::INSTANCE->zTypeRegistry()->getValidator<BlockFilter>())
  1114. ->withRequiredAttribute("x",
  1115. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>())
  1116. ->withRequiredAttribute("y",
  1117. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>())
  1118. ->withRequiredAttribute("z",
  1119. Game::INSTANCE->zTypeRegistry()->getValidator<JFloatExpression>());
  1120. }
  1121. const char* JSpecificBlockBoolExpressionFactory::getTypeToken() const
  1122. {
  1123. return "specificBlockMatches";
  1124. }
  1125. JFirstBlockAboveBoolExpression::JFirstBlockAboveBoolExpression()
  1126. : JBoolExpression(),
  1127. filter(0),
  1128. maxDistance(0)
  1129. {}
  1130. JFirstBlockAboveBoolExpression::~JFirstBlockAboveBoolExpression()
  1131. {
  1132. if (filter) filter->release();
  1133. }
  1134. Framework::Assembly::AssemblyBlock&
  1135. JFirstBlockAboveBoolExpression::buildAssembly(JExpressionMemory* zMemory)
  1136. {
  1137. // load x into R12
  1138. codeBlock.addLoadValue(
  1139. zMemory->getFloatVariableP("x"), Framework::Assembly::MM0);
  1140. codeBlock.addConversion(Framework::Assembly::R12,
  1141. Framework::Assembly::MM0,
  1142. Framework::Assembly::SINGLE_FLOAT,
  1143. Framework::Assembly::LOWER32,
  1144. 1);
  1145. // load y into R13
  1146. codeBlock.addLoadValue(
  1147. zMemory->getFloatVariableP("y"), Framework::Assembly::MM0);
  1148. codeBlock.addConversion(Framework::Assembly::R13,
  1149. Framework::Assembly::MM0,
  1150. Framework::Assembly::SINGLE_FLOAT,
  1151. Framework::Assembly::LOWER32,
  1152. 1);
  1153. // load z into R14
  1154. codeBlock.addLoadValue(
  1155. zMemory->getFloatVariableP("z"), Framework::Assembly::MM0);
  1156. codeBlock.addConversion(Framework::Assembly::R14,
  1157. Framework::Assembly::MM0,
  1158. Framework::Assembly::SINGLE_FLOAT,
  1159. Framework::Assembly::LOWER32,
  1160. 1);
  1161. // load current chunk into R15
  1162. codeBlock.addLoadValue(
  1163. (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::R15);
  1164. if (maxDistance)
  1165. {
  1166. // calculate loop end
  1167. codeBlock.addMoveValue(
  1168. Framework::Assembly::RBX, Framework::Assembly::R14);
  1169. codeBlock.addAddition(Framework::Assembly::RBX, maxDistance + 1);
  1170. codeBlock.addCompare(Framework::Assembly::RBX, WORLD_HEIGHT);
  1171. codeBlock.addJump(Framework::Assembly::JL, "continue");
  1172. codeBlock.addMoveValue(Framework::Assembly::RBX, WORLD_HEIGHT);
  1173. codeBlock.defineJumpTarget("continue");
  1174. }
  1175. // begin loop to check above blocks
  1176. codeBlock.defineJumpTarget("loop_start");
  1177. // increment height
  1178. codeBlock.addAddition(
  1179. Framework::Assembly::R14, (char)1, Framework::Assembly::LOWER32);
  1180. // check if height is above loop end
  1181. if (maxDistance)
  1182. {
  1183. codeBlock.addCompare(Framework::Assembly::R14,
  1184. Framework::Assembly::RBX,
  1185. Framework::Assembly::LOWER32);
  1186. }
  1187. else
  1188. {
  1189. codeBlock.addCompare(Framework::Assembly::R14, WORLD_HEIGHT);
  1190. }
  1191. codeBlock.addJump(Framework::Assembly::JGE, "end_false");
  1192. // load block type at current position into RAX
  1193. codeBlock.addMoveValue(Framework::Assembly::RCX, Framework::Assembly::R15);
  1194. codeBlock.addMoveValue(Framework::Assembly::RDX, Framework::Assembly::R12);
  1195. codeBlock.addMoveValue(Framework::Assembly::R8, Framework::Assembly::R13);
  1196. codeBlock.addMoveValue(Framework::Assembly::R9, Framework::Assembly::R14);
  1197. if (maxDistance)
  1198. { // save loop end in RBX for later comparison
  1199. codeBlock.addPush(
  1200. Framework::Assembly::RBX, Framework::Assembly::LOWER32);
  1201. }
  1202. codeBlock.addMemberCall<int (Chunk::*)(int, int, int) const>(
  1203. &Chunk::getBlockTypeAtWC,
  1204. Framework::Assembly::INT_VALUE,
  1205. {Framework::Assembly::RCX,
  1206. Framework::Assembly::RDX,
  1207. Framework::Assembly::R8,
  1208. Framework::Assembly::R9},
  1209. {});
  1210. if (maxDistance)
  1211. {
  1212. // restore loop end from stack
  1213. codeBlock.addPop(
  1214. Framework::Assembly::RBX, Framework::Assembly::LOWER32);
  1215. }
  1216. // check if block type is 0 (NO_BLOCK) or 1 (AIR)
  1217. codeBlock.addCompare(Framework::Assembly::RAX, 1);
  1218. codeBlock.addJump(Framework::Assembly::JLE, "loop_start");
  1219. // end of loop
  1220. // load current block into RDX
  1221. codeBlock.addMoveValue(Framework::Assembly::RCX, Framework::Assembly::R15);
  1222. codeBlock.addMoveValue(Framework::Assembly::RDX, Framework::Assembly::R12);
  1223. codeBlock.addMoveValue(Framework::Assembly::R8, Framework::Assembly::R13);
  1224. codeBlock.addMoveValue(Framework::Assembly::R9, Framework::Assembly::R14);
  1225. codeBlock.addMemberCall<const Block* (Chunk::*)(int, int, int) const>(
  1226. &Chunk::zBlockConstWC,
  1227. Framework::Assembly::INT_VALUE,
  1228. {Framework::Assembly::RCX,
  1229. Framework::Assembly::RDX,
  1230. Framework::Assembly::R8,
  1231. Framework::Assembly::R9},
  1232. {});
  1233. codeBlock.addMoveValue(Framework::Assembly::RDX, Framework::Assembly::RAX);
  1234. // load filter into RCX
  1235. codeBlock.addLoadValue((__int64*)&filter, Framework::Assembly::RCX);
  1236. // check filter condition
  1237. codeBlock.addMemberCall<bool (BlockFilter::*)(const Block*) const>(
  1238. &BlockFilter::test,
  1239. Framework::Assembly::INT_VALUE,
  1240. {Framework::Assembly::RCX, Framework::Assembly::RDX},
  1241. {});
  1242. codeBlock.addJump(Framework::Assembly::JMP, "end");
  1243. codeBlock.defineJumpTarget("end_false");
  1244. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
  1245. codeBlock.defineJumpTarget("end");
  1246. return codeBlock;
  1247. }
  1248. void JFirstBlockAboveBoolExpression::setFilter(BlockFilter* filter)
  1249. {
  1250. if (this->filter)
  1251. {
  1252. this->filter->release();
  1253. }
  1254. this->filter = filter;
  1255. }
  1256. BlockFilter* JFirstBlockAboveBoolExpression::zFilter() const
  1257. {
  1258. return filter;
  1259. }
  1260. void JFirstBlockAboveBoolExpression::setMaxDistance(short maxDistance)
  1261. {
  1262. this->maxDistance = maxDistance;
  1263. }
  1264. short JFirstBlockAboveBoolExpression::getMaxDistance() const
  1265. {
  1266. return maxDistance;
  1267. }
  1268. JFirstBlockAboveBoolExpressionFactory::JFirstBlockAboveBoolExpressionFactory()
  1269. : SubTypeFactory()
  1270. {}
  1271. JFirstBlockAboveBoolExpression* JFirstBlockAboveBoolExpressionFactory::fromJson(
  1272. Framework::JSON::JSONObject* zJson) const
  1273. {
  1274. JFirstBlockAboveBoolExpression* result
  1275. = new JFirstBlockAboveBoolExpression();
  1276. result->setFilter(Game::INSTANCE->zTypeRegistry()->fromJson<BlockFilter>(
  1277. zJson->zValue("condition")));
  1278. if (zJson->hasValue("maxDistance"))
  1279. {
  1280. result->setMaxDistance(
  1281. (short)zJson->zValue("maxDistance")->asNumber()->getNumber());
  1282. }
  1283. return result;
  1284. }
  1285. Framework::JSON::JSONObject*
  1286. JFirstBlockAboveBoolExpressionFactory::toJsonObject(
  1287. JFirstBlockAboveBoolExpression* zObject) const
  1288. {
  1289. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  1290. result->addValue("condition",
  1291. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zFilter()));
  1292. if (zObject->getMaxDistance())
  1293. {
  1294. result->addValue("maxDistance",
  1295. new Framework::JSON::JSONNumber(zObject->getMaxDistance()));
  1296. }
  1297. return result;
  1298. }
  1299. JSONObjectValidationBuilder*
  1300. JFirstBlockAboveBoolExpressionFactory::addToValidator(
  1301. JSONObjectValidationBuilder* builder) const
  1302. {
  1303. return builder
  1304. ->withRequiredAttribute("condition",
  1305. Game::INSTANCE->zTypeRegistry()->getValidator<BlockFilter>())
  1306. ->withOptionalNumber("maxDistance")
  1307. ->whichIsGreaterThen(0)
  1308. ->whichIsLessThen(WORLD_HEIGHT)
  1309. ->finishNumber();
  1310. }
  1311. const char* JFirstBlockAboveBoolExpressionFactory::getTypeToken() const
  1312. {
  1313. return "firstBlockAboveMatches";
  1314. }
  1315. JNaighborBlockBoolExpression::JNaighborBlockBoolExpression()
  1316. : JBoolExpression(),
  1317. filter(0),
  1318. validDirections(Direction::NO_DIRECTION)
  1319. {}
  1320. JNaighborBlockBoolExpression::~JNaighborBlockBoolExpression()
  1321. {
  1322. if (filter)
  1323. {
  1324. filter->release();
  1325. }
  1326. }
  1327. bool JNaighborBlockBoolExpression::isValidPosition(
  1328. int x, int y, Chunk* currentChunk)
  1329. {
  1330. return currentChunk
  1331. && Game::getChunkCenter(x, y) == currentChunk->getCenter();
  1332. }
  1333. void JNaighborBlockBoolExpression::addEvaluation(
  1334. Framework::Assembly::AssemblyBlock& codeBlock, JExpressionMemory* zMemory)
  1335. {
  1336. // call currentChunk->zBlockConstWC(x, y, z)
  1337. codeBlock.addLoadValue(
  1338. (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::RCX);
  1339. codeBlock.addMemberCall<const Block* (Chunk::*)(int, int, int) const>(
  1340. &Chunk::zBlockConstWC,
  1341. Framework::Assembly::INT_VALUE,
  1342. {Framework::Assembly::RCX,
  1343. Framework::Assembly::RDX,
  1344. Framework::Assembly::R8,
  1345. Framework::Assembly::R9},
  1346. {});
  1347. // call filter->test(block)
  1348. codeBlock.addLoadValue((__int64*)&filter, Framework::Assembly::RCX);
  1349. codeBlock.addMoveValue(Framework::Assembly::RDX, Framework::Assembly::RAX);
  1350. codeBlock.addMemberCall<bool (BlockFilter::*)(const Block*) const>(
  1351. &BlockFilter::test,
  1352. Framework::Assembly::INT_VALUE,
  1353. {Framework::Assembly::RCX, Framework::Assembly::RDX},
  1354. {});
  1355. // if filter returns true, jump to end
  1356. codeBlock.addTest(Framework::Assembly::RAX,
  1357. Framework::Assembly::RAX,
  1358. Framework::Assembly::LOWER8);
  1359. codeBlock.addJump(Framework::Assembly::JNZ, "end_true");
  1360. }
  1361. Framework::Assembly::AssemblyBlock& JNaighborBlockBoolExpression::buildAssembly(
  1362. JExpressionMemory* zMemory)
  1363. {
  1364. if (validDirections == Direction::NO_DIRECTION)
  1365. {
  1366. // no directions to check, return false
  1367. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
  1368. }
  1369. else
  1370. {
  1371. // load x into R12
  1372. codeBlock.addLoadValue(
  1373. zMemory->getFloatVariableP("x"), Framework::Assembly::MM0);
  1374. codeBlock.addConversion(Framework::Assembly::R12,
  1375. Framework::Assembly::MM0,
  1376. Framework::Assembly::SINGLE_FLOAT,
  1377. Framework::Assembly::LOWER32,
  1378. 1);
  1379. // load y into R13
  1380. codeBlock.addLoadValue(
  1381. zMemory->getFloatVariableP("y"), Framework::Assembly::MM0);
  1382. codeBlock.addConversion(Framework::Assembly::R13,
  1383. Framework::Assembly::MM0,
  1384. Framework::Assembly::SINGLE_FLOAT,
  1385. Framework::Assembly::LOWER32,
  1386. 1);
  1387. // load z into R14
  1388. codeBlock.addLoadValue(
  1389. zMemory->getFloatVariableP("z"), Framework::Assembly::MM0);
  1390. codeBlock.addConversion(Framework::Assembly::R14,
  1391. Framework::Assembly::MM0,
  1392. Framework::Assembly::SINGLE_FLOAT,
  1393. Framework::Assembly::LOWER32,
  1394. 1);
  1395. if (validDirections & Direction::TOP)
  1396. {
  1397. // add 1 to z and check if it's above world height
  1398. codeBlock.addMoveValue(
  1399. Framework::Assembly::R9, Framework::Assembly::R14);
  1400. codeBlock.addAddition(
  1401. Framework::Assembly::R9, (char)1, Framework::Assembly::LOWER16);
  1402. codeBlock.addCompare(Framework::Assembly::R9, WORLD_HEIGHT);
  1403. codeBlock.addJump(Framework::Assembly::JGE, "skip_top");
  1404. // evaluates filter on block at current position
  1405. codeBlock.addMoveValue(
  1406. Framework::Assembly::RDX, Framework::Assembly::R12);
  1407. codeBlock.addMoveValue(
  1408. Framework::Assembly::R8, Framework::Assembly::R13);
  1409. addEvaluation(codeBlock, zMemory);
  1410. codeBlock.defineJumpTarget("skip_top");
  1411. }
  1412. if (validDirections & Direction::BOTTOM)
  1413. {
  1414. // subtract 1 from z and check if it's >= 0
  1415. codeBlock.addMoveValue(
  1416. Framework::Assembly::R9, Framework::Assembly::R14);
  1417. codeBlock.addSubtraction(
  1418. Framework::Assembly::R9, (char)1, Framework::Assembly::LOWER16);
  1419. codeBlock.addTest(Framework::Assembly::R9,
  1420. Framework::Assembly::R9,
  1421. Framework::Assembly::LOWER32);
  1422. codeBlock.addJump(Framework::Assembly::JL, "skip_bottom");
  1423. // evaluates filter on block at current position
  1424. codeBlock.addMoveValue(
  1425. Framework::Assembly::RDX, Framework::Assembly::R12);
  1426. codeBlock.addMoveValue(
  1427. Framework::Assembly::R8, Framework::Assembly::R13);
  1428. addEvaluation(codeBlock, zMemory);
  1429. codeBlock.defineJumpTarget("skip_bottom");
  1430. }
  1431. for (int i = 0; i < 4; i++)
  1432. { // check horizontal directions
  1433. Direction dir = getDirectionFromIndex(i);
  1434. if (validDirections & dir)
  1435. {
  1436. Framework::Vec3<int> offset = getDirection(dir);
  1437. codeBlock.addMoveValue(
  1438. Framework::Assembly::RDX, Framework::Assembly::R12);
  1439. codeBlock.addMoveValue(
  1440. Framework::Assembly::R8, Framework::Assembly::R13);
  1441. if (offset.x > 0)
  1442. {
  1443. codeBlock.addAddition(Framework::Assembly::RDX,
  1444. (char)1,
  1445. Framework::Assembly::LOWER32);
  1446. }
  1447. else if (offset.x < 0)
  1448. {
  1449. codeBlock.addSubtraction(Framework::Assembly::RDX,
  1450. (char)1,
  1451. Framework::Assembly::LOWER32);
  1452. }
  1453. if (offset.y > 0)
  1454. {
  1455. codeBlock.addAddition(Framework::Assembly::R8,
  1456. (char)1,
  1457. Framework::Assembly::LOWER32);
  1458. }
  1459. else if (offset.y < 0)
  1460. {
  1461. codeBlock.addSubtraction(Framework::Assembly::R8,
  1462. (char)1,
  1463. Framework::Assembly::LOWER32);
  1464. }
  1465. // check if new position is in the same chunk
  1466. codeBlock.addLoadValue((__int64*)zMemory->zzCurrentChunk(),
  1467. Framework::Assembly::R9);
  1468. codeBlock.addLoadAddress(this, Framework::Assembly::RCX);
  1469. codeBlock.addPush(
  1470. Framework::Assembly::RDX, Framework::Assembly::LOWER32);
  1471. codeBlock.addPush(
  1472. Framework::Assembly::R8, Framework::Assembly::LOWER32);
  1473. codeBlock.addMemberCall<bool (JNaighborBlockBoolExpression::*)(
  1474. int, int, Chunk*)>(
  1475. &JNaighborBlockBoolExpression::isValidPosition,
  1476. Framework::Assembly::INT_VALUE,
  1477. {Framework::Assembly::RCX,
  1478. Framework::Assembly::RDX,
  1479. Framework::Assembly::R8,
  1480. Framework::Assembly::R9},
  1481. {});
  1482. codeBlock.addPop(
  1483. Framework::Assembly::R8, Framework::Assembly::LOWER32);
  1484. codeBlock.addPop(
  1485. Framework::Assembly::RDX, Framework::Assembly::LOWER32);
  1486. // abort if position is not valid
  1487. codeBlock.addTest(Framework::Assembly::RAX,
  1488. Framework::Assembly::RAX,
  1489. Framework::Assembly::LOWER8);
  1490. Framework::Text jumpLabel = "skip_dir_";
  1491. jumpLabel.append(i);
  1492. codeBlock.addJump(Framework::Assembly::JZ, jumpLabel);
  1493. // restore parameters for block access
  1494. codeBlock.addMoveValue(
  1495. Framework::Assembly::R9, Framework::Assembly::R14);
  1496. addEvaluation(codeBlock, zMemory);
  1497. codeBlock.defineJumpTarget(jumpLabel);
  1498. }
  1499. }
  1500. // set return value to false if no direction matched
  1501. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
  1502. codeBlock.addJump(Framework::Assembly::JMP, "end");
  1503. codeBlock.defineJumpTarget("end_true");
  1504. // set return value to true if any direction matched
  1505. codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1);
  1506. codeBlock.defineJumpTarget("end");
  1507. }
  1508. return codeBlock;
  1509. }
  1510. void JNaighborBlockBoolExpression::setFilter(BlockFilter* filter)
  1511. {
  1512. this->filter = filter;
  1513. }
  1514. BlockFilter* JNaighborBlockBoolExpression::zFilter() const
  1515. {
  1516. return filter;
  1517. }
  1518. void JNaighborBlockBoolExpression::setValidDirections(
  1519. Directions validDirections)
  1520. {
  1521. this->validDirections = validDirections;
  1522. }
  1523. Directions JNaighborBlockBoolExpression::getValidDirections() const
  1524. {
  1525. return validDirections;
  1526. }
  1527. JNaighborBlockBoolExpressionFactory::JNaighborBlockBoolExpressionFactory()
  1528. : SubTypeFactory()
  1529. {}
  1530. JNaighborBlockBoolExpression* JNaighborBlockBoolExpressionFactory::fromJson(
  1531. Framework::JSON::JSONObject* zJson) const
  1532. {
  1533. JNaighborBlockBoolExpression* result = new JNaighborBlockBoolExpression();
  1534. result->setFilter(Game::INSTANCE->zTypeRegistry()->fromJson<BlockFilter>(
  1535. zJson->zValue("condition")));
  1536. for (Framework::JSON::JSONValue* direction :
  1537. *zJson->zValue("directions")->asArray())
  1538. {
  1539. Framework::Text dirStr = direction->asString()->getString();
  1540. if (dirStr.isEqual("TOP"))
  1541. {
  1542. result->setValidDirections(
  1543. result->getValidDirections() | Direction::TOP);
  1544. }
  1545. else if (dirStr.isEqual("BOTTOM"))
  1546. {
  1547. result->setValidDirections(
  1548. result->getValidDirections() | Direction::BOTTOM);
  1549. }
  1550. else if (dirStr.isEqual("EAST"))
  1551. {
  1552. result->setValidDirections(
  1553. result->getValidDirections() | Direction::EAST);
  1554. }
  1555. else if (dirStr.isEqual("NORTH"))
  1556. {
  1557. result->setValidDirections(
  1558. result->getValidDirections() | Direction::NORTH);
  1559. }
  1560. else if (dirStr.isEqual("WEST"))
  1561. {
  1562. result->setValidDirections(
  1563. result->getValidDirections() | Direction::WEST);
  1564. }
  1565. else if (dirStr.isEqual("SOUTH"))
  1566. {
  1567. result->setValidDirections(
  1568. result->getValidDirections() | Direction::SOUTH);
  1569. }
  1570. }
  1571. return result;
  1572. }
  1573. Framework::JSON::JSONObject* JNaighborBlockBoolExpressionFactory::toJsonObject(
  1574. JNaighborBlockBoolExpression* zObject) const
  1575. {
  1576. Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
  1577. result->addValue("condition",
  1578. Game::INSTANCE->zTypeRegistry()->toJson(zObject->zFilter()));
  1579. Framework::JSON::JSONArray* directionsArray
  1580. = new Framework::JSON::JSONArray();
  1581. if (zObject->getValidDirections() & Direction::TOP)
  1582. {
  1583. directionsArray->addValue(new Framework::JSON::JSONString("TOP"));
  1584. }
  1585. if (zObject->getValidDirections() & Direction::BOTTOM)
  1586. {
  1587. directionsArray->addValue(new Framework::JSON::JSONString("BOTTOM"));
  1588. }
  1589. if (zObject->getValidDirections() & Direction::EAST)
  1590. {
  1591. directionsArray->addValue(new Framework::JSON::JSONString("EAST"));
  1592. }
  1593. if (zObject->getValidDirections() & Direction::NORTH)
  1594. {
  1595. directionsArray->addValue(new Framework::JSON::JSONString("NORTH"));
  1596. }
  1597. if (zObject->getValidDirections() & Direction::WEST)
  1598. {
  1599. directionsArray->addValue(new Framework::JSON::JSONString("WEST"));
  1600. }
  1601. if (zObject->getValidDirections() & Direction::SOUTH)
  1602. {
  1603. directionsArray->addValue(new Framework::JSON::JSONString("SOUTH"));
  1604. }
  1605. result->addValue("directions", directionsArray);
  1606. return result;
  1607. }
  1608. JSONObjectValidationBuilder*
  1609. JNaighborBlockBoolExpressionFactory::addToValidator(
  1610. JSONObjectValidationBuilder* builder) const
  1611. {
  1612. Framework::JSON::JSONArray* defaultDirectionsArray
  1613. = new Framework::JSON::JSONArray();
  1614. defaultDirectionsArray->addValue(new Framework::JSON::JSONString("EAST"));
  1615. defaultDirectionsArray->addValue(new Framework::JSON::JSONString("NORTH"));
  1616. defaultDirectionsArray->addValue(new Framework::JSON::JSONString("WEST"));
  1617. defaultDirectionsArray->addValue(new Framework::JSON::JSONString("SOUTH"));
  1618. return builder
  1619. ->withRequiredAttribute("condition",
  1620. Game::INSTANCE->zTypeRegistry()->getValidator<BlockFilter>())
  1621. ->withRequiredArray("directions")
  1622. ->addAcceptedStringInArray()
  1623. ->whichIsOneOf({"TOP", "BOTTOM", "EAST", "NORTH", "WEST", "SOUTH"})
  1624. ->finishString()
  1625. ->withDefault(defaultDirectionsArray)
  1626. ->finishArray();
  1627. }
  1628. const char* JNaighborBlockBoolExpressionFactory::getTypeToken() const
  1629. {
  1630. return "anyNeighborBlockMatches";
  1631. }