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