JsonExpression.cpp 57 KB

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