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