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