yaml2sql.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <fstream>
  4. #include <functional>
  5. #include <iostream>
  6. #include <locale>
  7. #include <unordered_map>
  8. #include <vector>
  9. #ifdef WIN32
  10. #include <conio.h>
  11. #else
  12. #include <termios.h>
  13. #include <unistd.h>
  14. #include <stdio.h>
  15. #endif
  16. #include <yaml-cpp/yaml.h>
  17. #include <ryml_std.hpp>
  18. #include <ryml.hpp>
  19. #include "../common/cbasetypes.hpp"
  20. #include "../common/core.hpp"
  21. #include "../common/malloc.hpp"
  22. #include "../common/mmo.hpp"
  23. #include "../common/nullpo.hpp"
  24. #include "../common/showmsg.hpp"
  25. #include "../common/strlib.hpp"
  26. #include "../common/utilities.hpp"
  27. #include "../common/utils.hpp"
  28. #ifdef WIN32
  29. #include "../common/winapi.hpp"
  30. #endif
  31. // Only for constants - do not use functions of it or linking will fail
  32. #include "../map/achievement.hpp"
  33. #include "../map/battle.hpp"
  34. #include "../map/battleground.hpp"
  35. #include "../map/channel.hpp"
  36. #include "../map/chat.hpp"
  37. #include "../map/date.hpp"
  38. #include "../map/elemental.hpp"
  39. #include "../map/instance.hpp"
  40. #include "../map/mercenary.hpp"
  41. #include "../map/mob.hpp"
  42. #include "../map/npc.hpp"
  43. #include "../map/pc.hpp"
  44. #include "../map/pet.hpp"
  45. #include "../map/quest.hpp"
  46. #include "../map/script.hpp"
  47. #include "../map/skill.hpp"
  48. #include "../map/storage.hpp"
  49. using namespace rathena;
  50. #ifndef WIN32
  51. int getch( void ){
  52. struct termios oldattr, newattr;
  53. int ch;
  54. tcgetattr( STDIN_FILENO, &oldattr );
  55. newattr = oldattr;
  56. newattr.c_lflag &= ~( ICANON | ECHO );
  57. tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
  58. ch = getchar();
  59. tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
  60. return ch;
  61. }
  62. #endif
  63. // Constants for conversion
  64. std::unordered_map<const char *, int64> constants;
  65. // Forward declaration of conversion functions
  66. static bool item_db_yaml2sql(const std::string &file, const std::string &table);
  67. static bool mob_db_yaml2sql(const std::string &file, const std::string &table);
  68. bool fileExists( const std::string& path );
  69. bool askConfirmation( const char* fmt, ... );
  70. YAML::Node inNode;
  71. std::ofstream outFile;
  72. // Implement the function instead of including the original version by linking
  73. void script_set_constant_(const char *name, int64 value, const char *constant_name, bool isparameter, bool deprecated) {
  74. constants[name] = value;
  75. }
  76. const char *constant_lookup(int32 value, const char *prefix) {
  77. if (prefix == nullptr)
  78. return nullptr;
  79. for (auto const &pair : constants) {
  80. // Same prefix group and same value
  81. if (strncasecmp(pair.first, prefix, strlen(prefix)) == 0 && pair.second == value) {
  82. return pair.first;
  83. }
  84. }
  85. return nullptr;
  86. }
  87. int64 constant_lookup_int(const char *constant) {
  88. if (constant == nullptr)
  89. return -100;
  90. for (auto const &pair : constants) {
  91. if (strlen(pair.first) == strlen(constant) && strncasecmp(pair.first, constant, strlen(constant)) == 0) {
  92. return pair.second;
  93. }
  94. }
  95. return -100;
  96. }
  97. void copyFileIfExists( std::ofstream& file,const std::string& name ){
  98. std::string path = "doc/yaml/sql/" + name + ".sql";
  99. if( fileExists( path ) ){
  100. std::ifstream source( path, std::ios::binary );
  101. std::istreambuf_iterator<char> begin_source(source);
  102. std::istreambuf_iterator<char> end_source;
  103. std::ostreambuf_iterator<char> begin_dest( file );
  104. copy( begin_source, end_source, begin_dest );
  105. source.close();
  106. }
  107. }
  108. void prepareHeader(std::ofstream &file, const std::string& name) {
  109. copyFileIfExists( file, name );
  110. file << "\n";
  111. }
  112. template<typename Func>
  113. bool process( const std::string& type, uint32 version, const std::vector<std::string>& paths, const std::string& name, const std::string& to_table, const std::string& table, Func lambda ){
  114. for( const std::string& path : paths ){
  115. const std::string name_ext = name + ".yml";
  116. const std::string from = path + name_ext;
  117. const std::string to = "sql-files/" + to_table + ".sql";
  118. if( fileExists( from ) ){
  119. #ifndef CONVERT_ALL
  120. if( !askConfirmation( "Found the file \"%s\", which can be converted to sql.\nDo you want to convert it now? (Y/N)\n", from.c_str() ) ){
  121. continue;
  122. }
  123. #else
  124. ShowMessage("Found the file \"%s\", converting from yml to sql.\n", from.c_str());
  125. #endif
  126. inNode.reset();
  127. try {
  128. inNode = YAML::LoadFile(from);
  129. } catch (YAML::Exception &e) {
  130. ShowError("%s (Line %d: Column %d)\n", e.msg.c_str(), e.mark.line, e.mark.column);
  131. if (!askConfirmation("Error found in \"%s\" while attempting to load.\nPress any key to continue.\n", from.c_str()))
  132. continue;
  133. }
  134. if (!inNode["Body"].IsDefined())
  135. continue;
  136. #ifndef CONVERT_ALL
  137. if (fileExists(to)) {
  138. if (!askConfirmation("The file \"%s\" already exists.\nDo you want to replace it? (Y/N)\n", to.c_str())) {
  139. continue;
  140. }
  141. }
  142. #endif
  143. outFile.open(to);
  144. if (!outFile.is_open()) {
  145. ShowError("Can not open file \"%s\" for writing.\n", to.c_str());
  146. return false;
  147. }
  148. prepareHeader(outFile, table.compare(to_table) == 0 ? table : to_table);
  149. if( !lambda( path, name_ext, table ) ){
  150. outFile.close();
  151. return false;
  152. }
  153. outFile.close();
  154. }
  155. }
  156. return true;
  157. }
  158. int do_init( int argc, char** argv ){
  159. const std::string path_db = std::string( db_path );
  160. const std::string path_db_mode = path_db + "/" + DBPATH;
  161. const std::string path_db_import = path_db + "/" + DBIMPORT + "/";
  162. #ifdef RENEWAL
  163. const std::string item_table_name = "item_db_re";
  164. const std::string item_import_table_name = "item_db2_re";
  165. const std::string mob_table_name = "mob_db_re";
  166. const std::string mob_import_table_name = "mob_db2_re";
  167. #else
  168. const std::string item_table_name = "item_db";
  169. const std::string item_import_table_name = "item_db2";
  170. const std::string mob_table_name = "mob_db";
  171. const std::string mob_import_table_name = "mob_db2";
  172. #endif
  173. std::vector<std::string> item_table_suffixes = {
  174. "usable",
  175. "equip",
  176. "etc"
  177. };
  178. // Load constants
  179. #include "../map/script_constants.hpp"
  180. for( const std::string& suffix : item_table_suffixes ){
  181. if (!process("ITEM_DB", 1, { path_db_mode }, "item_db_" + suffix, item_table_name + "_" + suffix, item_table_name, [](const std::string& path, const std::string& name_ext, const std::string& table) -> bool {
  182. return item_db_yaml2sql(path + name_ext, table);
  183. })) {
  184. return 0;
  185. }
  186. }
  187. if (!process("ITEM_DB", 1, { path_db_import }, "item_db", item_import_table_name, item_import_table_name, [](const std::string& path, const std::string& name_ext, const std::string& table) -> bool {
  188. return item_db_yaml2sql(path + name_ext, table);
  189. })) {
  190. return 0;
  191. }
  192. if (!process("MOB_DB", 1, { path_db_mode }, "mob_db", mob_table_name, mob_table_name, [](const std::string &path, const std::string &name_ext, const std::string &table) -> bool {
  193. return mob_db_yaml2sql(path + name_ext, table);
  194. })) {
  195. return 0;
  196. }
  197. if (!process("MOB_DB", 1, { path_db_import }, "mob_db", mob_import_table_name, mob_import_table_name, [](const std::string &path, const std::string &name_ext, const std::string &table) -> bool {
  198. return mob_db_yaml2sql(path + name_ext, table);
  199. })) {
  200. return 0;
  201. }
  202. // TODO: add implementations ;-)
  203. return 0;
  204. }
  205. void do_final(void){
  206. }
  207. bool fileExists( const std::string& path ){
  208. std::ifstream in;
  209. in.open( path );
  210. if( in.is_open() ){
  211. in.close();
  212. return true;
  213. }else{
  214. return false;
  215. }
  216. }
  217. bool askConfirmation( const char* fmt, ... ){
  218. va_list ap;
  219. va_start( ap, fmt );
  220. _vShowMessage( MSG_NONE, fmt, ap );
  221. va_end( ap );
  222. char c = getch();
  223. if( c == 'Y' || c == 'y' ){
  224. return true;
  225. }else{
  226. return false;
  227. }
  228. }
  229. std::string name2Upper(std::string name) {
  230. std::transform(name.begin(), name.end(), name.begin(), ::tolower);
  231. name[0] = toupper(name[0]);
  232. for (size_t i = 0; i < name.size(); i++) {
  233. if (name[i - 1] == '_' || (name[i - 2] == '1' && name[i - 1] == 'h') || (name[i - 2] == '2' && name[i - 1] == 'h'))
  234. name[i] = toupper(name[i]);
  235. }
  236. return name;
  237. }
  238. const std::string WHITESPACE = " \n\r\t\f\v";
  239. std::string ltrim(const std::string &s) {
  240. size_t start = s.find_first_not_of(WHITESPACE);
  241. return (start == std::string::npos) ? "" : s.substr(start);
  242. }
  243. std::string rtrim(const std::string &s) {
  244. size_t end = s.find_last_not_of(WHITESPACE);
  245. return (end == std::string::npos) ? "" : s.substr(0, end + 1);
  246. }
  247. std::string string_trim(const std::string &s) {
  248. return rtrim(ltrim(s));
  249. }
  250. std::string string_escape(const std::string &s) {
  251. size_t n = s.length();
  252. std::string escaped;
  253. escaped.reserve(n * 2);
  254. for (size_t i = 0; i < n; ++i) {
  255. if (s[i] == '\r')
  256. continue;
  257. if (s[i] == '\n' && (i + 1) < n) {
  258. escaped += "\\n";
  259. continue;
  260. }
  261. if (s[i] == '\\' || s[i] == '\'')
  262. escaped += '\\';
  263. escaped += s[i];
  264. }
  265. return escaped;
  266. }
  267. /**
  268. * Append the entry value to the string if the Node exists
  269. * @param node: Node with entry
  270. * @param value: String to store node value to
  271. * @param string: If value is a string or not
  272. */
  273. static bool appendEntry(const YAML::Node &node, std::string &value, bool string = false) {
  274. if (node.IsDefined()) {
  275. if (string) {
  276. value.append("'");
  277. value.append(string_trim(string_escape(node.as<std::string>())));
  278. value.append("',");
  279. } else {
  280. value.append(string_trim(node.as<std::string>()));
  281. value.append(",");
  282. }
  283. return true;
  284. }
  285. return false;
  286. }
  287. // Implementation of the conversion functions
  288. // Copied and adjusted from itemdb.cpp
  289. static bool item_db_yaml2sql(const std::string &file, const std::string &table) {
  290. size_t entries = 0;
  291. for (const YAML::Node &input : inNode["Body"]) {
  292. std::string column = "", value = "";
  293. if (appendEntry(input["Id"], value))
  294. column.append("`id`,");
  295. if (appendEntry(input["AegisName"], value, true))
  296. column.append("`name_aegis`,");
  297. if (appendEntry(input["Name"], value, true))
  298. column.append("`name_english`,");
  299. if (appendEntry(input["Type"], value, true))
  300. column.append("`type`,");
  301. if (appendEntry(input["SubType"], value, true))
  302. column.append("`subtype`,");
  303. if (appendEntry(input["Buy"], value))
  304. column.append("`price_buy`,");
  305. if (appendEntry(input["Sell"], value))
  306. column.append("`price_sell`,");
  307. if (appendEntry(input["Weight"], value))
  308. column.append("`weight`,");
  309. if (appendEntry(input["Attack"], value))
  310. column.append("`attack`,");
  311. #ifdef RENEWAL
  312. if (appendEntry(input["MagicAttack"], value))
  313. column.append("`magic_attack`,");
  314. #endif
  315. if (appendEntry(input["Defense"], value))
  316. column.append("`defense`,");
  317. if (appendEntry(input["Range"], value))
  318. column.append("`range`,");
  319. if (appendEntry(input["Slots"], value))
  320. column.append("`slots`,");
  321. const YAML::Node &jobs = input["Jobs"];
  322. if (jobs) {
  323. if (appendEntry(jobs["All"], value))
  324. column.append("`job_all`,");
  325. if (appendEntry(jobs["Acolyte"], value))
  326. column.append("`job_acolyte`,");
  327. if (appendEntry(jobs["Alchemist"], value))
  328. column.append("`job_alchemist`,");
  329. if (appendEntry(jobs["Archer"], value))
  330. column.append("`job_archer`,");
  331. if (appendEntry(jobs["Assassin"], value))
  332. column.append("`job_assassin`,");
  333. if (appendEntry(jobs["BardDancer"], value))
  334. column.append("`job_barddancer`,");
  335. if (appendEntry(jobs["Blacksmith"], value))
  336. column.append("`job_blacksmith`,");
  337. if (appendEntry(jobs["Crusader"], value))
  338. column.append("`job_crusader`,");
  339. if (appendEntry(jobs["Gunslinger"], value))
  340. column.append("`job_gunslinger`,");
  341. if (appendEntry(jobs["Hunter"], value))
  342. column.append("`job_hunter`,");
  343. #ifdef RENEWAL
  344. if (appendEntry(jobs["KagerouOboro"], value))
  345. column.append("`job_kagerouoboro`,");
  346. #endif
  347. if (appendEntry(jobs["Knight"], value))
  348. column.append("`job_knight`,");
  349. if (appendEntry(jobs["Mage"], value))
  350. column.append("`job_mage`,");
  351. if (appendEntry(jobs["Merchant"], value))
  352. column.append("`job_merchant`,");
  353. if (appendEntry(jobs["Monk"], value))
  354. column.append("`job_monk`,");
  355. if (appendEntry(jobs["Ninja"], value))
  356. column.append("`job_ninja`,");
  357. if (appendEntry(jobs["Novice"], value))
  358. column.append("`job_novice`,");
  359. if (appendEntry(jobs["Priest"], value))
  360. column.append("`job_priest`,");
  361. #ifdef RENEWAL
  362. if (appendEntry(jobs["Rebellion"], value))
  363. column.append("`job_rebellion`,");
  364. #endif
  365. if (appendEntry(jobs["Rogue"], value))
  366. column.append("`job_rogue`,");
  367. if (appendEntry(jobs["Sage"], value))
  368. column.append("`job_sage`,");
  369. if (appendEntry(jobs["SoulLinker"], value))
  370. column.append("`job_soullinker`,");
  371. #ifdef RENEWAL
  372. if (appendEntry(jobs["Spirit_Handler"], value))
  373. column.append("`job_spirit_handler`,");
  374. #endif
  375. if (appendEntry(jobs["StarGladiator"], value))
  376. column.append("`job_stargladiator`,");
  377. #ifdef RENEWAL
  378. if (appendEntry(jobs["Summoner"], value))
  379. column.append("`job_summoner`,");
  380. #endif
  381. if (appendEntry(jobs["SuperNovice"], value))
  382. column.append("`job_supernovice`,");
  383. if (appendEntry(jobs["Swordman"], value))
  384. column.append("`job_swordman`,");
  385. if (appendEntry(jobs["Taekwon"], value))
  386. column.append("`job_taekwon`,");
  387. if (appendEntry(jobs["Thief"], value))
  388. column.append("`job_thief`,");
  389. if (appendEntry(jobs["Wizard"], value))
  390. column.append("`job_wizard`,");
  391. }
  392. const YAML::Node &classes = input["Classes"];
  393. if (classes) {
  394. std::string str_all_upper;
  395. std::string str_all_baby;
  396. if (classes["All_Upper"].IsDefined())
  397. str_all_upper = string_trim(classes["All_Upper"].as<std::string>());
  398. if (classes["All_Baby"].IsDefined())
  399. str_all_baby = string_trim(classes["All_Baby"].as<std::string>());
  400. if (appendEntry(classes["All"], value))
  401. column.append("`class_all`,");
  402. if (appendEntry(classes["Normal"], value))
  403. column.append("`class_normal`,");
  404. if (appendEntry(classes["Upper"], value))
  405. column.append("`class_upper`,");
  406. else if (!str_all_upper.empty()) {
  407. value.append(str_all_upper);
  408. value.append(",");
  409. column.append("`class_upper`,");
  410. }
  411. if (appendEntry(classes["Baby"], value))
  412. column.append("`class_baby`,");
  413. else if (!str_all_baby.empty()) {
  414. value.append(str_all_baby);
  415. value.append(",");
  416. column.append("`class_baby`,");
  417. }
  418. #ifdef RENEWAL
  419. std::string str_all_third;
  420. if (classes["All_Third"].IsDefined())
  421. str_all_third = string_trim(classes["All_Third"].as<std::string>());
  422. if (appendEntry(classes["Third"], value))
  423. column.append("`class_third`,");
  424. else if (!str_all_third.empty()) {
  425. value.append(str_all_third);
  426. value.append(",");
  427. column.append("`class_third`,");
  428. }
  429. if (appendEntry(classes["Third_Upper"], value))
  430. column.append("`class_third_upper`,");
  431. else if (!str_all_upper.empty() || !str_all_third.empty()) {
  432. if (!str_all_upper.empty())
  433. value.append(str_all_upper);
  434. else
  435. value.append(str_all_third);
  436. value.append(",");
  437. column.append("`class_third_upper`,");
  438. }
  439. if (appendEntry(classes["Third_Baby"], value))
  440. column.append("`class_third_baby`,");
  441. else if (!str_all_baby.empty() || !str_all_third.empty()) {
  442. if (!str_all_baby.empty())
  443. value.append(str_all_baby);
  444. else
  445. value.append(str_all_third);
  446. value.append(",");
  447. column.append("`class_third_baby`,");
  448. }
  449. if (appendEntry(classes["Fourth"], value))
  450. column.append("`class_fourth`,");
  451. #endif
  452. }
  453. if (appendEntry(input["Gender"], value, true))
  454. column.append("`gender`,");
  455. const YAML::Node &locations = input["Locations"];
  456. if (locations) {
  457. if (appendEntry(locations["Head_Top"], value))
  458. column.append("`location_head_top`,");
  459. if (appendEntry(locations["Head_Mid"], value))
  460. column.append("`location_head_mid`,");
  461. if (appendEntry(locations["Head_Low"], value))
  462. column.append("`location_head_low`,");
  463. if (appendEntry(locations["Armor"], value))
  464. column.append("`location_armor`,");
  465. if (locations["Both_Hand"].IsDefined()) {
  466. std::string tmp_value = string_trim(locations["Both_Hand"].as<std::string>());
  467. if (!appendEntry(locations["Left_Hand"], value)) {
  468. value.append(tmp_value);
  469. value.append(",");
  470. }
  471. if (!appendEntry(locations["Right_Hand"], value)) {
  472. value.append(tmp_value);
  473. value.append(",");
  474. }
  475. column.append("`location_left_hand`,");
  476. column.append("`location_right_hand`,");
  477. }
  478. else {
  479. if (appendEntry(locations["Left_Hand"], value))
  480. column.append("`location_left_hand`,");
  481. if (appendEntry(locations["Right_Hand"], value))
  482. column.append("`location_right_hand`,");
  483. }
  484. if (appendEntry(locations["Garment"], value))
  485. column.append("`location_garment`,");
  486. if (appendEntry(locations["Shoes"], value))
  487. column.append("`location_shoes`,");
  488. if (locations["Both_Accessory"].IsDefined()) {
  489. std::string tmp_value = string_trim(locations["Both_Accessory"].as<std::string>());
  490. if (!appendEntry(locations["Right_Accessory"], value)) {
  491. value.append(tmp_value);
  492. value.append(",");
  493. }
  494. if (!appendEntry(locations["Left_Accessory"], value)) {
  495. value.append(tmp_value);
  496. value.append(",");
  497. }
  498. column.append("`location_right_accessory`,");
  499. column.append("`location_left_accessory`,");
  500. }
  501. else {
  502. if (appendEntry(locations["Right_Accessory"], value))
  503. column.append("`location_right_accessory`,");
  504. if (appendEntry(locations["Left_Accessory"], value))
  505. column.append("`location_left_accessory`,");
  506. }
  507. if (appendEntry(locations["Costume_Head_Top"], value))
  508. column.append("`location_costume_head_top`,");
  509. if (appendEntry(locations["Costume_Head_Mid"], value))
  510. column.append("`location_costume_head_Mid`,");
  511. if (appendEntry(locations["Costume_Head_Low"], value))
  512. column.append("`location_costume_head_Low`,");
  513. if (appendEntry(locations["Costume_Garment"], value))
  514. column.append("`location_costume_garment`,");
  515. if (appendEntry(locations["Ammo"], value))
  516. column.append("`location_ammo`,");
  517. if (appendEntry(locations["Shadow_Armor"], value))
  518. column.append("`location_shadow_armor`,");
  519. if (appendEntry(locations["Shadow_Weapon"], value))
  520. column.append("`location_shadow_weapon`,");
  521. if (appendEntry(locations["Shadow_Shield"], value))
  522. column.append("`location_shadow_shield`,");
  523. if (appendEntry(locations["Shadow_Shoes"], value))
  524. column.append("`location_shadow_shoes`,");
  525. if (appendEntry(locations["Shadow_Right_Accessory"], value))
  526. column.append("`location_shadow_right_accessory`,");
  527. if (appendEntry(locations["Shadow_Left_Accessory"], value))
  528. column.append("`location_shadow_left_accessory`,");
  529. }
  530. if (appendEntry(input["WeaponLevel"], value))
  531. column.append("`weapon_level`,");
  532. if (appendEntry(input["ArmorLevel"], value))
  533. column.append("`armor_level`,");
  534. if (appendEntry(input["EquipLevelMin"], value))
  535. column.append("`equip_level_min`,");
  536. if (appendEntry(input["EquipLevelMax"], value))
  537. column.append("`equip_level_max`,");
  538. if (appendEntry(input["Refineable"], value))
  539. column.append("`refineable`,");
  540. if (appendEntry(input["Gradable"], value))
  541. column.append("`gradable`,");
  542. if (appendEntry(input["View"], value))
  543. column.append("`view`,");
  544. if (appendEntry(input["AliasName"], value, true))
  545. column.append("`alias_name`,");
  546. const YAML::Node &flags = input["Flags"];
  547. if (flags) {
  548. if (appendEntry(flags["BuyingStore"], value))
  549. column.append("`flag_buyingstore`,");
  550. if (appendEntry(flags["DeadBranch"], value))
  551. column.append("`flag_deadbranch`,");
  552. if (appendEntry(flags["Container"], value))
  553. column.append("`flag_container`,");
  554. if (appendEntry(flags["UniqueId"], value))
  555. column.append("`flag_uniqueid`,");
  556. if (appendEntry(flags["BindOnEquip"], value))
  557. column.append("`flag_bindonequip`,");
  558. if (appendEntry(flags["DropAnnounce"], value))
  559. column.append("`flag_dropannounce`,");
  560. if (appendEntry(flags["NoConsume"], value))
  561. column.append("`flag_noconsume`,");
  562. if (appendEntry(flags["DropEffect"], value, true))
  563. column.append("`flag_dropeffect`,");
  564. }
  565. const YAML::Node &delay = input["Delay"];
  566. if (delay) {
  567. if (appendEntry(delay["Duration"], value))
  568. column.append("`delay_duration`,");
  569. if (appendEntry(delay["Status"], value, true))
  570. column.append("`delay_status`,");
  571. }
  572. const YAML::Node &stack = input["Stack"];
  573. if (stack) {
  574. if (appendEntry(stack["Amount"], value))
  575. column.append("`stack_amount`,");
  576. if (appendEntry(stack["Inventory"], value))
  577. column.append("`stack_inventory`,");
  578. if (appendEntry(stack["Cart"], value))
  579. column.append("`stack_cart`,");
  580. if (appendEntry(stack["Storage"], value))
  581. column.append("`stack_storage`,");
  582. if (appendEntry(stack["GuildStorage"], value))
  583. column.append("`stack_guildstorage`,");
  584. }
  585. const YAML::Node &nouse = input["NoUse"];
  586. if (nouse) {
  587. if (appendEntry(nouse["Override"], value))
  588. column.append("`nouse_override`,");
  589. if (appendEntry(nouse["Sitting"], value))
  590. column.append("`nouse_sitting`,");
  591. }
  592. const YAML::Node &trade = input["Trade"];
  593. if (trade) {
  594. if (appendEntry(trade["Override"], value))
  595. column.append("`trade_override`,");
  596. if (appendEntry(trade["NoDrop"], value))
  597. column.append("`trade_nodrop`,");
  598. if (appendEntry(trade["NoTrade"], value))
  599. column.append("`trade_notrade`,");
  600. if (appendEntry(trade["TradePartner"], value))
  601. column.append("`trade_tradepartner`,");
  602. if (appendEntry(trade["NoSell"], value))
  603. column.append("`trade_nosell`,");
  604. if (appendEntry(trade["NoCart"], value))
  605. column.append("`trade_nocart`,");
  606. if (appendEntry(trade["NoStorage"], value))
  607. column.append("`trade_nostorage`,");
  608. if (appendEntry(trade["NoGuildStorage"], value))
  609. column.append("`trade_noguildstorage`,");
  610. if (appendEntry(trade["NoMail"], value))
  611. column.append("`trade_nomail`,");
  612. if (appendEntry(trade["NoAuction"], value))
  613. column.append("`trade_noauction`,");
  614. }
  615. if (appendEntry(input["Script"], value, true))
  616. column.append("`script`,");
  617. if (appendEntry(input["EquipScript"], value, true))
  618. column.append("`equip_script`,");
  619. if (appendEntry(input["UnEquipScript"], value, true))
  620. column.append("`unequip_script`,");
  621. column.pop_back(); // Remove last ','
  622. value.pop_back(); // Remove last ','
  623. outFile << "REPLACE INTO `" + table + "` (" + column + ") VALUES (" + value + ");\n";
  624. entries++;
  625. }
  626. ShowStatus("Done converting '" CL_WHITE "%zu" CL_RESET "' items in '" CL_WHITE "%s" CL_RESET "'.\n", entries, file.c_str());
  627. return true;
  628. }
  629. // Copied and adjusted from mob.cpp
  630. static bool mob_db_yaml2sql(const std::string &file, const std::string &table) {
  631. size_t entries = 0;
  632. for (const YAML::Node &input : inNode["Body"]) {
  633. std::string column = "", value = "";
  634. if (appendEntry(input["Id"], value))
  635. column.append("`id`,");
  636. if (appendEntry(input["AegisName"], value, true))
  637. column.append("`name_aegis`,");
  638. if (appendEntry(input["Name"], value, true))
  639. column.append("`name_english`,");
  640. if (appendEntry(input["Name"], value, true))
  641. column.append("`name_japanese`,");
  642. if (appendEntry(input["Level"], value))
  643. column.append("`level`,");
  644. if (appendEntry(input["Hp"], value))
  645. column.append("`hp`,");
  646. if (appendEntry(input["Sp"], value))
  647. column.append("`sp`,");
  648. if (appendEntry(input["BaseExp"], value))
  649. column.append("`base_exp`,");
  650. if (appendEntry(input["JobExp"], value))
  651. column.append("`job_exp`,");
  652. if (appendEntry(input["MvpExp"], value))
  653. column.append("`mvp_exp`,");
  654. if (appendEntry(input["Attack"], value))
  655. column.append("`attack`,");
  656. if (appendEntry(input["Attack2"], value))
  657. column.append("`attack2`,");
  658. if (appendEntry(input["Defense"], value))
  659. column.append("`defense`,");
  660. if (appendEntry(input["MagicDefense"], value))
  661. column.append("`magic_defense`,");
  662. #ifdef RENEWAL
  663. if (appendEntry(input["Resistance"], value))
  664. column.append("`resistance`,");
  665. if (appendEntry(input["MagicResistance"], value))
  666. column.append("`magic_resistance`,");
  667. #endif
  668. if (appendEntry(input["Str"], value))
  669. column.append("`str`,");
  670. if (appendEntry(input["Agi"], value))
  671. column.append("`agi`,");
  672. if (appendEntry(input["Vit"], value))
  673. column.append("`vit`,");
  674. if (appendEntry(input["Int"], value))
  675. column.append("`int`,");
  676. if (appendEntry(input["Dex"], value))
  677. column.append("`dex`,");
  678. if (appendEntry(input["Luk"], value))
  679. column.append("`luk`,");
  680. if (appendEntry(input["AttackRange"], value))
  681. column.append("`attack_range`,");
  682. if (appendEntry(input["SkillRange"], value))
  683. column.append("`skill_range`,");
  684. if (appendEntry(input["ChaseRange"], value))
  685. column.append("`chase_range`,");
  686. if (appendEntry(input["Size"], value, true))
  687. column.append("`size`,");
  688. if (appendEntry(input["Race"], value, true))
  689. column.append("`race`,");
  690. const YAML::Node &racegroups = input["RaceGroups"];
  691. if (racegroups) {
  692. for (uint16 i = 1; i < RC2_MAX; i++) {
  693. std::string constant = constant_lookup(i, "RC2_");
  694. constant.erase(0, 4);
  695. if (appendEntry(racegroups[name2Upper(constant)], value)) {
  696. std::transform(constant.begin(), constant.end(), constant.begin(), ::tolower);
  697. column.append("`racegroup_" + constant + "`,");
  698. }
  699. }
  700. }
  701. if (appendEntry(input["Element"], value, true))
  702. column.append("`element`,");
  703. if (appendEntry(input["ElementLevel"], value))
  704. column.append("`element_level`,");
  705. if (appendEntry(input["WalkSpeed"], value))
  706. column.append("`walk_speed`,");
  707. if (appendEntry(input["AttackDelay"], value))
  708. column.append("`attack_delay`,");
  709. if (appendEntry(input["AttackMotion"], value))
  710. column.append("`attack_motion`,");
  711. if (appendEntry(input["DamageMotion"], value))
  712. column.append("`damage_motion`,");
  713. if (appendEntry(input["DamageTaken"], value))
  714. column.append("`damage_taken`,");
  715. if (appendEntry(input["Ai"], value, true))
  716. column.append("`ai`,");
  717. if (appendEntry(input["Class"], value, true))
  718. column.append("`class`,");
  719. const YAML::Node &modes = input["Modes"];
  720. if (modes) {
  721. if (appendEntry(modes["CanMove"], value))
  722. column.append("`mode_canmove`,");
  723. if (appendEntry(modes["Looter"], value))
  724. column.append("`mode_looter`,");
  725. if (appendEntry(modes["Aggressive"], value))
  726. column.append("`mode_aggressive`,");
  727. if (appendEntry(modes["Assist"], value))
  728. column.append("`mode_assist`,");
  729. if (appendEntry(modes["CastSensorIdle"], value))
  730. column.append("`mode_castsensoridle`,");
  731. if (appendEntry(modes["NoRandomWalk"], value))
  732. column.append("`mode_norandomwalk`,");
  733. if (appendEntry(modes["NoCast"], value))
  734. column.append("`mode_nocast`,");
  735. if (appendEntry(modes["CanAttack"], value))
  736. column.append("`mode_canattack`,");
  737. if (appendEntry(modes["CastSensorChase"], value))
  738. column.append("`mode_castsensorchase`,");
  739. if (appendEntry(modes["ChangeChase"], value))
  740. column.append("`mode_changechase`,");
  741. if (appendEntry(modes["Angry"], value))
  742. column.append("`mode_angry`,");
  743. if (appendEntry(modes["ChangeTargetMelee"], value))
  744. column.append("`mode_changetargetmelee`,");
  745. if (appendEntry(modes["ChangeTargetChase"], value))
  746. column.append("`mode_changetargetchase`,");
  747. if (appendEntry(modes["TargetWeak"], value))
  748. column.append("`mode_targetweak`,");
  749. if (appendEntry(modes["RandomTarget"], value))
  750. column.append("`mode_randomtarget`,");
  751. if (appendEntry(modes["IgnoreMelee"], value))
  752. column.append("`mode_ignoremelee`,");
  753. if (appendEntry(modes["IgnoreMagic"], value))
  754. column.append("`mode_ignoremagic`,");
  755. if (appendEntry(modes["IgnoreRanged"], value))
  756. column.append("`mode_ignoreranged`,");
  757. if (appendEntry(modes["Mvp"], value))
  758. column.append("`mode_mvp`,");
  759. if (appendEntry(modes["IgnoreMisc"], value))
  760. column.append("`mode_ignoremisc`,");
  761. if (appendEntry(modes["KnockBackImmune"], value))
  762. column.append("`mode_knockbackimmune`,");
  763. if (appendEntry(modes["TeleportBlock"], value))
  764. column.append("`mode_teleportblock`,");
  765. if (appendEntry(modes["FixedItemDrop"], value))
  766. column.append("`mode_fixeditemdrop`,");
  767. if (appendEntry(modes["Detector"], value))
  768. column.append("`mode_detector`,");
  769. if (appendEntry(modes["StatusImmune"], value))
  770. column.append("`mode_statusimmune`,");
  771. if (appendEntry(modes["SkillImmune"], value))
  772. column.append("`mode_skillimmune`,");
  773. }
  774. for (uint16 i = 0; i < MAX_MVP_DROP; i++) {
  775. if (!input["MvpDrops"].IsDefined())
  776. continue;
  777. const YAML::Node &mvpdrops = input["MvpDrops"][i];
  778. if (mvpdrops) {
  779. if (appendEntry(mvpdrops["Item"], value, true))
  780. column.append("`mvpdrop" + std::to_string(i + 1) + "_item`,");
  781. if (appendEntry(mvpdrops["Rate"], value))
  782. column.append("`mvpdrop" + std::to_string(i + 1) + "_rate`,");
  783. if (appendEntry(mvpdrops["RandomOptionGroup"], value, true))
  784. column.append("`mvpdrop" + std::to_string(i + 1) + "_option`,");
  785. if (appendEntry(mvpdrops["Index"], value))
  786. column.append("`mvpdrop" + std::to_string(i + 1) + "_index`,");
  787. }
  788. }
  789. for (uint16 i = 0; i < MAX_MOB_DROP; i++) {
  790. if (!input["Drops"].IsDefined())
  791. continue;
  792. const YAML::Node &drops = input["Drops"][i];
  793. if (drops) {
  794. if (appendEntry(drops["Item"], value, true))
  795. column.append("`drop" + std::to_string(i + 1) + "_item`,");
  796. if (appendEntry(drops["Rate"], value))
  797. column.append("`drop" + std::to_string(i + 1) + "_rate`,");
  798. if (appendEntry(drops["StealProtected"], value))
  799. column.append("`drop" + std::to_string(i + 1) + "_nosteal`,");
  800. if (appendEntry(drops["RandomOptionGroup"], value, true))
  801. column.append("`drop" + std::to_string(i + 1) + "_option`,");
  802. if (appendEntry(drops["Index"], value))
  803. column.append("`drop" + std::to_string(i + 1) + "_index`,");
  804. }
  805. }
  806. column.pop_back(); // Remove last ','
  807. value.pop_back(); // Remove last ','
  808. outFile << "REPLACE INTO `" + table + "` (" + column + ") VALUES (" + value + ");\n";
  809. entries++;
  810. }
  811. ShowStatus("Done converting '" CL_WHITE "%zu" CL_RESET "' mobs in '" CL_WHITE "%s" CL_RESET "'.\n", entries, file.c_str());
  812. return true;
  813. }