You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1078 lines
31 KiB

  1. /*
  2. Minetest
  3. Copyright (C) 2013 sapier
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "lua_api/l_mainmenu.h"
  17. #include "lua_api/l_internal.h"
  18. #include "common/c_content.h"
  19. #include "cpp_api/s_async.h"
  20. #include "guiEngine.h"
  21. #include "guiMainMenu.h"
  22. #include "guiKeyChangeMenu.h"
  23. #include "guiPathSelectMenu.h"
  24. #include "subgame.h"
  25. #include "version.h"
  26. #include "porting.h"
  27. #include "filesys.h"
  28. #include "convert_json.h"
  29. #include "serverlist.h"
  30. #include "mapgen.h"
  31. #include "settings.h"
  32. #include <IFileArchive.h>
  33. #include <IFileSystem.h>
  34. #include "client/renderingengine.h"
  35. /******************************************************************************/
  36. std::string ModApiMainMenu::getTextData(lua_State *L, std::string name)
  37. {
  38. lua_getglobal(L, "gamedata");
  39. lua_getfield(L, -1, name.c_str());
  40. if(lua_isnil(L, -1))
  41. return "";
  42. return luaL_checkstring(L, -1);
  43. }
  44. /******************************************************************************/
  45. int ModApiMainMenu::getIntegerData(lua_State *L, std::string name,bool& valid)
  46. {
  47. lua_getglobal(L, "gamedata");
  48. lua_getfield(L, -1, name.c_str());
  49. if(lua_isnil(L, -1)) {
  50. valid = false;
  51. return -1;
  52. }
  53. valid = true;
  54. return luaL_checkinteger(L, -1);
  55. }
  56. /******************************************************************************/
  57. int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid)
  58. {
  59. lua_getglobal(L, "gamedata");
  60. lua_getfield(L, -1, name.c_str());
  61. if(lua_isnil(L, -1)) {
  62. valid = false;
  63. return false;
  64. }
  65. valid = true;
  66. return readParam<bool>(L, -1);
  67. }
  68. /******************************************************************************/
  69. int ModApiMainMenu::l_update_formspec(lua_State *L)
  70. {
  71. GUIEngine* engine = getGuiEngine(L);
  72. sanity_check(engine != NULL);
  73. if (engine->m_startgame)
  74. return 0;
  75. //read formspec
  76. std::string formspec(luaL_checkstring(L, 1));
  77. if (engine->m_formspecgui != 0) {
  78. engine->m_formspecgui->setForm(formspec);
  79. }
  80. return 0;
  81. }
  82. /******************************************************************************/
  83. int ModApiMainMenu::l_start(lua_State *L)
  84. {
  85. GUIEngine* engine = getGuiEngine(L);
  86. sanity_check(engine != NULL);
  87. //update c++ gamedata from lua table
  88. bool valid = false;
  89. MainMenuData *data = engine->m_data;
  90. data->selected_world = getIntegerData(L, "selected_world",valid) -1;
  91. data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
  92. data->do_reconnect = getBoolData(L, "do_reconnect", valid);
  93. if (!data->do_reconnect) {
  94. data->name = getTextData(L,"playername");
  95. data->password = getTextData(L,"password");
  96. data->address = getTextData(L,"address");
  97. data->port = getTextData(L,"port");
  98. }
  99. data->serverdescription = getTextData(L,"serverdescription");
  100. data->servername = getTextData(L,"servername");
  101. //close menu next time
  102. engine->m_startgame = true;
  103. return 0;
  104. }
  105. /******************************************************************************/
  106. int ModApiMainMenu::l_close(lua_State *L)
  107. {
  108. GUIEngine* engine = getGuiEngine(L);
  109. sanity_check(engine != NULL);
  110. engine->m_kill = true;
  111. return 0;
  112. }
  113. /******************************************************************************/
  114. int ModApiMainMenu::l_set_background(lua_State *L)
  115. {
  116. GUIEngine* engine = getGuiEngine(L);
  117. sanity_check(engine != NULL);
  118. std::string backgroundlevel(luaL_checkstring(L, 1));
  119. std::string texturename(luaL_checkstring(L, 2));
  120. bool tile_image = false;
  121. bool retval = false;
  122. unsigned int minsize = 16;
  123. if (!lua_isnone(L, 3)) {
  124. tile_image = readParam<bool>(L, 3);
  125. }
  126. if (!lua_isnone(L, 4)) {
  127. minsize = lua_tonumber(L, 4);
  128. }
  129. if (backgroundlevel == "background") {
  130. retval |= engine->setTexture(TEX_LAYER_BACKGROUND, texturename,
  131. tile_image, minsize);
  132. }
  133. if (backgroundlevel == "overlay") {
  134. retval |= engine->setTexture(TEX_LAYER_OVERLAY, texturename,
  135. tile_image, minsize);
  136. }
  137. if (backgroundlevel == "header") {
  138. retval |= engine->setTexture(TEX_LAYER_HEADER, texturename,
  139. tile_image, minsize);
  140. }
  141. if (backgroundlevel == "footer") {
  142. retval |= engine->setTexture(TEX_LAYER_FOOTER, texturename,
  143. tile_image, minsize);
  144. }
  145. lua_pushboolean(L,retval);
  146. return 1;
  147. }
  148. /******************************************************************************/
  149. int ModApiMainMenu::l_set_clouds(lua_State *L)
  150. {
  151. GUIEngine* engine = getGuiEngine(L);
  152. sanity_check(engine != NULL);
  153. bool value = readParam<bool>(L,1);
  154. engine->m_clouds_enabled = value;
  155. return 0;
  156. }
  157. /******************************************************************************/
  158. int ModApiMainMenu::l_get_textlist_index(lua_State *L)
  159. {
  160. // get_table_index accepts both tables and textlists
  161. return l_get_table_index(L);
  162. }
  163. /******************************************************************************/
  164. int ModApiMainMenu::l_get_table_index(lua_State *L)
  165. {
  166. GUIEngine* engine = getGuiEngine(L);
  167. sanity_check(engine != NULL);
  168. std::string tablename(luaL_checkstring(L, 1));
  169. GUITable *table = engine->m_menu->getTable(tablename);
  170. s32 selection = table ? table->getSelected() : 0;
  171. if (selection >= 1)
  172. lua_pushinteger(L, selection);
  173. else
  174. lua_pushnil(L);
  175. return 1;
  176. }
  177. /******************************************************************************/
  178. int ModApiMainMenu::l_get_worlds(lua_State *L)
  179. {
  180. std::vector<WorldSpec> worlds = getAvailableWorlds();
  181. lua_newtable(L);
  182. int top = lua_gettop(L);
  183. unsigned int index = 1;
  184. for (unsigned int i = 0; i < worlds.size(); i++)
  185. {
  186. lua_pushnumber(L,index);
  187. lua_newtable(L);
  188. int top_lvl2 = lua_gettop(L);
  189. lua_pushstring(L,"path");
  190. lua_pushstring(L,worlds[i].path.c_str());
  191. lua_settable(L, top_lvl2);
  192. lua_pushstring(L,"name");
  193. lua_pushstring(L,worlds[i].name.c_str());
  194. lua_settable(L, top_lvl2);
  195. lua_pushstring(L,"gameid");
  196. lua_pushstring(L,worlds[i].gameid.c_str());
  197. lua_settable(L, top_lvl2);
  198. lua_settable(L, top);
  199. index++;
  200. }
  201. return 1;
  202. }
  203. /******************************************************************************/
  204. int ModApiMainMenu::l_get_games(lua_State *L)
  205. {
  206. std::vector<SubgameSpec> games = getAvailableGames();
  207. lua_newtable(L);
  208. int top = lua_gettop(L);
  209. unsigned int index = 1;
  210. for (unsigned int i = 0; i < games.size(); i++)
  211. {
  212. lua_pushnumber(L,index);
  213. lua_newtable(L);
  214. int top_lvl2 = lua_gettop(L);
  215. lua_pushstring(L,"id");
  216. lua_pushstring(L,games[i].id.c_str());
  217. lua_settable(L, top_lvl2);
  218. lua_pushstring(L,"path");
  219. lua_pushstring(L,games[i].path.c_str());
  220. lua_settable(L, top_lvl2);
  221. lua_pushstring(L,"gamemods_path");
  222. lua_pushstring(L,games[i].gamemods_path.c_str());
  223. lua_settable(L, top_lvl2);
  224. lua_pushstring(L,"name");
  225. lua_pushstring(L,games[i].name.c_str());
  226. lua_settable(L, top_lvl2);
  227. lua_pushstring(L,"menuicon_path");
  228. lua_pushstring(L,games[i].menuicon_path.c_str());
  229. lua_settable(L, top_lvl2);
  230. lua_pushstring(L,"addon_mods_paths");
  231. lua_newtable(L);
  232. int table2 = lua_gettop(L);
  233. int internal_index=1;
  234. for (std::set<std::string>::iterator iter = games[i].addon_mods_paths.begin();
  235. iter != games[i].addon_mods_paths.end(); ++iter) {
  236. lua_pushnumber(L,internal_index);
  237. lua_pushstring(L,(*iter).c_str());
  238. lua_settable(L, table2);
  239. internal_index++;
  240. }
  241. lua_settable(L, top_lvl2);
  242. lua_settable(L, top);
  243. index++;
  244. }
  245. return 1;
  246. }
  247. /******************************************************************************/
  248. int ModApiMainMenu::l_get_mod_info(lua_State *L)
  249. {
  250. std::string path = luaL_checkstring(L, 1);
  251. ModSpec spec;
  252. spec.path = path;
  253. parseModContents(spec);
  254. lua_newtable(L);
  255. lua_pushstring(L, spec.name.c_str());
  256. lua_setfield(L, -2, "name");
  257. lua_pushstring(L, spec.is_modpack ? "modpack" : "mod");
  258. lua_setfield(L, -2, "type");
  259. lua_pushstring(L, spec.desc.c_str());
  260. lua_setfield(L, -2, "description");
  261. lua_pushstring(L, spec.path.c_str());
  262. lua_setfield(L, -2, "path");
  263. // Dependencies
  264. lua_newtable(L);
  265. int i = 1;
  266. for (const auto &dep : spec.depends) {
  267. lua_pushstring(L, dep.c_str());
  268. lua_rawseti(L, -2, i);
  269. i++;
  270. }
  271. lua_setfield(L, -2, "depends");
  272. // Optional Dependencies
  273. lua_newtable(L);
  274. i = 1;
  275. for (const auto &dep : spec.optdepends) {
  276. lua_pushstring(L, dep.c_str());
  277. lua_rawseti(L, -2, i);
  278. i++;
  279. }
  280. lua_setfield(L, -2, "optional_depends");
  281. return 1;
  282. }
  283. /******************************************************************************/
  284. int ModApiMainMenu::l_get_favorites(lua_State *L)
  285. {
  286. std::string listtype = "local";
  287. if (!lua_isnone(L,1)) {
  288. listtype = luaL_checkstring(L,1);
  289. }
  290. std::vector<ServerListSpec> servers;
  291. if(listtype == "online") {
  292. servers = ServerList::getOnline();
  293. } else {
  294. servers = ServerList::getLocal();
  295. }
  296. lua_newtable(L);
  297. int top = lua_gettop(L);
  298. unsigned int index = 1;
  299. for (unsigned int i = 0; i < servers.size(); i++)
  300. {
  301. lua_pushnumber(L,index);
  302. lua_newtable(L);
  303. int top_lvl2 = lua_gettop(L);
  304. if (servers[i]["clients"].asString().size()) {
  305. std::string clients_raw = servers[i]["clients"].asString();
  306. char* endptr = 0;
  307. int numbervalue = strtol(clients_raw.c_str(),&endptr,10);
  308. if ((clients_raw != "") && (*endptr == 0)) {
  309. lua_pushstring(L,"clients");
  310. lua_pushnumber(L,numbervalue);
  311. lua_settable(L, top_lvl2);
  312. }
  313. }
  314. if (servers[i]["clients_max"].asString().size()) {
  315. std::string clients_max_raw = servers[i]["clients_max"].asString();
  316. char* endptr = 0;
  317. int numbervalue = strtol(clients_max_raw.c_str(),&endptr,10);
  318. if ((clients_max_raw != "") && (*endptr == 0)) {
  319. lua_pushstring(L,"clients_max");
  320. lua_pushnumber(L,numbervalue);
  321. lua_settable(L, top_lvl2);
  322. }
  323. }
  324. if (servers[i]["version"].asString().size()) {
  325. lua_pushstring(L,"version");
  326. std::string topush = servers[i]["version"].asString();
  327. lua_pushstring(L,topush.c_str());
  328. lua_settable(L, top_lvl2);
  329. }
  330. if (servers[i]["proto_min"].asString().size()) {
  331. lua_pushstring(L,"proto_min");
  332. lua_pushinteger(L,servers[i]["proto_min"].asInt());
  333. lua_settable(L, top_lvl2);
  334. }
  335. if (servers[i]["proto_max"].asString().size()) {
  336. lua_pushstring(L,"proto_max");
  337. lua_pushinteger(L,servers[i]["proto_max"].asInt());
  338. lua_settable(L, top_lvl2);
  339. }
  340. if (servers[i]["password"].asString().size()) {
  341. lua_pushstring(L,"password");
  342. lua_pushboolean(L,servers[i]["password"].asBool());
  343. lua_settable(L, top_lvl2);
  344. }
  345. if (servers[i]["creative"].asString().size()) {
  346. lua_pushstring(L,"creative");
  347. lua_pushboolean(L,servers[i]["creative"].asBool());
  348. lua_settable(L, top_lvl2);
  349. }
  350. if (servers[i]["damage"].asString().size()) {
  351. lua_pushstring(L,"damage");
  352. lua_pushboolean(L,servers[i]["damage"].asBool());
  353. lua_settable(L, top_lvl2);
  354. }
  355. if (servers[i]["pvp"].asString().size()) {
  356. lua_pushstring(L,"pvp");
  357. lua_pushboolean(L,servers[i]["pvp"].asBool());
  358. lua_settable(L, top_lvl2);
  359. }
  360. if (servers[i]["description"].asString().size()) {
  361. lua_pushstring(L,"description");
  362. std::string topush = servers[i]["description"].asString();
  363. lua_pushstring(L,topush.c_str());
  364. lua_settable(L, top_lvl2);
  365. }
  366. if (servers[i]["name"].asString().size()) {
  367. lua_pushstring(L,"name");
  368. std::string topush = servers[i]["name"].asString();
  369. lua_pushstring(L,topush.c_str());
  370. lua_settable(L, top_lvl2);
  371. }
  372. if (servers[i]["address"].asString().size()) {
  373. lua_pushstring(L,"address");
  374. std::string topush = servers[i]["address"].asString();
  375. lua_pushstring(L,topush.c_str());
  376. lua_settable(L, top_lvl2);
  377. }
  378. if (servers[i]["port"].asString().size()) {
  379. lua_pushstring(L,"port");
  380. std::string topush = servers[i]["port"].asString();
  381. lua_pushstring(L,topush.c_str());
  382. lua_settable(L, top_lvl2);
  383. }
  384. if (servers[i].isMember("ping")) {
  385. float ping = servers[i]["ping"].asFloat();
  386. lua_pushstring(L, "ping");
  387. lua_pushnumber(L, ping);
  388. lua_settable(L, top_lvl2);
  389. }
  390. lua_settable(L, top);
  391. index++;
  392. }
  393. return 1;
  394. }
  395. /******************************************************************************/
  396. int ModApiMainMenu::l_delete_favorite(lua_State *L)
  397. {
  398. std::vector<ServerListSpec> servers;
  399. std::string listtype = "local";
  400. if (!lua_isnone(L,2)) {
  401. listtype = luaL_checkstring(L,2);
  402. }
  403. if ((listtype != "local") &&
  404. (listtype != "online"))
  405. return 0;
  406. if(listtype == "online") {
  407. servers = ServerList::getOnline();
  408. } else {
  409. servers = ServerList::getLocal();
  410. }
  411. int fav_idx = luaL_checkinteger(L,1) -1;
  412. if ((fav_idx >= 0) &&
  413. (fav_idx < (int) servers.size())) {
  414. ServerList::deleteEntry(servers[fav_idx]);
  415. }
  416. return 0;
  417. }
  418. /******************************************************************************/
  419. int ModApiMainMenu::l_show_keys_menu(lua_State *L)
  420. {
  421. GUIEngine* engine = getGuiEngine(L);
  422. sanity_check(engine != NULL);
  423. GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(RenderingEngine::get_gui_env(),
  424. engine->m_parent,
  425. -1,
  426. engine->m_menumanager);
  427. kmenu->drop();
  428. return 0;
  429. }
  430. /******************************************************************************/
  431. int ModApiMainMenu::l_create_world(lua_State *L)
  432. {
  433. const char *name = luaL_checkstring(L, 1);
  434. int gameidx = luaL_checkinteger(L,2) -1;
  435. std::string path = porting::path_user + DIR_DELIM
  436. "worlds" + DIR_DELIM
  437. + name;
  438. std::vector<SubgameSpec> games = getAvailableGames();
  439. if ((gameidx >= 0) &&
  440. (gameidx < (int) games.size())) {
  441. // Create world if it doesn't exist
  442. if (!loadGameConfAndInitWorld(path, games[gameidx])) {
  443. lua_pushstring(L, "Failed to initialize world");
  444. } else {
  445. lua_pushnil(L);
  446. }
  447. } else {
  448. lua_pushstring(L, "Invalid game index");
  449. }
  450. return 1;
  451. }
  452. /******************************************************************************/
  453. int ModApiMainMenu::l_delete_world(lua_State *L)
  454. {
  455. int worldidx = luaL_checkinteger(L,1) -1;
  456. std::vector<WorldSpec> worlds = getAvailableWorlds();
  457. if ((worldidx >= 0) &&
  458. (worldidx < (int) worlds.size())) {
  459. WorldSpec spec = worlds[worldidx];
  460. std::vector<std::string> paths;
  461. paths.push_back(spec.path);
  462. fs::GetRecursiveSubPaths(spec.path, paths);
  463. // Delete files
  464. if (!fs::DeletePaths(paths)) {
  465. lua_pushstring(L, "Failed to delete world");
  466. }
  467. else {
  468. lua_pushnil(L);
  469. }
  470. }
  471. else {
  472. lua_pushstring(L, "Invalid world index");
  473. }
  474. return 1;
  475. }
  476. /******************************************************************************/
  477. int ModApiMainMenu::l_set_topleft_text(lua_State *L)
  478. {
  479. GUIEngine* engine = getGuiEngine(L);
  480. sanity_check(engine != NULL);
  481. std::string text = "";
  482. if (!lua_isnone(L,1) && !lua_isnil(L,1))
  483. text = luaL_checkstring(L, 1);
  484. engine->setTopleftText(text);
  485. return 0;
  486. }
  487. /******************************************************************************/
  488. int ModApiMainMenu::l_get_mapgen_names(lua_State *L)
  489. {
  490. std::vector<const char *> names;
  491. bool include_hidden = lua_isboolean(L, 1) && readParam<bool>(L, 1);
  492. Mapgen::getMapgenNames(&names, include_hidden);
  493. lua_newtable(L);
  494. for (size_t i = 0; i != names.size(); i++) {
  495. lua_pushstring(L, names[i]);
  496. lua_rawseti(L, -2, i + 1);
  497. }
  498. return 1;
  499. }
  500. /******************************************************************************/
  501. int ModApiMainMenu::l_get_modpath(lua_State *L)
  502. {
  503. std::string modpath = fs::RemoveRelativePathComponents(
  504. porting::path_user + DIR_DELIM + "mods" + DIR_DELIM);
  505. lua_pushstring(L, modpath.c_str());
  506. return 1;
  507. }
  508. /******************************************************************************/
  509. int ModApiMainMenu::l_get_clientmodpath(lua_State *L)
  510. {
  511. std::string modpath = fs::RemoveRelativePathComponents(
  512. porting::path_user + DIR_DELIM + "clientmods" + DIR_DELIM);
  513. lua_pushstring(L, modpath.c_str());
  514. return 1;
  515. }
  516. /******************************************************************************/
  517. int ModApiMainMenu::l_get_gamepath(lua_State *L)
  518. {
  519. std::string gamepath = fs::RemoveRelativePathComponents(
  520. porting::path_user + DIR_DELIM + "games" + DIR_DELIM);
  521. lua_pushstring(L, gamepath.c_str());
  522. return 1;
  523. }
  524. /******************************************************************************/
  525. int ModApiMainMenu::l_get_texturepath(lua_State *L)
  526. {
  527. std::string gamepath = fs::RemoveRelativePathComponents(
  528. porting::path_user + DIR_DELIM + "textures");
  529. lua_pushstring(L, gamepath.c_str());
  530. return 1;
  531. }
  532. int ModApiMainMenu::l_get_texturepath_share(lua_State *L)
  533. {
  534. std::string gamepath = fs::RemoveRelativePathComponents(
  535. porting::path_share + DIR_DELIM + "textures");
  536. lua_pushstring(L, gamepath.c_str());
  537. return 1;
  538. }
  539. /******************************************************************************/
  540. int ModApiMainMenu::l_create_dir(lua_State *L) {
  541. const char *path = luaL_checkstring(L, 1);
  542. if (ModApiMainMenu::isMinetestPath(path)) {
  543. lua_pushboolean(L, fs::CreateAllDirs(path));
  544. return 1;
  545. }
  546. lua_pushboolean(L, false);
  547. return 1;
  548. }
  549. /******************************************************************************/
  550. int ModApiMainMenu::l_delete_dir(lua_State *L)
  551. {
  552. const char *path = luaL_checkstring(L, 1);
  553. std::string absolute_path = fs::RemoveRelativePathComponents(path);
  554. if (ModApiMainMenu::isMinetestPath(absolute_path)) {
  555. lua_pushboolean(L, fs::RecursiveDelete(absolute_path));
  556. return 1;
  557. }
  558. lua_pushboolean(L, false);
  559. return 1;
  560. }
  561. /******************************************************************************/
  562. int ModApiMainMenu::l_copy_dir(lua_State *L)
  563. {
  564. const char *source = luaL_checkstring(L, 1);
  565. const char *destination = luaL_checkstring(L, 2);
  566. bool keep_source = true;
  567. if ((!lua_isnone(L,3)) &&
  568. (!lua_isnil(L,3))) {
  569. keep_source = readParam<bool>(L,3);
  570. }
  571. std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
  572. std::string absolute_source = fs::RemoveRelativePathComponents(source);
  573. if ((ModApiMainMenu::isMinetestPath(absolute_destination))) {
  574. bool retval = fs::CopyDir(absolute_source,absolute_destination);
  575. if (retval && (!keep_source)) {
  576. retval &= fs::RecursiveDelete(absolute_source);
  577. }
  578. lua_pushboolean(L,retval);
  579. return 1;
  580. }
  581. lua_pushboolean(L,false);
  582. return 1;
  583. }
  584. /******************************************************************************/
  585. int ModApiMainMenu::l_extract_zip(lua_State *L)
  586. {
  587. const char *zipfile = luaL_checkstring(L, 1);
  588. const char *destination = luaL_checkstring(L, 2);
  589. std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
  590. if (ModApiMainMenu::isMinetestPath(absolute_destination)) {
  591. fs::CreateAllDirs(absolute_destination);
  592. io::IFileSystem *fs = RenderingEngine::get_filesystem();
  593. if (!fs->addFileArchive(zipfile,true,false,io::EFAT_ZIP)) {
  594. lua_pushboolean(L,false);
  595. return 1;
  596. }
  597. sanity_check(fs->getFileArchiveCount() > 0);
  598. /**********************************************************************/
  599. /* WARNING this is not threadsafe!! */
  600. /**********************************************************************/
  601. io::IFileArchive* opened_zip =
  602. fs->getFileArchive(fs->getFileArchiveCount()-1);
  603. const io::IFileList* files_in_zip = opened_zip->getFileList();
  604. unsigned int number_of_files = files_in_zip->getFileCount();
  605. for (unsigned int i=0; i < number_of_files; i++) {
  606. std::string fullpath = destination;
  607. fullpath += DIR_DELIM;
  608. fullpath += files_in_zip->getFullFileName(i).c_str();
  609. std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath);
  610. if (!files_in_zip->isDirectory(i)) {
  611. if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) {
  612. fs->removeFileArchive(fs->getFileArchiveCount()-1);
  613. lua_pushboolean(L,false);
  614. return 1;
  615. }
  616. io::IReadFile* toread = opened_zip->createAndOpenFile(i);
  617. FILE *targetfile = fopen(fullpath.c_str(),"wb");
  618. if (targetfile == NULL) {
  619. fs->removeFileArchive(fs->getFileArchiveCount()-1);
  620. lua_pushboolean(L,false);
  621. return 1;
  622. }
  623. char read_buffer[1024];
  624. long total_read = 0;
  625. while (total_read < toread->getSize()) {
  626. unsigned int bytes_read =
  627. toread->read(read_buffer,sizeof(read_buffer));
  628. if ((bytes_read == 0 ) ||
  629. (fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read))
  630. {
  631. fclose(targetfile);
  632. fs->removeFileArchive(fs->getFileArchiveCount()-1);
  633. lua_pushboolean(L,false);
  634. return 1;
  635. }
  636. total_read += bytes_read;
  637. }
  638. fclose(targetfile);
  639. }
  640. }
  641. fs->removeFileArchive(fs->getFileArchiveCount()-1);
  642. lua_pushboolean(L,true);
  643. return 1;
  644. }
  645. lua_pushboolean(L,false);
  646. return 1;
  647. }
  648. /******************************************************************************/
  649. int ModApiMainMenu::l_get_mainmenu_path(lua_State *L)
  650. {
  651. GUIEngine* engine = getGuiEngine(L);
  652. sanity_check(engine != NULL);
  653. lua_pushstring(L,engine->getScriptDir().c_str());
  654. return 1;
  655. }
  656. /******************************************************************************/
  657. bool ModApiMainMenu::isMinetestPath(std::string path)
  658. {
  659. if (fs::PathStartsWith(path,fs::TempPath()))
  660. return true;
  661. /* games */
  662. if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_share + DIR_DELIM + "games")))
  663. return true;
  664. /* mods */
  665. if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "mods")))
  666. return true;
  667. /* worlds */
  668. if (fs::PathStartsWith(path,fs::RemoveRelativePathComponents(porting::path_user + DIR_DELIM + "worlds")))
  669. return true;
  670. return false;
  671. }
  672. /******************************************************************************/
  673. int ModApiMainMenu::l_show_path_select_dialog(lua_State *L)
  674. {
  675. GUIEngine* engine = getGuiEngine(L);
  676. sanity_check(engine != NULL);
  677. const char *formname= luaL_checkstring(L, 1);
  678. const char *title = luaL_checkstring(L, 2);
  679. bool is_file_select = readParam<bool>(L, 3);
  680. GUIFileSelectMenu* fileOpenMenu =
  681. new GUIFileSelectMenu(RenderingEngine::get_gui_env(),
  682. engine->m_parent,
  683. -1,
  684. engine->m_menumanager,
  685. title,
  686. formname,
  687. is_file_select);
  688. fileOpenMenu->setTextDest(engine->m_buttonhandler);
  689. fileOpenMenu->drop();
  690. return 0;
  691. }
  692. /******************************************************************************/
  693. int ModApiMainMenu::l_download_file(lua_State *L)
  694. {
  695. const char *url = luaL_checkstring(L, 1);
  696. const char *target = luaL_checkstring(L, 2);
  697. //check path
  698. std::string absolute_destination = fs::RemoveRelativePathComponents(target);
  699. if (ModApiMainMenu::isMinetestPath(absolute_destination)) {
  700. if (GUIEngine::downloadFile(url,absolute_destination)) {
  701. lua_pushboolean(L,true);
  702. return 1;
  703. }
  704. } else {
  705. errorstream << "DOWNLOAD denied: " << absolute_destination
  706. << " isn't a allowed path" << std::endl;
  707. }
  708. lua_pushboolean(L,false);
  709. return 1;
  710. }
  711. /******************************************************************************/
  712. int ModApiMainMenu::l_get_video_drivers(lua_State *L)
  713. {
  714. std::vector<irr::video::E_DRIVER_TYPE> drivers = RenderingEngine::getSupportedVideoDrivers();
  715. lua_newtable(L);
  716. for (u32 i = 0; i != drivers.size(); i++) {
  717. const char *name = RenderingEngine::getVideoDriverName(drivers[i]);
  718. const char *fname = RenderingEngine::getVideoDriverFriendlyName(drivers[i]);
  719. lua_newtable(L);
  720. lua_pushstring(L, name);
  721. lua_setfield(L, -2, "name");
  722. lua_pushstring(L, fname);
  723. lua_setfield(L, -2, "friendly_name");
  724. lua_rawseti(L, -2, i + 1);
  725. }
  726. return 1;
  727. }
  728. /******************************************************************************/
  729. int ModApiMainMenu::l_get_video_modes(lua_State *L)
  730. {
  731. std::vector<core::vector3d<u32> > videomodes
  732. = RenderingEngine::getSupportedVideoModes();
  733. lua_newtable(L);
  734. for (u32 i = 0; i != videomodes.size(); i++) {
  735. lua_newtable(L);
  736. lua_pushnumber(L, videomodes[i].X);
  737. lua_setfield(L, -2, "w");
  738. lua_pushnumber(L, videomodes[i].Y);
  739. lua_setfield(L, -2, "h");
  740. lua_pushnumber(L, videomodes[i].Z);
  741. lua_setfield(L, -2, "depth");
  742. lua_rawseti(L, -2, i + 1);
  743. }
  744. return 1;
  745. }
  746. /******************************************************************************/
  747. int ModApiMainMenu::l_gettext(lua_State *L)
  748. {
  749. std::string text = strgettext(std::string(luaL_checkstring(L, 1)));
  750. lua_pushstring(L, text.c_str());
  751. return 1;
  752. }
  753. /******************************************************************************/
  754. int ModApiMainMenu::l_get_screen_info(lua_State *L)
  755. {
  756. lua_newtable(L);
  757. int top = lua_gettop(L);
  758. lua_pushstring(L,"density");
  759. lua_pushnumber(L,RenderingEngine::getDisplayDensity());
  760. lua_settable(L, top);
  761. lua_pushstring(L,"display_width");
  762. lua_pushnumber(L,RenderingEngine::getDisplaySize().X);
  763. lua_settable(L, top);
  764. lua_pushstring(L,"display_height");
  765. lua_pushnumber(L,RenderingEngine::getDisplaySize().Y);
  766. lua_settable(L, top);
  767. const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
  768. lua_pushstring(L,"window_width");
  769. lua_pushnumber(L, window_size.X);
  770. lua_settable(L, top);
  771. lua_pushstring(L,"window_height");
  772. lua_pushnumber(L, window_size.Y);
  773. lua_settable(L, top);
  774. return 1;
  775. }
  776. /******************************************************************************/
  777. int ModApiMainMenu::l_get_min_supp_proto(lua_State *L)
  778. {
  779. u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ?
  780. CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN;
  781. lua_pushinteger(L, proto_version_min);
  782. return 1;
  783. }
  784. int ModApiMainMenu::l_get_max_supp_proto(lua_State *L)
  785. {
  786. lua_pushinteger(L, CLIENT_PROTOCOL_VERSION_MAX);
  787. return 1;
  788. }
  789. /******************************************************************************/
  790. int ModApiMainMenu::l_do_async_callback(lua_State *L)
  791. {
  792. GUIEngine* engine = getGuiEngine(L);
  793. size_t func_length, param_length;
  794. const char* serialized_func_raw = luaL_checklstring(L, 1, &func_length);
  795. const char* serialized_param_raw = luaL_checklstring(L, 2, &param_length);
  796. sanity_check(serialized_func_raw != NULL);
  797. sanity_check(serialized_param_raw != NULL);
  798. std::string serialized_func = std::string(serialized_func_raw, func_length);
  799. std::string serialized_param = std::string(serialized_param_raw, param_length);
  800. lua_pushinteger(L, engine->queueAsync(serialized_func, serialized_param));
  801. return 1;
  802. }
  803. /******************************************************************************/
  804. void ModApiMainMenu::Initialize(lua_State *L, int top)
  805. {
  806. API_FCT(update_formspec);
  807. API_FCT(set_clouds);
  808. API_FCT(get_textlist_index);
  809. API_FCT(get_table_index);
  810. API_FCT(get_worlds);
  811. API_FCT(get_games);
  812. API_FCT(get_mod_info);
  813. API_FCT(start);
  814. API_FCT(close);
  815. API_FCT(get_favorites);
  816. API_FCT(show_keys_menu);
  817. API_FCT(create_world);
  818. API_FCT(delete_world);
  819. API_FCT(delete_favorite);
  820. API_FCT(set_background);
  821. API_FCT(set_topleft_text);
  822. API_FCT(get_mapgen_names);
  823. API_FCT(get_modpath);
  824. API_FCT(get_clientmodpath);
  825. API_FCT(get_gamepath);
  826. API_FCT(get_texturepath);
  827. API_FCT(get_texturepath_share);
  828. API_FCT(create_dir);
  829. API_FCT(delete_dir);
  830. API_FCT(copy_dir);
  831. API_FCT(extract_zip);
  832. API_FCT(get_mainmenu_path);
  833. API_FCT(show_path_select_dialog);
  834. API_FCT(download_file);
  835. API_FCT(gettext);
  836. API_FCT(get_video_drivers);
  837. API_FCT(get_video_modes);
  838. API_FCT(get_screen_info);
  839. API_FCT(get_min_supp_proto);
  840. API_FCT(get_max_supp_proto);
  841. API_FCT(do_async_callback);
  842. }
  843. /******************************************************************************/
  844. void ModApiMainMenu::InitializeAsync(lua_State *L, int top)
  845. {
  846. API_FCT(get_worlds);
  847. API_FCT(get_games);
  848. API_FCT(get_favorites);
  849. API_FCT(get_mapgen_names);
  850. API_FCT(get_modpath);
  851. API_FCT(get_clientmodpath);
  852. API_FCT(get_gamepath);
  853. API_FCT(get_texturepath);
  854. API_FCT(get_texturepath_share);
  855. API_FCT(create_dir);
  856. API_FCT(delete_dir);
  857. API_FCT(copy_dir);
  858. //API_FCT(extract_zip); //TODO remove dependency to GuiEngine
  859. API_FCT(download_file);
  860. //API_FCT(gettext); (gettext lib isn't threadsafe)
  861. }